<?
////////////////////////////////////////////////////////////////////////
/*SMI - SHOUTcast Management Interface
A web based shoutcast server management program
Founding Author: Scott D. Harvanek <scotth@sourcemirrors.org>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.*/
////////////////////////////////////////////////////////////////////////

// id3.class.php utilized in scan_directory_recursively()
/***********************************************************
* Class:       ID3
* Version:     1.0
* Date:        Janeiro 2004
* Author:      Tadeu F. Oliveira
* Contact:     tadeu_fo@yahoo.com.br
* Use:         Extract ID3 Tag information from mp3 files
***********************************************************/

//////////////////////////////////////////////////
//
//Include our configuration file and db class
//
//////////////////////////////////////////////////
require_once('db.inc.php');

//////////////////////////////////////////////////
//
// Create connection with MySQLDB class
//
//////////////////////////////////////////////////
function dbConnect()
{
  $dataset = new MySQLDB(DB_SERVER, DB_NAME, DB_USERNAME, DB_PASSWORD);
  return $dataset;
}

//////////////////////////////////////////////////
//
// Function to verify a user login
//
//////////////////////////////////////////////////
function login_check($username,$password) {
  $db = dbConnect();
  $password = md5($password);
  $cond = array('username' => sprintf("%s", mysql_real_escape_string($username)));
  $row = $db->getRow('members', $cond);
  if($username == $row['username'] && $password == $row['password']) {
    $login_check = true;
  } else {
    $login_check = false;
  }
  return $login_check;
}

//////////////////////////////////////////////////
//
// Here we setup our function to connect to our MySQL server
// FIXME: Can be removed when db class use is implemented
//////////////////////////////////////////////////
function connectdb() {
  require('config.php');
  global $dbhost, $dbuser, $dbpass, $dbname, $db;
  $db = mysql_connect("$dbhost", "$dbuser", "$dbpass") or die('Script Could not connect to database');
  mysql_select_db("$dbname",$db);
  return $db;
}

//////////////////////////////////////////////////
//
//Here is the disconnect function
// FIXME: Can be removed when db class use is implemented
//////////////////////////////////////////////////
function disconnectdb() {
  //global $db;
  //if($db != false) {
  //  mysql_close($db);
  //}
  //$db = false;
}

//////////////////////////////////////////////////
//
// Function to add event to log database table
//
//////////////////////////////////////////////////

function addevent($user, $event) {
  $timestamp = "".strftime('%T')." ".date('Y-m-d')."";
  $db = dbConnect();
  $insert = array(	'event_user'	=> 	$user,
			'event'		=>	$user.$event,
			'timestamp'	=>	$timestamp	);
  $db->insert('events', $insert);
}

//////////////////////////////////////////////////
//
// Function to check if running OS is Windows
//
//////////////////////////////////////////////////

function iswin() {
  if (strtoupper(substr(PHP_OS, 0, 3)) == "WIN") {
    return true;
  } else {
    return;
  }
}

//////////////////////////////////////////////////
//
// Function to GET a web URL and return the reponse
//
//////////////////////////////////////////////////
function webget($url) {
  $handle = curl_init($url);

  curl_setopt ($handle, CURLOPT_HEADER, 0);
  curl_setopt ($handle, CURLOPT_USERAGENT, "User-Agent: SMI (Mozilla Compatible)");
  //curl_setopt ($handle, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt ($handle, CURLOPT_CONNECTTIMEOUT, 120);
  curl_setopt ($handle, CURLOPT_TIMEOUT, 120);
  ob_start();
  curl_exec($handle);
  curl_close($handle);
  $contents = ob_get_contents();
  ob_end_clean();
  return $contents;
}

//////////////////////////////////////////////////
//
// Function to check the stats of a server for 
// listeners, peak listeners and max listeners
//
//////////////////////////////////////////////////

function checklistener($port, $id) {
  $config = settings();
  $dataset = webget($config['host_addr'].":".$port."/7.html");
  if($dataset == "") {
    echo "N/A";
  } else {
    $entries = explode(",",$dataset);
    $listener=$entries[0];
    $status=$entries[1];
    $listenerpeak = $entries[2];
    $maxlisteners=$entries[3];
    $totallisteners=$entries[4];
    $bitrate=$entries[5];
    $songtitel=$entries[6];
    echo "$listener / $listenerpeak / $maxlisteners";
  } 
} 

//////////////////////////////////////////////////
//
// Function to get aggregate listeners
//
//////////////////////////////////////////////////
function getagg() {
  $db = dbConnect();
  $config = settings();
  $null = NULL;
  $servers = $db->getRows('servers','','PortBase, id', 'PortBase', 'ASC');
  foreach ($servers as $row) {
    $port = $row[0];
    $id = $row[1];
    $dataset = webget($config['host_addr'].":".$port."/7.html");
    if ($dataset == "") {
      $db->update('servers', array('listeners' => '0'), array('id' => $id));
    } else {
      $dataset = preg_replace("/.*<body>/", "", $dataset);
      $dataset = preg_replace("/<\/body>.*/", "", $dataset);
      $entries = explode(",",trim($dataset));
      $listener = $entries[0];
      $db->update('servers', array('listeners' => $listener), array('PortBase' => $port));
    } 
    $row = $db->getRow("SELECT SUM(listeners) FROM servers");
    return "$row[0]\n0\n".$null."\n".$config['host_addr'];
  }
}


