Commit db1fb033 authored by Jean-Paul Saman's avatar Jean-Paul Saman

Import dotProject backup module.

parents
Backup Module for dotProject
============================
Copyright (c) 2003 Daniel Vijge [danielvijge@users.sourceforge.net]
This work is based on the work of the phpMyAdmin group:
Copyright (C) 1998-2000 Tobias Ratschiller <tobias.ratschiller_at_maguma.com>
Copyright (C) 2001- Olivier Müller <om_at_omnis.ch>
Loïc Chapeaux <lolo_at_phpHeaven.net>
Marc Delisle <DelislMa_at_CollegeSherbrooke.qc.ca>
Changes to upgrade to dotProject v2.x by Adam Donnison <ajdonnison@dotproject.net>
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.
These files add a backup option to dotProject. It allows you to make backups
of your entire database easily. All you have to do is push a button and the
backup will be generated. You are then presented with a download dialog. You can
save this backup anywhere you want.
To install, create a new directory in the modules directory of dotproject name
'backup' (without quotes). Copy all files into this directory. Open your web-browser
and log in to dotproject. Goto System Admin, View Modules. At the bottom the new module
backup is listed. Press install and the module will be installed. Now press activate and
you're ready.
<?php
// backup database module for dotProject
// (c)2003 Daniel Vijge
// Licensed under GNU/GPL v2 or later
// Based on the work of the phpMyAdmin
// (c)2001-2002 phpMyAdmin group [http://www.phpmyadmin.net]
// Completely rewritten for 2.0 by Adam Donnison <ajdonnison@dotproject.net>
$perms =& $AppUI->acl();
if (! $perms->checkModule('backup', 'view'))
$AppUI->redirect('m=public&a=access_denied');
$export_what = dPgetParam($_POST, 'export_what');
$output_format = dPgetParam($_POST, 'output_format');
$droptable = dPgetParam($_POST, 'droptable', false);
$valid_export_options = array('all', 'table', 'data');
$valid_output_formats = array('xml', 'zip', 'sql');
if (! in_array($export_what, $valid_export_options)
|| ! in_array($output_format, $valid_output_formats)) {
$AppUI->setMsg('Invalid Options', UI_MSG_ERR);
$AppUI->redirect('m=public&a=access_denied');
}
require_once "$baseDir/lib/adodb/adodb-xmlschema.inc.php";
if ($output_format == 'xml') {
$schema = new adoSchema($GLOBALS['db']);
$output = $schema->ExtractSchema(($export_what == 'table') ? false : true);
} else {
// Build the SQL manually.
$db->setFetchMode(ADODB_FETCH_NUM);
$alltables = $db->MetaTables('TABLES');
$output = '';
$output .= '# Backup of database \'' . $dPconfig['dbname'] . '\'' . "\r\n";
$output .= '# Generated on ' . date('j F Y, H:i:s') . "\r\n";
$output .= '# OS: ' . PHP_OS . "\r\n";
$output .= '# PHP version: ' . PHP_VERSION . "\r\n";
if ($dPconfig['dbtype'] == 'mysql')
$output .= '# MySQL version: ' . mysql_get_server_info() . "\r\n";
$output .= "\r\n";
$output .= "\r\n";
// fetch all tables on by one
foreach ($alltables as $table)
{
// introtext for this table
$output .= '# TABLE: ' . $table . "\r\n";
$output .= '# --------------------------' . "\r\n";
$output .= '#' . "\r\n";
$output .= "\r\n";
if ($drop_table)
{
// drop table
$output .= 'DROP TABLE IF EXISTS `' . $table . '`;' . "\r\n";
$output .= "\r\n";
}
if ($export_what != 'data')
{
// structure of the table
$rs = $db->Execute('SELECT * FROM ' . $table . ' WHERE -1');
$fields = $db->MetaColumns($table);
$indexes = $db->MetaIndexes($table);
$output .= 'CREATE TABLE `' . $table . '` (' . "\r\n";
$primary = array();
$first = true;
if (is_array($fields)) {
foreach ($fields as $details) {
if ($first)
$first = false;
else
$output .= ",\r\n";
if ($details->primary_key)
$primary[] = $details->name;
$output .= ' `' . $details->name . '` ' . $details->type;
if ($details->max_length > -1) {
$output .= '(' . $details->max_length;
if (isset($details->scale))
$output .= ',' . $details->scale;
$output .= ')';
}
if ($details->not_null)
$output .= ' NOT NULL';
if ($details->has_default)
$output .= ' DEFAULT ' . "'$details->default_value'";
if ($details->auto_increment)
$output .= ' auto_increment';
}
}
if (is_array($indexes)) {
foreach ($indexes as $index => $details) {
if ($first)
$first = false;
else
$output .= ",\r\n";
$output .= ' ';
if ($details['unique'])
$output .= 'UNIQUE ';
$output .= 'KEY `' . $index . '` ( `' . implode('`, `', $details['columns'] ) . '` )';
}
}
if (count($primary)) {
$output .= "\r\n" . ' PRIMARY KEY ( `'. implode('`, `', $primary) . '` )';
}
$output .= "\r\n" . ');' . "\r\n\r\n";
}
if ($export_what != 'table')
{
// all data from table
$db->setFetchMode(ADODB_FETCH_ASSOC) ;
$result = $db->Execute('SELECT * FROM '.$table);
while($tablerow = $result->fetchRow())
{
$output .= 'INSERT INTO `'.$table.'` ( `' . implode('`, `', array_keys($tablerow)) . '` )' . "\r\n";
$output .= ' VALUES (';
$first = true;
foreach ($tablerow as $value) {
if ($first)
$first = false;
else
$output .= ',';
// remove all enters from the field-string. MySql stamement must be on one line
$value = str_replace("\r\n",'\n',$value);
$value = str_replace("\n", '\n', $value); // Just in case there are unadorned newlines.
// replace ' by \'
$value = str_replace('\'',"\'",$value);
$output .= '\''.$value.'\'';
}
$output .= ');' . "\r\n";
} // while
$output .= "\r\n";
$output .= "\r\n";
}
}
}
switch ($output_format) {
case 'xml':
header('Content-Disposition: attachment; filename="backup.xml"');
header('Content-Type: text/xml');
echo $output;
break;
case 'zip':
header('Content-Disposition: inline; filename="backup.zip"');
header('Content-Type: application/x-zip');
include_once $baseDir . '/modules/backup/zip.lib.php';
$zip = new zipfile;
$zip->addFile($output,'backup.sql');
echo $zip->file();
break;
case 'sql':
header('Content-Disposition: inline; filename="backup.sql"');
header('Content-Type: text/sql');
echo $output;
break;
}
?>
<?php
// Copyright 2005, Adam Donnison <adam@saki.com.au>
// Released under GPL version 2 or later
// Restores an XML file.
$perms =& $AppUI->acl();
if (! $perms->checkModule('backup', 'edit'))
$AppUI->redirect('m=public&a=access_denied');
// Try restoring the XML file.
if (! isset($_FILES['xmlfile'])) {
$AppUI->setMsg('No upload file', UI_MSG_ERR);
$AppUI->redirect();
}
$upload_tmp_file = $_FILES['xmlfile']['tmp_name'];
$continue = dPgetParam($_POST, 'continue', false);
require_once $baseDir . '/lib/adodb/adodb-xmlschema.inc.php';
$schema = new adoSchema($GLOBALS['db']);
$schema->setUpgradeMethod('REPLACE');
$schema->ContinueOnError(true);
if (($sql = $schema->ParseSchemaFile($upload_tmp_file)) == false) {
$AppUI->setMsg('Error in parsing XML file', UI_MSG_ERR);
$AppUI->redirect();
}
$result = 0;
$AppUI->setMsg('');
$errs = array();
echo '<pre>' . "\n";
foreach ($sql as $query) {
if ( $db->Execute($query)) {
if (! $result)
$result = 2;
} else {
echo 'Error in Query: ' . $query . "\n";
echo 'Error: ' . $db->ErrorMsg() . "\n";
if (! $continue) {
$result = 0;
break;
} else {
$result = 1;
}
}
}
echo "</pre>\n";
switch ($result) {
case 0:
echo "<B>" . $AppUI->_('Failed to restore backup') . "</b>";
break;
case 1:
echo "<B>" . $AppUI->_('Backup restored, but with errors') . "</b>";
break;
case 2:
echo "<B>" . $AppUI->_('Backup Restored OK') . "</b>";
break;
}
echo '<br/><b>' . $AppUI->_('xmlLoginMsg') . '</b>';
exit;
?>
<?php
// backup database module for dotProject
// (c)2003 Daniel Vijge
// 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.
// Changes by Adam Donnison <ajdonnison@dotproject.net>
// Changes include:
// Upgraded to work with dotProject 2.0
// Added permissions check to ensure user is allowed to backup
// Added XML backup option
// Completely reworked the backup system to use ADODB primitives.
// Added localisation code so that it can be translated.
$perms =& $AppUI->acl();
if (! $perms->checkModule('backup', 'view')) // Should we have an exec permission?
$AppUI->redirect("m=public&a=access_denied");
$title =& new CTitleBlock('Backup Database', 'companies.gif', $m, $m .'.'.$a);
$title->addCrumb('index.php?m=backup&a=restore', 'restore xml file');
$title->show();
?>
<script>
function check_backup_options()
{
var f = document.frmBackup;
if(f.export_what.options[f.export_what.selectedIndex].value == 'data')
{
f.droptable.enabled=false;
f.droptable.checked=false;
}
else
{
f.droptable.enabled=true;
}
}
</script>
<table cellspacing="0" cellpadding="4" border="0" width="100%" class="std">
<form onclick="check_backup_options()" name="frmBackup" action="<?php echo "$baseUrl/index.php?m=backup&a=do_backup&suppressHeaders=1"; ?>" method="post">
<tr>
<td align="right" valign="top" nowrap="nowrap">
<?php echo $AppUI->_('Export'); ?>
</td>
<td width="100%" nowrap="nowrap">
<select name="export_what" class="text" >
<option value="all" checked="checked"><?php echo $AppUI->_('Table structure and data'); ?></option>
<option value="table"><?php echo $AppUI->_('Only table structure'); ?></option>
<option value="data"><?php echo $AppUI->_('Only data'); ?></option>
</select>
</td>
</tr>
<tr>
<td align="right" valign="top" nowrap="nowrap"><?php echo $AppUI->_('Options'); ?></td>
<td width="100%" nowrap="nowrap">
<input type="checkbox" name="droptable" value="1" checked="checked" /><?php echo $AppUI->_("Add 'DROP TABLE' to output-script"); ?><br />
</td>
</tr>
<tr>
<td align="right" valign="top" nowrap="nowrap"><?php echo $AppUI->_('Save as'); ?></td>
<td width="100%" nowrap="nowrap">
<select name="output_format" class="text" >
<option value="zip" checked="checked"><?php echo $AppUI->_('Compressed ZIP SQL file', UI_OUTPUT_RAW); ?></option>
<option value="sql"><?php echo $AppUI->_('Plain text SQL file', UI_OUTPUT_RAW); ?></option>
<option value="xml"><?php echo $AppUI->_('XML file', UI_OUTPUT_RAW); ?></option>
</select>
</td>
</tr>
<tr>
<td>
&nbsp;
</td>
<td align="right">
<input type="submit" value="<?php echo $AppUI->_('Download backup'); ?>" class="button"/>
</td>
</tr>
</form>
</table>
##
## DO NOT MODIFY THIS FILE BY HAND!
##
"upload",
"Add \'DROP TABLE\' to output-script",
"Backup Database",
"Compressed ZIP SQL file",
"Continue On Error?",
"Download backup",
"Export",
"Only data",
"Only table structure",
"Options",
"Plain text SQL file",
"Restore Database",
"Restore From XML File",
"Save as",
"Table structure and data",
"XML File to Restore",
"XML file",
"xmlLoginMsg"=>"You may need to log out and back in again",
"xmlRestoreWarning"=>"This utitily will restore schema and data from an XML file created by this utility.<br/>It will NOT restore from SQL files.",
<?php
// Copyright 2005, Adam Donnison <adam@saki.com.au>
// Released under GPL version 2 or later.
// Take an XML file and restore it to the database overwriting
// all the data in the database.
$perms =& $AppUI->acl();
if (! $perms->checkModule('backup', 'edit'))
$AppUI->redirect('m=public&a=access_denied');
$AppUI->savePlace();
// Make sure the user realises that this is a drastic operation!
$titleBlock = new CTitleBlock('Restore Database', 'companies.gif', $m, $m.'.'.$a);
$titleBlock->show();
?>
<form name="frmRestore" enctype="multipart/form-data" action="<?php echo "$baseUrl/index.php?m=backup&a=do_restore"; ?>" method="post">
<div align="center">
<table cellspacing="0" cellpadding="4" border="0" width="80%" class="std">
<tr>
<th align="center" colspan="2"><?php echo $AppUI->_('Restore From XML File'); ?></th>
</tr>
<tr>
<td align="center" colspan="2"><?php echo $AppUI->_('xmlRestoreWarning'); ?></td>
</tr>
<tr>
<td align="right" valign="top" nowrap="nowrap"><?php echo $AppUI->_('XML File to Restore'); ?></td>
<td align="left"><input type="file" class="button" name="xmlfile" /></td>
</tr>
<tr>
<td align="right" valign="top" nowrap="nowrap"><?php echo $AppUI->_('Continue On Error?'); ?></td>
<td align="left"><input type="checkbox" class="button" value="1" name="continue" /></td>
</tr>
<tr>
<td align="right">&nbsp;</td>
<td align="right"><input type="submit" class="button" name="restore" value="<?php echo $AppUI->_('upload'); ?>"</td>
</tr>
</table>
</div>
</form>
<?php
/*
* Name: Backup
* Directory: backup
* Version: 2.0
* Class: user
* UI Name: Backup
* UI Icon: companies.gif
*/
// MODULE CONFIGURATION DEFINITION
$config = array();
$config['mod_name'] = 'Backup';
$config['mod_version'] = '2.0';
$config['mod_directory'] = 'backup';
$config['mod_setup_class'] = 'CSetupBackup';
$config['mod_type'] = 'user';
$config['mod_ui_name'] = 'Backup';
$config['mod_ui_icon'] = 'companies.gif';
$config['mod_description'] = 'A module for backing up the database';
if (@$a == 'setup') {
echo dPshowModuleConfig( $config );
}
class CSetupBackup {
function install() {
return null;
}
function remove() {
return null;
}
function upgrade() {
return null;
}
}
?>
<?php
/* $Id: zip.lib.php,v 1.1 2003/11/05 15:39:58 jcgonz Exp $ */
/**
* Zip file creation class.
* Makes zip files.
*
* Based on :
*
* http://www.zend.com/codex.php?id=535&single=1
* By Eric Mueller <eric@themepark.com>
*
* http://www.zend.com/codex.php?id=470&single=1
* by Denis125 <webmaster@atlant.ru>
*
* a patch from Peter Listiak <mlady@users.sourceforge.net> for last modified
* date and time of the compressed file
*
* Official ZIP file format: http://www.pkware.com/appnote.txt
*
* @access public
*/
class zipfile
{
/**
* Array to store compressed data
*
* @var array $datasec
*/
var $datasec = array();
/**
* Central directory
*
* @var array $ctrl_dir
*/
var $ctrl_dir = array();
/**
* End of central directory record
*
* @var string $eof_ctrl_dir
*/
var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
/**
* Last offset position
*
* @var integer $old_offset
*/
var $old_offset = 0;
/**
* Converts an Unix timestamp to a four byte DOS date and time format (date
* in high two bytes, time in low two bytes allowing magnitude comparison).
*
* @param integer the current Unix timestamp
*
* @return integer the current date in a four byte DOS format
*
* @access private
*/
function unix2DosTime($unixtime = 0) {
$timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
if ($timearray['year'] < 1980) {
$timearray['year'] = 1980;
$timearray['mon'] = 1;
$timearray['mday'] = 1;
$timearray['hours'] = 0;
$timearray['minutes'] = 0;
$timearray['seconds'] = 0;
} // end if
return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) |
($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
} // end of the 'unix2DosTime()' method
/**
* Adds "file" to archive
*
* @param string file contents
* @param string name of the file in the archive (may contains the path)
* @param integer the current timestamp
*
* @access public
*/
function addFile($data, $name, $time = 0)
{
$name = str_replace('\\', '/', $name);
$dtime = dechex($this->unix2DosTime($time));
$hexdtime = '\x' . $dtime[6] . $dtime[7]
. '\x' . $dtime[4] . $dtime[5]
. '\x' . $dtime[2] . $dtime[3]
. '\x' . $dtime[0] . $dtime[1];
eval('$hexdtime = "' . $hexdtime . '";');
$fr = "\x50\x4b\x03\x04";
$fr .= "\x14\x00"; // ver needed to extract
$fr .= "\x00\x00"; // gen purpose bit flag
$fr .= "\x08\x00"; // compression method
$fr .= $hexdtime; // last mod time and date
// "local file header" segment
$unc_len = strlen($data);
$crc = crc32($data);
$zdata = gzcompress($data);
$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
$c_len = strlen($zdata);
$fr .= pack('V', $crc); // crc32
$fr .= pack('V', $c_len); // compressed filesize
$fr .= pack('V', $unc_len); // uncompressed filesize
$fr .= pack('v', strlen($name)); // length of filename
$fr .= pack('v', 0); // extra field length
$fr .= $name;
// "file data" segment
$fr .= $zdata;
// "data descriptor" segment (optional but necessary if archive is not
// served as file)
$fr .= pack('V', $crc); // crc32
$fr .= pack('V', $c_len); // compressed filesize
$fr .= pack('V', $unc_len); // uncompressed filesize
// add this entry to array
$this -> datasec[] = $fr;
$new_offset = strlen(implode('', $this->datasec));
// now add to central directory record
$cdrec = "\x50\x4b\x01\x02";
$cdrec .= "\x00\x00"; // version made by
$cdrec .= "\x14\x00"; // version needed to extract
$cdrec .= "\x00\x00"; // gen purpose bit flag
$cdrec .= "\x08\x00"; // compression method
$cdrec .= $hexdtime; // last mod time & date
$cdrec .= pack('V', $crc); // crc32
$cdrec .= pack('V', $c_len); // compressed filesize
$cdrec .= pack('V', $unc_len); // uncompressed filesize
$cdrec .= pack('v', strlen($name) ); // length of filename
$cdrec .= pack('v', 0 ); // extra field length
$cdrec .= pack('v', 0 ); // file comment length
$cdrec .= pack('v', 0 ); // disk number start
$cdrec .= pack('v', 0 ); // internal file attributes
$cdrec .= pack('V', 32 ); // external file attributes - 'archive' bit set
$cdrec .= pack('V', $this -> old_offset ); // relative offset of local header
$this -> old_offset = $new_offset;
$cdrec .= $name;
// optional extra field, file comment goes here
// save to central directory
$this -> ctrl_dir[] = $cdrec;
} // end of the 'addFile()' method
/**
* Dumps out file
*
* @return string the zipped file
*
* @access public
*/
function file()
{
$data = implode('', $this -> datasec);
$ctrldir = implode('', $this -> ctrl_dir);
return
$data .
$ctrldir .
$this -> eof_ctrl_dir .
pack('v', sizeof($this -> ctrl_dir)) . // total # of entries "on this disk"
pack('v', sizeof($this -> ctrl_dir)) . // total # of entries overall
pack('V', strlen($ctrldir)) . // size of central dir
pack('V', strlen($data)) . // offset to start of central dir
"\x00\x00"; // .zip file comment length
} // end of the 'file()' method
} // end of the 'zipfile' class
?>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment