This commit is contained in:
Mario Vavti 2017-03-27 12:08:55 +02:00
commit 779cab047a
2 changed files with 116 additions and 118 deletions

View File

@ -2,26 +2,32 @@
namespace Zotlabs\Module; namespace Zotlabs\Module;
// Import a channel, either by direct file upload or via
// connection to original server.
require_once('include/zot.php'); require_once('include/zot.php');
require_once('include/channel.php'); require_once('include/channel.php');
require_once('include/import.php'); require_once('include/import.php');
require_once('include/perm_upgrade.php'); require_once('include/perm_upgrade.php');
/**
* @brief Module for channel import.
*
* Import a channel, either by direct file upload or via
* connection to another server.
*/
class Import extends \Zotlabs\Web\Controller { class Import extends \Zotlabs\Web\Controller {
/**
* @brief Import channel into account.
*
* @param int $account_id
*/
function import_account($account_id) { function import_account($account_id) {
if(! $account_id){ if(! $account_id){
logger("import_account: No account ID supplied"); logger('No account ID supplied');
return; return;
} }
$max_friends = account_service_class_fetch($account_id,'total_channels'); $max_friends = account_service_class_fetch($account_id,'total_channels');
$max_feeds = account_service_class_fetch($account_id,'total_feeds'); $max_feeds = account_service_class_fetch($account_id,'total_feeds');
$data = null; $data = null;
@ -32,35 +38,39 @@ class Import extends \Zotlabs\Web\Controller {
$filename = basename($_FILES['filename']['name']); $filename = basename($_FILES['filename']['name']);
$filesize = intval($_FILES['filename']['size']); $filesize = intval($_FILES['filename']['size']);
$filetype = $_FILES['filename']['type']; $filetype = $_FILES['filename']['type'];
// import channel from file
if($src) { if($src) {
// This is OS specific and could also fail if your tmpdir isn't very large // This is OS specific and could also fail if your tmpdir isn't very
// mostly used for Diaspora which exports gzipped files. // large mostly used for Diaspora which exports gzipped files.
if(strpos($filename,'.gz')){ if(strpos($filename,'.gz')){
@rename($src,$src . '.gz'); @rename($src,$src . '.gz');
@system('gunzip ' . escapeshellarg($src . '.gz')); @system('gunzip ' . escapeshellarg($src . '.gz'));
} }
if($filesize) { if($filesize) {
$data = @file_get_contents($src); $data = @file_get_contents($src);
} }
unlink($src); unlink($src);
} }
// import channel from another server
if(! $src) { if(! $src) {
$old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : ''); $old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
if(! $old_address) { if(! $old_address) {
logger('mod_import: nothing to import.'); logger('Nothing to import.');
notice( t('Nothing to import.') . EOL); notice( t('Nothing to import.') . EOL);
return; return;
} else if(strpos($old_address, '')) {
// if you copy the identity address from your profile page, make it work for convenience
$old_address = str_replace('', '@', $old_address);
} }
$email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : ''); $email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : '');
$password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : ''); $password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : '');
$channelname = substr($old_address,0,strpos($old_address,'@')); $channelname = substr($old_address,0,strpos($old_address,'@'));
$servername = substr($old_address,strpos($old_address,'@')+1); $servername = substr($old_address,strpos($old_address,'@')+1);
@ -85,19 +95,18 @@ class Import extends \Zotlabs\Web\Controller {
return; return;
} }
} }
if(! $data) { if(! $data) {
logger('mod_import: empty file.'); logger('Empty import file.');
notice( t('Imported file is empty.') . EOL); notice( t('Imported file is empty.') . EOL);
return; return;
} }
$data = json_decode($data,true); $data = json_decode($data,true);
// logger('import: data: ' . print_r($data,true)); // logger('import: data: ' . print_r($data,true));
// print_r($data); // print_r($data);
if(! array_key_exists('compatibility',$data)) { if(! array_key_exists('compatibility',$data)) {
call_hooks('import_foreign_channel_data',$data); call_hooks('import_foreign_channel_data',$data);
if($data['handled']) if($data['handled'])
@ -108,24 +117,24 @@ class Import extends \Zotlabs\Web\Controller {
$v1 = substr($data['compatibility']['database'],-4); $v1 = substr($data['compatibility']['database'],-4);
$v2 = substr(DB_UPDATE_VERSION,-4); $v2 = substr(DB_UPDATE_VERSION,-4);
if($v2 > $v1) { if($v2 > $v1) {
$t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 ); $t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 );
notice($t); notice($t);
} }
if(array_key_exists('server_role',$data['compatibility']) && $data['compatibility']['server_role'] == 'basic') if(array_key_exists('server_role',$data['compatibility']) && $data['compatibility']['server_role'] == 'basic')
$moving = true; $moving = true;
} }
if($moving) if($moving)
$seize = 1; $seize = 1;
// import channel // import channel
$relocate = ((array_key_exists('relocate',$data)) ? $data['relocate'] : null); $relocate = ((array_key_exists('relocate',$data)) ? $data['relocate'] : null);
if(array_key_exists('channel',$data)) { if(array_key_exists('channel',$data)) {
$max_identities = account_service_class_fetch($account_id,'total_identities'); $max_identities = account_service_class_fetch($account_id,'total_identities');
if($max_identities !== false) { if($max_identities !== false) {
$r = q("select channel_id from channel where channel_account_id = %d", $r = q("select channel_id from channel where channel_account_id = %d",
intval($account_id) intval($account_id)
@ -137,46 +146,40 @@ class Import extends \Zotlabs\Web\Controller {
} }
$channel = import_channel($data['channel'], $account_id, $seize); $channel = import_channel($data['channel'], $account_id, $seize);
} }
else { else {
$moving = false; $moving = false;
$channel = \App::get_channel(); $channel = \App::get_channel();
} }
if(! $channel) { if(! $channel) {
logger('mod_import: channel not found. ', print_r($channel,true)); logger('Channel not found. ', print_r($channel,true));
notice( t('No channel. Import failed.') . EOL); notice( t('No channel. Import failed.') . EOL);
return; return;
} }
if(is_array($data['config'])) { if(is_array($data['config'])) {
import_config($channel,$data['config']); import_config($channel,$data['config']);
} }
logger('import step 2');
logger('import step 2');
if(array_key_exists('channel',$data)) { if(array_key_exists('channel',$data)) {
if($data['photo']) { if($data['photo']) {
require_once('include/photo/photo_driver.php'); require_once('include/photo/photo_driver.php');
import_channel_photo(base64url_decode($data['photo']['data']),$data['photo']['type'],$account_id,$channel['channel_id']); import_channel_photo(base64url_decode($data['photo']['data']),$data['photo']['type'],$account_id,$channel['channel_id']);
} }
if(is_array($data['profile'])) if(is_array($data['profile']))
import_profiles($channel,$data['profile']); import_profiles($channel,$data['profile']);
} }
logger('import step 3'); logger('import step 3');
if(is_array($data['hubloc'])) { if(is_array($data['hubloc'])) {
import_hublocs($channel,$data['hubloc'],$seize,$moving); import_hublocs($channel,$data['hubloc'],$seize,$moving);
} }
logger('import step 4'); logger('import step 4');
// create new hubloc for the new channel at this site // create new hubloc for the new channel at this site
@ -200,7 +203,7 @@ class Import extends \Zotlabs\Web\Controller {
); );
// reset the original primary hubloc if it is being seized // reset the original primary hubloc if it is being seized
if($seize) { if($seize) {
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ", $r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
dbesc($channel['channel_hash']), dbesc($channel['channel_hash']),
@ -210,20 +213,18 @@ class Import extends \Zotlabs\Web\Controller {
} }
logger('import step 5'); logger('import step 5');
// import xchans and contact photos // import xchans and contact photos
if(array_key_exists('channel',$data) && $seize) { if(array_key_exists('channel',$data) && $seize) {
// replace any existing xchan we may have on this site if we're seizing control // replace any existing xchan we may have on this site if we're seizing control
$r = q("delete from xchan where xchan_hash = '%s'", $r = q("delete from xchan where xchan_hash = '%s'",
dbesc($channel['channel_hash']) dbesc($channel['channel_hash'])
); );
$r = xchan_store_lowlevel( $r = xchan_store_lowlevel(
[ [
'xchan_hash' => $channel['channel_hash'], 'xchan_hash' => $channel['channel_hash'],
@ -242,23 +243,22 @@ class Import extends \Zotlabs\Web\Controller {
'xchan_photo_date' => datetime_convert(), 'xchan_photo_date' => datetime_convert(),
'xchan_name_date' => datetime_convert() 'xchan_name_date' => datetime_convert()
] ]
); );
} }
logger('import step 6'); logger('import step 6');
$xchans = $data['xchan']; $xchans = $data['xchan'];
if($xchans) { if($xchans) {
foreach($xchans as $xchan) { foreach($xchans as $xchan) {
$hash = make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_guid_sig']); $hash = make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_guid_sig']);
if($xchan['xchan_network'] === 'zot' && $hash !== $xchan['xchan_hash']) { if($xchan['xchan_network'] === 'zot' && $hash !== $xchan['xchan_hash']) {
logger('forged xchan: ' . print_r($xchan,true)); logger('forged xchan: ' . print_r($xchan,true));
continue; continue;
} }
if(! array_key_exists('xchan_hidden',$xchan)) { if(! array_key_exists('xchan_hidden',$xchan)) {
$xchan['xchan_hidden'] = (($xchan['xchan_flags'] & 0x0001) ? 1 : 0); $xchan['xchan_hidden'] = (($xchan['xchan_flags'] & 0x0001) ? 1 : 0);
$xchan['xchan_orphan'] = (($xchan['xchan_flags'] & 0x0002) ? 1 : 0); $xchan['xchan_orphan'] = (($xchan['xchan_flags'] & 0x0002) ? 1 : 0);
@ -268,22 +268,22 @@ class Import extends \Zotlabs\Web\Controller {
$xchan['xchan_pubforum'] = (($xchan['xchan_flags'] & 0x0020) ? 1 : 0); $xchan['xchan_pubforum'] = (($xchan['xchan_flags'] & 0x0020) ? 1 : 0);
$xchan['xchan_deleted'] = (($xchan['xchan_flags'] & 0x1000) ? 1 : 0); $xchan['xchan_deleted'] = (($xchan['xchan_flags'] & 0x1000) ? 1 : 0);
} }
$r = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1", $r = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1",
dbesc($xchan['xchan_hash']) dbesc($xchan['xchan_hash'])
); );
if($r) if($r)
continue; continue;
create_table_from_array('xchan',$xchan); create_table_from_array('xchan',$xchan);
require_once('include/photo/photo_driver.php'); require_once('include/photo/photo_driver.php');
$photos = import_xchan_photo($xchan['xchan_photo_l'],$xchan['xchan_hash']); $photos = import_xchan_photo($xchan['xchan_photo_l'],$xchan['xchan_hash']);
if($photos[4]) if($photos[4])
$photodate = NULL_DATE; $photodate = NULL_DATE;
else else
$photodate = $xchan['xchan_photo_date']; $photodate = $xchan['xchan_photo_date'];
$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'", $r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'",
dbesc($photos[0]), dbesc($photos[0]),
dbesc($photos[1]), dbesc($photos[1]),
@ -292,27 +292,27 @@ class Import extends \Zotlabs\Web\Controller {
dbesc($photodate), dbesc($photodate),
dbesc($xchan['xchan_hash']) dbesc($xchan['xchan_hash'])
); );
} }
logger('import step 7'); logger('import step 7');
} }
$friends = 0; $friends = 0;
$feeds = 0; $feeds = 0;
// import contacts // import contacts
$abooks = $data['abook']; $abooks = $data['abook'];
if($abooks) { if($abooks) {
foreach($abooks as $abook) { foreach($abooks as $abook) {
$abook_copy = $abook; $abook_copy = $abook;
$abconfig = null; $abconfig = null;
if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && count($abook['abconfig'])) if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && count($abook['abconfig']))
$abconfig = $abook['abconfig']; $abconfig = $abook['abconfig'];
unset($abook['abook_id']); unset($abook['abook_id']);
unset($abook['abook_rating']); unset($abook['abook_rating']);
unset($abook['abook_rating_text']); unset($abook['abook_rating_text']);
@ -332,7 +332,7 @@ class Import extends \Zotlabs\Web\Controller {
$abook['abook_self'] = (($abook['abook_flags'] & 0x0080 ) ? 1 : 0); $abook['abook_self'] = (($abook['abook_flags'] & 0x0080 ) ? 1 : 0);
$abook['abook_feed'] = (($abook['abook_flags'] & 0x0100 ) ? 1 : 0); $abook['abook_feed'] = (($abook['abook_flags'] & 0x0100 ) ? 1 : 0);
} }
if($abook['abook_self']) { if($abook['abook_self']) {
$role = get_pconfig($channel['channel_id'],'system','permissions_role'); $role = get_pconfig($channel['channel_id'],'system','permissions_role');
if(($role === 'forum') || ($abook['abook_my_perms'] & PERMS_W_TAGWALL)) { if(($role === 'forum') || ($abook['abook_my_perms'] & PERMS_W_TAGWALL)) {
@ -340,14 +340,14 @@ class Import extends \Zotlabs\Web\Controller {
dbesc($abook['abook_xchan']) dbesc($abook['abook_xchan'])
); );
} }
} }
else { else {
if($max_friends !== false && $friends > $max_friends) if($max_friends !== false && $friends > $max_friends)
continue; continue;
if($max_feeds !== false && intval($abook['abook_feed']) && ($feeds > $max_feeds)) if($max_feeds !== false && intval($abook['abook_feed']) && ($feeds > $max_feeds))
continue; continue;
} }
create_table_from_array('abook',$abook); create_table_from_array('abook',$abook);
$friends ++; $friends ++;
@ -355,9 +355,9 @@ class Import extends \Zotlabs\Web\Controller {
$feeds ++; $feeds ++;
translate_abook_perms_inbound($channel,$abook_copy); translate_abook_perms_inbound($channel,$abook_copy);
if($abconfig) { if($abconfig) {
// @fixme does not handle sync of del_abconfig /// @FIXME does not handle sync of del_abconfig
foreach($abconfig as $abc) { foreach($abconfig as $abc) {
set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']); set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
} }
@ -366,7 +366,7 @@ class Import extends \Zotlabs\Web\Controller {
logger('import step 8'); logger('import step 8');
} }
$groups = $data['group']; $groups = $data['group'];
if($groups) { if($groups) {
$saved = array(); $saved = array();
@ -388,10 +388,10 @@ class Import extends \Zotlabs\Web\Controller {
foreach($r as $rr) { foreach($r as $rr) {
$saved[$rr['hash']]['new'] = $rr['id']; $saved[$rr['hash']]['new'] = $rr['id'];
} }
} }
} }
$group_members = $data['group_member']; $group_members = $data['group_member'];
if($group_members) { if($group_members) {
foreach($group_members as $group_member) { foreach($group_members as $group_member) {
@ -406,31 +406,31 @@ class Import extends \Zotlabs\Web\Controller {
} }
logger('import step 9'); logger('import step 9');
if(is_array($data['obj'])) if(is_array($data['obj']))
import_objs($channel,$data['obj']); import_objs($channel,$data['obj']);
if(is_array($data['likes'])) if(is_array($data['likes']))
import_likes($channel,$data['likes']); import_likes($channel,$data['likes']);
if(is_array($data['app'])) if(is_array($data['app']))
import_apps($channel,$data['app']); import_apps($channel,$data['app']);
if(is_array($data['chatroom'])) if(is_array($data['chatroom']))
import_chatrooms($channel,$data['chatroom']); import_chatrooms($channel,$data['chatroom']);
if(is_array($data['conv'])) if(is_array($data['conv']))
import_conv($channel,$data['conv']); import_conv($channel,$data['conv']);
if(is_array($data['mail'])) if(is_array($data['mail']))
import_mail($channel,$data['mail']); import_mail($channel,$data['mail']);
if(is_array($data['event'])) if(is_array($data['event']))
import_events($channel,$data['event']); import_events($channel,$data['event']);
if(is_array($data['event_item'])) if(is_array($data['event_item']))
import_items($channel,$data['event_item'],false,$relocate); import_items($channel,$data['event_item'],false,$relocate);
if(is_array($data['menu'])) if(is_array($data['menu']))
import_menus($channel,$data['menu']); import_menus($channel,$data['menu']);
@ -439,56 +439,61 @@ class Import extends \Zotlabs\Web\Controller {
if(is_array($data['webpages'])) if(is_array($data['webpages']))
import_items($channel,$data['webpages'],false,$relocate); import_items($channel,$data['webpages'],false,$relocate);
$addon = array('channel' => $channel,'data' => $data); $addon = array('channel' => $channel,'data' => $data);
call_hooks('import_channel',$addon); call_hooks('import_channel',$addon);
$saved_notification_flags = notifications_off($channel['channel_id']); $saved_notification_flags = notifications_off($channel['channel_id']);
if($import_posts && array_key_exists('item',$data) && $data['item']) if($import_posts && array_key_exists('item',$data) && $data['item'])
import_items($channel,$data['item'],false,$relocate); import_items($channel,$data['item'],false,$relocate);
notifications_on($channel['channel_id'],$saved_notification_flags); notifications_on($channel['channel_id'],$saved_notification_flags);
if(array_key_exists('item_id',$data) && $data['item_id']) if(array_key_exists('item_id',$data) && $data['item_id'])
import_item_ids($channel,$data['item_id']); import_item_ids($channel,$data['item_id']);
// send out refresh requests // send out refresh requests
// notify old server that it may no longer be primary. // notify old server that it may no longer be primary.
\Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id'])); \Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id']));
// This will indirectly perform a refresh_all *and* update the directory // This will indirectly perform a refresh_all *and* update the directory
\Zotlabs\Daemon\Master::Summon(array('Directory', $channel['channel_id'])); \Zotlabs\Daemon\Master::Summon(array('Directory', $channel['channel_id']));
notice( t('Import completed.') . EOL); notice( t('Import completed.') . EOL);
change_channel($channel['channel_id']); change_channel($channel['channel_id']);
goaway(z_root() . '/network' ); goaway(z_root() . '/network' );
} }
/**
* @brief Handle POST action on channel import page.
*/
function post() { function post() {
$account_id = get_account_id(); $account_id = get_account_id();
if(! $account_id) if(! $account_id)
return; return;
$this->import_account($account_id); $this->import_account($account_id);
} }
/**
* @brief Generate channel import page.
*
* @return string with parsed HTML.
*/
function get() { function get() {
if(! get_account_id()) { if(! get_account_id()) {
notice( t('You must be logged in to use this feature.')); notice( t('You must be logged in to use this feature.'));
return ''; return '';
} }
$o = replace_macros(get_markup_template('channel_import.tpl'),array( $o = replace_macros(get_markup_template('channel_import.tpl'),array(
'$title' => t('Import Channel'), '$title' => t('Import Channel'),
'$desc' => t('Use this form to import an existing channel from a different server/hub. You may retrieve the channel identity from the old server/hub via the network or provide an export file.'), '$desc' => t('Use this form to import an existing channel from a different server/hub. You may retrieve the channel identity from the old server/hub via the network or provide an export file.'),
@ -501,14 +506,13 @@ class Import extends \Zotlabs\Web\Controller {
'$label_import_primary' => t('Make this hub my primary location'), '$label_import_primary' => t('Make this hub my primary location'),
'$label_import_moving' => t('Move this channel (disable all previous locations)'), '$label_import_moving' => t('Move this channel (disable all previous locations)'),
'$label_import_posts' => t('Import a few months of posts if possible (limited by available memory'), '$label_import_posts' => t('Import a few months of posts if possible (limited by available memory'),
'$pleasewait' => t('This process may take several minutes to complete. Please submit the form only once and leave this page open until finished.'), '$pleasewait' => t('This process may take several minutes to complete. Please submit the form only once and leave this page open until finished.'),
'$email' => '', '$email' => '',
'$pass' => '', '$pass' => '',
'$submit' => t('Submit') '$submit' => t('Submit')
)); ));
return $o; return $o;
} }
} }

View File

@ -85,12 +85,6 @@ function import_channel($channel, $account_id, $seize) {
create_table_from_array('channel',$clean); create_table_from_array('channel',$clean);
} }
if(! $r) {
logger('mod_import: channel clone failed. ' . print_r($channel,true));
notice( t('Channel clone failed. Import failed.') . EOL);
return false;
}
$r = q("select * from channel where channel_account_id = %d and channel_guid = '%s' limit 1", $r = q("select * from channel where channel_account_id = %d and channel_guid = '%s' limit 1",
intval($account_id), intval($account_id),
$channel['channel_guid'] // Already dbesc'd $channel['channel_guid'] // Already dbesc'd