//////////////////////////////////////////////////
//
// function called every time a server is added or 
// deleted so that it can generate a new mrtg configuration file
//
//////////////////////////////////////////////////
function generatemrtg() {
  // Spawn MySQLDB
  $db = dbConnect();
  // Get settings from database
  $config = settings();
  // Stop MRTG in case it is running
  stopmrtg();
  
  // (Re)generate new mrtg.cfg and restart if MRTG is enabled and we have servers
  if ($config['mrtg'] == "on" && $db->numRows('servers') > 0) {
    $db = dbConnect();
    deletefile($config['smi_path']."/mrtg/mrtg.cfg");

    $header = "#MRTG Config File\n"
     . "WorkDir: ".$config['smi_path']."/mrtg\n"
     . "Interval: ".$config['mrtg_interval']."\n"
     . "RunAsDaemon: yes\n\n";
    $fd = fopen($config['smi_path']."/mrtg/mrtg.cfg", "w+");
    fputs($fd, $header . "\n\n");
    fclose($fd);
    
      $servers = $db->getRows('servers','','PortBase, id', 'PortBase');
      foreach ($servers as $row) {
        $port = $row[0];
        $id = $row[1];
        $header = "#MRTG Config for port ".$port."\n"
        . "WithPeak[$port$id]: ymw\n"
        . "Target[$port$id] : `php ".$config['smi_path']."/mrtg/getlisteners.php ".$port." ".$id." ".$config['host_addr']."`\n"
        . "Title[$port$id]: Total $port Listeners\n"
        . "PageTop[$port$id]: <H1> Listeners on port $port (server #$id)</H1>\n"
        . "MaxBytes[$port$id]: 100\n"
        . "XSize[$port$id]: 500\n"
        . "YSize[$port$id]: 150\n"
        . "ShortLegend[$port$id]: listeners\n"
        . "YLegend[$port$id]: total listeners\n"
        . "Legend1[$port$id]:\n"
        . "Legend2[$port$id]:\n"
        . "Legend3[$port$id]:\n"
        . "LegendI[$port$id]: tuned in:\n"
        . "LegendO[$port$id]:\n"
        . "Options[$port$id]: gauge,growright,nopercent\n";
        $fd = fopen($config['smi_path']."/mrtg/mrtg.cfg", "a+");
        fputs($fd, $header . "\n\n");
        fclose($fd);
      }

      // Here we form the aggregate graph

      $header = "#MRTG Aggregate Config File\n"
      . "WithPeak[aggregate]: ymw\n"
      . "Target[aggregate]: `php ".$config['smi_path']."/mrtg/getTotal.php`\n"
      . "Title[aggregate]: Total Listeners\n"
      . "PageTop[aggregate]: <H1> Listeners on all ports </H1>\n"
      . "MaxBytes[aggregate]: 100\n"
      . "XSize[aggregate]: 500\n"
      . "YSize[aggregate]: 150\n"
      . "ShortLegend[aggregate]: listeners\n"
      . "YLegend[aggregate]: total listeners\n"
      . "Legend1[aggregate]:\n"
      . "Legend2[aggregate]:\n"
      . "Legend3[aggregate]:\n"
      . "LegendI[aggregate]: tuned in:\n"
      . "LegendO[aggregate]:\n"
      . "Options[aggregate]: gauge,growright,nopercent\n";
      $fd = fopen($config['smi_path']."/mrtg/mrtg.cfg", "a+");
      fputs($fd, $header."\n\n");
      fclose($fd);

      // Start MRTG
      startmrtg();
  }

}
                 

//////////////////////////////////////////////////
//
// function to start the MRTG daemon
//
//////////////////////////////////////////////////
function startmrtg() {
  $config = settings();
  if (iswin()) {
    $output = start_proc("wperl ".$_SERVER['DOCUMENT_ROOT']."/mrtg/bin/mrtg --logging=eventlog ".$config['smi_path']."/mrtg/mrtg.cfg \n");
  } else {
    $output =shell_exec("nohup env LANG=C /usr/bin/mrtg ".$config['smi_path']."/mrtg/mrtg.cfg > /dev/null & echo $!");
  }
  return $output;
}

//////////////////////////////////////////////////
//
// function to stop MRTG from running
//
//////////////////////////////////////////////////
function stopmrtg() {
  $config = settings();
  ( iswin() ) ? ( $pidfile = 'mrtg.cfg_l' ) : ( $pidfile = 'mrtg.pid' );
  if ($mrtgpid = getcontent($config['smi_path']."/mrtg/".$pidfile)) {
    if (iswin()) {
      proc_kill(trim($mrtgpid));
    } else {
      shell_exec("kill -9 ".trim($mrtgpid));
    }
  }
  // Delete MRTG PID file
  deletefile($config['smi_path']."/mrtg/".$pidfile);
  return 1;
}

//////////////////////////////////////////////////
//
// function to clean up the mrtg files from a deleted server
//
//////////////////////////////////////////////////
function cleanmrtg($port) {
  $config = settings();
  $path = $config['smi_path']."/mrtg";
  if ($handle = opendir($path)) {
    // Read contents of 'mrtg/' directory
    while ($file=readdir($handle)) {
      if (is_file($file) && substr($file, 0, strlen($port)) == $port) {
        // If filename begins with $port, delete it
        deletefile($path."/".$file);
      }
    }
  }
}

