summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKarl 'vollmerk' Vollmer <vollmer@ampache.org>2005-06-09 16:34:40 +0000
committerKarl 'vollmerk' Vollmer <vollmer@ampache.org>2005-06-09 16:34:40 +0000
commitbcad40a05ab2dc2a341a3227e30b96668bce4500 (patch)
tree6fca27588d53a1b24705bd2834e9e643bb729bd1 /lib
downloadampache-bcad40a05ab2dc2a341a3227e30b96668bce4500.tar.gz
ampache-bcad40a05ab2dc2a341a3227e30b96668bce4500.tar.bz2
ampache-bcad40a05ab2dc2a341a3227e30b96668bce4500.zip
New Import
Diffstat (limited to 'lib')
-rw-r--r--lib/Browser.php1082
-rw-r--r--lib/album.php31
-rw-r--r--lib/archive.php778
-rw-r--r--lib/artist.php122
-rw-r--r--lib/batch.php63
-rw-r--r--lib/debug.php361
-rw-r--r--lib/duplicates.php117
-rw-r--r--lib/flag.php348
-rw-r--r--lib/general.php554
-rw-r--r--lib/gettext.php36
-rw-r--r--lib/install.php238
-rw-r--r--lib/log.php77
-rw-r--r--lib/mpd.php75
-rwxr-xr-xlib/perl/Local/Ampache/Ampache.pm237
-rwxr-xr-xlib/perl/Local/Ampache/Makefile.PL7
-rw-r--r--lib/preferences.php281
-rw-r--r--lib/rss.php64
-rw-r--r--lib/search.php185
-rw-r--r--lib/song.php57
-rw-r--r--lib/themes.php124
-rw-r--r--lib/ui.php437
-rw-r--r--lib/xmlrpc.php143
22 files changed, 5417 insertions, 0 deletions
diff --git a/lib/Browser.php b/lib/Browser.php
new file mode 100644
index 00000000..cf97dc41
--- /dev/null
+++ b/lib/Browser.php
@@ -0,0 +1,1082 @@
+<?php
+/**
+ * The Browser:: class provides capability information for the current
+ * web client. Browser identification is performed by examining the
+ * HTTP_USER_AGENT environmental variable provide by the web server.
+ *
+ * $Horde: framework/Browser/Browser.php,v 1.167 2005/03/02 16:05:15 jan Exp $
+ *
+ * Copyright 1999-2005 Chuck Hagenbuch <chuck@horde.org>
+ * Copyright 1999-2005 Jon Parise <jon@horde.org>
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Jon Parise <jon@horde.org>
+ * @since Horde 1.3
+ * @package Horde_Browser
+ */
+class Browser {
+
+ /**
+ * Major version number.
+ *
+ * @var integer $_majorVersion
+ */
+ var $_majorVersion = 0;
+
+ /**
+ * Minor version number.
+ *
+ * @var integer $_minorVersion
+ */
+ var $_minorVersion = 0;
+
+ /**
+ * Browser name.
+ *
+ * @var string $_browser
+ */
+ var $_browser = '';
+
+ /**
+ * Full user agent string.
+ *
+ * @var string $_agent
+ */
+ var $_agent = '';
+
+ /**
+ * Lower-case user agent string.
+ *
+ * @var string $_agent
+ */
+ var $_lowerAgent = '';
+
+ /**
+ * HTTP_ACCEPT string
+ *
+ * @var string $_accept
+ */
+ var $_accept = '';
+
+ /**
+ * Platform the browser is running on.
+ *
+ * @var string $_platform
+ */
+ var $_platform = '';
+
+ /**
+ * Known robots.
+ *
+ * @var array $_robots
+ */
+ var $_robots = array(
+ /* The most common ones. */
+ 'Googlebot',
+ 'msnbot',
+ 'Slurp',
+ 'Yahoo',
+ /* The rest alphabetically. */
+ 'Arachnoidea',
+ 'ArchitextSpider',
+ 'Ask Jeeves',
+ 'B-l-i-t-z-Bot',
+ 'ConveraCrawler',
+ 'ExtractorPro',
+ 'FAST-WebCrawler',
+ 'FDSE robot',
+ 'fido',
+ 'geckobot',
+ 'Gigabot',
+ 'Girafabot',
+ 'grub-client',
+ 'Gulliver',
+ 'ia_archiver',
+ 'InfoSeek',
+ 'KIT-Fireball',
+ 'LEIA',
+ 'Lycos_Spider',
+ 'Mediapartners-Google',
+ 'MuscatFerret',
+ 'NaverBot',
+ 'polybot',
+ 'Pompos',
+ 'Scooter',
+ 'Teoma',
+ 'TurnitinBot',
+ 'Ultraseek',
+ 'ViolaBot',
+ 'webbandit',
+ 'www.almaden.ibm.com/cs/crawler',
+ 'ZyBorg',
+ );
+
+ /**
+ * Is this a mobile browser?
+ *
+ * @var boolean $_mobile
+ */
+ var $_mobile = false;
+
+ /**
+ * Features.
+ *
+ * @var array $_features
+ */
+ var $_features = array(
+ 'html' => true,
+ 'hdml' => false,
+ 'wml' => false,
+ 'images' => true,
+ 'iframes' => false,
+ 'frames' => true,
+ 'tables' => true,
+ 'java' => true,
+ 'javascript' => true,
+ 'dom' => false,
+ 'utf' => false,
+ 'rte' => false,
+ 'homepage' => false,
+ 'accesskey' => false,
+ 'optgroup' => false,
+ 'xmlhttpreq' => false,
+ 'cite' => false,
+ );
+
+ /**
+ * Quirks
+ *
+ * @var array $_quirks
+ */
+ var $_quirks = array(
+ 'avoid_popup_windows' => false,
+ 'break_disposition_header' => false,
+ 'break_disposition_filename' => false,
+ 'broken_multipart_form' => false,
+ 'buggy_compression' => false,
+ 'cache_same_url' => false,
+ 'cache_ssl_downloads' => false,
+ 'double_linebreak_textarea' => false,
+ 'empty_file_input_value' => false,
+ 'must_cache_forms' => false,
+ 'no_filename_spaces' => false,
+ 'no_hidden_overflow_tables' => false,
+ 'ow_gui_1.3' => false,
+ 'png_transparency' => false,
+ 'scrollbar_in_way' => false,
+ 'scroll_tds' => false,
+ );
+
+ /**
+ * List of viewable image MIME subtypes.
+ * This list of viewable images works for IE and Netscape/Mozilla.
+ *
+ * @var array $_images
+ */
+ var $_images = array('jpeg', 'gif', 'png', 'pjpeg', 'x-png', 'bmp');
+
+ /**
+
+ /**
+ * Returns a reference to the global Browser object, only creating it
+ * if it doesn't already exist.
+ *
+ * This method must be invoked as:
+ * $browser = &Browser::singleton([$userAgent[, $accept]]);
+ *
+ * @access public
+ *
+ * @param optional string $userAgent The browser string to parse.
+ * @param optional string $accept The HTTP_ACCEPT settings to use.
+ *
+ * @return object Browser The Browser object.
+ */
+ function &singleton($userAgent = null, $accept = null)
+ {
+ static $instances;
+
+ if (!isset($instances)) {
+ $instances = array();
+ }
+
+ $signature = serialize(array($userAgent, $accept));
+ if (empty($instances[$signature])) {
+ $instances[$signature] = new Browser($userAgent, $accept);
+ }
+
+ return $instances[$signature];
+ }
+
+ /**
+ * Create a browser instance (Constructor).
+ *
+ * @access public
+ *
+ * @param optional string $userAgent The browser string to parse.
+ * @param optional string $accept The HTTP_ACCEPT settings to use.
+ */
+ function Browser($userAgent = null, $accept = null)
+ {
+ $this->match($userAgent, $accept);
+ }
+
+ /**
+ * Parses the user agent string and inititializes the object with
+ * all the known features and quirks for the given browser.
+ *
+ * @access public
+ *
+ * @param optional string $userAgent The browser string to parse.
+ * @param optional string $accept The HTTP_ACCEPT settings to use.
+ */
+ function match($userAgent = null, $accept = null)
+ {
+ // Set our agent string.
+ if (is_null($userAgent)) {
+ if (isset($_SERVER['HTTP_USER_AGENT'])) {
+ $this->_agent = trim($_SERVER['HTTP_USER_AGENT']);
+ }
+ } else {
+ $this->_agent = $userAgent;
+ }
+ $this->_lowerAgent = strtolower($this->_agent);
+
+ // Set our accept string.
+ if (is_null($accept)) {
+ if (isset($_SERVER['HTTP_ACCEPT'])) {
+ $this->_accept = strtolower(trim($_SERVER['HTTP_ACCEPT']));
+ }
+ } else {
+ $this->_accept = strtolower($accept);
+ }
+
+ // Check for UTF support.
+ if (isset($_SERVER['HTTP_ACCEPT_CHARSET'])) {
+ $this->setFeature('utf', strpos(strtolower($_SERVER['HTTP_ACCEPT_CHARSET']), 'utf') !== false);
+ }
+
+ if (!empty($this->_agent)) {
+ $this->_setPlatform();
+
+ if (preg_match('|Opera[/ ]([0-9.]+)|', $this->_agent, $version)) {
+ $this->setBrowser('opera');
+ list($this->_majorVersion, $this->_minorVersion) = explode('.', $version[1]);
+ $this->setFeature('javascript', true);
+ $this->setQuirk('no_filename_spaces');
+
+ switch ($this->_majorVersion) {
+ case 7:
+ $this->setFeature('dom');
+ $this->setFeature('iframes');
+ $this->setFeature('accesskey');
+ $this->setFeature('optgroup');
+ $this->setQuirk('double_linebreak_textarea');
+ break;
+ }
+ } elseif (strpos($this->_lowerAgent, 'elaine/') !== false ||
+ strpos($this->_lowerAgent, 'palmsource') !== false ||
+ strpos($this->_lowerAgent, 'digital paths') !== false) {
+ $this->setBrowser('palm');
+ $this->setFeature('images', false);
+ $this->setFeature('frames', false);
+ $this->setFeature('javascript', false);
+ $this->setQuirk('avoid_popup_windows');
+ $this->_mobile = true;
+ } elseif ((preg_match('|MSIE ([0-9.]+)|', $this->_agent, $version)) ||
+ (preg_match('|Internet Explorer/([0-9.]+)|', $this->_agent, $version))) {
+
+ $this->setBrowser('msie');
+ $this->setQuirk('cache_ssl_downloads');
+ $this->setQuirk('cache_same_url');
+ $this->setQuirk('break_disposition_filename');
+
+ if (strpos($version[1], '.') !== false) {
+ list($this->_majorVersion, $this->_minorVersion) = explode('.', $version[1]);
+ } else {
+ $this->_majorVersion = $version[1];
+ $this->_minorVersion = 0;
+ }
+
+ /* IE on Windows does not support alpha transparency in PNG
+ * images. */
+ if (preg_match('/windows/i', $this->_agent)) {
+ $this->setQuirk('png_transparency');
+ }
+
+ /* IE 6 (pre-SP1) and 5.5 (pre-SP1) has buggy compression.
+ * The versions affected are as follows:
+ * 6.00.2462.0000 Internet Explorer 6 Public Preview (Beta)
+ * 6.00.2479.0006 Internet Explorer 6 Public Preview (Beta)
+ Refresh
+ * 6.00.2600.0000 Internet Explorer 6 (Windows XP)
+ * 5.50.3825.1300 Internet Explorer 5.5 Developer Preview (Beta)
+ * 5.50.4030.2400 Internet Explorer 5.5 & Internet Tools Beta
+ * 5.50.4134.0100 Internet Explorer 5.5 for Windows Me (4.90.3000)
+ * 5.50.4134.0600 Internet Explorer 5.5
+ * 5.50.4308.2900 Internet Explorer 5.5 Advanced Security Privacy Beta
+ *
+ * See:
+ * ====
+ * http://support.microsoft.com/kb/164539;
+ * http://support.microsoft.com/default.aspx?scid=kb;en-us;Q312496)
+ * http://support.microsoft.com/default.aspx?scid=kb;en-us;Q313712
+ */
+ $ie_vers = $this->getIEVersion();
+ $buggy_list = array(
+ '6,00,2462,0000', '6,00,2479,0006', '6,00,2600,0000',
+ '5,50,3825,1300', '5,50,4030,2400', '5,50,4134,0100',
+ '5,50,4134,0600', '5,50,4308,2900'
+ );
+ if (!is_null($ie_vers) && in_array($ie_vers, $buggy_list)) {
+ $this->setQuirk('buggy_compression');
+ }
+
+ /* Some Handhelds have their screen resolution in the
+ * user agent string, which we can use to look for
+ * mobile agents. */
+ if (preg_match('/; (120x160|240x280|240x320)\)/', $this->_agent)) {
+ $this->_mobile = true;
+ }
+
+ switch ($this->_majorVersion) {
+ case 6:
+ $this->setFeature('javascript', 1.4);
+ $this->setFeature('dom');
+ $this->setFeature('iframes');
+ $this->setFeature('utf');
+ $this->setFeature('rte');
+ $this->setFeature('homepage');
+ $this->setFeature('accesskey');
+ $this->setFeature('optgroup');
+ $this->setFeature('xmlhttpreq');
+ $this->setQuirk('scrollbar_in_way');
+ $this->setQuirk('broken_multipart_form');
+ break;
+
+ case 5:
+ if ($this->getPlatform() == 'mac') {
+ $this->setFeature('javascript', 1.2);
+ $this->setFeature('optgroup');
+ } else {
+ // MSIE 5 for Windows.
+ $this->setFeature('javascript', 1.4);
+ $this->setFeature('dom');
+ $this->setFeature('xmlhttpreq');
+ if ($this->_minorVersion >= 5) {
+ $this->setFeature('rte');
+ }
+ }
+ $this->setFeature('iframes');
+ $this->setFeature('utf');
+ $this->setFeature('homepage');
+ $this->setFeature('accesskey');
+ if ($this->_minorVersion == 5) {
+ $this->setQuirk('break_disposition_header');
+ $this->setQuirk('broken_multipart_form');
+ }
+ break;
+
+ case 4:
+ $this->setFeature('javascript', 1.2);
+ $this->setFeature('accesskey');
+ if ($this->_minorVersion > 0) {
+ $this->setFeature('utf');
+ }
+ break;
+
+ case 3:
+ $this->setFeature('javascript', 1.1);
+ $this->setQuirk('avoid_popup_windows');
+ break;
+ }
+ } elseif (preg_match('|ANTFresco/([0-9]+)|', $this->_agent, $version)) {
+ $this->setBrowser('fresco');
+ $this->setFeature('javascript', 1.1);
+ $this->setQuirk('avoid_popup_windows');
+ } elseif (strpos($this->_lowerAgent, 'avantgo') !== false) {
+ $this->setBrowser('avantgo');
+ $this->_mobile = true;
+ } elseif (preg_match('|Konqueror/([0-9]+)|', $this->_agent, $version) ||
+ preg_match('|Safari/([0-9]+)\.?([0-9]+)?|', $this->_agent, $version)) {
+ // Konqueror and Apple's Safari both use the KHTML
+ // rendering engine.
+ $this->setBrowser('konqueror');
+ $this->setQuirk('empty_file_input_value');
+ $this->setQuirk('no_hidden_overflow_tables');
+ $this->_majorVersion = $version[1];
+ if (isset($version[2])) {
+ $this->_minorVersion = $version[2];
+ }
+
+ if (strpos($this->_agent, 'Safari') !== false &&
+ $this->_majorVersion >= 60) {
+ // Safari.
+ $this->setFeature('utf');
+ $this->setFeature('javascript', 1.4);
+ $this->setFeature('dom');
+ $this->setFeature('iframes');
+ if ($this->_majorVersion > 125 ||
+ ($this->_majorVersion == 125 &&
+ $this->_minorVersion >= 1)) {
+ $this->setFeature('utf');
+ $this->setFeature('accesskey');
+ $this->setFeature('xmlhttpreq');
+ }
+ } else {
+ // Konqueror.
+ $this->setFeature('javascript', 1.1);
+ switch ($this->_majorVersion) {
+ case 3:
+ $this->setFeature('dom');
+ $this->setFeature('iframes');
+ break;
+ }
+ }
+ } elseif (preg_match('|Mozilla/([0-9.]+)|', $this->_agent, $version)) {
+ $this->setBrowser('mozilla');
+ $this->setQuirk('must_cache_forms');
+
+ list($this->_majorVersion, $this->_minorVersion) = explode('.', $version[1]);
+ switch ($this->_majorVersion) {
+ case 5:
+ if ($this->getPlatform() == 'win') {
+ $this->setQuirk('break_disposition_filename');
+ }
+ $this->setFeature('javascript', 1.4);
+ $this->setFeature('dom');
+ $this->setFeature('accesskey');
+ $this->setFeature('optgroup');
+ $this->setFeature('xmlhttpreq');
+ $this->setFeature('cite');
+ if (preg_match('|rv:(.*)\)|', $this->_agent, $revision)) {
+ if ($revision[1] >= 1) {
+ $this->setFeature('iframes');
+ }
+ if ($revision[1] >= 1.3) {
+ $this->setFeature('rte');
+ }
+ }
+ break;
+
+ case 4:
+ $this->setFeature('javascript', 1.3);
+ $this->setQuirk('buggy_compression');
+ break;
+
+ case 3:
+ default:
+ $this->setFeature('javascript', 1);
+ $this->setQuirk('buggy_compression');
+ break;
+ }
+ } elseif (preg_match('|Lynx/([0-9]+)|', $this->_agent, $version)) {
+ $this->setBrowser('lynx');
+ $this->setFeature('images', false);
+ $this->setFeature('frames', false);
+ $this->setFeature('javascript', false);
+ $this->setQuirk('avoid_popup_windows');
+ } elseif (preg_match('|Links \(([0-9]+)|', $this->_agent, $version)) {
+ $this->setBrowser('links');
+ $this->setFeature('images', false);
+ $this->setFeature('frames', false);
+ $this->setFeature('javascript', false);
+ $this->setQuirk('avoid_popup_windows');
+ } elseif (preg_match('|HotJava/([0-9]+)|', $this->_agent, $version)) {
+ $this->setBrowser('hotjava');
+ $this->setFeature('javascript', false);
+ } elseif (strpos($this->_agent, 'UP/') !== false ||
+ strpos($this->_agent, 'UP.B') !== false ||
+ strpos($this->_agent, 'UP.L') !== false) {
+ $this->setBrowser('up');
+ $this->setFeature('html', false);
+ $this->setFeature('javascript', false);
+ $this->setFeature('hdml');
+ $this->setFeature('wml');
+
+ if (strpos($this->_agent, 'GUI') !== false &&
+ strpos($this->_agent, 'UP.Link') !== false) {
+ /* The device accepts Openwave GUI extensions for
+ * WML 1.3. Non-UP.Link gateways sometimes have
+ * problems, so exclude them. */
+ $this->setQuirk('ow_gui_1.3');
+ }
+ $this->_mobile = true;
+ } elseif (strpos($this->_agent, 'Xiino/') !== false) {
+ $this->setBrowser('xiino');
+ $this->setFeature('hdml');
+ $this->setFeature('wml');
+ $this->_mobile = true;
+ } elseif (strpos($this->_agent, 'Palmscape/') !== false) {
+ $this->setBrowser('palmscape');
+ $this->setFeature('javascript', false);
+ $this->setFeature('hdml');
+ $this->setFeature('wml');
+ $this->_mobile = true;
+ } elseif (strpos($this->_agent, 'Nokia') !== false) {
+ $this->setBrowser('nokia');
+ $this->setFeature('html', false);
+ $this->setFeature('wml');
+ $this->setFeature('xhtml');
+ $this->_mobile = true;
+ } elseif (strpos($this->_agent, 'Ericsson') !== false) {
+ $this->setBrowser('ericsson');
+ $this->setFeature('html', false);
+ $this->setFeature('wml');
+ $this->_mobile = true;
+ } elseif (strpos($this->_lowerAgent, 'wap') !== false) {
+ $this->setBrowser('wap');
+ $this->setFeature('html', false);
+ $this->setFeature('javascript', false);
+ $this->setFeature('hdml');
+ $this->setFeature('wml');
+ $this->_mobile = true;
+ } elseif (strpos($this->_lowerAgent, 'docomo') !== false ||
+ strpos($this->_lowerAgent, 'portalmmm') !== false) {
+ $this->setBrowser('imode');
+ $this->setFeature('images', false);
+ $this->_mobile = true;
+ } elseif (strpos($this->_lowerAgent, 'j-') !== false) {
+ $this->setBrowser('mml');
+ $this->_mobile = true;
+ }
+ }
+ }
+
+ /**
+ * Match the platform of the browser.
+ *
+ * This is a pretty simplistic implementation, but it's intended
+ * to let us tell what line breaks to send, so it's good enough
+ * for its purpose.
+ *
+ * @access public
+ *
+ * @since Horde 2.2
+ */
+ function _setPlatform()
+ {
+ if (strpos($this->_lowerAgent, 'wind') !== false) {
+ $this->_platform = 'win';
+ } elseif (strpos($this->_lowerAgent, 'mac') !== false) {
+ $this->_platform = 'mac';
+ } else {
+ $this->_platform = 'unix';
+ }
+ }
+
+ /**
+ * Return the currently matched platform.
+ *
+ * @return string The user's platform.
+ *
+ * @since Horde 2.2
+ */
+ function getPlatform()
+ {
+ return $this->_platform;
+ }
+
+ /**
+ * Sets the current browser.
+ *
+ * @access public
+ *
+ * @param string $browser The browser to set as current.
+ */
+ function setBrowser($browser)
+ {
+ $this->_browser = $browser;
+ }
+
+ /**
+ * Determine if the given browser is the same as the current.
+ *
+ * @access public
+ *
+ * @param string $browser The browser to check.
+ *
+ * @return boolean Is the given browser the same as the current?
+ */
+ function isBrowser($browser)
+ {
+ return ($this->_browser === $browser);
+ }
+
+ /**
+ * Do we consider the current browser to be a mobile device?
+ *
+ * @return boolean True if we do, false if we don't.
+ */
+ function isMobile()
+ {
+ return $this->_mobile;
+ }
+
+ /**
+ * Determines if the browser is a robot or not.
+ *
+ * @access public
+ *
+ * @return boolean True if browser is a known robot.
+ */
+ function isRobot()
+ {
+ foreach ($this->_robots as $robot) {
+ if (strpos($this->_agent, $robot) !== false) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Retrieve the current browser.
+ *
+ * @access public
+ *
+ * @return string The current browser.
+ */
+ function getBrowser()
+ {
+ return $this->_browser;
+ }
+
+ /**
+ * Retrieve the current browser's major version.
+ *
+ * @access public
+ *
+ * @return integer The current browser's major version.
+ */
+ function getMajor()
+ {
+ return $this->_majorVersion;
+ }
+
+ /**
+ * Retrieve the current browser's minor version.
+ *
+ * @access public
+ *
+ * @return integer The current browser's minor version.
+ */
+ function getMinor()
+ {
+ return $this->_minorVersion;
+ }
+
+ /**
+ * Retrieve the current browser's version.
+ *
+ * @access public
+ *
+ * @return string The current browser's version.
+ */
+ function getVersion()
+ {
+ return $this->_majorVersion . '.' . $this->_minorVersion;
+ }
+
+ /**
+ * Return the full browser agent string.
+ *
+ * @access public
+ *
+ * @return string The browser agent string.
+ */
+ function getAgentString()
+ {
+ return $this->_agent;
+ }
+
+ /**
+ * Set unique behavior for the current browser.
+ *
+ * @access public
+ *
+ * @param string $quirk The behavior to set.
+ * @param optional string $value Special behavior parameter.
+ */
+ function setQuirk($quirk, $value = true)
+ {
+ $this->_quirks[$quirk] = $value;
+ }
+
+ /**
+ * Check unique behavior for the current browser.
+ *
+ * @access public
+ *
+ * @param string $quirk The behavior to check.
+ *
+ * @return boolean Does the browser have the behavior set?
+ */
+ function hasQuirk($quirk)
+ {
+ return !empty($this->_quirks[$quirk]);
+ }
+
+ /**
+ * Retreive unique behavior for the current browser.
+ *
+ * @access public
+ *
+ * @param string $quirk The behavior to retreive.
+ *
+ * @return string The value for the requested behavior.
+ */
+ function getQuirk($quirk)
+ {
+ return isset($this->_quirks[$quirk])
+ ? $this->_quirks[$quirk]
+ : null;
+ }
+
+ /**
+ * Set capabilities for the current browser.
+ *
+ * @access public
+ *
+ * @param string $feature The capability to set.
+ * @param optional string $value Special capability parameter.
+ */
+ function setFeature($feature, $value = true)
+ {
+ $this->_features[$feature] = $value;
+ }
+
+ /**
+ * Check the current browser capabilities.
+ *
+ * @access public
+ *
+ * @param string $feature The capability to check.
+ *
+ * @return boolean Does the browser have the capability set?
+ */
+ function hasFeature($feature)
+ {
+ return !empty($this->_features[$feature]);
+ }
+
+ /**
+ * Retreive the current browser capability.
+ *
+ * @access public
+ *
+ * @param string $feature The capability to retreive.
+ *
+ * @return string The value of the requested capability.
+ */
+ function getFeature($feature)
+ {
+ return isset($this->_features[$feature])
+ ? $this->_features[$feature]
+ : null;
+ }
+
+ /**
+ * Determine if we are using a secure (SSL) connection.
+ *
+ * @access public
+ *
+ * @return boolean True if using SSL, false if not.
+ */
+ function usingSSLConnection()
+ {
+ return ((isset($_SERVER['HTTPS']) &&
+ ($_SERVER['HTTPS'] == 'on')) ||
+ getenv('SSL_PROTOCOL_VERSION'));
+ }
+
+ /**
+ * Returns the server protocol in use on the current server.
+ *
+ * @access public
+ *
+ * @return string The HTTP server protocol version.
+ */
+ function getHTTPProtocol()
+ {
+ if (isset($_SERVER['SERVER_PROTOCOL'])) {
+ if (($pos = strrpos($_SERVER['SERVER_PROTOCOL'], '/'))) {
+ return substr($_SERVER['SERVER_PROTOCOL'], $pos + 1);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Determine if files can be uploaded to the system.
+ *
+ * @access public
+ *
+ * @return integer If uploads allowed, returns the maximum size of the
+ * upload in bytes. Returns 0 if uploads are not
+ * allowed.
+ */
+ function allowFileUploads()
+ {
+ if (ini_get('file_uploads')) {
+ if (($dir = ini_get('upload_tmp_dir')) &&
+ !is_writable($dir)) {
+ return 0;
+ }
+ $size = ini_get('upload_max_filesize');
+ switch (strtolower(substr($size, -1, 1))) {
+ case 'k':
+ $size = intval(floatval($size) * 1024);
+ break;
+
+ case 'm':
+ $size = intval(floatval($size) * 1024 * 1024);
+ break;
+
+ default:
+ $size = intval($size);
+ break;
+ }
+ return $size;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Determines if the file was uploaded or not. If not, will return the
+ * appropriate error message.
+ *
+ * @access public
+ *
+ * @param string $field The name of the field containing the
+ * uploaded file.
+ * @param optional string $name The file description string to use in the
+ * error message. Default: 'file'.
+ *
+ * @return mixed True on success, PEAR_Error on error.
+ */
+ function wasFileUploaded($field, $name = null)
+ {
+ require_once 'PEAR.php';
+
+ if (is_null($name)) {
+ $name = _("file");
+ }
+
+ if (!($uploadSize = Browser::allowFileUploads())) {
+ return PEAR::raiseError(_("File uploads not supported."));
+ }
+
+ /* Get any index on the field name. */
+ require_once 'Horde/Array.php';
+ $index = Horde_Array::getArrayParts($field, $base, $keys);
+
+ if ($index) {
+ /* Index present, fetch the error var to check. */
+ $keys_path = array_merge(array($base, 'error'), $keys);
+ $error = Horde_Array::getElement($_FILES, $keys_path);
+
+ /* Index present, fetch the tmp_name var to check. */
+ $keys_path = array_merge(array($base, 'tmp_name'), $keys);
+ $tmp_name = Horde_Array::getElement($_FILES, $keys_path);
+ } else {
+ /* No index, simple set up of vars to check. */
+ if (!isset($_FILES[$field])) {
+ return PEAR::raiseError(_("No file uploaded"), UPLOAD_ERR_NO_FILE);
+ }
+ $error = $_FILES[$field]['error'];
+ $tmp_name = $_FILES[$field]['tmp_name'];
+ }
+
+ if (!isset($_FILES) || ($error == UPLOAD_ERR_NO_FILE)) {
+ return PEAR::raiseError(sprintf(_("There was a problem with the file upload: No %s was uploaded."), $name), UPLOAD_ERR_NO_FILE);
+ } elseif (($error == UPLOAD_ERR_OK) && is_uploaded_file($tmp_name)) {
+ return true;
+ } elseif (($error == UPLOAD_ERR_INI_SIZE) ||
+ ($error == UPLOAD_ERR_FORM_SIZE)) {
+ return PEAR::raiseError(sprintf(_("There was a problem with the file upload: The %s was larger than the maximum allowed size (%d bytes)."), $name, $uploadSize), $error);
+ } elseif ($error == UPLOAD_ERR_PARTIAL) {
+ return PEAR::raiseError(sprintf(_("There was a problem with the file upload: The %s was only partially uploaded."), $name), $error);
+ }
+ }
+
+ /**
+ * Returns the headers for a browser download.
+ *
+ * @access public
+ *
+ * @param optional string $filename The filename of the download.
+ * @param optional string $cType The content-type description of the
+ * file.
+ * @param optional boolean $inline True if inline, false if attachment.
+ * @param optional string $cLength The content-length of this file.
+ *
+ * @since Horde 2.2
+ */
+ function downloadHeaders($filename = 'unknown', $cType = null,
+ $inline = false, $cLength = null)
+ {
+ /* Remove linebreaks from file names. */
+ $filename = str_replace(array("\r\n", "\r", "\n"), ' ', $filename);
+
+ /* Some browsers don't like spaces in the filename. */
+ if ($this->hasQuirk('no_filename_spaces')) {
+ $filename = strtr($filename, ' ', '_');
+ }
+
+ /* MSIE doesn't like multiple periods in the file name. Convert
+ all periods (except the last one) to underscores. */
+ if ($this->isBrowser('msie')) {
+ if (($pos = strrpos($filename, '.'))) {
+ $filename = strtr(substr($filename, 0, $pos), '.', '_') . substr($filename, $pos);
+ }
+ }
+
+ /* Content-Type/Content-Disposition Header. */
+ if ($inline) {
+ if (!is_null($cType)) {
+ header('Content-Type: ' . trim($cType));
+ } elseif ($this->isBrowser('msie')) {
+ header('Content-Type: application/x-msdownload');
+ } else {
+ header('Content-Type: application/octet-stream');
+ }
+ header('Content-Disposition: inline; filename="' . $filename . '"');
+ } else {
+ if ($this->isBrowser('msie')) {
+ header('Content-Type: application/x-msdownload');
+ } elseif (!is_null($cType)) {
+ header('Content-Type: ' . trim($cType));
+ } else {
+ header('Content-Type: application/octet-stream');
+ }
+
+ if ($this->hasQuirk('break_disposition_header')) {
+ header('Content-Disposition: filename="' . $filename . '"');
+ } else {
+ header('Content-Disposition: attachment; filename="' . $filename . '"');
+ }
+ }
+
+ /* Content-Length Header. Don't send Content-Length for
+ * HTTP/1.1 servers. */
+ if (($this->getHTTPProtocol() != '1.1') && !is_null($cLength)) {
+ header('Content-Length: ' . $cLength);
+ }
+
+ /* Overwrite Pragma: and other caching headers for IE. */
+ if ($this->hasQuirk('cache_ssl_downloads')) {
+ header('Expires: 0');
+ header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+ header('Pragma: public');
+ }
+ }
+
+ /**
+ * Determines if a browser can display a given MIME type.
+ *
+ * @access public
+ *
+ * @param string $mimetype The MIME type to check.
+ *
+ * @return boolean True if the browser can display the MIME type.
+ */
+ function isViewable($mimetype)
+ {
+ $mimetype = strtolower($mimetype);
+ list($type, $subtype) = explode('/', $mimetype);
+
+ if (!empty($this->_accept)) {
+ $wildcard_match = false;
+
+ if (strpos($this->_accept, $mimetype) !== false) {
+ return true;
+ }
+
+ if (strpos($this->_accept, '*/*') !== false) {
+ $wildcard_match = true;
+ if ($type != 'image') {
+ return true;
+ }
+ }
+
+ /* image/jpeg and image/pjpeg *appear* to be the same
+ * entity, but Mozilla doesn't seem to want to accept the
+ * latter. For our purposes, we will treat them the
+ * same. */
+ if ($this->isBrowser('mozilla') &&
+ ($mimetype == 'image/pjpeg') &&
+ (strpos($this->_accept, 'image/jpeg') !== false)) {
+ return true;
+ }
+
+ if (!$wildcard_match) {
+ return false;
+ }
+ }
+
+ if (!$this->hasFeature('images') || ($type != 'image')) {
+ return false;
+ }
+
+ return (in_array($subtype, $this->_images));
+ }
+
+ /**
+ * Escape characters in javascript code if the browser requires it.
+ * %23, %26, and %2B (for IE) and %27 need to be escaped or else
+ * jscript will interpret it as a single quote, pound sign, or
+ * ampersand and refuse to work.
+ *
+ * @access public
+ *
+ * @param string $code The JS code to escape.
+ *
+ * @return string The escaped code.
+ */
+ function escapeJSCode($code)
+ {
+ $from = $to = array();
+
+ if ($this->isBrowser('msie') ||
+ ($this->isBrowser('mozilla') && ($this->getMajor() >= 5))) {
+ $from = array('%23', '%26', '%2B');
+ $to = array(urlencode('%23'), urlencode('%26'), urlencode('%2B'));
+ }
+ $from[] = '%27';
+ $to[] = '\%27';
+
+ return str_replace($from, $to, $code);
+ }
+
+ /**
+ * Set the IE version in the session.
+ *
+ * @access public
+ *
+ * @param string $ver The IE Version string.
+ */
+ function setIEVersion($ver)
+ {
+ $_SESSION['__browser'] = array(
+ 'ie_version' => $ver
+ );
+ }
+
+ /**
+ * Return the IE version stored in the session, if available.
+ *
+ * @access public
+ *
+ * @return mixed The IE Version string or null if no string is stored.
+ */
+ function getIEVersion()
+ {
+ return isset($_SESSION['__browser']['ie_version']) ? $_SESSION['__browser']['ie_version'] : null;
+ }
+
+}
diff --git a/lib/album.php b/lib/album.php
new file mode 100644
index 00000000..7d518ff8
--- /dev/null
+++ b/lib/album.php
@@ -0,0 +1,31 @@
+<?php
+/*
+
+ This library handles album related functions.... wooo!
+ //FIXME: Remove this in favor of /modules/class/album
+*/
+
+/*!
+ @function get_albums
+ @discussion pass a sql statement, and it gets full album info and returns
+ an array of the goods.. can be set to format them as well
+*/
+function get_albums($sql, $action=0) {
+
+ $db_results = mysql_query($sql, dbh());
+ while ($r = mysql_fetch_array($db_results)) {
+ $album = new Album($r[0]);
+ $album->format_album();
+ $albums[] = $album;
+ }
+
+ return $albums;
+
+
+} // get_albums
+
+
+
+
+
+?>
diff --git a/lib/archive.php b/lib/archive.php
new file mode 100644
index 00000000..1a605f10
--- /dev/null
+++ b/lib/archive.php
@@ -0,0 +1,778 @@
+<?php
+/*--------------------------------------------------
+ | TAR/GZIP/BZIP2/ZIP ARCHIVE CLASSES 2.0
+ | By Devin Doucette
+ | Copyright (c) 2004 Devin Doucette
+ | Email: darksnoopy@shaw.ca
+ +--------------------------------------------------
+ | Email bugs/suggestions to darksnoopy@shaw.ca
+ +--------------------------------------------------
+ | This script has been created and released under
+ | the GNU GPL and is free to use and redistribute
+ | only if this copyright statement is not removed
+ +--------------------------------------------------*/
+
+class archive
+{
+ function archive($name)
+ {
+ $this->options = array(
+ 'basedir'=>".",
+ 'name'=>$name,
+ 'prepend'=>"",
+ 'inmemory'=>0,
+ 'overwrite'=>0,
+ 'recurse'=>1,
+ 'storepaths'=>1,
+ 'level'=>3,
+ 'method'=>1,
+ 'sfx'=>"",
+ 'type'=>"",
+ 'comment'=>""
+ );
+ $this->files = array();
+ $this->exclude = array();
+ $this->storeonly = array();
+ $this->error = array();
+ }
+
+ function set_options($options)
+ {
+ foreach($options as $key => $value)
+ {
+ $this->options[$key] = $value;
+ }
+ if(!empty($this->options['basedir']))
+ {
+ $this->options['basedir'] = str_replace("\\","/",$this->options['basedir']);
+ $this->options['basedir'] = preg_replace("/\/+/","/",$this->options['basedir']);
+ $this->options['basedir'] = preg_replace("/\/$/","",$this->options['basedir']);
+ }
+ if(!empty($this->options['name']))
+ {
+ $this->options['name'] = str_replace("\\","/",$this->options['name']);
+ $this->options['name'] = preg_replace("/\/+/","/",$this->options['name']);
+ }
+ if(!empty($this->options['prepend']))
+ {
+ $this->options['prepend'] = str_replace("\\","/",$this->options['prepend']);
+ $this->options['prepend'] = preg_replace("/^(\.*\/+)+/","",$this->options['prepend']);
+ $this->options['prepend'] = preg_replace("/\/+/","/",$this->options['prepend']);
+ $this->options['prepend'] = preg_replace("/\/$/","",$this->options['prepend']) . "/";
+ }
+ }
+
+ function create_archive()
+ {
+ $this->make_list();
+
+ if($this->options['inmemory'] == 0)
+ {
+ $pwd = getcwd();
+ chdir($this->options['basedir']);
+ if($this->options['overwrite'] == 0 && file_exists($this->options['name'] . ($this->options['type'] == "gzip" || $this->options['type'] == "bzip"? ".tmp" : "")))
+ {
+ $this->error[] = "File {$this->options['name']} already exists.";
+ chdir($pwd);
+ return 0;
+ }
+ else if($this->archive = @fopen($this->options['name'] . ($this->options['type'] == "gzip" || $this->options['type'] == "bzip"? ".tmp" : ""),"wb+"))
+ {
+ chdir($pwd);
+ }
+ else
+ {
+ $this->error[] = "Could not open {$this->options['name']} for writing.";
+ chdir($pwd);
+ return 0;
+ }
+ }
+ else
+ {
+ $this->archive = "";
+ }
+
+ switch($this->options['type'])
+ {
+ case "zip":
+ if(!$this->create_zip())
+ {
+ $this->error[] = "Could not create zip file.";
+ return 0;
+ }
+ break;
+ case "bzip":
+ if(!$this->create_tar())
+ {
+ $this->error[] = "Could not create tar file.";
+ return 0;
+ }
+ if(!$this->create_bzip())
+ {
+ $this->error[] = "Could not create bzip2 file.";
+ return 0;
+ }
+ break;
+ case "gzip":
+ if(!$this->create_tar())
+ {
+ $this->error[] = "Could not create tar file.";
+ return 0;
+ }
+ if(!$this->create_gzip())
+ {
+ $this->error[] = "Could not create gzip file.";
+ return 0;
+ }
+ break;
+ case "tar":
+ if(!$this->create_tar())
+ {
+ $this->error[] = "Could not create tar file.";
+ return 0;
+ }
+ }
+
+ if($this->options['inmemory'] == 0)
+ {
+ fclose($this->archive);
+ if($this->options['type'] == "gzip" || $this->options['type'] == "bzip")
+ {
+ unlink($this->options['basedir'] . "/" . $this->options['name'] . ".tmp");
+ }
+ }
+ }
+
+ function add_data($data)
+ {
+ if($this->options['inmemory'] == 0)
+ {
+ fwrite($this->archive,$data);
+ }
+ else
+ {
+ $this->archive .= $data;
+ }
+ }
+
+ function make_list()
+ {
+ if(!empty($this->exclude))
+ {
+ foreach($this->files as $key => $value)
+ {
+ foreach($this->exclude as $current)
+ {
+ if($value['name'] == $current['name'])
+ {
+ unset($this->files[$key]);
+ }
+ }
+ }
+ }
+ if(!empty($this->storeonly))
+ {
+ foreach($this->files as $key => $value)
+ {
+ foreach($this->storeonly as $current)
+ {
+ if($value['name'] == $current['name'])
+ {
+ $this->files[$key]['method'] = 0;
+ }
+ }
+ }
+ }
+ unset($this->exclude,$this->storeonly);
+ }
+
+ function add_files($list)
+ {
+ $temp = $this->list_files($list);
+ foreach($temp as $current)
+ {
+ $this->files[] = $current;
+ }
+ }
+
+ function exclude_files($list)
+ {
+ $temp = $this->list_files($list);
+ foreach($temp as $current)
+ {
+ $this->exclude[] = $current;
+ }
+ }
+
+ function store_files($list)
+ {
+ $temp = $this->list_files($list);
+ foreach($temp as $current)
+ {
+ $this->storeonly[] = $current;
+ }
+ }
+
+ function list_files($list)
+ {
+ if(!is_array($list))
+ {
+ $temp = $list;
+ $list = array($temp);
+ unset($temp);
+ }
+
+ $files = array();
+
+ $pwd = getcwd();
+ chdir($this->options['basedir']);
+
+ foreach($list as $current)
+ {
+ $current = str_replace("\\","/",$current);
+ $current = preg_replace("/\/+/","/",$current);
+ $current = preg_replace("/\/$/","",$current);
+ if(strstr($current,"*"))
+ {
+ $regex = preg_replace("/([\\\^\$\.\[\]\|\(\)\?\+\{\}\/])/","\\\\\\1",$current);
+ $regex = str_replace("*",".*",$regex);
+ $dir = strstr($current,"/")? substr($current,0,strrpos($current,"/")) : ".";
+ $temp = $this->parse_dir($dir);
+ foreach($temp as $current2)
+ {
+ if(preg_match("/^{$regex}$/i",$current2['name']))
+ {
+ $files[] = $current2;
+ }
+ }
+ unset($regex,$dir,$temp,$current);
+ }
+ else if(@is_dir($current))
+ {
+ $temp = $this->parse_dir($current);
+ foreach($temp as $file)
+ {
+ $files[] = $file;
+ }
+ unset($temp,$file);
+ }
+ else if(@file_exists($current))
+ {
+ $files[] = array('name'=>$current,'name2'=>$this->options['prepend'] .
+ preg_replace("/(\.+\/+)+/","",($this->options['storepaths'] == 0 && strstr($current,"/"))?
+ substr($current,strrpos($current,"/") + 1) : $current),'type'=>0,
+ 'ext'=>substr($current,strrpos($current,".")),'stat'=>stat($current));
+ }
+ }
+
+ chdir($pwd);
+
+ unset($current,$pwd);
+
+ usort($files,array("archive","sort_files"));
+
+ return $files;
+ }
+
+ function parse_dir($dirname)
+ {
+ if($this->options['storepaths'] == 1 && !preg_match("/^(\.+\/*)+$/",$dirname))
+ {
+ $files = array(array('name'=>$dirname,'name2'=>$this->options['prepend'] .
+ preg_replace("/(\.+\/+)+/","",($this->options['storepaths'] == 0 && strstr($dirname,"/"))?
+ substr($dirname,strrpos($dirname,"/") + 1) : $dirname),'type'=>5,'stat'=>stat($dirname)));
+ }
+ else
+ {
+ $files = array();
+ }
+ $dir = @opendir($dirname);
+
+ while($file = @readdir($dir))
+ {
+ if($file == "." || $file == "..")
+ {
+ continue;
+ }
+ else if(@is_dir($dirname."/".$file))
+ {
+ if(empty($this->options['recurse']))
+ {
+ continue;
+ }
+ $temp = $this->parse_dir($dirname."/".$file);
+ foreach($temp as $file2)
+ {
+ $files[] = $file2;
+ }
+ }
+ else if(@file_exists($dirname."/".$file))
+ {
+ $files[] = array('name'=>$dirname."/".$file,'name2'=>$this->options['prepend'] .
+ preg_replace("/(\.+\/+)+/","",($this->options['storepaths'] == 0 && strstr($dirname."/".$file,"/"))?
+ substr($dirname."/".$file,strrpos($dirname."/".$file,"/") + 1) : $dirname."/".$file),'type'=>0,
+ 'ext'=>substr($file,strrpos($file,".")),'stat'=>stat($dirname."/".$file));
+ }
+ }
+
+ @closedir($dir);
+
+ return $files;
+ }
+
+ function sort_files($a,$b)
+ {
+ if($a['type'] != $b['type'])
+ {
+ return $a['type'] > $b['type']? -1 : 1;
+ }
+ else if($a['type'] == 5)
+ {
+ return strcmp(strtolower($a['name']),strtolower($b['name']));
+ }
+ else
+ {
+ if($a['ext'] != $b['ext'])
+ {
+ return strcmp($a['ext'],$b['ext']);
+ }
+ else if($a['stat'][7] != $b['stat'][7])
+ {
+ return $a['stat'][7] > $b['stat'][7]? -1 : 1;
+ }
+ else
+ {
+ return strcmp(strtolower($a['name']),strtolower($b['name']));
+ }
+ }
+ return 0;
+ }
+
+ function download_file()
+ {
+ if($this->options['inmemory'] == 0)
+ {
+ $this->error[] = "Can only use download_file() if archive is in memory. Redirect to file otherwise, it is faster.";
+ return;
+ }
+ switch($this->options['type'])
+ {
+ case "zip":
+ header("Content-type:application/zip");
+ break;
+ case "bzip":
+ header("Content-type:application/x-compressed");
+ break;
+ case "gzip":
+ header("Content-type:application/x-compressed");
+ break;
+ case "tar":
+ header("Content-type:application/x-tar");
+ }
+ $header = "Content-disposition: attachment; filename=\"";
+ $header .= strstr($this->options['name'],"/")? substr($this->options['name'],strrpos($this->options['name'],"/") + 1) : $this->options['name'];
+ $header .= "\"";
+ header($header);
+ header("Content-length: " . strlen($this->archive));
+ header("Content-transfer-encoding: binary");
+ header("Pragma: no-cache");
+ header("Expires: 0");
+ print($this->archive);
+ }
+}
+
+class tar_file extends archive
+{
+ function tar_file($name)
+ {
+ $this->archive($name);
+ $this->options['type'] = "tar";
+ }
+
+ function create_tar()
+ {
+ $pwd = getcwd();
+ chdir($this->options['basedir']);
+
+ foreach($this->files as $current)
+ {
+ if($current['name'] == $this->options['name'])
+ {
+ continue;
+ }
+ if(strlen($current['name2']) > 99)
+ {
+ $path = substr($current['name2'],0,strpos($current['name2'],"/",strlen($current['name2']) - 100) + 1);
+ $current['name2'] = substr($current['name2'],strlen($path));
+ if(strlen($path) > 154 || strlen($current['name2']) > 99)
+ {
+ $this->error[] = "Could not add {$path}{$current['name2']} to archive because the filename is too long.";
+ continue;
+ }
+ }
+ $block = pack("a100a8a8a8a12a12a8a1a100a6a2a32a32a8a8a155a12",$current['name2'],decoct($current['stat'][2]),
+ sprintf("%6s ",decoct($current['stat'][4])),sprintf("%6s ",decoct($current['stat'][5])),
+ sprintf("%11s ",decoct($current['stat'][7])),sprintf("%11s ",decoct($current['stat'][9])),
+ " ",$current['type'],"","ustar","00","Unknown","Unknown","","",!empty($path)? $path : "","");
+
+ $checksum = 0;
+ for($i = 0; $i < 512; $i++)
+ {
+ $checksum += ord(substr($block,$i,1));
+ }
+ $checksum = pack("a8",sprintf("%6s ",decoct($checksum)));
+ $block = substr_replace($block,$checksum,148,8);
+
+ if($current['stat'][7] == 0)
+ {
+ $this->add_data($block);
+ }
+ else if($fp = @fopen($current['name'],"rb"))
+ {
+ $this->add_data($block);
+ while($temp = fread($fp,1048576))
+ {
+ $this->add_data($temp);
+ }
+ if($current['stat'][7] % 512 > 0)
+ {
+ $temp = "";
+ for($i = 0; $i < 512 - $current['stat'][7] % 512; $i++)
+ {
+ $temp .= "\0";
+ }
+ $this->add_data($temp);
+ }
+ fclose($fp);
+ }
+ else
+ {
+ $this->error[] = "Could not open file {$current['name']} for reading. It was not added.";
+ }
+ }
+
+ $this->add_data(pack("a512",""));
+
+ chdir($pwd);
+
+ return 1;
+ }
+
+ function extract_files()
+ {
+ $pwd = getcwd();
+ chdir($this->options['basedir']);
+
+ if($fp = $this->open_archive())
+ {
+ if($this->options['inmemory'] == 1)
+ {
+ $this->files = array();
+ }
+
+ while($block = fread($fp,512))
+ {
+ $temp = unpack("a100name/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1type/a100temp/a6magic/a2temp/a32temp/a32temp/a8temp/a8temp/a155prefix/a12temp",$block);
+ $file = array(
+ 'name'=>$temp['prefix'] . $temp['name'],
+ 'stat'=>array(
+ 2=>$temp['mode'],
+ 4=>octdec($temp['uid']),
+ 5=>octdec($temp['gid']),
+ 7=>octdec($temp['size']),
+ 9=>octdec($temp['mtime']),
+ ),
+ 'checksum'=>octdec($temp['checksum']),
+ 'type'=>$temp['type'],
+ 'magic'=>$temp['magic'],
+ );
+ if($file['checksum'] == 0x00000000)
+ {
+ break;
+ }
+ else if($file['magic'] != "ustar")
+ {
+ $this->error[] = "This script does not support extracting this type of tar file.";
+ break;
+ }
+ $block = substr_replace($block," ",148,8);
+ $checksum = 0;
+ for($i = 0; $i < 512; $i++)
+ {
+ $checksum += ord(substr($block,$i,1));
+ }
+ if($file['checksum'] != $checksum)
+ {
+ $this->error[] = "Could not extract from {$this->options['name']}, it is corrupt.";
+ }
+
+ if($this->options['inmemory'] == 1)
+ {
+ $file['data'] = fread($fp,$file['stat'][7]);
+ fread($fp,(512 - $file['stat'][7] % 512) == 512? 0 : (512 - $file['stat'][7] % 512));
+ unset($file['checksum'],$file['magic']);
+ $this->files[] = $file;
+ }
+ else
+ {
+ if($file['type'] == 5)
+ {
+ if(!is_dir($file['name']))
+ {
+ mkdir($file['name'],$file['stat'][2]);
+ chown($file['name'],$file['stat'][4]);
+ chgrp($file['name'],$file['stat'][5]);
+ }
+ }
+ else if($this->options['overwrite'] == 0 && file_exists($file['name']))
+ {
+ $this->error[] = "{$file['name']} already exists.";
+ }
+ else if($new = @fopen($file['name'],"wb"))
+ {
+ fwrite($new,fread($fp,$file['stat'][7]));
+ fread($fp,(512 - $file['stat'][7] % 512) == 512? 0 : (512 - $file['stat'][7] % 512));
+ fclose($new);
+ chmod($file['name'],$file['stat'][2]);
+ chown($file['name'],$file['stat'][4]);
+ chgrp($file['name'],$file['stat'][5]);
+ }
+ else
+ {
+ $this->error[] = "Could not open {$file['name']} for writing.";
+ }
+ }
+ unset($file);
+ }
+ }
+ else
+ {
+ $this->error[] = "Could not open file {$this->options['name']}";
+ }
+
+ chdir($pwd);
+ }
+
+ function open_archive()
+ {
+ return @fopen($this->options['name'],"rb");
+ }
+}
+
+class gzip_file extends tar_file
+{
+ function gzip_file($name)
+ {
+ $this->tar_file($name);
+ $this->options['type'] = "gzip";
+ }
+
+ function create_gzip()
+ {
+ if($this->options['inmemory'] == 0)
+ {
+ $pwd = getcwd();
+ chdir($this->options['basedir']);
+ if($fp = gzopen($this->options['name'],"wb{$this->options['level']}"))
+ {
+ fseek($this->archive,0);
+ while($temp = fread($this->archive,1048576))
+ {
+ gzwrite($fp,$temp);
+ }
+ gzclose($fp);
+ chdir($pwd);
+ }
+ else
+ {
+ $this->error[] = "Could not open {$this->options['name']} for writing.";
+ chdir($pwd);
+ return 0;
+ }
+ }
+ else
+ {
+ $this->archive = gzencode($this->archive,$this->options['level']);
+ }
+
+ return 1;
+ }
+
+ function open_archive()
+ {
+ return @gzopen($this->options['name'],"rb");
+ }
+}
+
+class bzip_file extends tar_file
+{
+ function bzip_file($name)
+ {
+ $this->tar_file($name);
+ $this->options['type'] = "bzip";
+ }
+
+ function create_bzip()
+ {
+ if($this->options['inmemory'] == 0)
+ {
+ $pwd = getcwd();
+ chdir($this->options['basedir']);
+ if($fp = bzopen($this->options['name'],"wb"))
+ {
+ fseek($this->archive,0);
+ while($temp = fread($this->archive,1048576))
+ {
+ bzwrite($fp,$temp);
+ }
+ bzclose($fp);
+ chdir($pwd);
+ }
+ else
+ {
+ $this->error[] = "Could not open {$this->options['name']} for writing.";
+ chdir($pwd);
+ return 0;
+ }
+ }
+ else
+ {
+ $this->archive = bzcompress($this->archive,$this->options['level']);
+ }
+
+ return 1;
+ }
+
+ function open_archive()
+ {
+ return @bzopen($this->options['name'],"rb");
+ }
+}
+
+class zip_file extends archive
+{
+ function zip_file($name)
+ {
+ $this->archive($name);
+ $this->options['type'] = "zip";
+ }
+
+ function create_zip()
+ {
+ $files = 0;
+ $offset = 0;
+ $central = "";
+
+ if(!empty($this->options['sfx']))
+ {
+ if($fp = @fopen($this->options['sfx'],"rb"))
+ {
+ $temp = fread($fp,filesize($this->options['sfx']));
+ fclose($fp);
+ $this->add_data($temp);
+ $offset += strlen($temp);
+ unset($temp);
+ }
+ else
+ {
+ $this->error[] = "Could not open sfx module from {$this->options['sfx']}.";
+ }
+ }
+
+ $pwd = getcwd();
+ chdir($this->options['basedir']);
+
+ foreach($this->files as $current)
+ {
+ if($current['name'] == $this->options['name'])
+ {
+ continue;
+ }
+
+ $translate = array('Ç'=>pack("C",128),'ü'=>pack("C",129),'é'=>pack("C",130),'â'=>pack("C",131),'ä'=>pack("C",132),
+ 'à'=>pack("C",133),'å'=>pack("C",134),'ç'=>pack("C",135),'ê'=>pack("C",136),'ë'=>pack("C",137),
+ 'è'=>pack("C",138),'ï'=>pack("C",139),'î'=>pack("C",140),'ì'=>pack("C",141),'Ä'=>pack("C",142),
+ 'Å'=>pack("C",143),'É'=>pack("C",144),'æ'=>pack("C",145),'Æ'=>pack("C",146),'ô'=>pack("C",147),
+ 'ö'=>pack("C",148),'ò'=>pack("C",149),'û'=>pack("C",150),'ù'=>pack("C",151),'Ö'=>pack("C",153),
+ 'Ü'=>pack("C",154),'£'=>pack("C",156),'¥'=>pack("C",157),'ƒ'=>pack("C",159),'á'=>pack("C",160),
+ 'í'=>pack("C",161),'ó'=>pack("C",162),'ú'=>pack("C",163),'ñ'=>pack("C",164),'Ñ'=>pack("C",165));
+ $current['name2'] = strtr($current['name2'],$translate);
+
+ $timedate = explode(" ",date("Y n j G i s",$current['stat'][9]));
+ $timedate = ($timedate[0] - 1980 << 25) | ($timedate[1] << 21) | ($timedate[2] << 16) |
+ ($timedate[3] << 11) | ($timedate[4] << 5) | ($timedate[5]);
+
+ $block = pack("VvvvV",0x04034b50,0x000A,0x0000,(isset($current['method']) || $this->options['method'] == 0)? 0x0000 : 0x0008,$timedate);
+
+ if($current['stat'][7] == 0 && $current['type'] == 5)
+ {
+ $block .= pack("VVVvv",0x00000000,0x00000000,0x00000000,strlen($current['name2']) + 1,0x0000);
+ $block .= $current['name2'] . "/";
+ $this->add_data($block);
+ $central .= pack("VvvvvVVVVvvvvvVV",0x02014b50,0x0014,$this->options['method'] == 0? 0x0000 : 0x000A,0x0000,
+ (isset($current['method']) || $this->options['method'] == 0)? 0x0000 : 0x0008,$timedate,
+ 0x00000000,0x00000000,0x00000000,strlen($current['name2']) + 1,0x0000,0x0000,0x0000,0x0000,$current['type'] == 5? 0x00000010 : 0x00000000,$offset);
+ $central .= $current['name2'] . "/";
+ $files++;
+ $offset += (31 + strlen($current['name2']));
+ }
+ else if($current['stat'][7] == 0)
+ {
+ $block .= pack("VVVvv",0x00000000,0x00000000,0x00000000,strlen($current['name2']),0x0000);
+ $block .= $current['name2'];
+ $this->add_data($block);
+ $central .= pack("VvvvvVVVVvvvvvVV",0x02014b50,0x0014,$this->options['method'] == 0? 0x0000 : 0x000A,0x0000,
+ (isset($current['method']) || $this->options['method'] == 0)? 0x0000 : 0x0008,$timedate,
+ 0x00000000,0x00000000,0x00000000,strlen($current['name2']),0x0000,0x0000,0x0000,0x0000,$current['type'] == 5? 0x00000010 : 0x00000000,$offset);
+ $central .= $current['name2'];
+ $files++;
+ $offset += (30 + strlen($current['name2']));
+ }
+ else if($fp = @fopen($current['name'],"rb"))
+ {
+ $temp = fread($fp,$current['stat'][7]);
+ fclose($fp);
+ $crc32 = crc32($temp);
+ if(!isset($current['method']) && $this->options['method'] == 1)
+ {
+ $temp = gzcompress($temp,$this->options['level']);
+ $size = strlen($temp) - 6;
+ $temp = substr($temp,2,$size);
+ }
+ else
+ {
+ $size = strlen($temp);
+ }
+ $block .= pack("VVVvv",$crc32,$size,$current['stat'][7],strlen($current['name2']),0x0000);
+ $block .= $current['name2'];
+ $this->add_data($block);
+ $this->add_data($temp);
+ unset($temp);
+ $central .= pack("VvvvvVVVVvvvvvVV",0x02014b50,0x0014,$this->options['method'] == 0? 0x0000 : 0x000A,0x0000,
+ (isset($current['method']) || $this->options['method'] == 0)? 0x0000 : 0x0008,$timedate,
+ $crc32,$size,$current['stat'][7],strlen($current['name2']),0x0000,0x0000,0x0000,0x0000,0x00000000,$offset);
+ $central .= $current['name2'];
+ $files++;
+ $offset += (30 + strlen($current['name2']) + $size);
+ }
+ else
+ {
+ $this->error[] = "Could not open file {$current['name']} for reading. It was not added.";
+ }
+ }
+
+ $this->add_data($central);
+
+ $this->add_data(pack("VvvvvVVv",0x06054b50,0x0000,0x0000,$files,$files,strlen($central),$offset,
+ !empty($this->options['comment'])? strlen($this->options['comment']) : 0x0000));
+
+ if(!empty($this->options['comment']))
+ {
+ $this->add_data($this->options['comment']);
+ }
+
+ chdir($pwd);
+
+ return 1;
+ }
+} ?> \ No newline at end of file
diff --git a/lib/artist.php b/lib/artist.php
new file mode 100644
index 00000000..5ccd200a
--- /dev/null
+++ b/lib/artist.php
@@ -0,0 +1,122 @@
+<?php
+/*
+
+ 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.
+
+
+ This library handles all artist mojo
+
+*/
+
+/*!
+ @function get_artists
+ @discussion run a search, takes string,field,type and returns an array
+ of results of the correct type (song, album, artist)
+*/
+function get_artists($sql, $action=0) {
+
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_array($db_results)) {
+ $artist_info = get_artist_info($r['id']);
+ if ($action ==='format') { $artist = format_artist($artist_info); }
+ else { $artist = $artist_info; }
+ $artists[] = $artist;
+ } // end while
+
+ return $artists;
+
+} // get_artists
+
+/*!
+ @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($artist) {
+
+ $web_path = conf('web_path');
+ $artist['name'] = "<a href=\"$web_path/artists.php?action=show&amp;artist=" . $artist['id'] . "\">" . $artist['prefix'] . " " . $artist['name'] . "</a>";
+
+ return $artist;
+
+} // format_artist
+
+/*!
+ @function show_artists
+ @discussion takes a match and accounts for the possiblity of a view
+ then displays _many_ artists
+*/
+function show_artists ($match = '') {
+
+ global $settings;
+ $dbh = dbh();
+
+ $view = new View();
+ $view->import_session_view();
+
+ // Check for the view object...
+ if ($_REQUEST['keep_view']) {
+ $view->initialize();
+ }
+
+ // If there isn't a view object we need to create a new one..
+ else {
+ if ( isset($match) && $match != '' ) {
+ $query = "SELECT id,name FROM artist " .
+ " WHERE name LIKE '$match%' ";
+ }
+ else {
+ $query = "SELECT id FROM artist ";
+ }
+
+ $db_results = mysql_query($query, $dbh);
+ $total_items = mysql_num_rows($db_results);
+ if ($_REQUEST['match'] === "Show_all") {
+ $offset_limit = 999999;
+ }
+ else {
+ $offset_limit = $_SESSION['userdata']['offset_limit'];
+ }
+ $view = new View($query,'artists.php','name',$total_items,$offset_limit);
+ } // end if creating view object
+
+ if (is_array($match)) {
+ $artists = $match;
+ $_SESSION['view_script'] = false;
+ }
+
+ $db_results = mysql_query($view->sql, $dbh);
+ while ($r = @mysql_fetch_array($db_results)) {
+ $artist_info = get_artist_info($r[0]);
+ $artist = format_artist($artist_info);
+ // Only Add this artist if there is information to go along with it
+ if ($artist_info) {
+ $artists[] = $artist;
+ }
+ }
+
+ if (count($artists)) {
+ require ( conf('prefix') . "/templates/show_artists.inc");
+ }
+
+} // show_artists
+
+
+
+
+?>
diff --git a/lib/batch.php b/lib/batch.php
new file mode 100644
index 00000000..a3a3aba3
--- /dev/null
+++ b/lib/batch.php
@@ -0,0 +1,63 @@
+<?php
+/*
+
+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.
+
+*/
+
+
+/*
+ @function get_song_files
+ @discussion tmakes array of song ids and returns
+ array of path to actual files
+ @param $song_ids an array of song ids whose filenames you need
+*/
+function get_song_files( $song_ids ) {
+ global $user;
+ $song_files = array();
+ foreach( $song_ids as $song_id ) {
+ $song = new Song( $song_id );
+ /* Don't archive disabled songs */
+ if ($song->status != 'disabled') {
+ $user->update_stats( $song_id );
+ $total_size += sprintf("%.2f",($song->size/1048576));;
+ array_push( $song_files, $song->file );
+ } // if song isn't disabled
+ }
+ return array($song_files,$total_size);
+} //get_song_files
+
+
+/*!
+ @function send_zip
+ @discussion takes array of full paths to songs
+ zips them and sends them
+ @param $song_files array of full paths to songs to zip
+ create w/ call to get_song_files
+*/
+function send_zip( $name, $song_files ) {
+ require_once(conf('prefix') . '/lib/archive.php' );
+ $arc = new zip_file( $name . ".zip" );
+ $options = array(
+ 'inmemory' => 1, // create archive in memory
+ 'storepaths' => 0, // only store file name, not full path
+ 'level' => 0 // no compression
+ );
+ $arc->set_options( $options );
+ $arc->add_files( $song_files );
+ $arc->create_archive();
+ $arc->download_file();
+}
+?>
diff --git a/lib/debug.php b/lib/debug.php
new file mode 100644
index 00000000..c554daf7
--- /dev/null
+++ b/lib/debug.php
@@ -0,0 +1,361 @@
+<?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 Debug Library
+ This library is loaded when somehow our mojo has
+ been lost, it contains functions for checking sql
+ connections, web paths etc..
+*/
+
+/*!
+ @function read_config_file
+ @discussion checks to see if the config
+ file is readable, overkill I know..
+ @param level 0 is readable, 1 detailed info
+*/
+function read_config_file($file,$level=0) {
+
+ $fp = @fopen($file, 'r');
+
+ if (!$level) {
+ return is_resource($fp);
+ }
+
+
+} // read_config_file
+
+/*!
+ @function check_database
+ @discussion checks the local mysql db
+ and make sure life is good
+*/
+function check_database($host,$username,$pass,$db,$level=0) {
+
+ $dbh = @mysql_connect($host, $username, $pass);
+
+ if (!is_resource($dbh)) {
+ $error['error_state'] = true;
+ $error['mysql_error'] = mysql_errno() . ": " . mysql_error() . "\n";
+ }
+ if (!$host || !$username || !$pass) {
+ $error['error_state'] = true;
+ $error['mysql_error'] .= "<br />HOST:$host<br />User:$username<br />Pass:$pass<br />";
+ }
+print_r($error);
+ if ($error['error_state']) { return false; }
+
+
+ return $dbh;
+
+} // check_database
+
+/*!
+ @function check_database_inserted
+ @discussion checks to make sure that you
+ have inserted the database and that the user
+ you are using has access to it
+*/
+function check_database_inserted($dbh,$db_name) {
+
+
+ if (!@mysql_select_db($db_name,$dbh)) {
+ return false;
+ }
+
+ $sql = "DESCRIBE session";
+ $db_results = @mysql_query($sql, $dbh);
+ if (!@mysql_num_rows($db_results)) {
+ return false;
+ }
+
+ return true;
+
+} // check_database_inserted
+
+/*!
+ @function check_php_ver
+ @discussion checks the php version and makes
+ sure that it's good enough
+*/
+function check_php_ver($level=0) {
+
+ if (strcmp('4.1.2',phpversion()) > 0) {
+ $error['error_state'] = true;
+ $error['php_ver'] = phpversion();
+ }
+
+ if ($error['error_state']) { return false; }
+
+ return true;
+
+} // check_php_ver
+
+/*!
+ @function check_php_mysql
+ @discussion checks for mysql support
+*/
+function check_php_mysql() {
+
+ if (!function_exists('mysql_query')) {
+ $error['error_state'] = true;
+ $error['php_mysql'] = false;
+ }
+
+ if ($error['error_state']) { return false; }
+
+ return true;
+
+} // check_php_mysql
+
+/*!
+ @function check_php_session
+ @discussion checks to make sure the needed functions
+ for sessions exist
+*/
+function check_php_session() {
+
+ if (!function_exists('session_set_save_handler')) {
+ $error['error_state'] = true;
+ $error['php_session'] = false;
+ }
+
+ if ($error['error_state']) { return false; }
+
+ return true;
+
+} // check_php_session
+
+/*!
+ @function check_php_iconv
+ @discussion checks to see if you have iconv installed
+*/
+function check_php_iconv() {
+
+ if (!function_exists('iconv')) {
+ $error['error_state'] = true;
+ $error['php_iconv'] = false;
+ }
+
+ if ($error['error_state']) { return false; }
+
+ return true;
+
+} // check_php_iconv
+
+/*!
+ @function check_config_values()
+ @discussion checks to make sure that they have at
+ least set the needed variables
+*/
+function check_config_values($conf) {
+
+ if (!$conf['libglue']['local_host']) {
+ return false;
+ }
+ if (!$conf['libglue']['local_db']) {
+ return false;
+ }
+ if (!$conf['libglue']['local_username']) {
+ return false;
+ }
+ if (!$conf['libglue']['local_pass']) {
+ return false;
+ }
+ if (!$conf['libglue']['local_length']) {
+ return false;
+ }
+
+ return true;
+
+} // check_config_values
+
+/*!
+ @function show_compare_config
+ @discussion shows the difference between ampache.cfg
+ and ampache.cfg.dst
+*/
+function show_compare_config($prefix) {
+
+
+ // Live Config File
+ $live_config = $prefix . "/config/ampache.cfg.php";
+
+ // Generic Config File
+ $generic_config = $prefix . "/config/ampache.cfg.dist";
+
+} // show_compare_config
+
+
+/*!
+ @function debug_read_config
+ @discussion this is the same as the read config function
+ except it will pull config values with a # before them
+ (basicly adding a #config="value" check) and not
+ ever dieing on a config file error
+*/
+function debug_read_config($config_file,$debug) {
+
+ $fp = @fopen($config_file,'r');
+ if(!is_resource($fp)) return false;
+ $file_data = fread($fp,filesize($config_file));
+ fclose($fp);
+
+ // explode the var by \n's
+ $data = explode("\n",$file_data);
+ if($debug) echo "<pre>";
+ $count = 0;
+
+ foreach($data as $value) {
+ $count++;
+
+ $value = trim($value);
+
+ if (preg_match("/^\[([A-Za-z]+)\]$/",$value,$matches)) {
+ // If we have previous data put it into $results...
+ if (isset($config_name) && isset(${$config_name}) && count(${$config_name})) {
+ $results[$config_name] = ${$config_name};
+ }
+
+ $config_name = $matches[1];
+
+ } // if it is a [section] name
+
+
+ elseif (isset($config_name)) {
+
+ // if it's not a comment
+ if (preg_match("/^#?([\w\d]+)\s+=\s+[\"]{1}(.*?)[\"]{1}$/",$value,$matches)
+ || preg_match("/^#?([\w\d]+)\s+=\s+[\']{1}(.*?)[\']{1}$/", $value, $matches)
+ || preg_match("/^#?([\w\d]+)\s+=\s+[\'\"]{0}(.*)[\'\"]{0}$/",$value,$matches)) {
+
+ if (isset(${$config_name}[$matches[1]]) && is_array(${$config_name}[$matches[1]]) && isset($matches[2]) ) {
+ if($debug) echo "Adding value <strong>$matches[2]</strong> to existing key <strong>$matches[1]</strong>\n";
+ array_push(${$config_name}[$matches[1]], $matches[2]);
+ }
+
+ elseif (isset(${$config_name}[$matches[1]]) && isset($matches[2]) ) {
+ if($debug) echo "Adding value <strong>$matches[2]</strong> to existing key $matches[1]</strong>\n";
+ ${$config_name}[$matches[1]] = array(${$config_name}[$matches[1]],$matches[2]);
+ }
+
+ elseif ($matches[2] !== "") {
+ if($debug) echo "Adding value <strong>$matches[2]</strong> for key <strong>$matches[1]</strong>\n";
+ ${$config_name}[$matches[1]] = $matches[2];
+ }
+
+ // if there is something there and it's not a comment
+ elseif ($value{0} !== "#" AND strlen(trim($value)) > 0 AND !$test AND strlen($matches[2]) > 0) {
+ echo "Error Invalid Config Entry --> Line:$count"; return false;
+ } // elseif it's not a comment and there is something there
+
+ else {
+ if($debug) echo "Key <strong>$matches[1]</strong> defined, but no value set\n";
+ }
+ } // end if it's not a comment
+
+ } // elseif no config_name
+
+ elseif (preg_match("/^#?([\w\d]+)\s+=\s+[\"]{1}(.*?)[\"]{1}$/",$value,$matches)
+ || preg_match("/^#?([\w\d]+)\s+=\s+[\']{1}(.*?)[\']{1}$/", $value, $matches)
+ || preg_match("/^#?([\w\d]+)\s+=\s+[\'\"]{0}(.*)[\'\"]{0}$/",$value,$matches)) {
+
+
+ if (is_array($results[$matches[1]]) && isset($matches[2]) ) {
+ if($debug) echo "Adding value <strong>$matches[2]</strong> to existing key <strong>$matches[1]</strong>\n";
+ array_push($results[$matches[1]], $matches[2]);
+ }
+
+ elseif (isset($results[$matches[1]]) && isset($matches[2]) ) {
+ if($debug) echo "Adding value <strong>$matches[2]</strong> to existing key $matches[1]</strong>\n";
+ $results[$matches[1]] = array($results[$matches[1]],$matches[2]);
+ }
+
+ elseif ($matches[2] !== "") {
+ if($debug) echo "Adding value <strong>$matches[2]</strong> for key <strong>$matches[1]</strong>\n";
+ $results[$matches[1]] = $matches[2];
+ }
+
+ // if there is something there and it's not a comment
+ elseif ($value{0} !== "#" AND strlen(trim($value)) > 0 AND !$test AND strlen($matches[2]) > 0) {
+ echo "Error Invalid Config Entry --> Line:$count"; return false;
+ } // elseif it's not a comment and there is something there
+
+ else {
+ if($debug) echo "Key <strong>$matches[1]</strong> defined, but no value set\n";
+ }
+
+ } // end else
+
+ } // foreach
+
+ if (isset($config_name) && isset(${$config_name}) && count(${$config_name})) {
+ $results[$config_name] = ${$config_name};
+ }
+
+ if($debug) echo "</pre>";
+
+ return $results;
+
+} // debug_read_config
+
+/*!
+ @function debug_compare_configs
+ @discussion this takes two config files, and then compares
+ the results and returns an array of the values
+ that are missing from the first one passed
+*/
+function debug_compare_configs($config,$dist_config) {
+
+
+
+ /* Get the results from the two difference configs including #'d values */
+ $results = debug_read_config($config,0);
+ $dist_results = debug_read_config($dist_config,0);
+
+ $missing = array();
+ if (!count($dist_results['conf'])) { $dist_results['conf'] = array(); }
+ if (!count($dist_results['libglue'])) { $dist_results['libglue'] = array(); }
+
+ foreach ($dist_results['conf'] as $key=>$value) {
+
+ if (!isset($results['conf'][$key])) {
+ $missing['conf'][$key] = $value;
+ }
+
+ } // end foreach conf
+
+ foreach ($dist_results['libglue'] as $key=>$value) {
+
+ if (!isset($results['libglue'][$key])) {
+ $missing['libglue'][$key] = $value;
+ }
+
+ } // end foreach libglue
+
+ return $missing;
+
+} // debug_compare_configs
+
+
+?>
diff --git a/lib/duplicates.php b/lib/duplicates.php
new file mode 100644
index 00000000..94f3deda
--- /dev/null
+++ b/lib/duplicates.php
@@ -0,0 +1,117 @@
+<?php
+/*!
+ @header Contains the functions for handling duplicate songs
+*/
+
+
+/*!
+ @function get_duplicate_songs
+ @discussion
+*/
+function get_duplicate_songs($search_type) {
+ $sql = "SELECT song.id as song,artist.name,album.name,title,count(title) as ctitle".
+ " FROM song,artist,album ".
+ " WHERE song.artist=artist.id AND song.album=album.id AND song.title<>'' ".
+ " GROUP BY title";
+ if ($search_type=="artist_title"||$search_type=="artist_album_title")
+ $sql = $sql.",artist";
+ if ($search_type=="artist_album_title")
+ $sql = $sql.",album";
+ $sql = $sql." HAVING count(title) > 1";
+ $sql = $sql." ORDER BY ctitle";
+
+ //echo $sql."<BR>";
+
+ $result = mysql_query($sql, dbh());
+
+ $arr = array();
+
+ while ($flag = mysql_fetch_array($result)) {
+ $arr[] = $flag;
+ } // end while
+ return $arr;
+} // get_duplicate_songs
+
+/*!
+ @function get_duplicate_info
+ @discussion
+*/
+function get_duplicate_info($song,$search_type) {
+ $artist = get_artist_name($song->artist);
+ $sql = "SELECT song.id as songid,song.title as song,file,bitrate,size,time,album.name AS album,album.id as albumid, artist.name AS artist,artist.id as artistid".
+ " FROM song,artist,album ".
+ " WHERE song.artist=artist.id AND song.album=album.id ".
+ " AND song.title= '".str_replace("'","''",$song->title)."'";
+
+ if ($search_type=="artist_title"||$search_type=="artist_album_title")
+ $sql = $sql." AND artist.id = '".$song->artist."'";
+ if ($search_type=="artist_album_title")
+ $sql = $sql." AND album.id = '".$song->album."'";
+
+ $result = mysql_query($sql, dbh());
+
+ $arr = array();
+
+ while ($flag = mysql_fetch_array($result)) {
+ $arr[] = $flag;
+ } // end while
+ return $arr;
+
+} // get_duplicate_info
+
+/*!
+ @function show_duplicate_songs
+ @discussion
+*/
+function show_duplicate_songs($flags,$search_type) {
+ require_once(conf('prefix').'/templates/list_duplicates.inc');
+} // show_duplicate_songs
+
+/*!
+ @function show_duplicate_searchbox
+ @discussion
+*/
+function show_duplicate_searchbox($search_type) {
+?>
+<br />
+<form name="songs" action="<?php echo conf('web_path'); ?>/admin/duplicates.php" method="post" enctype="multipart/form-data" >
+<table class="border" cellspacing="0" cellpadding="3" border="0" width="450px">
+ <tr class="table-header">
+ <td colspan="2"><b><?php echo _("Find Duplicates"); ?></b></td>
+ </tr>
+ <tr class="even">
+ <td><?php echo _("Search Type"); ?>:</td>
+ <td>
+ <?
+
+ if ($search_type=="title")
+ $checked = "checked=\"checked\"";
+ else
+ $checked = "";
+ echo "<input type=\"radio\" name=\"search_type\" value=\"title\" ".$checked." >" . _("Title") . "<br />";
+
+ if ($search_type=="artist_title")
+ $checked = "checked=\"checked\"";
+ else
+ $checked = "";
+ echo "<input type=\"radio\" name=\"search_type\" value=\"artist_title\" ".$checked." >" . _("Artist and Title") . "<br />";
+ if ($search_type=="artist_album_title"OR $search_type=="")
+ $checked = "checked=\"checked\"";
+ else
+ $checked = "";
+ echo "<input type=\"radio\" name=\"search_type\" value=\"artist_album_title\"".$checked." >" . _("Artist, Album and Title") . "<br />";
+ ?>
+ </td>
+ </tr>
+ <tr class="odd">
+ <td></td>
+ <td>
+ <input type="hidden" name="action" value="search">
+ <input type="submit" value="<?php echo _("Search"); ?>" />
+ </td>
+ </tr>
+</table>
+<br>
+<?
+} // show_duplicate_searchbox
+?>
diff --git a/lib/flag.php b/lib/flag.php
new file mode 100644
index 00000000..01b3ba9f
--- /dev/null
+++ b/lib/flag.php
@@ -0,0 +1,348 @@
+<?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.
+
+*/
+
+//
+//
+
+function add_to_edit_queue($flags=0)
+{
+ $oldflags = 0;
+ if(empty($flags)) $flags = 0;
+ if($_SESSION['edit_queue'])
+ {
+ $oldflags = $_SESSION['edit_queue'];
+ if(!is_array($oldflags)) $oldflags = array($oldflags);
+ }
+
+ if(!is_array($flags))
+ {
+ if($flags !== 0) $flags = array($flags);
+ }
+
+ if(is_array($flags))
+ {
+ if(is_array($oldflags)) $new_array = array_merge($flags, $oldflags);
+ else $new_array = $flags;
+ }
+ elseif (is_array($oldflags)) $new_array = $oldflags;
+
+ if(count($new_array))
+ {
+ $_SESSION['edit_queue'] = $new_array;
+ return count($new_array);
+ }
+ else
+ {
+ unset($_SESSION['edit_queue']);
+ return 0;
+ }
+}
+
+function show_edit_flagged($flag=0)
+{
+ if(empty($flag)||$flag === 0)
+ {
+ $flag = array_pop($_SESSION['edit_queue']);
+ }
+ $flaginfo = get_flag($flag);
+ if($flaginfo['type'] === 'badid3')
+ {
+ show_edit_badid3($flaginfo['song'],$flag);
+ }
+ else
+ {
+ echo "I don't know how to edit already edited songs yet: $flag.<br />";
+ }
+}
+
+function show_edit_badid3($songid,$flagid)
+{
+ $song = get_song_info($songid);
+ require(conf('prefix')."/templates/song_edit.inc");
+}
+
+function get_flag($id)
+{
+ if(!is_array($id)) $id = array($id);
+ $results = array();
+ $newid = array_pop($id);
+ $sql = "SELECT flagged.id,user.username,type,song,date,comment" .
+ " FROM flagged,user WHERE flagged.user = user.id AND (flagged.song = '$newid'";
+ foreach($id as $num)
+ {
+ $sql .= " OR flagged.song = '$num'";
+ }
+ $sql .= ")";
+ $result = mysql_query($sql, dbh());
+ while ($row = mysql_fetch_array($result))
+ {
+ $results[] = $row;
+ }
+ if(count($results) == 1) return $results[0];
+ else return $results;
+}
+
+
+function get_flagged_songs($user = 0)
+{
+ $sql = "SELECT flagged.id,user.username,type,song,date,comment" .
+ " FROM flagged,user WHERE flagged.user = user.id AND flagged.type <> 'notify' AND flagged.type <> 'done'";
+
+ // If the user is not an admin, they can only see songs they've flagged
+ if($user)
+ {
+ if($_SESSION['userdata']['access'] === 'admin')
+ {
+ $sql .= " AND user.id = '$user'";
+ }
+ else
+ {
+ $sql .= " AND user.id = '".$_SESSION['userdata']['id']."'";
+ }
+ }
+
+ $sql .= " ORDER BY date";
+ $result = mysql_query($sql, dbh());
+
+ $arr = array();
+
+ while ($flag = mysql_fetch_array($result))
+ {
+ $arr[] = $flag;
+ }
+ return $arr;
+}
+
+function show_flagged_songs($flags)
+{
+ require_once(conf('prefix').'/templates/list_flagged.inc');
+}
+
+function accept_new_tags($flags)
+{
+ if(!is_array($flags)) $flags = array($flags);
+ foreach($flags as $flag)
+ {
+ copy_updated_tag($flag);
+ }
+ set_flag_value($flags, 'setid3');
+}
+
+
+function reject_new_tags($flags)
+{
+ if(!is_array($flags)) $flags = array($flags);
+ $oldflags = $flags;
+ $flag = array_pop($flags);
+ $sql = "DELETE FROM flagged_songs WHERE song = '$flag'";
+
+ foreach($flags as $flag)
+ {
+ $sql .= " OR song = '$flag'";
+ }
+ $result = mysql_query($sql, dbh());
+ $user = $_SESSION['userdata']['username'];
+ set_flag_value($oldflags, 'notify', "Tag changes rejected by $user");
+}
+
+function set_flag_value($flags, $val, $comment = '')
+{
+ if(!is_array($flags)) $flags = array($flags);
+ $user = $_SESSION['userdata']['id'];
+/* $flagid = array_pop($flags);*/
+ $dbh = dbh();
+ foreach($flags as $flagid)
+ {
+ $sql = "REPLACE INTO flagged (type,song,comment,user,date)".
+ " VALUES ('$val','$flagid','$comment','$user','".time()."')";
+ $result = mysql_query($sql, $dbh);
+ }
+ return $result;
+}
+
+function copy_updated_tag($flag)
+{
+ $flagdata = get_flag($flag);
+ $sql = "SELECT * FROM flagged_song WHERE song = '".$flagdata['song']."'";
+ $result = mysql_query($sql, dbh());
+ $newtag = mysql_fetch_array($result);
+
+ if($newtag['new_artist'])
+ {
+ $newtag['artist'] = insert_artist($newtag['new_artist']);
+ }
+ if($newtag['new_album'])
+ {
+ $newtag['album'] = insert_album($newtag['new_album']);
+ }
+
+ $sql = "UPDATE song SET ".
+ "title = '".$newtag['title']."',".
+ "artist = '".$newtag['artist']."',".
+ "album = '".$newtag['album']."',".
+ "track = '".$newtag['track']."',".
+ "genre = '".$newtag['genre']."',".
+ "year = '".$newtag['year']."' ".
+ "WHERE song.id = '".$newtag['song']."'";
+ $result = mysql_query($sql, dbh());
+ if($result)
+ {
+ $sql2 = "DELETE FROM flagged_song WHERE song='".$flagdata['song']."'";
+ $result2 = mysql_query($sql2, dbh());
+ }
+ return ($result && $result2);
+
+}
+
+function update_flags($songs)
+{
+ $accepted = array();
+ $rejected = array();
+ $newflags = array();
+ foreach($songs as $song)
+ {
+ $accept = scrub_in($_REQUEST[$song.'_accept']);
+ if($accept === 'accept') $accepted[] = $song;
+ elseif ($accept === 'reject') $rejected[] = $song;
+ else
+ {
+ $newflag = scrub_in($_REQUEST[$song.'_newflag']);
+ $newflags[$song] = $newflag;
+ }
+ }
+
+ if(count($accepted))
+ {
+ accept_new_tags($accepted);
+ }
+ if(count($rejected))
+ {
+ reject_new_tags($rejected);
+ }
+ if(count($newflags))
+ {
+ foreach($newflags as $flag=>$type)
+ {
+ set_flag_value($flag, $type);
+ }
+ }
+
+}
+
+
+function update_song_info($song)
+{
+ $user = $_SESSION['userdata'];
+
+ $title = scrub_in($_REQUEST['title']);
+ $track = scrub_in($_REQUEST['track']);
+ $genre = scrub_in($_REQUEST['genre']);
+ $year = scrub_in($_REQUEST['year']);
+
+ if(isset($_REQUEST['update_id3']))
+ $update_id3 = 1;
+
+ if(isset($_REQUEST['new_artist']) && $_REQUEST['new_artist'] !== '')
+ {
+ $create_artist = 1;
+ $artist = scrub_in($_REQUEST['new_artist']);
+ }
+ else
+ $artist = scrub_in($_REQUEST['artist']);
+
+ if(isset($_REQUEST['new_album']) && $_REQUEST['new_album'] !== '')
+ {
+ $create_album = 1;
+ $album = scrub_in($_REQUEST['new_album']);
+ }
+ else
+ $album = scrub_in($_REQUEST['album']);
+
+ if(is_array($_REQUEST['genre'])) {
+ $genre = $genre[0];
+ }
+
+ if($user['access'] == 'admin')
+ // Update the file directly
+ {
+ if($create_artist)
+ {
+ $artist = insert_artist($artist);
+ }
+ if($create_album)
+ {
+ $album = insert_album($album);
+ }
+ // Escape data (prevent " or ' snafu's)
+ $title = sql_escape($title);
+ $artist = sql_escape($artist);
+ $album = sql_escape($album);
+ $genre = sql_escape($genre);
+ $year = sql_escape($year);
+
+ $sql = "UPDATE song SET" .
+ " title = '$title'," .
+ " track = '$track'," .
+ " genre = '$genre'," .
+ " year = '$year'," .
+ " artist = '$artist',".
+ " album = '$album'," .
+ " update_time = '".time()."'" .
+ " WHERE id = '$song' LIMIT 1";
+ $result = mysql_query($sql, dbh() );
+ if($result && $update_id3 )
+ {
+ //Add to flagged table so we can fix the id3 tags
+ $date = time();
+ $sql = "REPLACE INTO flagged SET " .
+ " type = 'setid3', song = '$song', date = '$date', user = '".$user['id']."'";
+ $result = mysql_query($sql, dbh());
+ }
+ }
+
+ else
+ // Stick in the flagged_songs table to be updated by an admin
+ {
+ if($create_artist) $artist_field = 'new_artist';
+ else $artist_field = 'artist';
+
+ if($create_album) $album_field = 'new_album';
+ else $album_field = 'album';
+
+ $sql = "INSERT INTO flagged_song(song,title,track,genre,year,$artist_field,$album_field,update_time) " .
+ "VALUES ('$song','$title','$track','$genre','$year','$artist','$album','".time()."')";
+ $result = mysql_query($sql, dbh() );
+
+ if($result && $update_id3 )
+ {
+ //Add to flagged table so we can fix the id3 tags
+ $date = time();
+ $sql = "REPLACE INTO flagged SET " .
+ " type = 'newid3', song = '$song', date = '$date', user = '".$user['id']."'";
+ $result = mysql_query($sql, dbh());
+ }
+ echo "Thanks for helping to keep the catalog up to date. Someone will review your changes, and you will be notified on the main page when they're approved.";
+
+ }
+}
+
diff --git a/lib/general.php b/lib/general.php
new file mode 100644
index 00000000..1184db45
--- /dev/null
+++ b/lib/general.php
@@ -0,0 +1,554 @@
+<?php
+/*
+ @header General Library
+ This is the general library that contains misc functions
+ that doesn't have a home elsewhere
+*/
+
+/*!
+ @function sql_escape
+ @discussion this takes a sql statement
+ and properly escapes it before a query is run
+ against it.
+*/
+function sql_escape($sql,$dbh=0) {
+
+ if (!is_resource($dbh)) {
+ $dbh = dbh();
+ }
+
+ if (function_exists('mysql_real_escape_string')) {
+ $sql = mysql_real_escape_string($sql,$dbh);
+ }
+ else {
+ $sql = mysql_escape_string($sql);
+ }
+
+ return $sql;
+
+} // sql_escape
+
+/*!
+ @function ip2int
+ @discussion turns a dotted quad ip into an
+ int
+*/
+function ip2int($ip) {
+
+ $a=explode(".",$ip);
+ return $a[0]*256*256*256+$a[1]*256*256+$a[2]*256+$a[3];
+
+} // ip2int
+
+/*!
+ @function int2ip
+ @discussion turns a int into a dotted quad
+*/
+function int2ip($i) {
+ $d[0]=(int)($i/256/256/256);
+ $d[1]=(int)(($i-$d[0]*256*256*256)/256/256);
+ $d[2]=(int)(($i-$d[0]*256*256*256-$d[1]*256*256)/256);
+ $d[3]=$i-$d[0]*256*256*256-$d[1]*256*256-$d[2]*256;
+ return "$d[0].$d[1].$d[2].$d[3]";
+} // int2ip
+
+/*!
+ @function show_template
+ @discussion show a template from the /templates directory, automaticly appends .inc
+ to the passed filename
+ @param $template Name of Template
+*/
+function show_template($template) {
+
+ /* Check for a 'Theme' template */
+ if (is_readable(conf('prefix') . conf('theme_path') . "/templates/$template".".inc")) {
+ require (conf('prefix') . conf('theme_path') . "/templates/$template".".inc");
+ }
+ else {
+ require (conf('prefix') . "/templates/$template".".inc");
+ }
+
+} // show_template
+
+
+/*!
+ @function read_config
+ @discussion reads the config file for ampache
+*/
+function read_config($config_file, $debug=0, $test=0) {
+
+ $fp = @fopen($config_file,'r');
+ if(!is_resource($fp)) return false;
+ $file_data = fread($fp,filesize($config_file));
+ fclose($fp);
+
+ // explode the var by \n's
+ $data = explode("\n",$file_data);
+ if($debug) echo "<pre>";
+
+ $count = 0;
+
+ foreach($data as $value) {
+ $count++;
+
+ $value = trim($value);
+
+ if (preg_match("/^\[([A-Za-z]+)\]$/",$value,$matches)) {
+ // If we have previous data put it into $results...
+ if (isset($config_name) && isset(${$config_name}) && count(${$config_name})) {
+ $results[$config_name] = ${$config_name};
+ }
+
+ $config_name = $matches[1];
+
+ } // if it is a [section] name
+
+
+ elseif (isset($config_name)) {
+
+ // if it's not a comment
+ if (preg_match("/^([\w\d]+)\s+=\s+[\"]{1}(.*?)[\"]{1}$/",$value,$matches)
+ || preg_match("/^([\w\d]+)\s+=\s+[\']{1}(.*?)[\']{1}$/", $value, $matches)
+ || preg_match("/^([\w\d]+)\s+=\s+[\'\"]{0}(.*)[\'\"]{0}$/",$value,$matches)) {
+
+ if (isset(${$config_name}[$matches[1]]) && is_array(${$config_name}[$matches[1]]) && isset($matches[2]) ) {
+ if($debug) echo "Adding value <strong>$matches[2]</strong> to existing key <strong>$matches[1]</strong>\n";
+ array_push(${$config_name}[$matches[1]], $matches[2]);
+ }
+
+ elseif (isset(${$config_name}[$matches[1]]) && isset($matches[2]) ) {
+ if($debug) echo "Adding value <strong>$matches[2]</strong> to existing key $matches[1]</strong>\n";
+ ${$config_name}[$matches[1]] = array(${$config_name}[$matches[1]],$matches[2]);
+ }
+
+ elseif ($matches[2] !== "") {
+ if($debug) echo "Adding value <strong>$matches[2]</strong> for key <strong>$matches[1]</strong>\n";
+ ${$config_name}[$matches[1]] = $matches[2];
+ }
+
+ // if there is something there and it's not a comment
+ elseif ($value{0} !== "#" AND strlen(trim($value)) > 0 AND !$test AND strlen($matches[2]) > 0) {
+ echo "Error Invalid Config Entry --> Line:$count"; return false;
+ } // elseif it's not a comment and there is something there
+
+ else {
+ if($debug) echo "Key <strong>$matches[1]</strong> defined, but no value set\n";
+ }
+ } // end if it's not a comment
+
+ } // elseif no config_name
+
+
+ elseif (preg_match("/^([\w\d]+)\s+=\s+[\"]{1}(.*?)[\"]{1}$/",$value,$matches)
+ || preg_match("/^([\w\d]+)\s+=\s+[\']{1}(.*?)[\']{1}$/", $value, $matches)
+ || preg_match("/^([\w\d]+)\s+=\s+[\'\"]{0}(.*)[\'\"]{0}$/",$value,$matches)) {
+
+
+ if (is_array($results[$matches[1]]) && isset($matches[2]) ) {
+ if($debug) echo "Adding value <strong>$matches[2]</strong> to existing key <strong>$matches[1]</strong>\n";
+ array_push($results[$matches[1]], $matches[2]);
+ }
+
+ elseif (isset($results[$matches[1]]) && isset($matches[2]) ) {
+ if($debug) echo "Adding value <strong>$matches[2]</strong> to existing key $matches[1]</strong>\n";
+ $results[$matches[1]] = array($results[$matches[1]],$matches[2]);
+ }
+
+ elseif ($matches[2] !== "") {
+ if($debug) echo "Adding value <strong>$matches[2]</strong> for key <strong>$matches[1]</strong>\n";
+ $results[$matches[1]] = $matches[2];
+ }
+
+ // if there is something there and it's not a comment
+ elseif ($value{0} !== "#" AND strlen(trim($value)) > 0 AND !$test AND strlen($matches[2]) > 0) {
+ echo "Error Invalid Config Entry --> Line:$count"; return false;
+ } // elseif it's not a comment and there is something there
+
+ else {
+ if($debug) echo "Key <strong>$matches[1]</strong> defined, but no value set\n";
+ }
+
+ } // end else
+
+ } // foreach
+
+ if (isset($config_name) && isset(${$config_name}) && count(${$config_name})) {
+ $results[$config_name] = ${$config_name};
+ }
+
+ if($debug) echo "</pre>";
+
+ return $results;
+
+
+} // read_config
+
+/*
+ * Conf function by Robert Hopson
+ * call it with a $parm name to retrieve
+ * a var, pass it a array to set them
+ * to reset a var pass the array plus
+ * Clobber! replaces global $conf;
+*/
+function conf($param,$clobber=0)
+{
+ static $params = array();
+
+ if(is_array($param))
+ //meaning we are setting values
+ {
+ foreach ($param as $key=>$val)
+ {
+ if(!$clobber && isset($params[$key]))
+ {
+ echo "Error: attempting to clobber $key = $val\n";
+ exit();
+ }
+ $params[$key] = $val;
+ }
+ return true;
+ }
+ else
+ //meaning we are trying to retrieve a parameter
+ {
+ if($params[$param]) return $params[$param];
+ else return;
+ }
+} //conf
+
+function libglue_param($param,$clobber=0)
+{
+ static $params = array();
+ if(is_array($param))
+ //meaning we are setting values
+ {
+ foreach ($param as $key=>$val)
+ {
+ if(!$clobber && isset($params[$key]))
+ {
+ echo "Error: attempting to clobber $key = $val\n";
+ exit();
+ }
+ $params[$key] = $val;
+ }
+ return true;
+ }
+ else
+ //meaning we are trying to retrieve a parameter
+ {
+ if(isset($params[$param])) return $params[$param];
+ else return false;
+ }
+}
+
+function error_results($param,$clobber=0)
+{
+ static $params = array();
+
+ if(is_array($param))
+ //meaning we are setting values
+ {
+ foreach ($param as $key=>$val)
+ {
+ if(!$clobber && isset($params[$key]))
+ {
+ echo "Error: attempting to clobber $key = $val\n";
+ exit();
+ }
+ $params[$key] = $val;
+ }
+ return true;
+ }
+ else
+ //meaning we are trying to retrieve a parameter
+ {
+ if($params[$param]) return $params[$param];
+ else return;
+ }
+} //error_results
+
+
+/*!
+ @function dbh
+ @discussion retrieves the DBH
+*/
+function dbh() { return check_sess_db('local'); }
+
+/*!
+ @function fix_preferences
+ @discussion cleans up the preferences
+*/
+function fix_preferences($results) {
+
+ foreach ($results as $key=>$data) {
+ if (strcasecmp($data, "yes") == "0") { $data = 1; }
+ if (strcasecmp($data,"true") == "0") { $data = 1; }
+ if (strcasecmp($data,"enabled") == "0") { $data = 1; }
+ if (strcasecmp($data,"disabled") == "0") { $data = 0; }
+ if (strcasecmp($data,"false") == "0") { $data = 0; }
+ if (strcasecmp($data,"no") == "0") { $data = 0; }
+ $results[$key] = $data;
+ }
+
+ return $results;
+
+} // fix_preferences
+
+/*!
+ @function session_exists
+ @discussion checks to make sure they've specified a
+ valid session
+*/
+function session_exists($sid) {
+
+ $sql = "SELECT * FROM session WHERE id = '$sid'";
+ $db_results = mysql_query($sql, dbh());
+
+ if (!mysql_num_rows($db_results)) {
+ return false;
+ }
+
+ return true;
+
+} // session_exists
+
+/*!
+ @function extend_session
+ @discussion just update the expire time
+*/
+function extend_session($sid) {
+
+ $new_time = time() + conf('local_length');
+
+ if ($_COOKIE['amp_longsess'] == '1') { $new_time = time() + 86400*364; }
+
+ $sql = "UPDATE session SET expire='$new_time' WHERE id='$sid'";
+ $db_results = mysql_query($sql, dbh());
+
+} // extend_session
+
+/*!
+ @function get_tag_type
+ @discussion finds out what tag the audioinfo
+ results returned
+*/
+function get_tag_type($results) {
+
+ // Check and see if we are dealing with an ogg
+ // If so order will be a little different
+ if ($results['ogg']) {
+ $order[0] = 'ogg';
+ } // end if ogg
+ elseif ($results['rm']) {
+ $order[0] = 'rm';
+ }
+ elseif ($results['flac']) {
+ $order[0] = 'flac';
+ }
+ elseif ($results['asf']) {
+ $order[0] = 'asf';
+ }
+ elseif ($results['m4a']) {
+ $order[0] = 'm4a';
+ }
+ elseif ($results['mpc']) {
+ $order[0] = 'mpc';
+ }
+ else {
+ $order = conf('id3tag_order');
+ } // end else
+
+ if (!is_array($order)) {
+ $order = array($order);
+ }
+
+ // set the $key to the first found tag style (according to their prefs)
+ foreach($order as $key) {
+ if ($results[$key]) {
+ break;
+ }
+ }
+
+ return $key;
+
+} // get_tag_type
+
+
+/*!
+ @function clean_tag_info
+ @discussion cleans up the tag information
+*/
+function clean_tag_info($results,$key,$filename) {
+
+ $info = array();
+
+ $clean_array = array("\n","\t","\r","\0");
+ $wipe_array = array("","","","");
+
+ $info['file'] = $filename;
+ $info['title'] = stripslashes(trim($results[$key]['title']));
+ $info['year'] = intval($results[$key]['year']);
+ $info['comment'] = sql_escape(str_replace($clean_array,$wipe_array,$results[$key]['comment']));
+ $info['bitrate'] = intval($results['avg_bit_rate']);
+ $info['rate'] = intval($results['sample_rate']);
+ $info['mode'] = $results['bitrate_mode'];
+ $info['size'] = filesize($filename);
+ $info['time'] = intval($results['playing_time']);
+ $info['track'] = intval($results[$key]['track']);
+
+ /* These are used to generate the correct ID's later */
+ $info['artist'] = trim($results[$key]['artist']);
+ $info['album'] = trim($results[$key]['album']);
+ $info['genre'] = trim($results[$key]['genre']);
+
+ return $info;
+
+} // clean_tag_info
+
+/*!
+ @function scrub_in()
+ @discussion Run on inputs, stuff that might get stuck in our db
+*/
+function scrub_in($str) {
+
+ if (!is_array($str)) {
+ return stripslashes( htmlspecialchars( strip_tags($str) ) );
+ }
+ else {
+ $ret = array();
+ foreach($str as $string) $ret[] = scrub_in($string);
+ return $ret;
+ }
+} // scrub_in
+
+/*!
+ @function batch_ok()
+ @discussion return boolean if user can batch download
+*/
+function batch_ok( ) {
+ global $user;
+ // i check this before showing any link
+ // should make it easy to tie to a new pref if you choose to add it
+ if (conf('allow_zip_download')) {
+ return( $user->prefs['download'] );
+ } // if allowed zip downloads
+
+ return false;
+
+} // batch_ok
+
+/*!
+ @function set_memory_limit
+ @discussion this function attempts to change the
+ php memory limit using init_set but it will
+ never reduce it
+*/
+function set_memory_limit($new_limit) {
+
+ /* Check their PHP Vars to make sure we're cool here */
+ // Up the memory
+ $current_memory = ini_get('memory_limit');
+ $current_memory = substr($current_memory,0,strlen($current_memory)-1);
+ if ($current_memory < $new_limit) {
+ $php_memory = $new_limit . "M";
+ ini_set (memory_limit, "$php_memory");
+ unset($php_memory);
+ }
+
+} // set_memory_limit
+
+/*!
+ @function get_random_songs
+ @discussion Returns a random set of songs/albums or artists
+ matchlist is an array of the WHERE mojo and options
+ defines special unplayed,album,artist,limit info
+*/
+function get_random_songs( $options, $matchlist) {
+
+ $dbh = dbh();
+
+ /* Define the options */
+ $limit = $options['limit'];
+ $unplayed = $options['unplayed'];
+
+ /* If they've passed -1 as limit then don't get everything */
+ if ($options['limit'] == "-1") { unset($options['limit']); }
+ else { $options['limit'] = "LIMIT " . $limit; }
+
+
+ $where = "1=1 ";
+ if(is_array($matchlist))
+ foreach ($matchlist as $type => $value) {
+ if (is_array($value)) {
+ foreach ($value as $v) {
+ $v = sql_escape($v);
+ if ($v != $value[0]) { $where .= " OR $type='$v' "; }
+ else { $where .= " AND ( $type='$v'"; }
+ }
+ $where .= " ) ";
+ }
+ else {
+ $value = sql_escape($value);
+ $where .= " AND $type='$value' ";
+ }
+ }
+
+
+
+ if ($options['full_album'] == 1) {
+ $query = "SELECT album.id FROM song,album WHERE song.album=album.id AND $where GROUP BY song.album ORDER BY RAND() " . $options['limit'];
+ $db_results = mysql_query($query, $dbh);
+ while ($data = mysql_fetch_row($db_results)) {
+ $albums_where .= " OR song.album=" . $data[0];
+ }
+ $albums_where = ltrim($albums_where," OR");
+ $query = "SELECT song.id FROM song WHERE $albums_where ORDER BY song.track ASC";
+ }
+ elseif ($options['full_artist'] == 1) {
+ $query = "SELECT artist.id FROM song,artist WHERE song.artist=artist.id AND $where GROUP BY song.artist ORDER BY RAND() " . $options['limit'];
+ $db_results = mysql_query($query, $dbh);
+ while ($data = mysql_fetch_row($db_results)) {
+ $artists_where .= " OR song.artist=" . $data[0];
+ }
+ $artists_where = ltrim($artists_where," OR");
+ $query = "SELECT song.id FROM song WHERE $artists_where ORDER BY RAND()";
+ }
+ elseif ($options['unplayed'] == 1) {
+ $uid = $_SESSION['userdata']['id'];
+ $query = "SELECT song.id FROM song LEFT JOIN object_count ON song.id = object_count.object_id " .
+ "WHERE ($where) AND ((object_count.object_type='song' AND userid = '$uid') OR object_count.count IS NULL ) " .
+ "ORDER BY CASE WHEN object_count.count IS NULL THEN RAND() WHEN object_count.count > 4 THEN RAND()*RAND()*object_count.count " .
+ "ELSE RAND()*object_count.count END " . $options['limit'];
+ } // If unplayed
+ else {
+ $query = "SELECT id FROM song WHERE $where ORDER BY RAND() " . $options['limit'];
+ }
+ $db_result = mysql_query($query, $dbh);
+
+ $songs = array();
+
+ while ( $r = mysql_fetch_array($db_result) ) {
+ $songs[] = $r[0];
+ }
+
+ return ($songs);
+
+} // get_random_songs
+
+/*!
+ @function cleanup_and_exit
+ @discussion used specificly for the play/index.php file
+ this functions nukes now playing and then exits
+*/
+function cleanup_and_exit($playing_id) {
+
+ /* Clear now playing */
+ // 900 = 15 min
+ $expire = time() - 900;
+ $sql = "DELETE FROM now_playing WHERE id='$lastid' OR start_time < $expire";
+ $db_results = mysql_query($sql, dbh());
+ exit();
+
+} // cleanup_and_exit
+
+?>
diff --git a/lib/gettext.php b/lib/gettext.php
new file mode 100644
index 00000000..064173d6
--- /dev/null
+++ b/lib/gettext.php
@@ -0,0 +1,36 @@
+<?php
+/*
+
+ 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.
+
+*/
+
+/*!
+ @function load_gettext
+ @discussion sets the local
+*/
+function load_gettext() {
+ /* If we have gettext */
+ if (function_exists('bindtextdomain')) {
+ bindtextdomain('messages', conf('prefix') . "/locale/");
+ textdomain('messages');
+ putenv("LANG=" . conf('lang'));
+ setlocale(LC_ALL, conf('lang'));
+ }
+
+} // load_gettext
+
+
+?>
diff --git a/lib/install.php b/lib/install.php
new file mode 100644
index 00000000..c337b1e8
--- /dev/null
+++ b/lib/install.php
@@ -0,0 +1,238 @@
+<?
+/*
+
+ 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 Install docuement
+ @discussion this document contains the functions needed to see if
+ ampache needs to be installed
+*/
+
+/*!
+ @function split_sql
+ @discussion splits up a standard SQL dump file into distinct
+ sql queryies
+*/
+function split_sql($sql) {
+ $sql = trim($sql);
+ $sql = ereg_replace("\n#[^\n]*\n", "\n", $sql);
+ $buffer = array();
+ $ret = array();
+ $in_string = false;
+ for($i=0; $i<strlen($sql)-1; $i++) {
+ if($sql[$i] == ";" && !$in_string) {
+ $ret[] = substr($sql, 0, $i);
+ $sql = substr($sql, $i + 1);
+ $i = 0;
+ }
+ if($in_string && ($sql[$i] == $in_string) && $buffer[1] != "\\") {
+ $in_string = false;
+ }
+ elseif(!$in_string && ($sql[$i] == '"' || $sql[$i] == "'") && (!isset($buffer[0]) || $buffer[0] != "\\")) {
+ $in_string = $sql[$i];
+ }
+ if(isset($buffer[1])) {
+ $buffer[0] = $buffer[1];
+ }
+ $buffer[1] = $sql[$i];
+ }
+ if(!empty($sql)) {
+ $ret[] = $sql;
+ }
+ return($ret);
+} // split_sql
+
+/*!
+ @function install_check_status()
+ @discussion this function checks to see if we actually
+ still need to install ampache. This function is
+ very important, we don't want to reinstall over top
+ of an existing install
+*/
+function install_check_status($configfile) {
+
+ /*
+ Check and see if the config file exists
+ if it does they can't use the web interface
+ to install ampache.
+ */
+ if (!file_exists($configfile)) {
+ return true;
+ }
+
+ /*
+ Check and see if they've got _any_ account
+ if they don't then they're cool
+ */
+ $results = read_config($GLOBALS['configfile'], 0, 0);
+ $dbh = check_database($results['libglue']['local_host'],$results['libglue']['local_username'],$results['libglue']['local_pass'],$results['libglue']['local_db']);
+
+ if (is_resource($dbh)) {
+ mysql_select_db($results['libglue']['local_db'],$dbh);
+ $sql = "SELECT * FROM user";
+ $db_results = @mysql_query($sql, $dbh);
+ if (!@mysql_num_rows($db_results)) {
+ return true;
+ }
+ }
+
+
+ /* Defaut to no */
+ return false;
+
+} // install_check_status
+
+/*!
+ @function install_insert_db()
+ @discussion this function inserts the database
+ using the username/pass/host provided
+ and reading the .sql file
+*/
+function install_insert_db($username,$password,$hostname,$database) {
+
+ /* Attempt to make DB connection */
+ $dbh = @mysql_pconnect($hostname,$username,$password);
+
+
+ /* Check/Create Database as needed */
+ $db_selected = @mysql_select_db($database, $dbh);
+ if (!$db_selected) {
+ $sql = "CREATE DATABASE `" . $database . "`";
+ if (!$db_results = @mysql_query($sql, $dbh)) {
+ return false;
+ }
+ @mysql_select_db($database, $dbh);
+ } // if db can't be selected
+
+
+ /* Attempt to insert database */
+ $query = fread(fopen("sql/ampache.sql", "r"), filesize("sql/ampache.sql"));
+ $pieces = split_sql($query);
+ for ($i=0; $i<count($pieces); $i++) {
+ $pieces[$i] = trim($pieces[$i]);
+ if(!empty($pieces[$i]) && $pieces[$i] != "#") {
+ //FIXME: This is for a DB prefix when we get around to it
+// $pieces[$i] = str_replace( "#__", $DBPrefix, $pieces[$i]);
+ if (!$result = mysql_query ($pieces[$i])) {
+ $errors[] = array ( mysql_error(), $pieces[$i] );
+ } // end if
+ } // end if
+ } // end for
+
+ return true;
+
+} // install_insert_db
+
+/*!
+ @function install_create_config()
+ @discussion attempts to write out the config file
+ if it can't write it out it will prompt the
+ user to download the config file.
+*/
+function install_create_config($web_path,$username,$password,$hostname,$database) {
+
+ /*
+ First Test The Variables they've given us to make
+ sure that they actually work!
+ */
+ // Connect to the DB
+ if(!$dbh = @mysql_pconnect($hostname,$username,$password)) {
+ return false;
+ }
+ if (!$db_selected = @mysql_select_db($database, $dbh)) {
+ return false;
+ }
+
+
+ /* Read in the .dist file and spit out the .cfg */
+ $dist_handle = @fopen("config/ampache.cfg.php.dist",'r');
+ $dist_data = @fread($dist_handle,filesize("config/ampache.cfg.php.dist"));
+ fclose($dist_handle);
+
+ $dist_array = explode("\n",$dist_data);
+
+ // Rather then write it out right away, let's build the string
+ // incase we can't write to the FS and have to make it a download
+
+ foreach ($dist_array as $row) {
+
+ if (preg_match("/^#?web_path\s*=/",$row)) {
+ $row = "web_path = \"$web_path\"";
+ }
+ elseif (preg_match("/^#?local_db\s*=/",$row)) {
+ $row = "local_db = \"$database\"";
+ }
+ elseif (preg_match("/^#?local_host\s*=/",$row)) {
+ $row = "local_host = \"$hostname\"";
+ }
+ elseif (preg_match("/^#?local_username\s*=/",$row)) {
+ $row = "local_username = \"$username\"";
+ }
+ elseif (preg_match("/^#?local_pass\s*=/",$row)) {
+ $row = "local_pass = \"$password\"";
+ }
+
+ $config_data .= $row . "\n";
+
+ } // foreach row in config file
+
+ /* Attempt to Write out File */
+ if (!$config_handle = @fopen("config/ampache.cfg.php",'w')) {
+ $browser = new Browser();
+ $browser->downloadHeaders("ampache.cfg.php","text/plain",false,filesize("config/ampache.cfg.php.dist"));
+
+ echo $config_data;
+ exit();
+
+ }
+ if (!@fwrite($config_handle,$config_data)) {
+ return false;
+ }
+
+ return true;
+
+} // install_create_config
+
+/*!
+ @function install_create_account
+ @discussion this creates your initial account
+*/
+function install_create_account($username,$password) {
+
+ $results = read_config($GLOBALS['configfile'], 0, 0);
+ $dbh = check_database($results['libglue']['local_host'],$results['libglue']['local_username'],$results['libglue']['local_pass'],$results['libglue']['local_db']);
+
+ @mysql_select_db($results['libglue']['local_db'],$dbh);
+
+ $username = sql_escape($username,$dbh);
+ $password = sql_escape($password,$dbh);
+
+ $sql = "INSERT INTO user (`username`,`password`,`offset_limit`,`access`) VALUES ('$username',PASSWORD('$password'),'50','admin')";
+ $db_results = mysql_query($sql, $dbh);
+
+ $insert_id = mysql_insert_id($dbh);
+
+ if (!$insert_id) { return false; }
+
+ return true;
+
+} // install_create_account
+
+?>
diff --git a/lib/log.php b/lib/log.php
new file mode 100644
index 00000000..7a3d8faf
--- /dev/null
+++ b/lib/log.php
@@ -0,0 +1,77 @@
+<?php
+/*
+
+ 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.
+
+*/
+
+/*!
+ @function log_event
+ @discussion logs an event either to a database
+ or to a defined log file based on config options
+*/
+function log_event($username='Unknown',$event_name,$event_description,$log_name='ampache') {
+
+ /* Set it up here to make sure it's _always_ the same */
+ $log_time = time();
+
+ set_time_limit(0);
+
+ $log_filename = conf('log_path') . "/$log_name." . date("Ymd",$log_time) . ".log";
+ $log_line = date("Y-m-d H:i:s",$log_time) . " { $username } ( $event_name ) - $event_description \n";
+
+
+ error_log($log_line, 3, $log_filename) or die("Error: Unable to write to log ($log_filename)");
+
+} // log_event
+
+/*!
+ @function ampache_error_handler
+ @discussion an error handler for ampache that traps
+ as many errors as it can and logs em
+*/
+function ampache_error_handler($errno, $errstr, $errfile, $errline) {
+
+ switch ($errno) {
+ case '2':
+ case '128':
+ case '8':
+ case '32':
+ return true;
+ break;
+ case '1':
+ $error_name = "Fatal run-time Error";
+ break;
+ case '4':
+ $error_name = "Parse Error";
+ break;
+ case '16':
+ $error_name = "Fatal Core Error";
+ break;
+ case '64':
+ $error_name = "Zend run-time Error";
+ break;
+ default:
+ $error_name = "Error";
+ break;
+ } // end switch
+
+
+ $log_line = "[$errstr] $error_name on line $errline in $errfile";
+ log_event($_SESSION['userdata']['username'],'error',$log_line,'ampache-error');
+
+} // ampache_error_handler
+
+?>
diff --git a/lib/mpd.php b/lib/mpd.php
new file mode 100644
index 00000000..166bfe5b
--- /dev/null
+++ b/lib/mpd.php
@@ -0,0 +1,75 @@
+<?php
+/*
+
+ 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.
+
+*/
+
+/*!
+ @function addToPlaylist()
+ @discussion adds a bunch of songs to the mpd playlist
+ this takes a mpd object, and an array of songs
+*/
+function addToPlaylist( $myMpd, $song_ids=array()) {
+
+ foreach( $song_ids as $song_id ) {
+
+ /* There are two ways to do this, filename or URL */
+ if (conf('mpd_method') == 'url') {
+ // We just need to generate a standard stream URL and pass that
+ $song = new Song($song_id);
+ $sess_id = session_id();
+ if ($song->type == ".flac") { $song->type = ".ogg"; }
+ if ($GLOBALS['user']->prefs['play_type'] == 'downsample') {
+ $ds = $GLOBALS['user']->prefs['sample_rate'];
+ }
+ $song_url = conf('web_path') . "/play/index.php?song=$song_id&uid=" . $GLOBALS['user']->id . "&sid=$sess_id&ds=$ds&name=." . $song->type;
+ if (is_null( $myMpd->PlAdd($song_url) ) ) {
+ $log_line = _("Error") . ": " . _("Could not add") . ": " . $song_url . " : " . $myMpd->errStr;
+ echo "<font class=\"error\">$log_line</font><br />\n";
+ log_event($GLOBALS['user']->username,'add',$log_line);
+ } // if it's null
+ } // if we want urls
+ else {
+ $song = new Song( $song_id );
+ $song_filename = $song->get_rel_path();
+ if( is_null( $myMpd->PLAdd( $song_filename ) ) ) {
+ $log_line = _("Error") . ": " . _("Could not add") . ": " . $song_filename . " : " . $myMpd->errStr;
+ echo "<font class=\"error\">$log_line</font><br />\n";
+ log_event($_SESSION['userdata']['username'],'add',$log_line);
+ } // end if it's null
+ // We still need to count if they use the file method
+ else {
+ $GLOBALS['user']->update_stats( $song_id );
+ } // end else
+
+ } // end else not url method
+ } // end foreach
+
+} // addToPlaylist
+
+/*!
+ @function show_mpd_control
+ @discussion shows the mpd controls
+*/
+function show_mpd_control() {
+
+ $_REQUEST['action'] = 'show_control';
+ require_once ('amp-mpd.php');
+
+
+} // show_mpd_control
+
+?>
diff --git a/lib/perl/Local/Ampache/Ampache.pm b/lib/perl/Local/Ampache/Ampache.pm
new file mode 100755
index 00000000..3bceb7e6
--- /dev/null
+++ b/lib/perl/Local/Ampache/Ampache.pm
@@ -0,0 +1,237 @@
+#!/usr/bin/perl -w
+
+# Find and file away MP3's. Run multiple times and will
+# ignore addition of duplicates in db (based on MD5 hash
+# of full file path.
+
+package Local::Ampache;
+#use File::Find;
+use DBI;
+#use strict;
+use Data::Dumper;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %ampache);
+require Exporter;
+
+@ISA = qw(Exporter AutoLoader);
+@EXPORT = qw(
+
+);
+
+my $TRUE = 1;
+my $FALSE = 0;
+$VERSION = '';
+
+
+my %ampache = ();
+
+
+sub new {
+ my ($class, $path) = @_;
+
+
+ open(CONFIG, "< $path/config/ampache.cfg")
+ or die "Could not find $path/config/ampache.cfg. Is it readable by me?\n";
+
+ my %config = ();
+
+ while (<CONFIG>) {
+ next if ($_ =~ /^#.*/);
+
+ if ( $_ =~ /(.*?)\s+=\s+(.*)/ ) {
+ $config{$1} = $2;
+ }
+ }
+
+ my $name = $config{'local_db'};
+
+ my $self =
+ {
+ _name => $config{'local_db'},
+ _database => $config{'local_db'},
+ _sth_cache => {},
+ _connect => {
+ dbd => 'mysql',
+ host => $config{'local_host'},
+ port => '3306',
+ username => $config{'local_username'},
+ password => $config{'local_pass'}
+ },
+ _dbh => '',
+ _path => $path,
+ _config => \%config,
+ _debug => $FALSE
+ };
+
+ $VERSION = $config{'VERSION'};
+
+ $Local::Ampache::ampache{$name} = bless ($self, $class);
+
+ $self->{_dbh} = $self->dbh( $name );
+
+ return $self;
+
+} # End New Ampache Module
+
+sub DESTROY {
+ my ($self) = @_;
+
+ foreach my $sth (values %{$self->{_sth_cache}}) {
+ if (defined($sth)) { $sth->finish(); }
+ }
+
+ if (defined($self->{_dbh}) and $self->{_dbh} ne "") {
+ $self->{_dbh}->disconnect();
+ }
+}
+
+sub get
+{
+ my ($class, $name) = @_;
+
+ if (not $Local::Ampache::ampache{$name}) {
+ $Local::Ampache::ampache{$name} = Local::Ampache->new($name);
+ }
+ return bless $Local::Ampache::ampache{$name}, $class;
+}
+
+sub dbh
+{
+ my ($self, $database) = @_;
+ my $dbh = '';
+
+ if($self->{_dbh} )
+ {
+ return $self->{_dbh};
+ }
+ else
+ {
+ my $connect_string = [ sprintf("dbi:%s:database=%s;host=%s;port=%s",
+ $self->{_connect}{dbd},
+ $self->{_database},
+ $self->{_connect}{host},
+ $self->{_connect}{port}),
+ $self->{_connect}{username},
+ $self->{_connect}{password} ];
+ $dbh = DBI->connect( @{$connect_string},
+ {PrintError => 0,
+ RaiseError => 0,
+ AutoCommit => 1});
+
+ if ( !$dbh )
+ {
+ die "Failed to connect to database. Exiting.";
+ }
+ }
+
+ return $dbh;
+}
+
+sub prepare_sth_cache {
+ my ($self, $sql) = @_;
+
+ # the call to dbh() forces a connection if one has dropped
+ my $dbh = $self->dbh();
+ return $dbh->prepare($sql);
+}
+
+sub get_table_where
+{
+ my ($self, $name, $where,$select) = @_;
+ if (!$select) { $select = "*"; }
+ my ($sql, $sth);
+ my $dbh = $self->dbh();
+ $sql = qq{SELECT $select FROM $name $where};
+ $sth = $dbh->prepare($sql);
+ $sth->execute();
+
+ my @table = ();
+ while ( my $ary = $sth->fetchrow_hashref() )
+ {
+ push(@table, $ary);
+ }
+ return (@table);
+}
+
+sub get_catalog_option
+{
+ my ($self, $catalog, $field) = @_;
+ if(!$self->{_catalog}{$catalog}) {
+ print "Loading catalog settings\n";
+ my ($sql, $sth);
+ $sql = qq{SELECT * FROM catalog WHERE path = '$catalog'};
+ my $dbh = $self->dbh();
+ $sth = $dbh->prepare($sql);
+ $sth->execute();
+ $self->{_catalog}{$catalog} = $sth->fetchrow_hashref();
+ }
+ return $self->{_catalog}->{$catalog}->{$field};
+}
+
+sub change_flags
+{
+ my ($self, $song, $oldflag, $newflag) = @_;
+ my ($sql, $sth);
+ my $dbh = $self->dbh();
+ $sql = "UPDATE flagged SET type = '$newflag' WHERE song = '".$song->{'id'}."' AND type = '$oldflag'";
+ $sth = $dbh->prepare($sql);
+ $sth->execute();
+}
+
+ sub update_song
+{
+ my ($self, $filename, $song) = @_;
+ my ($sql, $sth);
+ my $dbh = $self->dbh();
+ $filename =~ s/'/\\'/g;
+ $filename =~ s/"/\\"/g;
+ $filename =~ s/\Q%\E//g;
+ $sql = "UPDATE song SET file = '$filename' WHERE id = '".$song->{'id'}."'";
+ $sth = $dbh->prepare($sql);
+ $sth->execute();
+}
+
+sub get_song_info
+{
+ my ($self, $song) = @_;
+ my ($sql, $sth);
+ my $dbh = $self->dbh();
+ if ( not $self->{_sth_cache}{get_song_info})
+ {
+ $self->{_sth_cache}{get_song_info} = $self->prepare_sth_cache(
+ qq{SELECT catalog.path AS catalog,song.file,song.id,song.title,song.track,song.year,song.comment,album.name AS album, artist.name AS artist,genre FROM song,album,artist,catalog WHERE song.id = ? AND album.id = song.album AND artist.id = song.artist AND song.catalog = catalog.id});
+
+ }
+ $sth = $self->{_sth_cache}{get_song_info};
+ $sth->execute($song);
+
+ my @table = ();
+ while ( my $ary = $sth->fetchrow_hashref() )
+ {
+ push(@table, $ary);
+ }
+ return (@table);
+}
+
+#sub get_song_info
+#{
+# my ($self, $song) = @_;
+#
+# my ($sql, $sth);
+# my $dbh = $self->dbh();
+# if ( not $self->{_sth_cache}{song_info}{$song} )
+# {
+# $sql = qq{SELECT * FROM song WHERE id = $song};
+# $sth = $dbh->prepare($sql);
+# $self->{_sth_cache}{song_info}{$song} = $sth;
+# }
+#
+# $sth = $self->{_sth_cache}{song_info}{$song};
+# $sth->execute();
+#
+# my @song_info = $sth->fetchrow_hashref();
+# return (@song_info);
+#}
+
+
+1;
+__END__
diff --git a/lib/perl/Local/Ampache/Makefile.PL b/lib/perl/Local/Ampache/Makefile.PL
new file mode 100755
index 00000000..a51e5d54
--- /dev/null
+++ b/lib/perl/Local/Ampache/Makefile.PL
@@ -0,0 +1,7 @@
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+ 'NAME' => 'Local::Ampache',
+ 'VERSION_FROM' => 'Ampache.pm', # finds $VERSION
+);
diff --git a/lib/preferences.php b/lib/preferences.php
new file mode 100644
index 00000000..b6c6e0c9
--- /dev/null
+++ b/lib/preferences.php
@@ -0,0 +1,281 @@
+<?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 Preferences Library
+ @discussion This contains all of the functions needed for the preferences
+*/
+
+/*!
+ @function get_site_preferences
+ @discussion gets all of the preferences for this Ampache site
+*/
+function get_site_preferences() {
+
+ $results = array();
+
+ $sql = "SELECT preferences.name, preferences.type, user_preference.value, preferences.description FROM preferences,user_preference " .
+ " WHERE preferences.id=user_preference.preference AND user_preference.user = '0' ORDER BY `type`,`name`";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[] = $r;
+ }
+
+ return $results;
+
+} // get_site_preferences
+
+/*!
+ @function set_site_preferences
+ @discussion sets the conf() function with the current site preferences from the db
+*/
+function set_site_preferences() {
+
+ $results = array();
+
+ $sql = "SELECT preferences.name,user_preference.value FROM preferences,user_preference WHERE user='0' AND user_preference.preference=preferences.id";
+ $db_results = @mysql_query($sql, dbh());
+
+ while ($r = @mysql_fetch_object($db_results)) {
+ $results[$r->name] = $r->value;
+ } // db results
+
+ if (strlen($results['theme_name']) > 0) {
+ $results['theme_path'] = "/themes/" . $results['theme_name'];
+ }
+
+ conf($results,1);
+
+} // set_site_preferences
+
+/*!
+ @function clean_preference_name
+ @discussion s/_/ /g & upper case first
+*/
+function clean_preference_name($name) {
+
+ $name = str_replace("_"," ",$name);
+ $name = ucwords($name);
+
+ return $name;
+
+} // clean_preference_name
+
+/*!
+ @function update_preferences
+ @discussion grabs the current keys that should be added
+ and then runs throught $_REQUEST looking for those
+ values and updates them for this user
+*/
+function update_preferences($pref_id=0) {
+
+ $pref_user = new User(0,$pref_id);
+
+ /* Get current keys */
+ $sql = "SELECT id,name,type FROM preferences";
+ if ($pref_id != '0') { $sql .= " WHERE type='user'"; }
+ $db_results = mysql_query($sql, dbh());
+
+ // Collect the current possible keys
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[] = array('id' => $r->id, 'name' => $r->name,'type' => $r->type);
+ }
+
+ foreach ($results as $data) {
+ /* Get the Value from POST/GET var called $data */
+ //FIXME: Do this right....
+ $type = $data['type'];
+ $name = $data['name'];
+ $apply_to_all = "check_" . $data['name'];
+ $id = $data['id'];
+ $value = sql_escape(scrub_in($_REQUEST[$name]));
+
+ if (has_preference_access($name) AND isset($_REQUEST[$name])) {
+ $sql = "UPDATE user_preference SET `value`='$value' WHERE preference='$id' AND user='$pref_id'";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Check to see if this is a theme, and if so run the theme updater */
+ if ($name == "theme_name" AND $pref_user->prefs['theme_name'] != $_REQUEST[$name]) {
+ set_theme_colors($value,$pref_id);
+ } // run theme updater
+
+ } // if access
+
+ if ($GLOBALS['user']->has_access(100) AND $_REQUEST[$apply_to_all] =='1') {
+ $sql = "UPDATE user_preference SET `value`='$value' WHERE preference='$id'";
+ $db_results = mysql_query($sql, dbh());
+ }
+ } // end foreach preferences
+
+
+} // update_preferences
+
+/*!
+ @function has_preference_access
+ @discussion makes sure that the user has sufficient
+ rights to actually set this preference, handle
+ as allow all, deny X
+ //FIXME:
+ // This is no longer needed, we just need to check against preferences.level
+*/
+function has_preference_access($name) {
+ global $user;
+
+ if (conf('demo_mode')) {
+ return false;
+ }
+
+ switch($name) {
+
+ case 'download':
+ case 'upload':
+ case 'quarantine':
+ case 'upload_dir':
+ case 'sample_rate':
+ case 'direct_link':
+ $level = 100;
+ break;
+ default:
+ $level = 1;
+ break;
+ } // end switch key
+ if ($user->has_access($level)) {
+ return true;
+ }
+
+ return false;
+
+} // has_preference_access
+
+
+/*!
+ @function create_preference_input
+ @discussion takes the key and then creates
+ the correct type of input for updating it
+*/
+function create_preference_input($name,$value) {
+
+ $len = strlen($value);
+ if ($len <= 1) { $len = 8; }
+
+ if (!has_preference_access($name)) {
+ if ($value == '1') {
+ echo "Enabled";
+ }
+ elseif ($value == '0') {
+ echo "Disabled";
+ }
+ else {
+ echo $value;
+ }
+ return;
+ } // if we don't have access to it
+
+ switch($name) {
+
+ case 'download':
+ case 'quarantine':
+ case 'upload':
+ case 'access_list':
+ case 'lock_songs':
+ case 'xml_rpc':
+ case 'force_http_play':
+ case 'no_symlinks':
+ case 'use_auth':
+ case 'access_control':
+ case 'demo_mode':
+ case 'direct_link':
+ if ($value == '1') { $is_true = "selected=\"selected\""; }
+ else { $is_false = "selected=\"selected\""; }
+ echo "<select name=\"$name\">\n";
+ echo "\t<option value=\"1\" $is_true>" . _("Enable") . "</option>\n";
+ echo "\t<option value=\"0\" $is_false>" . _("Disable") . "</option>\n";
+ echo "</select>\n";
+ break;
+ case 'play_type':
+ if ($value == 'local_play') { $is_local = "selected=\"selected\""; }
+ elseif ($value == 'icecast2') { $is_ice = "selected=\"selected\""; }
+ elseif ($value == 'downsample') { $is_down = "selected=\"selected\""; }
+ elseif ($value == 'mpd') { $is_mpd = "selected=\"selected\""; }
+ elseif ($value == 'slim') { $is_slim = "selected=\"selected\""; }
+ else { $is_stream = "selected=\"selected\""; }
+ echo "<select name=\"$name\">\n";
+ if (conf('allow_local_playback')) {
+ echo "\t<option value=\"local_play\" $is_local>" . _("Local") . "</option>\n";
+ }
+ if (conf('allow_stream_playback')) {
+ echo "\t<option value=\"stream\" $is_stream>" . _("Stream") . "</option>\n";
+ }
+ if (conf('allow_icecast_playback')) {
+ echo "\t<option value=\"icecast2\" $is_ice>" . _("IceCast") . "</option>\n";
+ }
+ if (conf('allow_downsample_playback')) {
+ echo "\t<option value=\"downsample\" $is_down>" . _("Downsample") . "</option>\n";
+ }
+ if (conf('allow_mpd_playback')) {
+ echo "\t<option value=\"mpd\" $is_mpd>" . _("Music Player Daemon") . "</option>\n";
+ }
+ if (conf('allow_slim_playback')) {
+ echo "\t<option value=\"slim\" $is_slim>" . _("SlimServer") . "</option>\n";
+ }
+
+ echo "</select>\n";
+ break;
+ case 'playlist_type':
+ $var_name = $value . "_type";
+ ${$var_name} = "selected=\"selected\"";
+ echo "<select name=\"$name\">\n";
+ echo "\t<option value=\"m3u\" $m3u_type>" . _("M3U") . "</option>\n";
+ echo "\t<option value=\"simple_m3u\" $simple_m3u_type>" . _("Simple M3U") . "</option>\n";
+ echo "\t<option value=\"pls\" $pls_type>" . _("PLS") . "</option>\n";
+ echo "\t<option value=\"asx\" $asx_type>" . _("Asx") . "</option>\n";
+ echo "</select>\n";
+ break;
+ case 'lang':
+ $var_name = $value . "_lang";
+ ${$var_name} = "selected=\"selected\"";
+ echo "<select name=\"$name\">\n";
+ echo "\t<option value=\"en_US\" $en_US_lang>" . _("English") . "</option>\n";
+ echo "\t<option value=\"de_DE\" $de_DE_lang>" . _("German") . "</option>\n";
+ echo "\t<option value=\"fr_FR\" $fr_FR_lang>" . _("French") . "</option>\n";
+ echo "\t<option value=\"tr_TR\" $tr_TR_lang>" . _("Turkish") . "</option>\n";
+ echo "</select>\n";
+ break;
+ case 'theme_name':
+ $themes = get_themes();
+ echo "<select name=\"$name\">\n";
+ foreach ($themes as $theme) {
+ $is_selected = "";
+ if ($value == $theme['path']) { $is_selected = "selected=\"selected\""; }
+ echo "\t<option value=\"" . $theme['path'] . "\" $is_selected>" . $theme['name'] . "</option>\n";
+ } // foreach themes
+ echo "</select>\n";
+ break;
+ default:
+ echo "<input type=\"text\" size=\"$len\" name=\"$name\" value=\"$value\" />";
+ break;
+
+ }
+
+} // create_preference_input
+
+?>
diff --git a/lib/rss.php b/lib/rss.php
new file mode 100644
index 00000000..efb6cba9
--- /dev/null
+++ b/lib/rss.php
@@ -0,0 +1,64 @@
+<?php
+/*
+
+ 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.
+
+*/
+/*!
+ @function show_now_playingRSS
+ @discussion creates a RSS fead for the now
+ playing information
+*/
+function show_now_playingRSS () {
+
+ $dbh = dbh();
+ $web_path = conf('web_path');
+ $rss_main_title = conf('rss_main_title');
+ $rss_main_description = conf('rss_main_description');
+ $rss_main_copyright = conf('rss_main_copyright');
+ $rss_main_language = conf('rss_main_language');
+ $rss_song_description = conf('rss_song_description');
+
+ $sql = "SELECT * FROM now_playing ORDER BY start_time DESC";
+
+ $db_result = mysql_query($sql, $dbh);
+ $today = date("d-m-Y");
+
+ echo "<rss version=\"0.91\">";
+ echo "<channel>\n<title>$rss_main_title</title>\n";
+ echo "<link>$web_path</link>\n<description>$rss_main_description</description>\n";
+ echo "<copyright>$rss_main_copyright</copyright>";
+ echo "<pubDate>$today</pubDate>\n<language>$rss_main_language</language>\n";
+
+ while ($r = mysql_fetch_object($db_result)) {
+ $song = new Song($r->song_id);
+ $song->format_song();
+ $user = get_user_byid($r->user_id);
+ if (is_object($song)) {
+ $artist = $song->f_artist;
+ $album = $song->get_album_name();
+ $text = "$artist - $song->f_title";
+ echo "<item> ";
+ echo " <title><![CDATA[$text]]></title> ";
+ echo " <link>$web_path/albums.php?action=show&amp;album=$song->album</link>";
+ echo " <description>$rss_song_description</description>";
+ echo " <pubDate>$today</pubDate>";
+ echo "</item>";
+ }
+ }
+
+ echo "</channel>\n</rss>";
+} // show_now_playingRSS
+?>
diff --git a/lib/search.php b/lib/search.php
new file mode 100644
index 00000000..54192750
--- /dev/null
+++ b/lib/search.php
@@ -0,0 +1,185 @@
+<?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.
+
+ This library handles all the searching!
+
+*/
+
+/*!
+ @function run_search
+ @discussion run a search, takes string,field,type and returns an array
+ of results of the correct type (song, album, artist)
+*/
+function run_search($string,$field,$type) {
+
+ // Clear this so it doesn't try any fanzy view mojo on us
+ unset($_SESSION['view_script']);
+
+ // Escape input string
+ $string = sql_escape($string);
+
+ // Switch on the field --> type and setup sql statement
+ switch ($field === 0 ? '': $field) {
+ case 'artist':
+ if ($type === 'fuzzy') {
+ $sql = "SELECT id FROM artist WHERE name LIKE '%$string%'";
+ }
+ else {
+ $sql = "SELECT id FROM artist WHERE name ='$string'";
+ }
+ $artists = get_artists($sql, 'format');
+ if ($artists) {
+ show_artists($artists);
+ }
+ else {
+ echo "<div class=\"error\" align=\"center\">" . _("No Results Found") . "</div>";
+ }
+ break;
+
+ case 'album':
+ if ($type === 'fuzzy') {
+ $sql = "SELECT id FROM album WHERE name LIKE '%$string%'";
+ }
+ else {
+ $sql = "SELECT id FROM album WHERE name='$string'";
+ }
+ $albums = get_albums($sql);
+ if (count($albums)) {
+ show_albums($albums);
+ }
+ else {
+ echo "<div class=\"error\" align=\"center\">" . _("No Results Found") . "</div>";
+ }
+ break;
+
+ case 'song_title':
+ if ($type === 'fuzzy') {
+ $sql = "SELECT id FROM song WHERE title LIKE '%$string%'";
+ }
+ else {
+ $sql = "SELECT id FROM song WHERE title = '$string'";
+ }
+ $song_ids = get_songs($sql, 'format');
+ if ($song_ids) {
+ show_songs($song_ids);
+ }
+ else {
+ echo "<div class=\"error\" align=\"center\">" . _("No Results Found") . "</div>";
+ }
+ break;
+
+ case 'song_genre':
+ if ($type === 'fuzzy') {
+ $sql = "SELECT song.id FROM song,genre WHERE song.genre=genre.id AND genre.name LIKE '%$string%'";
+ }
+ else {
+ $sql = "SELECT song.id FROM song,genre WHERE song.genre=genre.id AND genre.name='$string'";
+ }
+ $song_ids = get_songs($sql, 'format');
+ if ($song_ids) {
+ show_songs($song_ids);
+ }
+ else {
+ echo "<div class=\"error\" align=\"center\">" . _("No Results Found") . "</div>";
+ }
+ break;
+
+ case 'song_year':
+ if ($type === 'fuzzy') {
+ $sql = "SELECT song.id FROM song WHERE song.year LIKE '%$string%'";
+ }
+ else {
+ $sql = "SELECT song.id FROM song WHERE song.year='$string'";
+ }
+ $song_ids = get_songs($sql, 'format');
+ if ($song_ids) {
+ show_songs($song_ids);
+ }
+ else {
+ echo "<div class=\"error\" align=\"center\">" . _("No Results Found") . "</div>";
+ }
+ break;
+
+ case 'song_length':
+ case 'song_bitrate':
+ if ($type === 'fuzzy') {
+ $sql = "SELECT song.id FROM song WHERE song.bitrate LIKE '%$string%'";
+ }
+ else {
+ $sql = "SELECT song.id FROM song WHERE song.bitrate='$string'";
+ }
+ $song_ids = get_songs($sql, 'format');
+ if ($song_ids) {
+ show_songs($song_ids);
+ }
+ else {
+ echo "<div class=\"error\" align=\"center\">" . _("No Results Found") . "</div>";
+ }
+ break;
+
+ case 'song_min_bitrate':
+ $string = $string * 1000;
+ $sql = "SELECT song.id FROM song WHERE song.bitrate >= '$string'";
+ $song_ids = get_songs($sql, 'format');
+ if ($song_ids) {
+ show_songs($song_ids);
+ }
+ else {
+ echo "<div class=\"error\" align=\"center\">" . _("No Results Found") . "</div>";
+ }
+ break;
+
+ case 'song_comment':
+ if ($type === 'fuzzy') {
+ $sql = "SELECT song.id FROM song WHERE song.comment LIKE '%$string%'";
+ }
+ else {
+ $sql = "SELECT song.id FROM song WHERE song.comment='$string'";
+ }
+ $song_ids = get_songs($sql, 'format');
+ if ($song_ids) {
+ show_songs($song_ids);
+ }
+ else {
+ echo "<div class=\"error\" align=\"center\">" . _("No Results Found") . "</div>";
+ }
+ break;
+
+ case 'song_filename':
+ if ($type === 'fuzzy') {
+ $sql = "SELECT song.id FROM song WHERE song.file LIKE '%$string%'";
+ }
+ else {
+ $sql = "SELECT song.id FROM song WHERE song.file='$string'";
+ }
+ $song_ids = get_songs($sql, 'format');
+ if ($song_ids) {
+ show_songs($song_ids);
+ }
+ else {
+ echo "<div class=\"error\" align=\"center\">" . _("No Results Found") . "</div>";
+ }
+ break;
+
+ } // end switch
+
+} // run_search
+
+?>
diff --git a/lib/song.php b/lib/song.php
new file mode 100644
index 00000000..0e847ad9
--- /dev/null
+++ b/lib/song.php
@@ -0,0 +1,57 @@
+<?php
+/*
+
+ 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 Library
+ @discussion This library handles song related functions.... woohoo!
+ This library is defunt, please try use the song class if possible
+
+*/
+
+/*!
+ @function get_songs
+ @discussion pass a sql statement, and it gets full song info and returns
+ an array of the goods.. can be set to format them as well
+*/
+function get_songs($sql, $action=0) {
+
+ $db_results = mysql_query($sql, dbh());
+ while ($r = mysql_fetch_array($db_results)) {
+// $song_info = get_songinfo($r['id']);
+// if ($action === 'format') { $song = format_song($song_info); }
+// else { $song = $song_info; }
+ $results[] = $r['id'];
+ }
+
+ return $results;
+
+
+} // get_albums
+
+/*!
+ @function format_song
+ @discussion takes a song array and makes it html friendly
+*/
+function format_song($song) {
+
+ return $song;
+
+} // format_song
+
+
+?>
diff --git a/lib/themes.php b/lib/themes.php
new file mode 100644
index 00000000..ca4a92c7
--- /dev/null
+++ b/lib/themes.php
@@ -0,0 +1,124 @@
+<?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.
+
+*/
+
+/*!
+ @function get_themes()
+ @discussion this looks in /themes and pulls all of the
+ theme.cfg.php files it can find and returns an
+ array of the results
+*/
+function get_themes() {
+
+ /* Open the themes dir and start reading it */
+ $handle = @opendir(conf('prefix') . "/themes");
+
+ if (!is_resource($handle)) {
+ if (conf('debug')) { log_event($_SESSION['userdata']['username'],'theme',"Error unable to open Themes Directory"); }
+ }
+
+ $results = array();
+
+ while ($file = readdir($handle)) {
+
+ $full_file = conf('prefix') . "/themes/" . $file;
+ /* See if it's a directory */
+ if (is_dir($full_file) AND substr($file,0,1) != ".") {
+ $config_file = $full_file . "/theme.cfg.php";
+ /* Open the theme.cfg.php file */
+ $r = read_config($config_file);
+ $r['path'] = $file;
+ $results[] = $r;
+ }
+
+ } // end while directory
+
+ return $results;
+
+} // get_themes
+
+/*!
+ @function get_theme
+ @discussion get a single theme and read the config file
+ then return the results
+*/
+function get_theme($name) {
+
+ $config_file = conf('prefix') . "/themes/" . $name . "/theme.cfg.php";
+ $results = read_config($config_file);
+ $results['path'] = $name;
+ return $results;
+
+} // get_theme
+
+/*!
+ @function set_theme
+ @discussion Resets all of the colors for this theme
+*/
+function set_theme_colors($theme_name,$user_id) {
+
+ /* We assume if we've made it this far we've got the right to do it
+ This could be dangerous but eah!
+ */
+ $theme = get_theme($theme_name);
+ if (!count($theme['color'])) { return false; }
+
+ foreach ($theme['color'] as $key=>$color) {
+
+ $sql = "SELECT id FROM preferences WHERE name='" . sql_escape($key) . "'";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_array($db_results);
+
+ $sql = "UPDATE user_preference SET `value`='" . sql_escape($color) . "' WHERE `user`='" . $user_id . "' AND " .
+ " preference='" . $results[0] . "'";
+ $db_results = mysql_query($sql, dbh());
+
+ } // theme colors
+
+} // set_theme_colors
+
+/*!
+ @function set_theme
+ @discussion this sets the needed vars for the theme
+*/
+function set_theme() {
+
+ if (strlen(conf('theme_name')) > 0) {
+ $theme_path = "/themes/" . conf('theme_name');
+ conf(array('theme_path'=>$theme_path),1);
+ }
+
+} // set_theme
+
+/*!
+ @function get_theme_author
+ @discussion returns the author of this theme
+*/
+function get_theme_author($theme_name) {
+
+ $theme_path = conf('prefix') . "/themes/" . conf('theme_name') . "/theme.cfg.php";
+ $results = read_config($theme_path);
+
+ return $results['author'];
+
+} // get_theme_author
+?>
diff --git a/lib/ui.php b/lib/ui.php
new file mode 100644
index 00000000..bd1bb882
--- /dev/null
+++ b/lib/ui.php
@@ -0,0 +1,437 @@
+<?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 UI Function Library
+ This contains functions that are generic, and display information
+ things like a confirmation box, etc and so forth
+*/
+
+/*!
+ @function show_confirmation
+ @discussion shows a confirmation of an action
+ @param $next_url Where to go next
+ @param $title The Title of the message
+ @param $text The details of the message
+*/
+function show_confirmation($title,$text,$next_url) {
+
+ if (substr_count($next_url,conf('web_path'))) {
+ $path = $next_url;
+ }
+ else {
+ $path = conf('web_path') . "/$next_url";
+ }
+
+ require (conf('prefix') . "/templates/show_confirmation.inc.php");
+
+} // show_confirmation
+
+/*!
+ @function set_preferences
+ @discussion legacy function...
+ //FIXME: Remove References
+*/
+function set_preferences() {
+
+ get_preferences();
+ return true;
+
+} // set_preferences
+
+/*!
+ @function get_preferences
+ @discussion reads this users preferences
+*/
+function get_preferences($username=0) {
+
+ /* Get System Preferences first */
+ $sql = "SELECT preferences.name,user_preference.value FROM preferences,user_preference WHERE user_preference.user='0' " .
+ " AND user_preference.preference = preferences.id AND preferences.type='system'";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[$r->name] = $r->value;
+ } // end while sys prefs
+
+ conf($results, 1);
+
+ unset($results);
+
+ if (!$username) { $username = $_SESSION['userdata']['username']; }
+
+ $user = new User($username);
+
+ $sql = "SELECT preferences.name,user_preference.value FROM preferences,user_preference WHERE user_preference.user='$user->id'" .
+ " AND user_preference.preference=preferences.id";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[$r->name] = $r->value;
+ }
+
+ unset($results['user'], $results['id']);
+
+ conf($results, 1);
+
+} // get_preferences
+
+/*!
+ @function flip_class
+ @discussion takes an array of 2 class names
+ and flips them back and forth and
+ then echo's out [0]
+*/
+function flip_class($array=0) {
+
+ static $classes = array();
+
+ if ($array) {
+ $classes = $array;
+ }
+ else {
+ $classes = array_reverse($classes);
+ return $classes[0];
+ }
+
+} // flip_class
+
+/*!
+ @function clear_now_playing
+ @discussion Clears the now playing information incase something has
+ gotten stuck in there
+*/
+function clear_now_playing() {
+
+ $sql = "DELETE FROM now_playing";
+ $db_results = mysql_query($sql, dbh());
+
+ return true;
+
+} // clear_now_playing
+
+/*!
+ @function show_tool_box
+ @discussion shows the toolbox
+*/
+function show_tool_box ($title, $items) {
+
+ include(conf('prefix') . "/templates/tool_box.inc");
+
+}// show_tool_box
+
+/*!
+ @function show_box
+ @discussion shows a generic box
+*/
+function show_box($title,$items) {
+
+ include(conf('prefix') . "/templates/show_box.inc");
+
+} // show_box
+
+/*!
+ @function show_menu_items
+ @discussion shows menu items
+*/
+function show_menu_items ($high) {
+
+ include(conf('prefix') . "/templates/menu.inc");
+
+} // show_menu_items
+
+/*!
+ @function _
+ @discussion checks to see if the alias _ is defined
+ if it isn't it defines it as a simple return
+*/
+if (!function_exists('_')) {
+ function _($string) {
+
+ return $string;
+
+ } // _
+} // if _ isn't defined
+
+/*!
+ @function show_playlist_menu
+ @discussion playlist functions
+*/
+function show_playlist_menu () {
+
+ echo "<br /><span class=\"header2\">" . _("Playlist Actions") . ": <a href=\"" . conf('web_path') . "/playlist.php?action=new\">" . _("New") ."</a> | ";
+ echo "<a href=\"" . conf('web_path') . "/playlist.php\"> " . _("View All") . "</a> | ";
+ echo "<a href=\"" . conf('web_path') . "/playlist.php?action=show_import_playlist\"> " . _("Import") . "</a>";
+ echo "</span><br /><br />";
+
+} // show_playlist_menu
+
+/*!
+ @function show_admin_menu
+ @discussion shows the admin menu
+*/
+function show_admin_menu ($admin_highlight) {
+ include(conf('prefix') . "/templates/admin_menu.inc");
+} // show_admin_menu
+
+/*!
+ @function access_denied
+ @discussion throws an error if they try to do something
+ that they aren't allowed to
+*/
+function access_denied() {
+
+ show_template('style');
+ show_footer();
+ echo "<br /><br /><br />";
+ echo "<div class=\"fatalerror\">Error Access Denied</div>\n";
+ show_footer();
+ exit();
+
+} // access_denied
+
+/*!
+ @function show_users
+ @discussion shows all users (admin function)
+*/
+function show_users () {
+
+ $dbh = dbh();
+
+ // Setup the View Ojbect
+ $view = new View();
+ $view->import_session_view();
+
+ // if we are returning
+ if ($_REQUEST['keep_view']) {
+ $view->initialize();
+ }
+ // If we aren't keeping the view then initlize it
+ else {
+ $sql = "SELECT username FROM user";
+ $db_results = mysql_query($sql, $dbh);
+ $total_items = mysql_num_rows($db_results);
+ if ($match != "Show_all") { $offset_limit = $_SESSION['userdata']['offset_limit']; }
+ $view = new View($sql, 'admin/users.php','fullname',$total_items,$offset_limit);
+ }
+
+ $db_result = mysql_query($view->sql, $dbh);
+
+ require(conf('prefix') . "/templates/show_users.inc");
+
+} // show_users()
+
+
+/*!
+ @function return_referer
+ @discussion returns the script part of the
+ referer address passed by the web browser
+ this is not %100 accurate
+*/
+function return_referer() {
+
+ $web_path = substr(conf('web_path'),0,strlen(conf('web_path'))-1-strlen($_SERVER['SERVER_PORT'])) . "/";
+ $next = str_replace($web_path,"",$_SERVER['HTTP_REFERER']);
+
+ // If there is more than one :// we know it's fudged
+ // and just return the index
+ if (substr_count($next,"://") > 1) {
+ return "index.php";
+ }
+
+ return $next;
+
+} // return_referer
+
+/*!
+ @function show_alphabet_list
+ @discussion shows the A-Z,0-9 lists for
+ albums and artist pages
+*/
+function show_alphabet_list ($type,$script="artist.php",$selected="false") {
+
+ $list = array(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,1,2,3,4,5,6,7,8,9,"0");
+
+ $style_name = "style_" . strtolower($selected);
+ ${$style_name} = "style=\"font-weight:bold;\"";
+
+ echo "<div class=\"alphabet\">";
+ foreach ($list as $l) {
+ $style_name = "style_" . strtolower($l);
+ echo "<a href=\"". conf('web_path') ."/$script?action=match&amp;match=$l\" " . ${$style_name} . ">$l</a> | \n";
+ }
+
+ echo " <a href=\"". conf('web_path') ."/$script?action=match&amp;match=Browse\" $style_browse>" . _("Browse") . "</a> | \n";
+ if ($script == "albums.php") {
+ echo " <a href=\"". conf('web_path') ."/$script?action=match&amp;match=Show_missing_art\" $style_show_missing_art>" . _("Show w/o art") . "</a> | \n";
+ } // if we are on the albums page
+
+ echo " <a href=\"". conf('web_path') ."/$script?action=match&amp;match=Show_all\" $style_show_all>" . _("Show all") . "</a>";
+
+ echo "</div>\n";
+} // show_alphabet_list
+
+/*!
+ @function show_local_control
+ @discussion shows the controls
+ for localplay
+*/
+function show_local_control () {
+
+ require_once(conf('prefix') . "/templates/show_localplay.inc");
+
+} // show_local_control
+
+/*!
+ @function truncate_with_ellipse
+ @discussion truncates a text file to specified length by adding
+ thre dots (ellipse) to the end
+ (Thx Nedko Arnaudov)
+*/
+function truncate_with_ellipse($text, $max=27) {
+
+ /* If we want it to be shorter than three, just throw it back */
+ if ($max > 3) {
+ /* Make sure the functions exist before doing the iconv mojo */
+ if (function_exists('iconv') && function_exists('iconv_substr') && function_exists('iconv_strlen')) {
+ if (iconv_strlen($text, conf('site_charset')) > $max) {
+ $text = iconv_substr($text, 0, $max-3, conf('site_charset'));
+ $text .= iconv("ISO-8859-1", conf('site_charset'), "...");
+ }
+ }
+ /* Do normal substr if we don't have iconv */
+ else {
+ if (strlen($text) > $max) {
+ $text = substr($text,0,$max-3)."...";
+ }
+ } // else no iconv
+ } // else greater than 3
+
+ return $text;
+} // truncate_with_ellipse
+
+/*!
+ @function show_footer
+ @discussion shows the footer of the page
+*/
+function show_footer() {
+ $class = "table-header";
+ echo "<br /><br /><br /><div class=\"$class\" style=\"border: solid thin black;\">&nbsp</div>";
+} // show_footer
+
+/*!
+ @function show_now_playing
+ @discussion shows the now playing template
+*/
+function show_now_playing() {
+
+ $dbh = dbh();
+ $web_path = conf('web_path');
+ $results = get_now_playing();
+ require (conf('prefix') . "/templates/show_now_playing.inc");
+
+} // show_now_playing
+
+/*!
+ @function show_user_registration
+ @discussion this function is called for a new user
+ registration
+ @author Terry
+*/
+//function show_user_registration ($id, $username, $fullname, $email, $access, $type, $error) {
+//FIXME: See above
+function show_user_registration ($values=array()) {
+
+ require (conf('prefix') . "/templates/show_user_registration.inc.php");
+
+} // show_user_registration
+
+/*!
+ @function show_edit_profile
+ @discussion shows a single user profile for editing
+*/
+function show_edit_profile($username) {
+
+ $this_user = new User($username);
+
+ require (conf('prefix') . "/templates/show_user.inc.php");
+
+} // show_edit_profile
+
+/*!
+ @function show_playlist
+ @discussion this shows the current playlist
+*/
+function show_playlist($playlist_id) {
+
+ /* Create the Playlist */
+ $playlist = new Playlist($playlist_id);
+ $song_ids = $playlist->get_songs();
+
+ if (count($song_ids) > 0) {
+ show_songs($song_ids, $playlist->id);
+ }
+ else {
+ echo "<p>" . _("No songs in this playlist.") . "</p>\n";
+ }
+
+} // show_playlist
+
+/*!
+ @function show_play_selected
+ @discussion this shows the playselected/add to playlist
+ box, which includes a little javascript
+*/
+function show_play_selected() {
+
+ require (conf('prefix') . "/templates/show_play_selected.inc.php");
+
+} // show_play_selected
+
+/*!
+ @function get_now_playing
+ @discussion gets the now playing information
+*/
+function get_now_playing() {
+
+ $sql = "SELECT song_id,user_id FROM now_playing ORDER BY start_time DESC";
+ $db_results = mysql_query($sql, dbh());
+ while ($r = mysql_fetch_assoc($db_results)) {
+ $song = new Song($r['song_id']);
+ $song->format_song();
+ $np_user = new User(0,$r['user_id']);
+ $results[] = array('song'=>$song,'user'=>$np_user);
+ } // end while
+ return $results;
+
+} // get_now_playing
+
+/*!
+ @function show_clear
+ @discussion this is a hack because of the float mojo
+*/
+function show_clear() {
+
+ echo "\n<div style=\"clear:both;\">&nbsp;</div>\n";
+
+} // show_clear
+
+?>
diff --git a/lib/xmlrpc.php b/lib/xmlrpc.php
new file mode 100644
index 00000000..7b810dd6
--- /dev/null
+++ b/lib/xmlrpc.php
@@ -0,0 +1,143 @@
+<?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 XML-RPC Library
+ @discussion If you want an honest answer NFC. Copy and paste baby!
+*/
+
+/*!
+ @function remote_server_query
+ @discussion don't ask don't tell
+*/
+function remote_server_query($m) {
+
+ $result = array();
+
+ // we only want to send the local entries
+ $sql = "SELECT name FROM catalog WHERE catalog_type='local'";
+ $db_result = mysql_query($sql, dbh());
+
+ while ( $i = mysql_fetch_row($db_result) ) {
+ $result[] = $i;
+ }
+
+
+ set_time_limit(0);
+ $encoded_array = new xmlrpcval($result);
+ log_event($_SESSION['userdata']['username'],'xml-rpc_encoded',$encoded_array);
+ return new xmlrpcresp($encoded_array);
+ return $result;
+
+} // remote_server_query
+
+/*!
+ @function remote_song_query
+ @discussion return all local songs and their
+ information
+*/
+function remote_song_query() {
+
+
+ //FIXME: We should add catalog level access control
+
+ // Get me a list of all local catalogs
+ $sql = "SELECT catalog.id FROM catalog WHERE catalog_type='local'";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = array();
+ //FIXME: enabled --> smallint(1) T/F boolean mojo
+ $sql = "SELECT song.id FROM song WHERE song.status='enabled' AND";
+
+ // Get the catalogs and build the query!
+ while ($r = mysql_fetch_object($db_results)) {
+ if (preg_match("/catalog/",$sql)) {
+ $sql .= " OR song.catalog='$r->id'";
+ }
+ else {
+ $sql .= " song.catalog='$r->id'";
+ }
+ } // build query
+
+ $db_results = mysql_query($sql, dbh());
+
+ // Recurse through the songs and build a results
+ // array that is base64_encoded
+ while ($r = mysql_fetch_object($db_results)) {
+
+ $song = new Song($r->id);
+ $song->album = $song->get_album_name();
+ $song->artist = $song->get_artist_name();
+ $song->genre = $song->get_genre_name();
+
+ // Format the output
+ $output = '';
+ $output = $song->artist . "::" . $song->album . "::" . $song->title . "::" . $song->comment .
+ "::" . $song->year . "::" . $song->bitrate . "::" . $song->rate . "::" . $song->mode .
+ "::" . $song->size . "::" . $song->time . "::" . $song->track . "::" . $song->genre . "::" . $r->id;
+ $output = base64_encode($output);
+ $results[] = $output;
+
+ // Prevent Timeout
+ set_time_limit(0);
+
+ } // while songs
+
+ set_time_limit(0);
+ $encoded_array = old_xmlrpc_encode($results);
+ return new xmlrpcresp($encoded_array);
+
+} // remote_song_query
+
+/*!
+ @function remote_server_denied
+ @discussion Access Denied Sucka!
+*/
+function remote_server_denied() {
+
+ $result = array();
+
+ $result['access_denied'] = "Access Denied: Sorry, but " . $_SERVER['REMOTE_ADDR'] . " does not have access to " .
+ "this server's catalog. Please make sure that you have been added to this server's access list.\n";
+
+ $encoded_array = old_xmlrpc_encode($result);
+ return new xmlrpcresp($encoded_array);
+
+} // remote_server_deniee
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+?>