<?php
/*
dv at josheli.com
backup client/reseller databases on a WHM/Cpanel server

How it works:
Reads all accounts (domain, username,cpanel theme specifically) from the listaccts page in WHM
Creates filenames like "dbbk_dbname_domain_com_1_11_04.gz"
Uses php file_get_contents to download the SQL backup

This script doesn't require cron, but i use it. Cron for Windows: 
http://www.kalab.com/freeware/cron/cron.htm 

Instructions:
1. Install PHP if needed
2. Place this script somewhere
3. Modify "config" variables below, to suit
4. From the command prompt:
    >cd /path/to/script
    >php bkup_dbs.php
4. ([Or] Optionally) Set up a cron job to call this script

Notes: 
- This hasn't been tested *at all* on huge (multi-megabyte) databases
- This only backs up an sql dump, not the actual mysql files
- Right now it's "all or nothing"; i.e. it only backs up *every* db on
  *every* client domain; this will change
- This doesn't use wget, but it could
- The user and password are passed through the url, so they're visible by 
  pretty much anyone, if they're looking.
- This script could easily be run from the server (but why backup a site 
  on its own server); running it from another server is a pretty good 
  option though.
- I have a high-speed internet connection. It takes < 1 minute to download
  17 small .gzipped databases
- Remember that you will be using the sub-accounts' bandwidth
- My firewall needed to be configured to allow PHP to access the internet.
- I'm using the PHP 5 cli.


*/

/*** BEGIN CONFIG ***/

/*
do you want to backup the reseller account also? 
it's not in the WHM listaccts page
*/
$bkUpReseller true;

/*
This is hard-coded for now.... until i figure out a way
to figure out the reseller cpanel theme programmatically
*/
$resellerCpTheme 'vertex';

/*
Backup path on the local machine
*/
$dbBkUpPath '.\\db_backups';

/*
use SSL ?
must have at least php 4.3, the php_openssl extension, and the openSsl libraries
*/
$useSsl true;

/*
Insecure login stuff :)
the user and password are passed through the URL, unsecurely
*/
$resellerDomain 'mydomain.com';
$whmUser 'username';
$whmPass 'password';
/*
how many seconds to pause between downloads 
(be nice to your shared server friends :) )
set to 0 for none 
*/
$sleep 0;

/*
write a log to 'log' or 'echo' or 'none'(no log)
*/
$logEchoNone 'log';
/*
if 'log', where?
include the path if necessary
*/
$logFileName './db_bkups.log';

/*** END CONFIG ***/

/*** BEGIN FUNCTIONS ***/

function saveBackup(&$backup$fileName$path) {

  global 
$totalSize;

    if(!
is_dir($path)){
    
writeLog("Creating backup directory $path...\n");
        if(!
mkdir($path)){
            
writeLog("Could not create backup directory: $path.\n");
            return 
false;
        }
    }
    
$path realpath($path);
    if(
substr($pathstrlen($path)-1strlen($path) )!== '\\') {
        
$path .= '\\';
    }
    
$filePath $path.$fileName;
    
$fp fopen($filePath,'wb');
    if((
$len fwrite($fp$backup))===false){
        
writeLog("Could not backup $fileName to $path.\n");
        return;
    }
    else {
    
$totalSize += $len;
        
writeLog("Backed up $len bytes to $path$fileName.\n");
    }

    
fclose($fp);
    return;
}
function 
writeLog($entry) {
    global 
$logEchoNone,$logFileName;

  
$method strtolower($logEchoNone);
  
    if(
$method == 'log') {
        
$fp fopen($logFileName,'ab');
    }
    elseif(
$method == 'echo') {
        
$fp STDOUT;
    }
  else {
      return;
  }
        
    
$entry date('r').' - '.$entry;
    
    
fwrite($fp$entry);

    if(
$method == 'log')
        
fclose($fp);

    return;
}

function 
getMicroTime(){ 
  list(
$usec$sec) = explode(" ",microtime()); 
  return ((float)
$usec + (float)$sec); 
}

if(!
function_exists('file_get_contents')){
  function 
file_get_contents($filename) {
     
$fd fopen($filename"rb");
     
$content fread($fdfilesize($filename));
     
fclose($fd);
     return 
$content;
  }
}