//////////////////////////////////////////////////
//
// function to create/edit crontab file
//
//////////////////////////////////////////////////
function updatecrontab() {
//  USE RunAsDaemon: yes INSTEAD
//  $config = settings();
//  $crontab = $config['smi_path']."/mrtg/mrtg.cron";
//  $mrtg = "*/".$config['mrtg_interval']." * * * * env LANG=C /usr/bin/mrtg ".$config['smi_path']."/mrtg/mrtg.cfg";
/*
  // Remove old crontab if it exists
  if (file_exists($crontab)) {
    unlink($crontab);
  }

  // Set MRTG update enabled or disabled based on settings
  ($config['mrtg'] == "on") ? ($mrtg = $mrtg) : ($mrtg = "# ".$mrtg);

  // Create new crontab file
  $fd = fopen($crontab, "a+");
    fputs($fd, $mrtg."\n");
  fclose($fd);
  
  // Process CRON changes
  shell_exec("crontab ".$crontab);
*/ 
}

//////////////////////////////////////////////////
//
// Function to fetch configuration settings group
//
//////////////////////////////////////////////////
function confgroups() {
  $db = dbConnect();
  return $db->getRows('config_groups');
}

//////////////////////////////////////////////////
//
// Function to fetch settings for a particular group
//
//////////////////////////////////////////////////
function groupsettings($group) {
  $db = dbConnect();
  return $db->getRows('config', array('groupid' => $group));
}

//////////////////////////////////////////////////
//
// Function to fetch config_sets for a setting
//
//////////////////////////////////////////////////
function settingoptions($setting) {
  $db = dbConnect();
  return $db->getRows('config_sets', array('configid' => $setting));
}

//////////////////////////////////////////////////
//
// Function to update settings from an array set
//
//////////////////////////////////////////////////
function updatesettings($update) {
  $db = dbConnect();
  foreach ($update as $setting => $value)
  {
     $db->update('config', array('value' => $value), array('setting' => $setting));
  }

  /*
  / Stuff that should be done each time settings are updated
  */

  generatemrtg();  // Build mrtg.cfg and restart MRTG if enabled
}

//////////////////////////////////////////////////
//
// Function to return all settings and values as an associative array
// getRows(<table>, [<condition array> [, <fields> [, <orderfields> [, <ordertype> [, <fetch_type>]]]]])
//////////////////////////////////////////////////
function settings() {
  $db = dbConnect();
  // Get settings from the config table and place them in array $return	
  $settings = $db->getRows('config', '', 'setting, value', 'id', 'ASC', MYSQL_ASSOC);
  foreach ($settings as $id => $values)
  {
    $return[$values['setting']] = $values['value'];
  }
  return $return;
}


//////////////////////////////////////////////////
//
// Add user function
//
//////////////////////////////////////////////////
function adduser($username, $password, $fname, $lname, $email, $level) {
  $db = dbConnect();

  $insert = array(	'username'	=>	$username,
			'password'	=>	$password,
			'fname'		=>	$fname,
			'lname'		=>	$lname,
			'email'		=>	$email,
			'access'	=>	$level	);

  $db->insert('members', $insert);
  addevent($_SESSION['username'], " added ".$username." as a registered user");
  echo "Added ".$username." successfully!";
}

//////////////////////////////////////////////////
//
// Delete user function
//
//////////////////////////////////////////////////
function deluser($id, $username) {
  $db = dbConnect();
  $db->delete('members', array('user_id' => $id));
  addevent($_SESSION['username'], " deleted user ".$username);
  echo "Deleted ".$username." successfully!";
}

//////////////////////////////////////////////////
//
// Edit user function
//
//////////////////////////////////////////////////
function edituser($id, $username, $password, $fname, $lname, $email, $level) {
  $db = dbConnect();

  $update = array(	'username'	=>	$username,
			'password'	=>	$password,
			'fname'		=>	$fname,
			'lname'		=>	$lname,
			'email'		=>	$email,
			'access'	=>	$level	);

  $db->update('members', $update, array('user_id' => $id));
  addevent($_SESSION['username'], " updated ".$username);
  echo "Updated ".$username." successfully!";
}

//////////////////////////////////////////////////
//
// Get user access level function
//
//////////////////////////////////////////////////
function useraccess($username) {
  $db = dbConnect();
  $row = $db->getRow('members', array('username' => $username));
  return $row['access'];
}


//////////////////////////////////////////////////
//
// Get user id function
//
//////////////////////////////////////////////////
function getuid($username) {
  $db = dbConnect();
  $row = $db->getRow('members', array('username' => $username));
  return $row['user_id'];
}

/////////////////////////////////////////////////
//
// Get owner by server port and id
//
/////////////////////////////////////////////////

function getowner_byport($port,$id) {
  $db = dbConnect();
  $cond = array('PortBase' => $port, 'id' => $id);
  $row = $db->getRow('servers', $cond);
  return $row['owner'];
}

/////////////////////////////////////////////////
//
// Get owner by server id
//
/////////////////////////////////////////////////

function getowner_by($id) {
  $db = dbConnect();
  $row = $db->getRow('servers', array('id' => $id));
  return $row['owner'];
}

