home *** CD-ROM | disk | FTP | other *** search
- <?php
- /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
-
- // {{{ Header
-
- /**
- * Class to manage sqlite database. On object-oriented interface to sqlite
- * integrity check, optimizations and backup.
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * BSD License
- *
- * Copyright (c) 2004-2006 David Costa
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * 3. Neither the name of David Costa nor the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Database
- * @package DB_Sqlite_Tools
- * @license http://www.php.net/license/3_0.txt PHP License 3.0
- * @author David Costa <gurugeek@php.net>
- * @author Ashley Hewson <morbidness@gmail.com>
- * @author Firman Wandayandi <firman@php.net>
- * @copyright Copyright (c) 2004-2006 David Costa
- * @license http://www.opensource.org/licenses/bsd-license.php
- * BSD License
- * @version CVS: $Id: Tools.php,v 1.2 2006/05/26 17:23:43 firman Exp $
- */
-
- // }}}
- // {{{ Dependencies
-
- /**
- * Load PEAR_Exception to throws.
- */
- require_once 'PEAR/Exception.php';
-
- // }}}
- // {{{ Inline codes
-
- // Avoid the fatal error, caused by redeclare
- // the magic __autoload() function.
- if (!function_exists('__autoload')) {
- function __autoload($class)
- {
- switch ($class) {
- case 'DB_Sqlite_Tools_DBC':
- case 'DB_Sqlite_Tools_XMLParser':
- case 'DB_Sqlite_Tools_ArcFour':
- include str_replace('_', '/', $class) . '.php';
- break;
- }
- }
- } else {
- // __autoload() already declared in the other line.
- // There is no way just load all files.
-
- require_once 'DB/Sqlite/Tools/DBC.php';
- require_once 'DB/Sqlite/Tools/XMLParser.php';
- require_once 'DB/Sqlite/Tools/ArcFour.php';
- }
-
- // }}}
- // {{{ Class: DB_Sqlite_Tools
-
- /**
- * Class to manage sqlite database. An object-oriented interface to sqlite
- * integrity check, optimizations and backup and export. It curently supports
- * pragma integrity checks, cache values to optimize performance,
- * synchronisation values for an higher integrity protection.
- *
- * For backups it supports ftp, rsync (both local and remote) and local backups.
- *
- * It offer an extra in build export method to XML for a whole database schema
- * and data which can be particularly useful for backup and export purposes.
- *
- * Via the XML parser it allows to import and XML dump back to an Sqlite
- * database.
- *
- * @category Database
- * @package DB_Sqlite_Tools
- * @author David Costa <gurugeek@php.net>
- * @author Ashley Hewson <morbidness@gmail.com>
- * @author Firman Wandayandi <firman@php.net>
- * @copyright Copyright (c) 2004-2006 David Costa
- * @license http://www.opensource.org/licenses/bsd-license.php
- * BSD License
- * @version Release: 0.1.5
- */
- class DB_Sqlite_Tools
- {
- // {{{ Properties
-
- /**
- * Error handling related Constants
- *
- * Verbose error output in each of the cases
- */
- const DB_SQLITE_TOOLS_COD =
- 'DB_DB_Sqlite_Tools Cannot Open Database File Possible Problem:';
- const DB_SQLITE_TOOLS_QRS =
- 'Query Result.. ';
- const DB_SQLITE_TOOLS_QNR =
- 'Query executed with no object returned as result';
- const DB_SQLITE_TOOLS_NAV =
- 'Invalid parameter';
- const DB_SQLITE_TOOLS_COFL =
- 'Cannot Open file for Lock';
- const DB_SQLITE_TOOLS_CCFL =
- 'Cannot release lock on file';
- const DB_SQLITE_TOOLS_CLF =
- 'Unable to activate the lock in the database file';
- const DB_SQLITE_TOOLS_CSF =
- 'Cannot Save File';
- const DB_SQLITE_TOOLS_CCFS =
- 'Cannot Connect to FTP Server';
- const DB_SQLITE_TOOLS_CLFS =
- 'Cannot login to FTP Server';
- const DB_SQLITE_TOOLS_CUFS =
- 'Cannot upload file on FTP Server';
- const DB_SQLITE_TOOLS_NAR =
- 'The database array is empty';
- const DB_SQLITE_TOOLS_NNU =
- 'parameter must be an integer';
- const DB_SQLITE_TOOLS_RSE =
- 'Rsync Error see logfile for details';
- const DB_SQLITE_TOOLS_INSC =
- 'Cannot backup the database remotely without safecopy';
- const DB_SQLITE_TOOLS_CSD =
- 'Cannot scan directory';
- const DB_SQLITE_TOOLS_CCXML =
- 'Cannot create XML';
- const DB_SQLITE_TOOLS_CCLXML =
- 'Cannot close XML File';
-
- /**
- * Debug mode.
- *
- * @var string
- */
- public $debug = false;
-
- /**
- * List of databases.
- *
- * @var string
- */
- public $database = array();
-
- public $email;
-
- /**
- * Error storage.
- *
- * @var string
- */
- private $error;
-
- /**
- * Database opening process.
- *
- * @var string
- */
- private $opendb;
-
- /**
- * Query results.
- *
- * @var string
- */
- private $result;
-
- /**
- * FTP connection object.
- *
- * @var string
- */
- private $ftpconnection;
-
- /**
- * Info stores all the file related information for the given databases.
- *
- * @var string
- */
- private $info;
-
- /**
- * Used to verify if safecopy takes place before remote backup this is
- * necessary to ensure the live db integrity.
- *
- * @var string
- */
- private $safecopy;
-
- /**
- * Stores an array of log objects used for verbose output or logging
- * purposes.
- *
- * @array objects
- */
- private $logs = array();
-
- /**
- * Backup path.
- *
- * @var string
- */
- private $backupp;
-
- /**
- * An array of the databases available in the backup directory generated
- * after scanning the backup directory for all the .bkp files generated by
- * the copySafe function.
- *
- * @array
- */
- private $backupar;
-
- /**
- * Database object.
- *
- * @var string
- */
- private $dbobj;
-
- /**
- * If true, shows logs as they are added to DB.
- *
- * @var bool
- */
- public $showLogs ;
-
- // }}}
- // {{{ Constructor
-
- /**
- * Instantiate a new SQLite_Tools Object
- * Expects a db location or an array of db locations for
- * multiple checks
- *
- * @param string $database the Sqlite database.
- *
- * @return return $this->database array
- */
- public function __construct($database)
- {
- if (!is_array($database)) {
- $this->database[] = $database;
- } else{
- $this->database = $database;
- }
-
- }
-
- // }}}
- // {{{ displayLogs()
-
- /**
- * Display The logs on the screen in an XML-like format.
- */
- private function displayLogs()
- {
- foreach($this->logs as $logs) {
- if ($this->showLogs == true) {
- print $logs;
- /*echo "<pre>\n";
- echo strtr($lstr, get_html_translation_table(HTML_SPECIALCHARS));
- echo "<pre>\n";*/
- }
- }
- }
-
- // }}}
- // {{{ checkIntegrity()
-
- /**
- * Checks the database integrity does an integrity check of the entire
- * database including malformed records, corrupted pages out of order
- * records, invalid indeces returns okay on success or the error details,
- * if multiple is true the the value for $database in the constructor is
- * expected to be an array with a list of databases.
- *
- * @return true
- * @throws PEAR_Exception
- */
- public function checkIntegrity()
- {
- if (!count($this->database)){
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_NAR . $this->database, -1);
- } else {
- foreach($this->database as $databases) {
- $this->sqliteConnect($databases);
- $this->sqliteQuery('PRAGMA integrity_check');
- }
- }
-
- $this->logs[] = new DB_Sqlite_Tools_LogObject(
- __CLASS__, __FUNCTION__,
- 'Integrity check returned ' .
- $this->result->integrity_check);
- $this->displayLogs();
-
- return true;
- }
-
- // }}}
- // {{{ cacheSize()
-
- /**
- * Check or set the cacheSize of the database.
- *
- * As a default value an sqlite database will hold 2000 disk pages in the
- * memory each page requires approximately 1.5 K of memory. For intensive
- * UPDATE or DELETE queries an higher memory might result in a speed
- * increase. If pages parameter is not defined it will return the current
- * cache size of the database or the multiple databases if $this->database
- * is an array with more then one element
- *
- * If a valid integer is passed as $pages parameter it will set the cache
- * size for the database or for multiple database if $this->database is an
- * array with more then one element
- *
- * If defined it will set the new cache size (in pages) as per the specified
- * integer.
- *
- * Note:
- * When setting a new cache size. It might get a query error if on
- * the database or one of the databases doesn't have the relevant write
- * permissions. Please set the necessary permissions on
- * the database/databases before attemping to change their cache value.
- *
- * @param int $pages (optional) number of pages to hold in the updated
- * memory allocation
- *
- * @return true
- * @throws PEAR_Exception
- */
- public function cacheSize($pages = false)
- {
- if (empty($pages)) {
- foreach($this->database as $databases) {
- $this->sqliteConnect($databases);
- $this->sqliteQuery('PRAGMA default_cache_size');
- }
- } else {
- if (!eregi('[[:digit:]]', $pages)) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_NNU . $pages, -1);
- } else {
- foreach($this->database as $databases) {
- $this->sqliteConnect($databases);
- $this->sqliteQuery('PRAGMA default_cache_size = ' . $pages);
- }
- }
- }
-
- $this->logs[] = new DB_Sqlite_Tools_LogObject(
- __CLASS__, __FUNCTION__,
- 'cache correctly reset to ' . $pages);
- $this->displayLogs();
-
- return true;
- }
-
- // }}}
- // {{{ sync()
-
- /**
- * Check or set the synchronous value for the database.
- *
- * Sqlite provides with different synchronous modes. The synchronous level
- * determines the integrity protection. At NORMAL (default mode) the sqlite
- * engine will stop at most critical moment providing with a limited
- * integrity protection of the database. In FULL mode the engine will stop
- * more often thus ensuring and higher integrity level. When OFF the engine
- * will continue as soon as the new data is provided without stopping.
- * Values are represented by an integer, 1 for NORMAL, 2 for FULL and 0 for
- * off.
- *
- * If the parameter value is not set it will return the current default
- * syncronous for the databases. If value is set with either FULL, NORMAL
- * or OFF it will change the default syncronous value for each of
- * the databases.
- *
- * @param sting $value (optional) A synchronous value.
- *
- * @return true
- * @throws PEAR_Exception
- */
- public function sync($value = false)
- {
- if (empty ($value)) {
- foreach($this->database as $databases) {
- $this->sqliteConnect($databases);
- $this->sqliteQuery('PRAGMA default_synchronous');
- }
- } else {
- foreach($this->database as $databases) {
- $this->sqliteConnect($databases);
- if (eregi('FULL|NORMAL|OFF', $value)) {
- $this->sqliteQuery('PRAGMA default_synchronous = ' . $value);
- } else {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_NAV . $value, -1);
- }
- }
- }
-
- $this->logs[] = new DB_Sqlite_Tools_LogObject(
- __CLASS__, __FUNCTION__,
- 'Synchronous value correctly reset to ' . $value);
- $this->displayLogs();
-
- return true;
- }
-
- // }}}
- // {{{ dbFileInfo()
-
- /**
- * Retrieve general information on the database files like filename,
- * owner id, group, name, permissions, library encoding and version,
- * the size of the database, last time it was modified, blocks and
- * generally every possible information on the database files.
- *
- * @return array An array of databases info.
- * @throws PEAR_Exception
- */
- public function dbFileInfo()
- {
- foreach($this->database as $databases) {
- $this->info[$databases] = array();
- $stat = lstat($databases);
- $this->info[$databases]['file_name'] = $databases;
- $this->info[$databases]['file_owner_id'] = fileowner($databases);
- if (function_exists('posix_getpwuid')) {
- $userinfo = posix_getpwuid($this->info[$databases]['file_owner_id']);
- }
-
- //on windows $userinfo=null
- $this->info[$databases]['file_owner_name'] =
- empty($userinfo['name']) ? '' : $userinfo['name'];
- //on windows $userinfo=null
- $this->info[$databases]['file_owner_group'] =
- empty($userinfo['gid']) ? '' : $userinfo['gid'];
- $this->info[$databases]['libenconding'] = sqlite_libencoding();
- $this->info[$databases]['libversion'] = sqlite_libversion();
- $this->info[$databases]['permissions'] = fileperms($databases);
- $this->info[$databases]['file_dev'] = $stat['dev'];
- $this->info[$databases]['file_ino'] = $stat['ino'];
- $this->info[$databases]['file_mode'] = $stat['mode'];
- $this->info[$databases]['file_nlink'] = $stat['nlink'];
- $this->info[$databases]['file_uid'] = $stat['uid'];
- $this->info[$databases]['file_rdev'] = $stat['rdev'];
- $this->info[$databases]['file_size'] = ($stat['size'] / 1024) .'KB';
- $this->info[$databases]['file_atime'] = date('r', $stat['atime']);
- $this->info[$databases]['file_mtime'] = date('r', $stat['mtime']);
- $this->info[$databases]['file_ctime'] = date('r', $stat['ctime']);
- $this->info[$databases]['file_blksize'] = $stat['blksize'];
- $this->info[$databases]['file_blocks'] = $stat['blocks'];
- $this->logs [] = new DB_Sqlite_Tools_LogObject(
- __CLASS__, __FUNCTION__,
- $this->info[$databases]);
- }
-
- $this->displayLogs();
-
- return $this->info;
- }
-
- // }}}
- // {{{ copySafe()
-
- /**
- * Safely duplicates a database file. copySafe should be performed before
- * a backup as transfering via ftp or rsync.
- *
- * With this function we obtain an exclusive lock on the database before the
- * copy, we then check the integrity of the copied databases.
- * if the integrity check on the copied database returns OK this means that
- * we have a cloned database ready for backup purposes.
- *
- * Individual or multiple databases are duplicated with the same name of the
- * original database and the suffix .bkp
- *
- * @param string $path (optional) Destination path, default is current
- * working path.
- *
- * @throws PEAR_Exception
- */
- public function copySafe($path = '')
- {
- // Set the output path to current working dir.
- if (trim($path) == '') {
- $path = './';
- }
-
- $this->backupp = $path;
-
- if (!count($this->database)) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_NAR . $this->database, -1);
- } else {
- foreach($this->database as $databases) {
- $fopenlock = @fopen($databases, 'r');
- if (!@$fopenlock) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_COFL,-1);
- }
-
- $lock = @flock($fopenlock, LOCK_EX);
- if (!@$lock) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_CLF,-1);
- }
-
- $clone = @copy($databases, $path . DIRECTORY_SEPARATOR . basename($databases) .'.bkp');
- if (!@$clone) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_CSF,-1);
- } else {
- $this->sqliteConnect($databases.'.bkp');
- $this->sqliteQuery('PRAGMA integrity_check');
- }
-
- $release = @flock($fopenlock, LOCK_UN);
- if (!@$release) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_CCFL,-1);
- }
- }
- }
-
- $this->safecopy = true;
- $this->logs[] = new DB_Sqlite_Tools_LogObject(__CLASS__, __FUNCTION__, 'done');
- $this->displayLogs();
- return true;
- }
-
- // }}}
- // {{{ scanBackupDir()
-
- /**
- * Scans the backup directory as defined on copysafe for sqlite database
- * preparing for the ftp backup
- *
- * It looks for previously backed up files with extension .bkp
- *
- * @return true
- * @throws PEAR_Exception
- */
- private function scanBackupDir()
- {
- //scanning the directory
- $scanned = @scandir($this->backupp, 0);
-
- if (!$scanned) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_CSD, -1);
- }
-
- foreach ($scanned as $this->parsed) {
- // check if is an backup db file obtained in the previous copySafe
- if(substr($this->parsed, -4) == '.bkp'){
- $this->backupar[] = $this->parsed;
- }
- }
-
- $this->logs[] = new DB_Sqlite_Tools_LogObject(
- __CLASS__, __FUNCTION__, $this->backupar);
- return true ;
- }
-
- // }}}
- // {{{ ftpBackup()
-
- /**
- * Safely copy the backup db to a remote ftp server. this function can be
- * called only after a copySafe operation is performed.
- *
- * It will backup every database in the backup dir which is set with
- * copySafe. If the intended use is to backup different group of databases
- * the user can simply set a different path for copySafe.
- *
- * @param string $server remote ftp server
- * @param string $username ftp username
- * @param string $password ftp password
- * @param string $path remote ftp path
- *
- * @return true
- * @throws PEAR_Exception
- */
- public function ftpBackup($server, $username, $password, $path = '')
- {
- if ($this->safecopy == false) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_INSC, -1);
- }
-
- $this->scanBackupDir();
- $this->ftpConnect($server, $username, $password);
-
- foreach($this->backupar as $database) {
- $localdb = $this->backupp . DIRECTORY_SEPARATOR . $database;
- $put = @ftp_put($this->ftpconnection, $path . '/' . $database,
- $localdb, FTP_BINARY);
-
- if (!$put) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_CUFS);
- } else {
- $this->logs[] = new DB_Sqlite_Tools_LogObject(
- __CLASS__, __FUNCTION__,
- $localdb . ' uploaded');
- }
- }
-
- $this->displayLogs();
- return true;
- }
-
- // }}}
- // {{{ ftpConnect()
-
- /**
- * Connects to the remote ftp server
- *
- * @param string $server remote ftp server
- * @param string $username ftp username
- * @param string $password ftp password
- *
- * @throws PEAR_Exception
- */
- private function ftpConnect ($server,$username,$password)
- {
- $this->ftpconnection = @ftp_connect($server);
- if (!@$this->ftpconnection) {
- throw new PEAR_Exception (self::DB_SQLITE_TOOLS_CCFS,-1);
- }
-
- $logged = ftp_login($this->ftpconnection, $username, $password);
- if (!@$logged) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_CLFS,-1);
- }
- }
-
- // }}}
- // {{{ localBackup()
-
- /**
- * Creates a local backup of the database file and checks for its integrity.
- *
- * @param string $destination Local backup path.
- *
- * @throws PEAR_Exception
- */
- public function localBackup($destination)
- {
- foreach($this->database as $databases) {
- $backupfile = $destination.'/'.$databases.'.bkp';
-
- $fopenlock = @fopen($databases, 'r');
- if (!@$fopenlock) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_COFL, -1);
- }
-
- $lock = @flock($fopenlock, LOCK_EX);
- if (!@$lock) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_CLF, -1);
- }
-
- $clone = @copy($databases, $backupfile);
- if (!@$clone) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_CSF, -1);
- } else {
- $this->logs[] = new DB_Sqlite_Tools_LogObject(
- __CLASS__, __FUNCTION__,
- $backupfile .' successfully copied');
-
- $this->sqliteConnect($backupfile);
- $this->sqliteQuery('PRAGMA integrity_check');
- }
-
- $release = @flock($fopenlock, LOCK_UN);
- if (!@$release) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_CCFL, -1);
- }
- }
-
- $this->displayLogs();
- return true;
- }
-
- // }}}
- // {{{ localRsync()
-
- /**
- * Initiaties a local rsync of a given database path requires rsync
- * installed locally.
- *
- * @param string $databasesPath Path to the databases folder to sync locally
- * @param string $backupsPath Sync Destionation path
- * @param string $options Rsync options
- *
- * @throws PEAR_Exception
- */
- public function localRsync ($databasesPath,$backupsPath,
- $options='--verbose --stats --recursive --progress --delete')
- {
- $command = 'rsync ' . $options . ' ' . $databasesPath . ' ' . $backupsPath;
- $this->logs[] = new DB_Sqlite_Tools_LogObject(__CLASS__, __FUNCTION__, $command);
- $command = escapeshellcmd($command);
- $exec = shell_exec($command);
- $this->logs[] = new DB_Sqlite_Tools_LogObject(__CLASS__, __FUNCTION__, $exec);
- $this->displayLogs();
- }
-
- // }}}
- // {{{ remoteRsync()
-
- /**
- * remoteRsync prepared the server where this package is running to receive
- * read connections over rsync for the purpose of remote synchronisation.
- * it created a valid rsync configuration file and starts the deamon
- * allowing connection from the allowed host.
- *
- * This function is experimental.
- *
- * @param sting $databasesPath Path for the databases folder
- * @param string $configfile name of the rsync config file
- * @param string $configfilepath path where the rsync config file will be saved
- * the users that runs apache must have permissions
- * on this path for the config, the pid and the lock file
- * @param string $uid user id under which rsync will run
- * @param string $gid group id under which rsync will run
- * @param string $allowedhost ip or domain of the allowed host
- * @param string $logs logs file name and path
- * @param string $secretfile rsync secret file location (which should contain the password)
- *
- * @throws PEAR_Exception
- */
- public function remoteRsync ($databasesPath, $configfile, $configfilepath,
- $uid ,$gid , $allowedhost,$logs,$secretfile)
- {
- $rsynconfig= <<<RSYNC
- uid = $uid
- gid = $gid
- use chroot = no
- max connections = 4
- syslog facility = local5
- pid file = $configfilepath/rsyncd.pid
- lock file = $configfilepath/rsyncd.lock
- strict modes = no
- [sqlite_tools]
- read only= yes
- path = $databasesPath
- auth users = rsync
- hosts allow = $allowedhost
- secrets file = $secretfile
- RSYNC;
-
- $cffile = $configfilepath . '/' . $configfile;
- $sfile=@fopen($cffile,'w+');
- if (!@$sfile){
- throw new PEAR_Exception (self::DB_SQLITE_TOOLS_RSE,-1);
- }
-
- $sfilew=@fwrite($sfile,$rsynconfig);
- if (!@$sfilew){
- throw new PEAR_Exception (self::DB_SQLITE_TOOLS_RSE,-1);
- }
-
- $sfileclose=fclose($sfile);
- if (!@$sfileclose){
- throw new PEAR_Exception (self::DB_SQLITE_TOOLS_RSE,-1);
- }
-
- print_r($cffile);
-
- $spec = array(
- 0 => array('pipe', 'r'), // read pipe
- 1 => array('pipe', 'w'), // write pipe
- 2 => array('file', $logs, 'a') // logs file
- );
- $pipes = '';
-
- // added port 2000 because the apache user doesn't have permissions in
- // the default rsync port
- $proc = proc_open("rsync --no-detach --daemon --port=2000 --config=$cffile",
- $spec, $pipes);
-
- fclose($pipes[1]);
- $output = proc_close($proc);
- $this->logs[] = new DB_Sqlite_Log_Object(__CLASS__, __FUNCTION__, $output);
- $this->displayLogs();
- }
-
- // }}}
- // {{{ sqliteLogs()
-
- /**
- * Logs all the perfomed action in a database log
- * this includes backups, integrity checks
- * each of the integrity queries. Verbose XML style output for each of the
- * actions.
- *
- * Sample log output -
- * <logevent> <class>DB_Sqlite_Tools</class> <function>cacheSize</function>
- * <data> 'cache correctly reset to 10000' </data> </logevent>
- *
- * All the logs are saved with the time of execution. The user can easily
- * generate customized logs from the raw data provided in this package.
- *
- * @param string $db Logs database
- * @param string $maketable create a default log table
- * @param string $table table name
- *
- * @throws PEAR_Exception on failure
- */
- public function sqliteLogs($db = '', $maketable = true, $table = '')
- {
- $this->sqliteConnect($db);
- if ($maketable == true) {
- $sql = "CREATE table $table (
- id INTEGER PRIMARY KEY,
- log VARCHAR (200),
- date VARCHAR (200))";
- $this->sqliteQuery($sql);
- }
-
- foreach($this->logs as $logs) {
- $time = time();
- $lstr = $logs->toString() ;
- $sstr = sqlite_escape_string($lstr);
- $sql = "INSERT into $table(log, date)
- VALUES ('$sstr',$time)";
- $this->sqliteQuery($sql);
- }
-
- unset($this->logs);
- }
-
- // }}}
- // {{{ sqliteConnect()
-
- /**
- * Connects to the SQLite database.
- *
- * @param string $db Path to the database
- *
- * @return true
- * @throws PEAR_Exception on failure
- */
- private function sqliteConnect($db)
- {
- $this->debug('Connecting to ' . $db . "\n");
-
- try {
- $obj = $this->dbobj = new SQLiteDatabase($db);
- } catch (PEAR_Exception $obj) {
- print $obj;
- return false ;
- }
-
- return true;
- }
-
- // }}}
- // {{{ sqliteConnectProc()
-
- /**
- * Procedural version of sqliteConnect.
- *
- * @param string $db Path to the database
- *
- * @return TRUE
- * @throws PEAR_Exception
- */
- private function sqliteConnectProc ($db)
- {
- $this->debug(print 'Connecting to ' . $db . "\n");
-
- $this->opendb = @sqlite_open($db, 0666, $this->error);
-
- if (!@$this->opendb){
- throw new PEAR_Exception (self::DB_SQLITE_TOOLS_COD . $this->error, -1);
- }
-
- return true ;
- }
-
- // }}}
- // {{{ sqliteQuery()
-
- /**
- * Queries the sqlite database.
- *
- * @param string $sql query
- *
- * @return $this->results
- */
- private function sqliteQuery($sql)
- {
- $results = $this->dbobj->query($sql);
- if ($results != false) {
- $this->result = $results->fetchObject();
- if (!is_object($this->result)) {
- $this->debug(self::DB_SQLITE_TOOLS_QNR);
- } else {
- $this->debug(
- self::DB_SQLITE_TOOLS_QRS . "\n" .
- print_r($this->result, true)
- );
- }
- }
- return $this->result;
- }
-
- // }}}
- // {{{ XMLDecode()
-
- /**
- * Decodes the XML content.
- *
- * @param string $str A content.
- *
- * @return string
- */
- public function XMLDecode($str)
- {
- return strtr($str, array_flip(get_html_translation_table(HTML_SPECIALCHARS)));
- }
-
- // }}}
- // {{{ XMLEncode()
-
- /**
- * Encodes the XML content.
- *
- * @param string $str A content.
- *
- * @return string
- */
- public function XMLEncode($str)
- {
- return strtr($str, get_html_translation_table(HTML_SPECIALCHARS));
- }
-
- // }}}
- // {{{ performXMLDump()
-
- /**
- * Creates an XML dump for a full sqlite database the dump can be
- * manipulated or used to export the data in several other formats or
- * converted back to an sqlite database with the method createDBFromXML
- *
- * @param string $db the sqlite database file to convert
- * @param string $fh the XML file used for the dump
- *
- */
- private function performXMLDump($db, $fh)
- {
- $this->sqliteConnectProc($db);
-
- // Obtain a list of all tables
- $tableList = array();
- $result = sqlite_query($this->opendb, "SELECT name FROM sqlite_master WHERE type='table'");
-
- if ($result) {
- while (sqlite_has_more($result)) {
- $table = array();
- // Fetch name
- $table["name"] = sqlite_fetch_single($result);
- // Perform a query on the table to get it's columns
- $table["columns"] = array();
- $columnQuery = sqlite_query($this->opendb, "SELECT ALL * FROM ".$table["name"]." LIMIT 1");
- $numColumns = sqlite_num_fields($columnQuery);
- for ($i = 0;$i<$numColumns;$i++) {
- $table["columns"][$i] = array();
- $table["columns"][$i]["name"] = sqlite_field_name($columnQuery, $i);
- $table["columns"][$i]["type"] = "";
- }
- array_push($tableList, $table);
- }
- }
-
- // XML declaration
- fputs($fh, '<?xml version="1.0" encoding="ISO-8859-1" ?>'."\n");
- fputs($fh, "<db name=\"$db\">\n");
- foreach($tableList as $table) {
- fputs($fh, " <table name=\"".$table["name"]."\">\n");
- fputs($fh, " <columns count=\"".count($table["columns"]) ."\">\n");
- foreach($table["columns"] as $column) {
- fputs($fh, " <column name=\"".$column["name"]."\" />\n");
- }
- fputs($fh, " </columns>\n");
- $rowQuery = sqlite_query($this->opendb, "SELECT ALL * FROM ".$table["name"]);
- fputs($fh, " <rows count=\"".sqlite_num_rows($rowQuery) ."\">\n");
- while (sqlite_has_more($rowQuery)) {
- $rowArray = sqlite_fetch_array($rowQuery);
- fputs($fh, " <row>\n");
- foreach($table["columns"] as $column) {
- fputs($fh, " <column name=\"".$column["name"]."\">");
- fputs($fh, $this->XMLEncode($rowArray[$column["name"]]));
- fputs($fh, "</column>\n");
- }
- fputs($fh, " </row>\n");
- }
- fputs($fh, " </rows>\n");
- fputs($fh, " </table>\n");
- }
- fputs($fh, "</db>");
- }
-
- // }}}
- // {{{ createXMLDumps()
-
- /**
- * For each of the databases in our contructor array creates an XML dump
- * including all the tables of that database.
- * The XML file is generated via the function performXMLDump
- * The backup file is by default the database name .xml
- *
- * @return true
- * @throws PEAR exception on failure
- */
- public function createXMLDumps($path ='')
- {
- if ($this->safecopy == false) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_INSC, -1);
- }
-
- $this->scanBackupDir();
- foreach($this->backupar as $database) {
- $XMLFile = @fopen($path . $database . '.xml', 'w');
- if (!$XMLFile) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_CCXML . $database . '.xml', -1);
- }
-
- $this->performXMLDump($this->backupp.DIRECTORY_SEPARATOR . $database, $XMLFile);
- $XMLclose = @fclose($XMLFile);
- if (!$XMLclose) {
- throw new PEAR_Exception(self::DB_SQLITE_TOOLS_CCLXML . $database . '.xml', -1);
- }
-
- $this->debug("{$database}.xml successfully created\n");
- $this->logs[] = new DB_Sqlite_Tools_LogObject(
- __CLASS__, __FUNCTION__, "{$database}.xml successfully created"
- );
- }
-
- $this->displayLogs();
- return true;
- }
-
- // }}}
- // {{{ createDBFromXML()
-
- /**
- * Converts an XML exported database back to an Sqlite database
- *
- * @param string $xmlFile the XML database dump to convert
- * @param string $db the sqlite db to be generated from the XML data
- *
- */
- public function createDBFromXML($xmlFile, $db)
- {
- $this->debug("Now importing XML from $xmlFile to $db\n");
-
- $fh = fopen($xmlFile, "r");
-
- $this->debug("opened $xmlFile as $fh\n");
-
- $parser = new DB_Sqlite_Tools_XMLParser( $fh ) ;
- $parser->ignore('^\?.*$') ;
- $parser->ignore('^!--.*$') ;
-
- $parser->getNextElement() ;
-
- if ($parser->getElementName() != 'db') {
- return false;
- }
-
- $tables = array() ;
-
- while ($parser->getNextElement()) {
- if ($parser->getElementName() == '/db') {
- break ;
- } else if ($parser->getElementName() == 'table') {
- $tableName = $parser->getElementAttribute('name');
- $columns = array() ;
- $rows = array() ;
-
- while($parser->getNextElement()) {
- if($parser->getElementName() == 'rows') {
- $this->debug("Begin rows\n");
- $i = 0 ;
- while ($parser->getNextElement()) {
- if ($parser->getElementName() == 'row') {
- $rows[$i] = array() ;
- while ($parser->getNextElement()) {
- if ($parser->getElementName() == 'column') {
- $curColumn = $parser->getElementAttribute('name');
- $this->debug("Column $curColumn in row $i\n");
- } else if ($parser->getElementName() == '/column') {
- $rows[$i][$curColumn] = $this->XMLDecode($parser->getEnclosed());
- $this->debug("Close column $curColumn in row $i\n");
- } else if ($parser->getElementName() == '/row') {
- break ;
- }
- // end while
- }
- $i++ ;
- // end "row"
- } else if ($parser->getElementName() == '/rows') {
- break ;
- }
- // end while
- }
- // end "rows"
- } else if ($parser->getElementName() == 'columns') {
- $this->debug("Begin columns\n");
- $i = 0 ;
- while ($parser->getNextElement()) {
- if ($parser->getElementName() == 'column') {
- $columns[$i] = array() ;
- $columns[$i]['name'] = $parser->getElementAttribute('name');
- $i++ ;
- // end "row"
- } else if ($parser->getElementName() == '/columns') {
- $this->debug("End columns\n");
- break ;
- }
- // end while
- }
- // end columns
- }
-
- if ($parser->getElementName() == '/table') {
- break ;
- }
-
- // end while
- }
-
- array_push( $tables, array( "name" => $tableName, "columns" => $columns, "rows" => $rows ) ) ;
-
- // end table
- }
-
- // end while
- }
-
- $this->debug("Now performing SQL queries...\n");
-
- $this->sqliteConnect($db);
- $this->sqliteQuery('BEGIN TRANSACTION;');
-
- foreach ($tables as $table) {
- $columnList ='';
- foreach ($table['columns'] as $column) {
- $columnList=$columnList.$column["name"]."," ;
- }
-
- // Remove trailing comma
- $columnList = substr($columnList, 0, strlen($columnList) - 1);
-
- $this->sqliteQuery("CREATE TABLE {$table['name']} ($columnList);");
- foreach ($table['rows'] as $row ) {
- $fieldNameList = '';
- $fieldDataList = '';
- foreach( $row as $fieldName => $fieldData ) {
- $fieldNameList = $fieldNameList . $fieldName . ',';
- $fieldDataList = $fieldDataList . '\'' . sqlite_escape_string($fieldData) . '\',';
- }
-
- // Remove trailing commas
- $fieldNameList=substr($fieldNameList,0,strlen($fieldNameList)-1) ;
- $fieldDataList=substr($fieldDataList,0,strlen($fieldDataList)-1) ;
- $this->sqliteQuery(
- "INSERT OR ROLLBACK INTO
- {$table['name']} ($fieldNameList)
- VALUES
- ($fieldDataList);"
- );
- }
- }
-
- $this->sqliteQuery('COMMIT;') ;
- fclose($fh) ;
- }
-
- // }}}
- // {{{ debug()
-
- /**
- * Set and display debug message if debug is On.
- *
- * @param string $msg Debug message.
- */
- private function debug($msg)
- {
- if ($this->debug) {
- // Web context.
- if (isset($_SERVER['REQUEST_URI'])) {
- $msg = nl2br($msg);
- }
-
- echo 'DB_Sqlite_Tools debug: ' . $msg;
- }
- }
-
- // }}}
- }
-
- // }}}
- // {{{ Class: DB_Sqlite_Tools_LogObject
-
- /**
- * A class provides few function for working with the event log.
- *
- * @category Database
- * @package DB_Sqlite_Tools
- * @author David Costa <gurugeek@php.net>
- * @author Ashley Hewson <morbidness@gmail.com>
- * @author Firman Wandayandi <firman@php.net>
- * @copyright Copyright (c) 2004-2006 David Costa
- * @license http://www.opensource.org/licenses/bsd-license.php
- * BSD License
- * @version Release: 0.1.5
- */
- class DB_Sqlite_Tools_LogObject
- {
- // {{{ Properties
-
- /**
- * Class name.
- *
- * @var string
- */
- private $class;
-
- /**
- * Function name.
- *
- * @var string
- */
- private $function;
-
- /**
- * Log data or message.
- *
- * @var string
- */
- public $data;
-
- // }}}
- // {{{ Constructor()
-
- /**
- * Constructor.
- *
- * @param string $class A class name.
- * @param string $function A function name.
- * @param string $data Log data or message.
- */
- public function __construct($class, $function, $data)
- { $this->class = $class;
- $this->function = $function;
- $this->data = $data;
- }
-
- // }}}
- // {{{ __toString()
-
- /**
- * Magic function, to print this object.
- *
- * This function determine the context of which representation
- * to return.
- *
- * @return string The event log.
- */
- public function __toString()
- {
- if (isset($_SERVER['REQUEST_URI'])) {
- return $this->toHtml();
- }
- return $this->toText();
- }
-
- // }}}
- // {{{ toXML()
-
- /**
- * Creates an XML representation of event log.
- *
- * @return string The XML representation of the event log.
- */
- public function toXML()
- {
- $data = var_export($this->data, true);
-
- return <<<XML
- <logevent>
- <class>$this->class</class>
- <function>$this->function</function>
- <data>$data</data>
- </logevent>
- XML;
- }
-
- // }}}
- // {{{ toText()
-
- /**
- * Creates a plain-text representation of event log.
- *
- * @return string The plain-text representation of event log.
- */
- public function toText()
- {
- return 'DB_Sqlite_Tools log: ' .
- 'logged on ' . $this->class . '::' . $this->function . '(), ' .
- 'data=' . print_r($this->data, true) . "\n";
- }
-
- // }}}
- // {{{ toHTML()
-
- /**
- * Creates a HTML representation of event log.
- *
- * @return string The HTML representation of event log.
- */
- public function toHTML()
- {
- $data = $this->data;
- if (is_array($data) || is_object($this->data)) {
- $data = '<pre>' . "\n"
- . print_r($data, true)
- . '</pre>' . "\n";
- }
-
- return '<table border="1" cellspacing="0">' . "\n"
- . '<tr><td colspan="3" bgcolor="#aaaaaa" align="center"><b>DB_Sqlite_Tools log</b></td></tr>' . "\n"
- . '<tr>'
- . '<td align="center" bgcolor="#cccccc"><b>Event</b></td>'
- . '<td align="center" bgcolor="#cccccc"><b>Data</b></td>'
- . '</tr>' . "\n"
- . '<tr>'
- . '<td valign="top">' . $this->class . '::' . $this->function . '()' . '</td>'
- . '<td>' . $data . '</td>'
- . '</tr>' . "\n"
- . '</table>';
- }
-
- // }}}
- }
-
- // }}}
-
- /*
- * Local variables:
- * mode: php
- * tab-width: 4
- * c-basic-offset: 4
- * c-hanging-comment-ender-p: nil
- * End:
- */
- ?>