aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/admin_export/settings.php134
-rw-r--r--apps/bookmarks/lib/migrate.php20
-rw-r--r--apps/user_migrate/settings.php2
-rw-r--r--lib/migrate.php773
-rw-r--r--lib/migrate/provider.php28
-rw-r--r--lib/migration/content.php239
-rw-r--r--lib/migration/provider.php49
7 files changed, 589 insertions, 656 deletions
diff --git a/apps/admin_export/settings.php b/apps/admin_export/settings.php
index 1c98bb552f1..af8dd0dbf54 100644
--- a/apps/admin_export/settings.php
+++ b/apps/admin_export/settings.php
@@ -27,11 +27,10 @@ OC_Util::checkAppEnabled('admin_export');
define('DS', '/');
-
// Export?
if (isset($_POST['admin_export'])) {
// Create the export zip
- if( !$path = OC_Migrate::createSysExportFile( $_POST['export_type'] ) ){
+ if( !$path = OC_Migrate::export( $_POST['export_type'] ) ){
// Error
die('error');
} else {
@@ -46,136 +45,11 @@ if (isset($_POST['admin_export'])) {
// Import?
} else if( isset($_POST['admin_import']) ){
- $root = OC::$SERVERROOT . "/";
- $importname = "owncloud_import_" . date("y-m-d_H-i-s");
-
- // Save data dir for later
- $datadir = OC_Config::getValue( 'datadirectory' );
-
- // Copy the uploaded file
- $from = $_FILES['owncloud_import']['tmp_name'];
- $to = get_temp_dir().'/'.$importname.'.zip';
- if( !move_uploaded_file( $from, $to ) ){
- OC_Log::write('admin_export',"Failed to copy the uploaded file",OC_Log::INFO);
- exit();
- }
-
- // Extract zip
- $zip = new ZipArchive();
- if ($zip->open(get_temp_dir().'/'.$importname.'.zip') != TRUE) {
- OC_Log::write('admin_export',"Failed to open zip file",OC_Log::INFO);
- exit();
- }
- $zip->extractTo(get_temp_dir().'/'.$importname.'/');
- $zip->close();
-
- // Delete uploaded file
- unlink( get_temp_dir() . '/' . $importname . '.zip' );
-
- // Now we need to check if everything is present. Data and dbexport.xml
-
-
- // Delete current data folder.
- OC_Log::write('admin_export',"Deleting current data dir",OC_Log::INFO);
- unlinkRecursive( $datadir, false );
-
- // Copy over data
- if( !copy_r( get_temp_dir() . '/' . $importname . '/data', $datadir ) ){
- OC_Log::write('admin_export',"Failed to copy over data directory",OC_Log::INFO);
- exit();
- }
-
- OC_DB::replaceDB( get_temp_dir() . '/' . $importname . '/dbexport.xml' );
+ // TODO
+ // OC_Migrate::import( $pathtozipfile );
} else {
// fill template
$tmpl = new OC_Template('admin_export', 'settings');
return $tmpl->fetchPage();
-}
-
-function zipAddDir($dir, $zip, $recursive=true, $internalDir='') {
- $dirname = basename($dir);
- $zip->addEmptyDir($internalDir . $dirname);
- $internalDir.=$dirname.='/';
-
- if ($dirhandle = opendir($dir)) {
- while (false !== ( $file = readdir($dirhandle))) {
-
- if (( $file != '.' ) && ( $file != '..' )) {
-
- if (is_dir($dir . '/' . $file) && $recursive) {
- zipAddDir($dir . '/' . $file, $zip, $recursive, $internalDir);
- } elseif (is_file($dir . '/' . $file)) {
- $zip->addFile($dir . '/' . $file, $internalDir . $file);
- }
- }
- }
- closedir($dirhandle);
- } else {
- OC_Log::write('admin_export',"Was not able to open directory: " . $dir,OC_Log::ERROR);
- }
-}
-
-function unlinkRecursive($dir, $deleteRootToo)
-{
- if(!$dh = @opendir($dir))
- {
- return;
- }
- while (false !== ($obj = readdir($dh)))
- {
- if($obj == '.' || $obj == '..')
- {
- continue;
- }
-
- if (!@unlink($dir . '/' . $obj))
- {
- unlinkRecursive($dir.'/'.$obj, true);
- }
- }
-
- closedir($dh);
-
- if ($deleteRootToo)
- {
- @rmdir($dir);
- }
-
- return;
-}
-
- function copy_r( $path, $dest )
- {
- if( is_dir($path) )
- {
- @mkdir( $dest );
- $objects = scandir($path);
- if( sizeof($objects) > 0 )
- {
- foreach( $objects as $file )
- {
- if( $file == "." || $file == ".." )
- continue;
- // go on
- if( is_dir( $path.DS.$file ) )
- {
- copy_r( $path.DS.$file, $dest.DS.$file );
- }
- else
- {
- copy( $path.DS.$file, $dest.DS.$file );
- }
- }
- }
- return true;
- }
- elseif( is_file($path) )
- {
- return copy($path, $dest);
- }
- else
- {
- return false;
- }
- }
+} \ No newline at end of file
diff --git a/apps/bookmarks/lib/migrate.php b/apps/bookmarks/lib/migrate.php
index ffc5e9f8387..36a08c0cf40 100644
--- a/apps/bookmarks/lib/migrate.php
+++ b/apps/bookmarks/lib/migrate.php
@@ -1,16 +1,16 @@
<?php
-class OC_Migrate_Provider_Bookmarks extends OC_Migrate_Provider{
+class OC_Migration_Provider_Bookmarks extends OC_Migration_Provider{
// Create the xml for the user supplied
- function export( $uid ){
+ function export( ){
OC_Log::write('migration','starting export for bookmarks',OC_Log::INFO);
$options = array(
'table'=>'bookmarks',
'matchcol'=>'user_id',
- 'matchval'=>$uid,
+ 'matchval'=>$this->uid,
'idcol'=>'id'
);
- $ids = OC_Migrate::copyRows( $options );
+ $ids = $this->content->copyRows( $options );
$options = array(
'table'=>'bookmarks_tags',
@@ -19,7 +19,7 @@ class OC_Migrate_Provider_Bookmarks extends OC_Migrate_Provider{
);
// Export tags
- $ids2 = OC_Migrate::copyRows( $options );
+ $ids2 = $this->content->copyRows( $options );
// If both returned some ids then they worked
if( is_array( $ids ) && is_array( $ids2 ) )
@@ -32,17 +32,17 @@ class OC_Migrate_Provider_Bookmarks extends OC_Migrate_Provider{
}
// Import function for bookmarks
- function import( $app, $info ){
- switch( $app->version ){
+ function import( ){
+ switch( $this->appinfo->version ){
default:
// All versions of the app have had the same db structure, so all can use the same import function
$query = OC_Migrate::prepare( "SELECT * FROM bookmarks WHERE user_id LIKE ?" );
- $results = $query->execute( array( $info['olduid'] ) );
+ $results = $query->execute( array( $this->info['olduid'] ) );
$idmap = array();
while( $row = $data->fetchRow() ){
// Import each bookmark, saving its id into the map
$query = OC_DB::prepare( "INSERT INTO *PREFIX*bookmarks(url, title, user_id, public, added, lastmodified) VALUES (?, ?, ?, ?, ?, ?)" );
- $query->execute( array( $row['url'], $row['title'], $info['newuid'], $row['public'], $row['added'], $row['lastmodified'] ) );
+ $query->execute( array( $row['url'], $row['title'], $this->info['newuid'], $row['public'], $row['added'], $row['lastmodified'] ) );
// Map the id
$idmap[$row['id']] = OC_DB::insertid();
}
@@ -66,4 +66,4 @@ class OC_Migrate_Provider_Bookmarks extends OC_Migrate_Provider{
}
// Load the provider
-new OC_Migrate_Provider_Bookmarks( 'bookmarks' ); \ No newline at end of file
+new OC_Migration_Provider_Bookmarks( 'bookmarks' ); \ No newline at end of file
diff --git a/apps/user_migrate/settings.php b/apps/user_migrate/settings.php
index 62f5e3f20d7..38eee990b46 100644
--- a/apps/user_migrate/settings.php
+++ b/apps/user_migrate/settings.php
@@ -26,7 +26,7 @@ OC_Util::checkAppEnabled('user_migrate');
if (isset($_POST['user_export'])) {
// Create the export zip
- if( !$path = OC_Migrate::createUserExportFile() ){
+ if( !$path = OC_Migrate::export() ){
// Error
die('error');
} else {
diff --git a/lib/migrate.php b/lib/migrate.php
index 84eafcd4cdc..338d091af8b 100644
--- a/lib/migrate.php
+++ b/lib/migrate.php
@@ -22,28 +22,31 @@
/**
- * provides an interface to all search providers
+ * provides an interface to migrate users and whole ownclouds
*/
class OC_Migrate{
- // Holds the db object
- static private $MDB2=false;
+
// Array of OC_Migration_Provider objects
static private $providers=array();
- // Schema db object
- static private $schema=false;
// User id of the user to import/export
static private $uid=false;
- // Path to the sqlite db
- static private $dbpath=false;
// Holds the ZipArchive object
static private $zip=false;
- // String path to export
- static private $zippath=false;
// Stores the type of export
static private $exporttype=false;
// Array of temp files to be deleted after zip creation
static private $tmpfiles=array();
+ // Holds the db object
+ static private $MDB2=false;
+ // Schema db object
+ static private $schema=false;
+ // Path to the sqlite db
+ static private $dbpath=false;
+ // Holds the path to the zip file
+ static private $zippath=false;
+ // Holds the OC_Migration_Content object
+ static private $content=false;
/**
* register a new migration provider
@@ -69,48 +72,180 @@ class OC_Migrate{
}
/**
+ * @breif exports a user, or owncloud instance
+ * @param ootional $type string type of export, defualts to user
+ * @param otional $path string path to zip output folder
+ * @param optional $uid string user id of user to export if export type is user, defaults to current
+ */
+ public static function export( $type='user', $path=null, $uid=null ){
+ $datadir = OC_Config::getValue( 'datadirectory' );
+ // Validate export type
+ $types = array( 'user', 'instance', 'system', 'userfiles' );
+ if( !in_array( $type, $types ) ){
+ OC_Log::write( 'migration', 'Invalid export type', OC_Log::ERROR );
+ return false;
+ }
+ self::$exporttype = $type;
+ // Userid?
+ if( self::$exporttype == 'user' ){
+ // Check user exists
+ if( !is_null($uid) ){
+ if( !OC_User_Database::userExists( $uid ) ){
+ OC_Log::write('migration', 'User: '.$uid.' is not in the database and so cannot be exported.', OC_Log::ERROR);
+ return false;
+ }
+ self::$uid = $uid;
+ } else {
+ self::$uid = OC_User::getUser();
+ }
+ }
+ // Calculate zipname
+ if( self::$exporttype == 'user' ){
+ $zipname = 'oc_export_' . self::$uid . '_' . date("y-m-d_H-i-s") . '.zip';
+ } else {
+ $zipname = 'oc_export_' . self::$exporttype . '_' . date("y-m-d_H-i-s") . '.zip';
+ }
+ // Calculate path
+ if( self::$exporttype == 'user' ){
+ self::$zippath = $datadir . '/' . self::$uid . '/' . $zipname;
+ } else {
+ if( !is_null( $path ) ){
+ // Validate custom path
+ if( !file_exists( $path ) || !is_writeable( $path ) ){
+ OC_Log::write( 'migration', 'Path supplied is invalid.', OC_Log::ERROR );
+ return false;
+ }
+ self::$zippath = $path . $zipname;
+ } else {
+ // Default path
+ self::$zippath = get_temp_dir() . '/' . $zipname;
+ }
+ }
+ // Create the zip object
+ self::$zip = new ZipArchive;
+ if( !self::createZip() ){
+ return false;
+ }
+ // Do the export
+ self::findProviders();
+ $exportdata = array();
+ switch( self::$exporttype ){
+ case 'user':
+ // Connect to the db
+ self::$dbpath = $datadir . '/' . self::$uid . '/migration.db';
+ if( !self::connectDB() ){
+ return false;
+ }
+ self::$content = new OC_Migration_Content( self::$zip, self::$MDB2 );
+ // Export the app info
+ $exportdata = self::exportAppData();
+ // Add the data dir to the zip
+ self::$content->addDir( $datadir . '/' . self::$uid, true, '/' );
+ break;
+ case 'instance':
+ self::$content = new OC_Migration_Content( self::$zip );
+ // Creates a zip that is compatable with the import function
+ $dbfile = tempnam( "/tmp", "owncloud_export_data_" );
+ OC_DB::getDbStructure( $dbfile, 'MDB2_SCHEMA_DUMP_ALL');
+
+ // Now add in *dbname* and *dbprefix*
+ $dbexport = file_get_contents( $dbfile );
+ $dbnamestring = "<database>\n\n <name>" . OC_Config::getValue( "dbname", "owncloud" );
+ $dbtableprefixstring = "<table>\n\n <name>" . OC_Config::getValue( "dbtableprefix", "oc_" );
+ $dbexport = str_replace( $dbnamestring, "<database>\n\n <name>*dbname*", $dbexport );
+ $dbexport = str_replace( $dbtableprefixstring, "<table>\n\n <name>*dbprefix*", $dbexport );
+ // Add the export to the zip
+ self::$content->addFromString( $dbexport, "dbexport.xml" );
+ // Add user data
+ foreach(OC_User::getUsers() as $user){
+ self::$content->addDir( $datadir . '/' . $user . '/', true, "/userdata/" );
+ }
+ break;
+ case 'userfiles':
+ self::$content = new OC_Migration_Content( self::$zip );
+ // Creates a zip with all of the users files
+ foreach(OC_User::getUsers() as $user){
+ self::$content->addDir( $datadir . '/' . $user . '/', true, "/" );
+ }
+ break;
+ case 'system':
+ self::$content = new OC_Migration_Content( self::$zip );
+ // Creates a zip with the owncloud system files
+ self::$content->addDir( OC::$SERVERROOT . '/', false, '/');
+ foreach (array(".git", "3rdparty", "apps", "core", "files", "l10n", "lib", "ocs", "search", "settings", "tests") as $dir) {
+ self::$content->addDir( OC::$SERVERROOT . '/' . $dir, true, "/");
+ }
+ break;
+ }
+ if( !$info = self::getExportInfo( $exportdata ) ){
+ return false;
+ }
+ // Add the export info json to the export zip
+ self::$content->addFromString( $info, 'export_info.json' );
+ if( !self::$content->finish() ){
+ return false;
+ }
+ return self::$zippath;
+ }
+
+ /**
+ * @brief connects to a MDB2 database scheme
+ * @returns bool
+ */
+ static private function connectScheme(){
+ // We need a mdb2 database connection
+ self::$MDB2->loadModule( 'Manager' );
+ self::$MDB2->loadModule( 'Reverse' );
+
+ // Connect if this did not happen before
+ if( !self::$schema ){
+ require_once('MDB2/Schema.php');
+ self::$schema=MDB2_Schema::factory( self::$MDB2 );
+ }
+
+ return true;
+ }
+
+ /**
* @breif creates a migration.db in the users data dir with their app data in
* @return bool whether operation was successfull
*/
private static function exportAppData( ){
- self::connectDB();
- $ok = true;
+ $success = true;
$return = array();
-
- // Find the providers
- self::findProviders();
-
+
// Foreach provider
foreach( self::$providers as $provider ){
- $failed = false;
-
+ $success = true;
// Does this app use the database?
- if(file_exists(OC::$SERVERROOT.'/apps/'.$provider->id.'/appinfo/database.xml')){
+ if( file_exists( OC::$SERVERROOT.'/apps/'.$provider->getID().'/appinfo/database.xml' ) ){
// Create some app tables
- $tables = self::createAppTables( $provider->id );
+ $tables = self::createAppTables( $provider->getID() );
if( is_array( $tables ) ){
// Save the table names
foreach($tables as $table){
- $return['apps'][$provider->id]['tables'][] = $table;
+ $return['apps'][$provider->getID()]['tables'][] = $table;
}
} else {
// It failed to create the tables
- $failed = true;
+ $success = false;
}
}
- // Run the import function?
- if( !$failed ){
- $return['apps'][$provider->id]['success'] = $provider->export( self::$uid );
+ // Run the export function?
+ if( $success ){
+ // Set the provider properties
+ $provider->setData( self::$uid, self::$content );
+ $return['apps'][$provider->getID()]['success'] = $provider->export();
} else {
- $return['apps'][$provider->id]['success'] = false;
- $return['apps'][$provider->id]['message'] = 'failed to create the app tables';
+ $return['apps'][$provider->getID()]['success'] = false;
+ $return['apps'][$provider->getID()]['message'] = 'failed to create the app tables';
}
// Now add some app info the the return array
- $appinfo = OC_App::getAppInfo( $provider->id );
- $return['apps'][$provider->id]['version'] = $appinfo['version'];
+ $appinfo = OC_App::getAppInfo( $provider->getID() );
+ $return['apps'][$provider->getID()]['version'] = $appinfo['version'];
}
@@ -118,97 +253,13 @@ class OC_Migrate{
}
- /**
- * @breif creates an export file for the whole system
- * @param optional $exporttype string export type ('instance','system' or 'userfiles')
- * @param optional $path string path to zip destination (with trailing slash)
- * @return path to the zip or false if there was a problem
- */
- static public function createSysExportFile( $exporttype='instance', $path=null ){
- // Calculate zip name
- $zipname = "oc_export_" . date("y-m-d_H-i-s") . ".zip";
- // Get the data dir
- $datadir = OC_Config::getValue( 'datadirectory' );
- // Calculate destination
- if( !is_null( $path ) ){
- // Path given
- // Is a directory?
- if( !is_dir( $path ) ){
- OC_Log::write('migration', 'Path supplied to createSysExportFile() is not a directory', OC_Log::ERROR);
- return false;
- }
- // Is writeable
- if( !is_writeable( $path ) ){
- OC_Log::write('migration', 'Path supplied to createSysExportFile() is not writeable', OC_Log::ERROR);
- return false;
- }
- self::$zippath = $path . $zipname;
- } else {
- // Save in tmp dir
- self::$zippath = sys_get_temp_dir() . '/' . $zipname;
- }
- // Create the zip object
- self::$zip = new ZipArchive;
- // Try to create the zip
- if( !self::createZip() ){
- return false;
- }
- // Handle export types
- $exporttypes = array( 'userfiles', 'instance', 'system' );
- self::$exporttype = in_array( $exporttype, $exporttypes ) ? $exporttype : false;
- if( !self::$exporttype ){
- OC_Log::write( 'migration', 'Export type: '.$exporttype.' is not supported.', OC_Log::ERROR);
- return false;
- }
- switch( self::$exporttype ){
- case 'instance':
- // Creates a zip that is compatable with the import function
- $dbfile = tempnam( "/tmp", "owncloud_export_data_" );
- OC_DB::getDbStructure( $dbfile, 'MDB2_SCHEMA_DUMP_ALL');
-
- // Now add in *dbname* and *dbprefix*
- $dbexport = file_get_contents( $dbfile );
- $dbnamestring = "<database>\n\n <name>" . OC_Config::getValue( "dbname", "owncloud" );
- $dbtableprefixstring = "<table>\n\n <name>" . OC_Config::getValue( "dbtableprefix", "oc_" );
- $dbexport = str_replace( $dbnamestring, "<database>\n\n <name>*dbname*", $dbexport );
- $dbexport = str_replace( $dbtableprefixstring, "<table>\n\n <name>*dbprefix*", $dbexport );
- // Write the new db export file
- file_put_contents( $dbfile, $dbexport );
- self::$zip->addFile( $dbfile, "dbexport.xml" );
- // Add user data
- foreach(OC_User::getUsers() as $user){
- self::addDirToZip( $datadir . '/' . $user . '/', true, "/userdata/" );
- }
- break;
- case 'userfiles':
- // Creates a zip with all of the users files
- foreach(OC_User::getUsers() as $user){
- self::addDirToZip( $datadir . '/' . $user . '/', true, "/" );
- }
- break;
- case 'system':
- // Creates a zip with the owncloud system files
- self::addDirToZip( OC::$SERVERROOT . '/', false, '/');
- foreach (array(".git", "3rdparty", "apps", "core", "files", "l10n", "lib", "ocs", "search", "settings", "tests") as $dir) {
- self::addDirToZip( OC::$SERVERROOT . '/' . $dir, true, "/");
- }
- break;
- }
- // Add export info
- self::addExportInfo();
- // Close the zip
- if( !self::closeZip() ){
- return false;
- }
- return self::$zippath;
-
- }
/**
- * @breif adds a json file with infomation on the export to the zips root (used on import)
- * @return bool
- */
- static private function addExportInfo( $array=array() ){
+ * @breif generates json containing export info, and merges any data supplied
+ * @param optional $array array of data to include in the returned json
+ * @return bool
+ */
+ static private function getExportInfo( $array=array() ){
$info = array(
'ocversion' => OC_Util::getVersion(),
'exporttime' => time(),
@@ -216,11 +267,12 @@ class OC_Migrate{
'exporttype' => self::$exporttype
);
// Add hash if user export
- if( self::$exporttype = 'user' ){
+ if( self::$exporttype == 'user' ){
$query = OC_DB::prepare( "SELECT password FROM *PREFIX*users WHERE uid LIKE ?" );
$result = $query->execute( array( self::$uid ) );
$row = $result->fetchRow();
$hash = $row ? $row['password'] : false;
+ die(var_dump($hash));
if( !$hash ){
OC_Log::write( 'migration', 'Failed to get the users password hash', OC_log::ERROR);
return false;
@@ -228,110 +280,122 @@ class OC_Migrate{
$info['hash'] = $hash;
$info['exporteduser'] = self::$uid;
}
+ if( !is_array( $array ) ){
+ OC_Log::write( 'migration', 'Supplied $array was not an array in getExportInfo()', OC_Log::ERROR );
+ }
// Merge in other data
- $info = array_merge( $info, $array );
+ $info = array_merge( $info, (array)$array );
// Create json
$json = json_encode( $info );
- $tmpfile = tempnam("/tmp", "oc_export_info_");
- self::$tmpfiles[] = $tmpfile;
- if( !file_put_contents( $tmpfile, $json ) ){
- return false;
- } else {
- self::$zip->addFile( $tmpfile, "/" . self::$uid . "/export_info.json" );
- return true;
- }
- }
-
-
- /**
- * @breif tried to finalise the zip
- * @return bool
- */
- static private function closeZip(){
- if( !self::$zip->close() ){
- OC_Log::write('migration', 'Failed to save the zip with error: '.self::$zip->getStatusString(), OC_Log::ERROR);
- self::cleanup();
- return false;
- } else {
- OC_Log::write('migration', 'Export zip created ok', OC_Log::INFO);
- self::cleanup();
- return true;
- }
- }
-
- /**
- * @breif cleans up after the zip
- */
- static private function cleanup(){
- // Delete tmp files
- foreach(self::$tmpfiles as $i){
- unlink( $i );
- }
+ return true;
}
/**
- * @breif creates a zip user export
- * @param optional $uid string user id of the user to export (defaults to current)
- * @param optional $path string path to folder to create file in (with trailing slash) (defaults to current user's data dir)
- * @return false on failure | string path on success
- */
- static public function createUserExportFile( $uid=null, $path=null ){
- // User passed?
- $uid = is_null( $uid ) ? OC_User::getUser() : $uid ;
- // Is a database user?
- if( !OC_User_Database::userExists( $uid ) ){
- OC_Log::write('migration', 'User: '.$uid.' is not in the database and so cannot be exported.', OC_Log::ERROR);
+ * @breif connects to migration.db, or creates if not found
+ * @param $db optional path to migration.db, defaults to user data dir
+ * @return bool whether the operation was successful
+ */
+ static private function connectDB( $path=null ){
+ // Has the dbpath been set?
+ self::$dbpath = !is_null( $path ) ? $path : self::$dbpath;
+ if( !self::$dbpath ){
+ OC_Log::write( 'migration', 'connectDB() was called without dbpath being set', OC_Log::ERROR );
return false;
}
- // Set the uid
- self::$uid = $uid;
- // Create the zip object
- self::$zip = new ZipArchive;
- // Set export type
- self::$exporttype = 'user';
- // Calculate users data dir
- $user = OC_User::getUser();
- $userdatadir = OC_Config::getValue( 'datadirectory' ) . '/' . $user . '/';
- // Calculate zip name
- $zipname = "oc_userexport_" . $user . '_' . date("y-m-d_H-i-s") . ".zip";
- // Calculate destination
- if( !is_null( $path ) ){
- // Path given
- // Is a directory?
- if( !is_dir( $path ) ){
- OC_Log::write('migration', 'Path supplied to createUserExportFile() is not a directory', OC_Log::ERROR);
- return false;
- }
- // Is writeable
- if( !is_writeable( $path ) ){
- OC_Log::write('migration', 'Path supplied to createUserExportFile() is not writeable', OC_Log::ERROR);
+ // Already connected
+ if(!self::$MDB2){
+ require_once('MDB2.php');
+
+ $datadir = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" );
+
+ // Prepare options array
+ $options = array(
+ 'portability' => MDB2_PORTABILITY_ALL & (!MDB2_PORTABILITY_FIX_CASE),
+ 'log_line_break' => '<br>',
+ 'idxname_format' => '%s',
+ 'debug' => true,
+ 'quote_identifier' => true
+ );
+ $dsn = array(
+ 'phptype' => 'sqlite3',
+ 'database' => self::$dbpath,
+ 'mode' => '0644'
+ );
+
+ // Try to establish connection
+ self::$MDB2 = MDB2::factory( $dsn, $options );
+ // Die if we could not connect
+ if( PEAR::isError( self::$MDB2 ) ){
+ die( self::$MDB2->getMessage() );
+ OC_Log::write( 'migration', 'Failed to create/connect to migration.db', OC_Log::FATAL );
+ OC_Log::write( 'migration', self::$MDB2->getUserInfo(), OC_Log::FATAL );
+ OC_Log::write( 'migration', self::$MDB2->getMessage(), OC_Log::FATAL );
return false;
}
- self::$zippath = $path . $zipname;
- } else {
- // Save in users data dir
- self::$zippath = $userdatadir . $zipname;
+ // We always, really always want associative arrays
+ self::$MDB2->setFetchMode(MDB2_FETCHMODE_ASSOC);
}
- // Try to create the zip
- if( !self::createZip() ){
- return false;
- }
- // Export the app info
- $appinfo = self::exportAppData();
- // Save the migration results
- self::addExportInfo( $appinfo );
- // Add the data dir to the zip
- self::addDirToZip( $userdatadir );
- // Close the zip
- if( !self::closeZip() ){
+ return true;
+
+ }
+
+ /**
+ * @breif creates the tables in migration.db from an apps database.xml
+ * @param $appid string id of the app
+ * @return bool whether the operation was successful
+ */
+ static private function createAppTables( $appid ){
+
+ if( !self::connectScheme() ){
return false;
}
- // All good
- return self::$zippath;
- }
-
+
+ // There is a database.xml file
+ $content = file_get_contents( OC::$SERVERROOT . '/apps/' . $appid . '/appinfo/database.xml' );
+
+ $file2 = 'static://db_scheme';
+ // TODO get the relative path to migration.db from the data dir
+ // For now just cheat
+ $path = pathinfo( self::$dbpath );
+ $content = str_replace( '*dbname*', self::$uid.'/migration', $content );
+ $content = str_replace( '*dbprefix*', '', $content );
+
+ $xml = new SimpleXMLElement($content);
+ foreach($xml->table as $table){
+ $tables[] = (string)$table->name;
+ }
+
+ file_put_contents( $file2, $content );
+
+ // Try to create tables
+ $definition = self::$schema->parseDatabaseDefinitionFile( $file2 );
+
+ unlink( $file2 );
+
+ // Die in case something went wrong
+ if( $definition instanceof MDB2_Schema_Error ){
+ OC_Log::write( 'migration', 'Failed to parse database.xml for: '.$appid, OC_Log::FATAL );
+ OC_Log::write( 'migration', $definition->getMessage().': '.$definition->getUserInfo(), OC_Log::FATAL );
+ return false;
+ }
+
+ $definition['overwrite'] = true;
+
+ $ret = self::$schema->createDatabase( $definition );
+
+ // Die in case something went wrong
+ if( $ret instanceof MDB2_Error ){
+ OC_Log::write( 'migration', 'Failed to create tables for: '.$appid, OC_Log::FATAL );
+ OC_Log::write( 'migration', $ret->getMessage().': '.$ret->getUserInfo(), OC_Log::FATAL );
+ return false;
+ }
+ return $tables;
+
+ }
+
/**
* @breif tries to create the zip
+ * @param $path string path to zip destination
* @return bool
*/
static private function createZip(){
@@ -340,45 +404,13 @@ class OC_Migrate{
OC_Log::write('migration', 'createZip() called but $zip and/or $zippath have not been set', OC_Log::ERROR);
return false;
}
- if ( self::$zip->open( self::$zippath, ZIPARCHIVE::CREATE ) !== TRUE ) {
+ if ( self::$zip->open( self::$zippath, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE ) !== TRUE ) {
OC_Log::write('migration', 'Failed to create the zip with error: '.self::$zip->getStatusString(), OC_Log::ERROR);
return false;
} else {
return true;
}
}
-
- /**
- * @breif adds a directory to the zip object
- * @param $dir string path of the directory to add
- * @param $recursive bool
- * @param $internaldir string path of folder to add dir to in zip
- * @return bool
- */
- static private function addDirToZip($dir, $recursive=true, $internaldir='') {
- $dirname = basename($dir);
- self::$zip->addEmptyDir($internaldir . $dirname);
- $internaldir.=$dirname.='/';
-
- if ($dirhandle = opendir($dir)) {
- while (false !== ( $file = readdir($dirhandle))) {
-
- if (( $file != '.' ) && ( $file != '..' )) {
-
- if (is_dir($dir . '/' . $file) && $recursive) {
- self::addDirToZip($dir . '/' . $file, $recursive, $internaldir);
- } elseif (is_file($dir . '/' . $file)) {
- self::$zip->addFile($dir . '/' . $file, $internaldir . $file);
- }
- }
- }
- closedir($dirhandle);
- } else {
- OC_Log::write('admin_export',"Was not able to open directory: " . $dir,OC_Log::ERROR);
- return false;
- }
- return true;
- }
/**
* @breif returns an array of apps that support migration
@@ -429,10 +461,17 @@ class OC_Migrate{
foreach( self::$providers as $provider){
// Is the app in the export?
- $id = $provider->id;
+ $id = $provider->getID();
if( isset( $info->apps->$id ) ){
// Did it succeed?
if( $info->apps->$id->success ){
+ // Give the provider the content object
+ // TODO PASS THE PATH TO MIGRATION.DB
+ if( !self::connectDB() ){
+ return false;
+ }
+ $content = new OC_Migration_Content( self::$zip, self::$db );
+ $provider->setObject( $content );
// Then do the import
$provider->import( $info->apps->$id, $importinfo );
}
@@ -443,252 +482,12 @@ class OC_Migrate{
}
- // @breif connects to migration.db, or creates if not found
- // @param $db optional path to migration.db, defaults to user data dir
- // @return bool whether the operation was successful
- private static function connectDB( $dbpath=null ){
- OC_Log::write('migration','connecting to migration.db for user: '.self::$uid,OC_Log::INFO);
- // Fail if no user is set
- if(!self::$uid){
- OC_Log::write('migration','connectDB() called without self::$uid being set',OC_Log::INFO);
- return false;
- }
- // Already connected
- if(!self::$MDB2){
- require_once('MDB2.php');
-
- $datadir = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" );
-
- self::$dbpath = $datadir.'/'.self::$uid.'/migration.db';//!is_null( $dbpath ) ? $dbpath : $datadir.'/'.self::$uid.'/migration.db';
-
- // Prepare options array
- $options = array(
- 'portability' => MDB2_PORTABILITY_ALL & (!MDB2_PORTABILITY_FIX_CASE),
- 'log_line_break' => '<br>',
- 'idxname_format' => '%s',
- 'debug' => true,
- 'quote_identifier' => true
- );
- $dsn = array(
- 'phptype' => 'sqlite3',
- 'database' => self::$dbpath,
- 'mode' => '0644'
- );
-
- // Try to establish connection
- self::$MDB2 = MDB2::factory( $dsn, $options );
- // Die if we could not connect
- if( PEAR::isError( self::$MDB2 )){
- die(self::$MDB2->getMessage());
- OC_Log::write('migration', 'Failed to create/connect to migration.db',OC_Log::FATAL);
- OC_Log::write('migration',self::$MDB2->getUserInfo(),OC_Log::FATAL);
- OC_Log::write('migration',self::$MDB2->getMessage(),OC_Log::FATAL);
- return false;
- } else {
- }
- // We always, really always want associative arrays
- self::$MDB2->setFetchMode(MDB2_FETCHMODE_ASSOC);
- }
- return true;
-
- }
-
- // @breif prepares the db
- // @param $query the sql query to prepare
- public static function prepare( $query ){
-
- // Optimize the query
- $query = self::processQuery( $query );
-
- // Optimize the query
- $query = self::$MDB2->prepare( $query );
-
- // Die if we have an error (error means: bad query, not 0 results!)
- if( PEAR::isError( $query )) {
- $entry = 'DB Error: "'.$result->getMessage().'"<br />';
- $entry .= 'Offending command was: '.$query.'<br />';
- OC_Log::write('migration',$entry,OC_Log::FATAL);
- return false;
- } else {
- return $query;
- }
-
- }
-
- // @breif processes the db query
- // @param $query the query to process
- // @return string of processed query
- private static function processQuery( $query ){
-
- self::connectDB();
- $prefix = '';
-
- $query = str_replace( '`', '\'', $query );
- $query = str_replace( 'NOW()', 'datetime(\'now\')', $query );
- $query = str_replace( 'now()', 'datetime(\'now\')', $query );
-
- // replace table name prefix
- $query = str_replace( '*PREFIX*', $prefix, $query );
-
- return $query;
-
- }
-
- // @brief copys rows to migration.db from the main database
- // @param $options array of options.
- // @return bool
- public static function copyRows( $options ){
- if( !array_key_exists( 'table', $options ) ){
- return false;
- }
-
- $return = array();
-
- // Need to include 'where' in the query?
- if( array_key_exists( 'matchval', $options ) && array_key_exists( 'matchcol', $options ) ){
-
- // If only one matchval, create an array
- if(!is_array($options['matchval'])){
- $options['matchval'] = array( $options['matchval'] );
- }
-
- foreach( $options['matchval'] as $matchval ){
- // Run the query for this match value (where x = y value)
- $query = OC_DB::prepare( "SELECT * FROM *PREFIX*" . $options['table'] . " WHERE " . $options['matchcol'] . " LIKE ?" );
- $results = $query->execute( array( $matchval ) );
- $newreturns = self::insertData( $results, $options );
- $return = array_merge( $return, $newreturns );
- }
-
- } else {
- // Just get everything
- $query = OC_DB::prepare( "SELECT * FROM *PREFIX*" . $options['table'] );
- $results = $query->execute();
- $return = self::insertData( $results, $options );
-
- }
-
- return $return;
-
- }
-
- // @breif saves a sql data set into migration.db
- // @param $data a sql data set returned from self::prepare()->query()
- // @param $options array of copyRows options
- // @return void
- private static function insertData( $data, $options ){
- $return = array();
- while( $row = $data->fetchRow() ){
- // Now save all this to the migration.db
- $fields = array();
- $values = array();
- foreach($row as $field=>$value){
- $fields[] = $field;
- $values[] = $value;
- }
-
- // Generate some sql
- $sql = "INSERT INTO `" . $options['table'] . '` ( `';
- $fieldssql = implode( '`, `', $fields );
- $sql .= $fieldssql . "` ) VALUES( ";
- $valuessql = substr( str_repeat( '?, ', count( $fields ) ),0,-2 );
- $sql .= $valuessql . " )";
- // Make the query
- $query = self::prepare( $sql );
- if(!$query){
- OC_Log::write('migration','Invalid sql produced: '.$sql,OC_Log::FATAL);
- return false;
- exit();
- } else {
- $query->execute( $values );
- // Do we need to return some values?
- if( array_key_exists( 'idcol', $options ) ){
- // Yes we do
- $return[] = $row[$options['idcol']];
- } else {
- // Take a guess and return the first field :)
- $return[] = reset($row);
- }
- }
- }
- return $return;
- }
-
- // @breif creates the tables in migration.db from an apps database.xml
- // @param $appid string id of the app
- // @return bool whether the operation was successful
- private static function createAppTables( $appid ){
-
- if(!self::connectScheme()){
- return false;
- }
-
- // There is a database.xml file
- $content = file_get_contents( OC::$SERVERROOT . '/apps/' . $appid . '/appinfo/database.xml' );
-
- $file2 = 'static://db_scheme';
- $content = str_replace( '*dbname*', self::$uid.'/migration', $content );
- $content = str_replace( '*dbprefix*', '', $content );
-
- $xml = new SimpleXMLElement($content);
- foreach($xml->table as $table){
- $tables[] = (string)$table->name;
- }
-
- file_put_contents( $file2, $content );
-
- // Try to create tables
- $definition = self::$schema->parseDatabaseDefinitionFile( $file2 );
-
- unlink( $file2 );
-
- // Die in case something went wrong
- if( $definition instanceof MDB2_Schema_Error ){
- OC_Log::write('migration','Failed to parse database.xml for: '.$appid,OC_Log::FATAL);
- OC_Log::write('migration',$definition->getMessage().': '.$definition->getUserInfo(),OC_Log::FATAL);
- return false;
- }
-
- $definition['overwrite'] = true;
-
- $ret = self::$schema->createDatabase( $definition );
- // Die in case something went wrong
-
- if( $ret instanceof MDB2_Error ){
- OC_Log::write('migration','Failed to create tables for: '.$appid,OC_Log::FATAL);
- OC_Log::write('migration',$ret->getMessage().': '.$ret->getUserInfo(),OC_Log::FATAL);
- return false;
- }
- return $tables;
-
- }
-
-
- /**
- * @brief connects to a MDB2 database scheme
- * @returns true/false
- *
- * Connects to a MDB2 database scheme
- */
- private static function connectScheme(){
- // We need a mdb2 database connection
- self::connectDB();
- self::$MDB2->loadModule( 'Manager' );
- self::$MDB2->loadModule( 'Reverse' );
-
- // Connect if this did not happen before
- if( !self::$schema ){
- require_once('MDB2/Schema.php');
- self::$schema=MDB2_Schema::factory( self::$MDB2 );
- }
-
- return true;
- }
-
- // @breif creates a new user in the database
- // @param $uid string user_id of the user to be created
- // @param $hash string hash of the user to be created
- // @return bool result of user creation
+ /*
+ * @breif creates a new user in the database
+ * @param $uid string user_id of the user to be created
+ * @param $hash string hash of the user to be created
+ * @return bool result of user creation
+ */
public static function createUser( $uid, $hash ){
// Check if userid exists
diff --git a/lib/migrate/provider.php b/lib/migrate/provider.php
deleted file mode 100644
index 7ac3cf97cad..00000000000
--- a/lib/migrate/provider.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-/**
- * provides search functionalty
- */
-abstract class OC_Migrate_Provider{
-
- public $id;
-
- public function __construct( $appid ){
- $this->id = $appid;
- OC_Migrate::registerProvider( $this );
- }
-
- /**
- * @breif exports data for apps
- * @param string $uid
- * @return array appdata to be exported
- */
- abstract function export($uid);
-
- /**
- * @breif imports data for the app
- * @param $appinfo object with the data that the app exported
- * @param $info array of info including exportinfo.json
- * @return void
- */
- abstract function import( $appinfo, $info );
-}
diff --git a/lib/migration/content.php b/lib/migration/content.php
new file mode 100644
index 00000000000..fe8a21a45b4
--- /dev/null
+++ b/lib/migration/content.php
@@ -0,0 +1,239 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Tom Needham
+ * @copyright 2012 Tom Needham tom@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+/**
+ * provides methods to add and access data from the migration
+ */
+class OC_Migration_Content{
+
+ private $zip=false;
+ // Holds the MDB2 object
+ private $db=false;
+ // Holds an array of tmpfiles to delete after zip creation
+ private $tmpfiles=false;
+
+ /**
+ * @breif sets up the
+ * @param $zip ZipArchive object
+ * @param optional $db a MDB2 database object (required for exporttype user)
+ * @return bool
+ */
+ public function __construct( $zip, $db=false ){
+
+ $this->zip = $zip;
+ $this->db = $db;
+
+ }
+
+ // @breif prepares the db
+ // @param $query the sql query to prepare
+ public function prepare( $query ){
+
+ // Optimize the query
+ $query = $this->processQuery( $query );
+
+ // Optimize the query
+ $query = $this->MDB2->prepare( $query );
+
+ // Die if we have an error (error means: bad query, not 0 results!)
+ if( PEAR::isError( $query ) ) {
+ $entry = 'DB Error: "'.$result->getMessage().'"<br />';
+ $entry .= 'Offending command was: '.$query.'<br />';
+ OC_Log::write( 'migration', $entry, OC_Log::FATAL );
+ return false;
+ } else {
+ return $query;
+ }
+
+ }
+
+ /**
+ * @breif processes the db query
+ * @param $query the query to process
+ * @return string of processed query
+ */
+ private function processQuery( $query ){
+ $query = str_replace( '`', '\'', $query );
+ $query = str_replace( 'NOW()', 'datetime(\'now\')', $query );
+ $query = str_replace( 'now()', 'datetime(\'now\')', $query );
+ // remove table prefixes
+ $query = str_replace( '*PREFIX*', '', $query );
+ return $query;
+ }
+
+ /**
+ * @brief copys rows to migration.db from the main database
+ * @param $options array of options.
+ * @return bool
+ */
+ public function copyRows( $options ){
+ if( !array_key_exists( 'table', $options ) ){
+ return false;
+ }
+
+ $return = array();
+
+ // Need to include 'where' in the query?
+ if( array_key_exists( 'matchval', $options ) && array_key_exists( 'matchcol', $options ) ){
+
+ // If only one matchval, create an array
+ if(!is_array($options['matchval'])){
+ $options['matchval'] = array( $options['matchval'] );
+ }
+
+ foreach( $options['matchval'] as $matchval ){
+ // Run the query for this match value (where x = y value)
+ $query = OC_DB::prepare( "SELECT * FROM *PREFIX*" . $options['table'] . " WHERE " . $options['matchcol'] . " LIKE ?" );
+ $results = $query->execute( array( $matchval ) );
+ $newreturns = $this->insertData( $results, $options );
+ $return = array_merge( $return, $newreturns );
+ }
+
+ } else {
+ // Just get everything
+ $query = OC_DB::prepare( "SELECT * FROM *PREFIX*" . $options['table'] );
+ $results = $query->execute();
+ $return = $this->insertData( $results, $options );
+
+ }
+
+ return $return;
+
+ }
+
+ /**
+ * @breif saves a sql data set into migration.db
+ * @param $data a sql data set returned from self::prepare()->query()
+ * @param $options array of copyRows options
+ * @return void
+ */
+ private function insertData( $data, $options ){
+ $return = array();
+ while( $row = $data->fetchRow() ){
+ // Now save all this to the migration.db
+ foreach($row as $field=>$value){
+ $fields[] = $field;
+ $values[] = $value;
+ }
+
+ // Generate some sql
+ $sql = "INSERT INTO `" . $options['table'] . '` ( `';
+ $fieldssql = implode( '`, `', $fields );
+ $sql .= $fieldssql . "` ) VALUES( ";
+ $valuessql = substr( str_repeat( '?, ', count( $fields ) ),0,-2 );
+ $sql .= $valuessql . " )";
+ // Make the query
+ $query = $this->prepare( $sql );
+ if( !$query ){
+ OC_Log::write( 'migration', 'Invalid sql produced: '.$sql, OC_Log::FATAL );
+ return false;
+ exit();
+ } else {
+ $query->execute( $values );
+ // Do we need to return some values?
+ if( array_key_exists( 'idcol', $options ) ){
+ // Yes we do
+ $return[] = $row[$options['idcol']];
+ } else {
+ // Take a guess and return the first field :)
+ $return[] = reset($row);
+ }
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * @breif adds a directory to the zip object
+ * @param $dir string path of the directory to add
+ * @param $recursive bool
+ * @param $internaldir string path of folder to add dir to in zip
+ * @return bool
+ */
+ public function addDir( $dir, $recursive=true, $internaldir='' ) {
+ $dirname = basename($dir);
+ $this->zip->addEmptyDir($internaldir . $dirname);
+ $internaldir.=$dirname.='/';
+
+ if ($dirhandle = opendir($dir)) {
+ while (false !== ( $file = readdir($dirhandle))) {
+
+ if (( $file != '.' ) && ( $file != '..' )) {
+
+ if (is_dir($dir . '/' . $file) && $recursive) {
+ $this->addDir($dir . '/' . $file, $recursive, $internaldir);
+ } elseif (is_file($dir . '/' . $file)) {
+ $this->zip->addFile($dir . '/' . $file, $internaldir . $file);
+ }
+ }
+ }
+ closedir($dirhandle);
+ } else {
+ OC_Log::write('admin_export',"Was not able to open directory: " . $dir,OC_Log::ERROR);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @breif adds a file to the zip from a given string
+ * @param $data string of data to add
+ * @param $path the relative path inside of the zip to save the file to
+ * @return bool
+ */
+ public function addFromString( $data, $path ){
+ // Create a temp file
+ $file = tempnam( get_temp_dir(). '/', 'oc_export_tmp_' );
+ $this->tmpfiles[] = $file;
+ if( !file_put_contents( $file, $data ) ){
+ OC_Log::write( 'migation', 'Failed to save data to a temporary file', OC_Log::ERROR );
+ return false;
+ }
+ // Add file to the zip
+ $this->zip->addFile( $file, $path );
+ return true;
+ }
+
+ /**
+ * @breif closes the zip, removes temp files
+ * @return bool
+ */
+ public function finish(){
+ if( !$this->zip->close() ){
+ OC_Log::write( 'migration', 'Failed to write the zip file with error: '.$this->zip->getStatusString(), OC_Log::ERROR );
+ return false;
+ }
+ $this->cleanup();
+ return true;
+ }
+
+ /**
+ * @breif cleans up after the zip
+ */
+ private function cleanup(){
+ // Delete tmp files
+ foreach($this->tmpfiles as $i){
+ unlink( $i );
+ }
+ }
+} \ No newline at end of file
diff --git a/lib/migration/provider.php b/lib/migration/provider.php
new file mode 100644
index 00000000000..b9e2c476203
--- /dev/null
+++ b/lib/migration/provider.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * provides search functionalty
+ */
+abstract class OC_Migration_Provider{
+
+ protected $id=false;
+ protected $content=false;
+ protected $uid=false;
+ protected $info=false;
+ protected $appinfo=false;
+
+ public function __construct( $appid ){
+ // Set the id
+ $this->id = $appid;
+ OC_Migrate::registerProvider( $this );
+ }
+
+ /**
+ * @breif exports data for apps
+ * @return array appdata to be exported
+ */
+ abstract function export( );
+
+ /**
+ * @breif imports data for the app
+ * @return void
+ */
+ abstract function import( );
+
+ /**
+ * @breif sets the OC_Migration_Content object to $this->content
+ * @param $content a OC_Migration_Content object
+ */
+ public function setData( $uid, $content, $info=false, $appinfo=false ){
+ $this->content = $content;
+ $this->uid = $uid;
+ $this->info = $info;
+ $this->appinfo = $appinfo;
+ }
+
+ /**
+ * @breif returns the appid of the provider
+ * @return string
+ */
+ public function getID(){
+ return $this->id;
+ }
+}