/////////////////////////////////////////////////
//
// Server restart function
//
/////////////////////////////////////////////////
function restart_server($portbase,$srvname) {
  $db = dbConnect();
  $config = settings();
  shell_exec("kill `cat ".$config['smi_path']."/servers/".$portbase."".$srvname.".pid`");
  $db->update('servers', array('enabled' => '1'), array('PortBase' => $portbase, 'servername' => $srvname));
  $pid = shell_exec("nohup ".$config['sc_serv']." ".$config['smi_path']."/servers/".$portbase."".$srvname.".conf > /dev/null & echo $!");
  $cleanpid = trim($pid);
  exec("echo $cleanpid > ".$config['smi_path']."/servers/".$portbase."".$srvname.".pid");
  $cond = array ('PortBase' => $portbase, 'servername' => $srvname);
  $autodj = $db->getRow('servers', $cond, 'autodj');
  if($autodj[0] == "1"){
    //restartstream($portbase, $srvname, $djpassword, $id);
  }
}

/////////////////////////////////////////////////
//
// Get PID from server's .pid file
// 
/////////////////////////////////////////////////
function getpid($portbase, $srvname) {
  $config = settings();
  $filename = $config['smi_path']."/servers/".$portbase.$srvname.".pid";
  if (file_exists($filename)) {
    $handle = fopen($filename, "r");
    $contents = fread($handle, filesize($filename));
    fclose($handle);
    return trim($contents);
  } else { 
    return false;
  }
}

/////////////////////////////////////////////////
//
// Generic function to read from a file
//
/////////////////////////////////////////////////
function getcontent($fullpath) {
  if (file_exists($fullpath) && filesize($fullpath) > 0) {
    $handle = fopen($fullpath, "r");
    $contents = fread($handle, filesize($fullpath));
    fclose($handle);
    return trim($contents);
  } else {
    return false;
  }
}


/////////////////////////////////////////////////
//
// Software Version
//
/////////////////////////////////////////////////
function softwarever() {
  $db = dbConnect();
  $row = $db->getRow('smi');
  $filename = "revision.txt";
  $handle = fopen($filename, "r");
  $contents = fread($handle, filesize($filename));
  fclose($handle);
  return $row['version']."-r".$contents;
}

/////////////////////////////////////////////////
//
// Get media directory
//
/////////////////////////////////////////////////

function getmediapath() {
  $db = dbConnect();
  $config = settings();
  return $config['media_path'];
}

/////////////////////////////////////////////////
//
// Parse media directory
//
/////////////////////////////////////////////////
function reloadmedia($i) {
  $db = dbConnect();
  $directory = $i;
  scan_directory_recursively($directory, "mp3");
  // Check if files listed in the DB exist in given path
  $dbmedia = $db->getRows('media','','*','id');
  foreach ((array)$dbmedia as $row) {
    if(file_exists($i."/".basename($row[1]))) {
     $db->update('media', array('files' => $i."/".basename($row[1])), array('id' => $row[0]));
    } else {
      $db->delete('media','id',$row[0]);
      $db->delete('playlist_content', 'fid', $row[0]);
    }
  }
}

/////////////////////////////////////////////////
//
// Recursively parse media directory
//
/////////////////////////////////////////////////

function scan_directory_recursively($directory,$filter) {   
  require_once('id3.class.php');
  $db = dbConnect();

  // if the path has a slash at the end we remove it here
  if(substr($directory,-1) == '/') {                                                      
    $directory = substr($directory,0,-1);              
  }                                                      

  // if the path is not valid or is not a directory ...  
  if(!file_exists($directory) || !is_dir($directory)) {                                                      
    // ... we return false and exit the function        
    return FALSE;                                      
  // ... else if the path is readable                     
  } elseif(is_readable($directory)) {                                                      
    // we open the directory                           
    $directory_list = opendir($directory);             
                                                            
    // and scan through the items inside               
    while (FALSE !== ($file = readdir($directory_list))) {                                                   
      // if the filepointer is not the current or parent directory
      if($file != '.' && $file != '..') {                                                 
        // we build the new path to scan              
        $path = $directory.'/'.$file;                 
        // if the path is readable                    
        if(is_readable($path)) {                        
          // we split the new path by directories   
          $subdirectories = explode('/',$path);     
          // if the new path is a directory         
          if(is_dir($path)) {                         
            // add the directory details to the file list
            $directory_tree[] = array(                   
                             'path'    => $path,                      
                             'name'    => end($subdirectories),       
                             'kind'    => 'directory',                
                             // we scan the new path by calling this function
                             'content' => scan_directory_recursively($path, $filter));
                                                                                      
           // if the new path is a file                                     
           } elseif(is_file($path)) {                                          
             // get the file extension by taking everything after the last dot
             $extension = end(explode('.',end($subdirectories)));             
             // if there is no filter set or the filter is set and matches    
             if($filter === FALSE || $filter == $extension) {                   
               // add the file details to the file list                     
               $directory_tree[] = array(                                   
                                 'path'      => $path,                                    
                                 'name'      => end($subdirectories),                     
                                 'extension' => $extension,                               
                                 'size'      => filesize($path),                          
                                 'kind'      => 'file');                                  
               if($db->numRows('media', array('files' => $path)) > 0) {
                 // Do nothing
               } else {                     
                 // Extract data from ID3 tag                          
                 $mp3 = "$path"; //MP3 file to be read                
		 $id3 = new ID3($mp3);
		 $id3->getInfo();
		 ($id3->getArtist() == '') ? $artist = ' ' : $artist = $id3->getArtist();
		 ($id3->getTitle() == '') ? $song = ' ' : $song = $id3->getTitle();
		 // If song is empty, use filename
		 if ($song == ' ') { 
		   $tempsong = split("[/.]", $mp3);
		   $song = $tempsong[sizeof($tempsong) - 2];
		 } 
		 ($id3->getAlbum() == '') ? $album = ' ' : $album = $id3->getAlbum();
		 ($id3->getYear() == '') ? $year = 0 : $year = $id3->getYear();
		 ($id3->getGender() == '') ? $genre = 255 : $genre = ereg_replace('[()]', '', $id3->getGender());
		 // If genre is not numeric, try reverse lookup in table 'genres'
		 if (!is_numeric($genre)) {
		   if ($db->numRows('genres', array('genreTitle' => $genre)) > 0) { 
		     $genre = $g[0]; 
                   } else { 
		     $genre = 255; 
		   }
		 } elseif ($genre < 0 || $genre > 255) {
		   $genre = 255;
		 }
		 ($id3->tags['COMM'] == '') ? $comment = ' ' : $comment = $id->tags['COMM'];
                 $insert = array(	'files'   => addslashes($path),
					'song'	  => addslashes($song),
					'artist'  => addslashes($artist),
					'album'   => addslashes($album),
					'year'    => addslashes($year),
					'comment' => addslashes($comment),
					'genre'   => addslashes($genre)		);
		  $db->insert('media', $insert);
                }
              }
            }
          }
        }
      }
    // close the directory
    closedir($directory_list);
  }
} // end function