/*** END CONFIG ***/

/***
BEGIN MAIN
***/
set_time_limit(0);
$timeStart getMicroTime();

if(
$useSsl) {
  if (!
extension_loaded('openssl')) {
    
dl('php_openssl.' .PHP_SHLIB_SUFFIX) or die("Could not load openssl extension");
  }
  
$protocol 'https://';
  
$cpPort '2083';
  
$whmPort '2087';
  
writeLog("Using SSL.\n");
}
else {
  
$protocol 'http://';
  
$cpPort '2082';
  
$whmPort '2086';
  
writeLog("Not using SSL.\n");

$totalSize 0;

writeLog("Retrieving WHM accounts page...\n");
//get the WHM 'list accounts' page
$acctsPage file_get_contents("$protocol$whmUser:$whmPass@$resellerDomain:$whmPort/scripts2/listaccts?viewall=1");

//get each accounts table row
$numAccts preg_match_all("/<tr class=(?:tdshade2|tdshade1)>(.*?)<\/tr>/is"$acctsPage$matches);

if(
$numAccts && is_array($matches[1])) { 

  
//foreach client domain....
    
foreach($matches[1] as $match) {
    
$account '';
        
$account explode('</td><td>',$match);
        
$cpDomain strip_tags(trim($account[0]));//domain
        
$cpUser strip_tags(trim($account[2]));//username
    
$cpTheme strip_tags(trim($account[9]));//cpanel theme

    //get the cpanel backup page
    
$cpDbPage file_get_contents("$protocol$cpUser:$whmPass@$cpDomain:$cpPort/frontend/$cpTheme/backup/index.html");

    
//find the dbs available
    
$numMatches preg_match_all('/"\/getsqlbackup\/(.*?)"/ims',$cpDbPage,$dbMatches);

    if(
$numMatches && is_array($dbMatches[1])) { 

      
//foreach db available...
      
foreach($dbMatches[1] as $dbMatch) {
        
$dbBkUp '';

        
//get the sql backup
        
writeLog("Retrieving $dbMatch...\n");
        
$dbBkUp file_get_contents("$protocol$cpUser:$whmPass@$cpDomain:$cpPort/getsqlbackup/$dbMatch");
        
        
$dbFileName 'db_'.basename($dbMatch,'.gz').'_'.str_replace('.','_',$cpDomain).'_'.date('n_j_y').'.gz';
         
        
//save the sql backup...
        
writeLog("Saving $dbFileName to $dbBkUpPath...\n");
        
saveBackup($dbBkUp,$dbFileName,$dbBkUpPath);

        
sleep($sleep);
      }
    }
  }
}

if(
$bkUpReseller){
  
$dbFileName '';
  
$dbBkUp '';
  
//get the cpanel backup page
    
$cpDbPage file_get_contents("$protocol$whmUser:$whmPass@$resellerDomain:$cpPort/frontend/$resellerCpTheme/backup/index.html");

    
//find the dbs available
    
$numMatches preg_match_all('/"\/getsqlbackup\/(.*?)"/ims',$cpDbPage,$rsMatches);

    if(
$numMatches && is_array($rsMatches[1])) { 
      
      
//foreach db available...
      
foreach($rsMatches[1] as $rsMatch) {
        
$dbBkUp '';
        
//get the sql backup
        
writeLog("Retrieving $rsMatch...\n");
        
$dbBkUp file_get_contents("$protocol$whmUser:$whmPass@$resellerDomain:$cpPort/getsqlbackup/$rsMatch");
        
        
$dbFileName 'db_'.basename($rsMatch,'.gz').'_'.str_replace('.','_',$resellerDomain).'_'.date('n_j_y').'.gz';
         
        
//save the sql backup...
        
writeLog("Saving $dbFileName to $dbBkUpPath...\n");
        
saveBackup($dbBkUp,$dbFileName,$dbBkUpPath);
      }
    }


$timeEnd getMicroTime();
$time $timeEnd $timeStart;
$totalKb round($totalSize/1024,2);
writeLog("Backed up $totalKb KB.\n");
writeLog("Elapsed time: ".round($time,2)." seconds.\n");

/*** END MAIN ***/
?>