/////////////////////////////////////////////////
//
// Rewrite the playlist file
//
/////////////////////////////////////////////////
function rebuildPlaylist($i) {
  $db = dbConnect();
  $cond = array( 'playlist_content.pid' => $i, 
		'playlist_content.fid' => 'media.id',
		'playlist_content.pid' => 'playlist.id' );
  $file = $db->getRow('media, playlist_content, playlist', $cond, 'media.files, playlist.name, playlist.uid');
  $fd = fopen("playlists/$file[2]$file[1].pls", "w+");
  fputs($fd, $file[0] . "\n");
  fclose($fd);
}

/////////////////////////////////////////////////
//
// Delete the playlist file
//
/////////////////////////////////////////////////
function deletePlaylist($pid,$uid) {
  $db = dbConnect();
  $cond = array(	'uid' => $uid,
			'id'  => $pid );
  $row = $db->getRow('playlist', $cond, 'uid, name');
  unlink("playlists/$row[0]$row[1].pls");
}


/////////////////////////////////////////////////
//
// Start a stream server 
//
/////////////////////////////////////////////////
function startstream($id) {
  $db = dbConnect();
  $stream = $db->getRow('servers', array('id' => $id), 'PortBase, servername, autodj');
  $port = $stream['PortBase'];
  $srvname = $stream['servername'];
  $config = settings();
  $sc_conf = $config['smi_path']."/servers/".$port."".$srvname.".conf";
  // Check that config file exists before trying to launch
  if(file_exists($sc_conf)) {
    if (iswin()) {
      $cmdstr = $config['sc_serv'];
      // sc_serv.exe needs Windows path with backslashes
      $cfg_path = str_replace("/", "\\", $sc_conf);
      $cmdstr .= " ".$cfg_path;
      debug($cmdstr);
      $pid = start_proc($cmdstr);
    } else {
      // POSIX launch procedure
      $cmdstr = "nohup ".$config['sc_serv']." ".$config['smi_path']."/servers/".$port."".$srvname.".conf";
      $cmdstr .= " > /dev/null & echo $!";
      $pid = shell_exec($cmdstr);
    }

    $cleanpid = trim($pid);
    // Write PID to file
    $fd = fopen($config['smi_path']."/servers/".$port."".$srvname.".pid", "w+");
    fputs($fd, $cleanpid);
    fclose($fd);

    // Flag server as enabled in database
    $db->update('servers', array('enabled' => '1'), array('PortBase' => $port, 'id' => $id));

    if($stream['autodj'] == "1") {
      $ices = geticesloc();
      $pid = shell_exec("$ices -c ".$config['smi_path']."/ices/".$id.".".$port.".conf > /dev/null & echo $!");
      $cleanpid = trim($pid);
      system("echo $cleanpid > ".$config['smi_path']."/ices/".$id.".".$port.".pid");
    }

    $username = $_SESSION['username'];
    $event = " Started server on port $port";
    addevent($username,$event);
  } else {

    // $sc_conf does not exist
    echo "Server configuration file is missing: ".$sc_conf."<br>";
    exit;
  }

}

/////////////////////////////////////////////////
//
// Stop a stream server
//
/////////////////////////////////////////////////
function stopstream($id) {
  $db = dbConnect();
  $stream = $db->getRow('servers', array('id' => $id), 'PortBase, servername, autodj');
  $port = $stream['PortBase'];
  $srvname = $stream['servername'];
  $config = settings();

  $db->update('servers', array('enabled' => '0'), array('PortBase' => $port, 'id' => $id));

  // Try to read PID from .pid-file
 
  if ($pid = trim(getpid($port, $srvname))) {
    if (iswin()) {
      proc_kill($pid);
    } else {
      shell_exec("kill -9 ".$pid);
    }

    // Delete .pid-file
    deletefile("".$config['smi_path']."/servers/".$port."".$srvname.".pid");

    if($stream['autodj'] == "1") {
      if (file_exists($config['smi_path']."/ices/".$id.".".$port.".pid")) {
        shell_exec("kill `cat ".$config['smi_path']."/ices/".$id.".".$port.".pid`");
        unlink("".$config['smi_path']."/ices/".$id.".".$port.".pid");
      }
    }

    $username = $_SESSION['username'];
    $event = " Stopped server on port $port";

    addevent($username,$event);
  }
}

/////////////////////////////////////////////////
//
// restart a stream server if AutoDJ is enabled
//
/////////////////////////////////////////////////
function reloadstream($id) {
  $db = dbConnect();
  $config = settings();
  $adj = $db->getRow('servers', array('id' => $id), 'autodj, PortBase');
  if(file_exists("".$config['smi_path']."/ices/".$id.".".$adj[1].".pid")) {
    stopstream($id);
    startstream($id);
  }
}


////////////////////////////////////////////////
//
// Generate ices0 configuration file
//
////////////////////////////////////////////////

function genIces0Conf($id, $port, $pls, $random) {
  $db = dbConnect();
  $config = settings();
  $iq = $db->getRows('servers', array('id' => $id, 'PortBase' => $port));
  foreach ($iq as $i) {
	$p = $db->getRow('playlist', array('id' => $pls));
$iconf = ""
. "<ices:Configuration xmlns:ices=\"http://www.icecast.org/projects/ices\">\n"
. "<Playlist>\n"
. "<File>".$p[0]."</File>\n"
. "<Randomize>".$random."</Randomize>\n"
. "<Type>script</Type>\n"
. "<Module>".$config['smi_path']."/ices/$id.pls.php</Module>\n"
. "<Crossfade>5</Crossfade>\n"
. "</Playlist>\n"
. "<Execution>\n"
. "<Background>0</Background>\n"
. "<Verbose>0</Verbose>\n"
. "<BaseDirectory>".$config['smi_path']."/ices</BaseDirectory>\n"
. "</Execution>\n"
. "<Stream>\n"
. "<Server>\n"
. "<Hostname>".$config['host_addr']."</Hostname>\n"
. "<Port>".$port."</Port>\n"
. "<Password>".$i[3]."</Password>\n"
. "<Protocol>icy</Protocol>\n"
. "</Server>\n"
. "<Mountpoint>/</Mountpoint>\n"
. "<Name>".$i[44]."</Name>\n"
. "<Genre>".$i[43]."</Genre>\n"
. "<Description></Description>\n"
. "<URL>".$i[44]."</URL>\n"
. "<Public>1</Public>\n"
. "<Bitrate>128</Bitrate>\n"
. "<Reencode>1</Reencode>\n"
. "</Stream>\n"
. "</ices:Configuration>\n";
$fd = fopen("".$config['smi_path']."/ices/$id.$port.conf", "a+");
fputs($fd, $iconf . "\n\n");
fclose($fd);
}
}

////////////////////////////////////////////////
//
// Get last server added id
//
////////////////////////////////////////////////

function getserverid() {
  $db = dbConnect();
  $row = $db->getRow("SELECT MAX(id) FROM ranch");
  return $row[0];
}

////////////////////////////////////////////////
//
// Get Ices0 Path
//
////////////////////////////////////////////////

function geticesloc() {
  $config = settings();
  return $config['ices_path'];
}

////////////////////////////////////////////////
//
// Get service title
//
////////////////////////////////////////////////

function serviceTitle() {
  $config = settings();
  echo $config['site_title'];
}

////////////////////////////////////////////////
//
// User list -> dropdown function
//
////////////////////////////////////////////////

function userlist() {
  $db = dbConnect();
  $users = $db->getRows('members', '', 'user_id, username', 'user_id');
  foreach ($users as $user)
  {
    echo "<option value=\"".$user[0]."\">".$user[1]."</option>";
  }
}

////////////////////////////////////////////////
//
// Create Javascript status dialog box
//
////////////////////////////////////////////////

function msgbox($message, $return='home.php') {
    $js = "<script type=\"text/javascript\">\n";
    $js .= " alert(\"".$message."\");\n";
    $js .= "  window.location=\"".$return."\";\n";
    $js .= "</script>\n";
    return $js;
}


////////////////////////////////////////////////
//
// Create playlist select field values
//
////////////////////////////////////////////////

function playlist() {
  // Create instance of MySQLDB class
  $db = dbConnect();
  // If query returns nothing, feed foreach an empty array to supress PHP warning
  ($rows = $db->getRows('playlist', '', '*', 'name', 'ASC')) ? ($rows = $rows) : ($rows[] = '');  
  // Build HTML option list
  foreach ($rows as $row)
  {
    echo "<option value=\"".$row[0]."\">".$row[3]."</option>";
  }
}


////////////////////////////////////////////////
//
// Generate playlist script for ices
//
////////////////////////////////////////////////

function genicespls($sid,$rand) {
require("config.php");
connectdb();
delicespls($sid);
$config = settings();
if($rand == "0") {
$rconf = ""
. "#!/usr/bin/php\n"
. "<?\n"
. "// Turn off all error reporting\n"
. "error_reporting(0);\n"
. "\$db = mysql_connect(\"$dbhost\", \"$dbuser\", \"$dbpass\") or die('Script Could not connect to database');\n"
. "mysql_select_db(\"$dbname\",\$db);\n"
. "\$query = mysql_query(\"SELECT * FROM requests WHERE sid=".$sid." ORDER BY id ASC LIMIT 1\");\n"
. "\n"
. "if(!\$row = mysql_fetch_row(\$query)){\n"
. "\$pq = mysql_query(\"SELECT playlist FROM servers WHERE id=".$sid."\");\n"
. "\$p = mysql_fetch_row(\$pq);\n"
. "\$cq = mysql_query(\"SELECT current_fid,fid,id FROM playlist_cache WHERE pid='\".\$p[0].\"'\");\n"
. "\$c = mysql_fetch_row(\$cq);\n"
. "\n"
. "if(!\$c){\n"
. "\$pos = \"0\";\n"
. "\$lq = mysql_query(\"SELECT fid FROM playlist_content WHERE pid='\".\$p[0].\"' AND position>'\".\$pos.\"' ORDER BY position ASC LIMIT 1\");\n"
. "\$l = mysql_fetch_row(\$lq);\n"
. "\$fid = \$l[0];\n"
. "mysql_query(\"INSERT INTO playlist_cache VALUES('','\".\$fid.\"','\".\$p[0].\"','1')\");\n"
. "}else{\n"
. "\$lq = mysql_query(\"SELECT fid FROM playlist_content WHERE pid='\".\$p[0].\"' AND position>'\".\$c[0].\"' ORDER BY position ASC LIMIT 1\");\n"
. "\$l = mysql_fetch_row(\$lq);\n"
. "\n"
. "if(!\$l){\n"
. "\$pos = \"0\";\n"
. "\$lq = mysql_query(\"SELECT fid FROM playlist_content WHERE pid='\".\$p[0].\"' AND position>'\".\$pos.\"' ORDER BY position ASC LIMIT 1\");\n"
. "\$l = mysql_fetch_row(\$lq);\n"
. "\$fid = \$l[0];\n"
. "mysql_query(\"UPDATE playlist_cache SET current_fid='1' WHERE pid='\".\$p[0].\"'\");\n"
. "}else{\n"
. "\$fid = \$l[0];\n"
. "\$adv = \$c[0] + 1;\n"
. "mysql_query(\"UPDATE playlist_cache SET current_fid='\".\$adv.\"' WHERE id='\".\$c[2].\"'\");\n"
. "\n"
. "}}\n"
. "\n"
. "\n"
. "}else{\n"
. "\$query = mysql_query(\"SELECT * FROM requests WHERE sid='".$sid."' ORDER BY id ASC LIMIT 1\");\n"
. "\$row = mysql_fetch_row(\$query);\n"
. "\$fid = \$row[1];\n"
. "mysql_query(\"DELETE FROM requests WHERE id=\".\$row[0].\"\");\n"
. "}\n"
. "\$query2 = mysql_query(\"SELECT * FROM media WHERE id=\".\$fid.\"\");\n"
. "\$row2 = mysql_fetch_row(\$query2);\n"
. "echo \$row2[1];\n"
. "?>\n";
}
if($rand == "1"){
$rconf = ""
. "#!/usr/bin/php\n"
. "<?\n"
. "// Turn off all error reporting\n"
. "error_reporting(0);\n"
. "\$db = mysql_connect(\"$dbhost\", \"$dbuser\", \"$dbpass\") or die('Script Could not connect to database');\n"
. "mysql_select_db(\"$dbname\",\$db);\n"
. "\$query = mysql_query(\"SELECT * FROM requests WHERE sid=".$sid." ORDER BY id ASC LIMIT 1\");\n"
. "\n"
. "if(!\$row = mysql_fetch_row(\$query)){\n"
. "\$pq = mysql_query(\"SELECT playlist FROM servers WHERE id=".$sid."\");\n"
. "\$p = mysql_fetch_row(\$pq);\n"
. "\$sq = mysql_query(\"SELECT fid from playlist_content where pid=\".\$p[0].\" ORDER BY RAND()\");\n"
. "\$s = mysql_fetch_row(\$sq);\n"
. "\$fid = \$s[0];\n"
. "}else{\n"
. "\$query = mysql_query(\"SELECT * FROM requests WHERE sid=137 ORDER BY id ASC LIMIT 1\");\n"
. "\$reg = mysql_fetch_row(\$query);\n"
. "\$fid = \$reg[1];\n"
. "mysql_query(\"DELETE FROM requests WHERE fid=\".\$fid.\" ORDER BY id LIMIT 1\");\n"
. "}\n"
. "\$query2 = mysql_query(\"SELECT * FROM media WHERE id=\".\$fid.\"\");\n"
. "\$row2 = mysql_fetch_row(\$query2);\n"
. "echo \$row2[1];\n"
. "?>\n";
}
$fd = fopen("".$config['smi_path']."/ices/$sid.pls.php", "a+");
fputs($fd, $rconf . "\n");
fclose($fd);
shell_exec("chmod +x ".$config['smi_path']."/ices/$sid.pls.php");
}

////////////////////////////////////////////////
//
// Remove playlist script for ices
//
////////////////////////////////////////////////

function delicespls($sid){
  $config = settings();
  if (file_exists($config['smi_path']."/ices/$sid.pls.php")) {
    unlink($config['smi_path']."/ices/$sid.pls.php");
  }
}

////////////////////////////////////////////////
//
// Find the next vacant portbase by method
// $method="high" - find next vacant port
// $method="low" - find lowest vacant port
//
////////////////////////////////////////////////
function nextport()
{
 $db = dbConnect();
 $config = settings();
 $newport = $config['start_portbase'];
 $row = $db->getRow("SELECT MAX(PortBase) AS LastPort FROM servers");
 if ($row['LastPort'] < $newport) {
   return $newport;
 } else if (strtolower($config['nextport_method']) == "high") {
   return $row['LastPort'] + 2;	// Use highest port number + 2
 } else {
   $servers = $db->getRows('servers','','PortBase','PortBase');
   $lastport = $config['start_portbase'] - 2;
   foreach ($servers as $row) {
     if($row[0] > $lastport + 2) {
       $newport = $lastport + 2;// Use the lowest vacant port
       break;
     } else {	
       $lastport = $row[0];
       $newport = $lastport + 2;
     }
   }
 }
 return $newport;
} // function end
  
////////////////////////////////////////////////
//
// Check if a portbase already is in use
// 
////////////////////////////////////////////////
function portexists($checkport)
{
 $db = dbConnect();
 return $db->numRows('servers', array('PortBase' => $checkport));
} 

////////////////////////////////////////////////
//
// Delete a file after checking that is exists
//
////////////////////////////////////////////////
function deletefile($path)
{
  if (file_exists($path)) {
    unlink($path);
    return true;
  } else {
    return false;
  }
}

////////////////////////////////////////////////
//
// Rename a file after checking that is exists
//
////////////////////////////////////////////////
function renamefile($oldpath, $newpath)
{
  if (file_exists($oldpath)) {
    rename($oldpath, $newpath);
  }
}

/////////////////////////////////////////////////
//
// Check and see if the install.php file has been removed
//
/////////////////////////////////////////////////
function check_install() {
  if(file_exists('./install/install.php')){
    $fe = '1';	
  } else {
    $fe = '0';
  }
  return $fe;
}

/*
Get our configuration settings from the database
Return as an array
FIXME: Remove this when new settings scheme works
*/
function get_settings() {
	connectdb();	
	$query = mysql_query('SELECT * FROM config');
	$result = mysql_fetch_row($query);
	return $result;
}

/********************************************************************/
/********************************************************************/
function start_proc ( $comm ) {
    $config = settings();
    $dn=dirname(__FILE__);
    $descriptorspec = array(
    0 => array('pipe', 'r'), // stdin
    1 => array('pipe', 'w'), // stdout
    2 => array('pipe', 'w') // stderr
    );
    $cmd = "start /b ".$config['smi_path']."/wintools/psexec.exe -d";
    $fpr = proc_open($cmd.' '.$comm, $descriptorspec, $pipes, $dn);
    fclose($pipes[0]);
    fclose($pipes[1]);
    $stderr = '';
    while(!feof($pipes[2])) { $stderr .= fgets($pipes[2], 128); }
    fclose($pipes[2]);
    proc_close ($fpr);
    $pid =FALSE;
    if ( preg_match ( "/process ID ([\d]{1,10})\./im", $stderr, $matches ) )
      $pid = $matches[1];
     else $pid=FALSE;
   
    return $pid;

}
/********************************************************************/
/********************************************************************/
function proc_isalive ( $pid ){
    $config = settings();
    $alive=FALSE;
    $dn=dirname(__FILE__);
    $descriptorspec = array(
    0 => array('pipe', 'r'),   // stdin
    1 => array('pipe', 'w'),  // stdout
    2 => array('pipe', 'w')  // stderr
    );
    $cmd = "start /b ".$config['smi_path']."/wintools/pslist.exe";
    $fpr = proc_open( $cmd.' '.$pid, $descriptorspec, $pipes, $dn );
    fclose($pipes[0]);
    $stdout = '';
    while(!feof($pipes[1])) { $stdout .= fgets($pipes[1], 128); }   
    fclose($pipes[1]);
    $stderr = '';
    while(!feof($pipes[2])) { $stderr .= fgets($pipes[2], 128); }
    fclose($pipes[2]);
    proc_close ($fpr);
    if ( strpos($stdout, 'not found') === FALSE )  $alive=TRUE;

    return $alive;   
   
}
/********************************************************************/
/********************************************************************/
function proc_kill ( $pid ){
    $config = settings();
    $succ=FALSE;
    $dn=dirname(__FILE__);
    $descriptorspec = array(
    0 => array('pipe', 'r'),   // stdin
    1 => array('pipe', 'w'),  // stdout
    2 => array('pipe', 'w')  // stderr
    );
    $fpr = proc_open( 'start /b '.$config['smi_path'].'/wintools/pskill.exe '.$pid, $descriptorspec, $pipes, $dn );
    fclose($pipes[0]);
    $stdout = '';
    while(!feof($pipes[1])) { $stdout .= fgets($pipes[1], 128); }   
    fclose($pipes[1]);
    $stderr = '';
    while(!feof($pipes[2])) { $stderr .= fgets($pipes[2], 128); }
    fclose($pipes[2]);
    proc_close ($fpr);
    if ( strpos($stdout, 'killed') !== FALSE )  $succ=TRUE;
   
    return $succ;   
   
}

/*
Function for dumping debug messages to the system log
Comment this out to disable
*/
function debug($msg) {
  error_log("[SMI] ".$msg);
}
?>
