2016-04-19 03:38:38 +00:00
< ? php
2017-02-06 04:26:06 +00:00
2022-02-16 04:08:28 +00:00
namespace Code\Module ;
2016-04-19 03:38:38 +00:00
2019-05-29 23:29:55 +00:00
use App ;
use URLify ;
2022-02-16 04:08:28 +00:00
use Code\Web\Controller ;
use Code\Web\HTTPSig ;
use Code\Lib\Libzot ;
use Code\Lib\Connect ;
use Code\Lib\Channel ;
2024-01-02 04:47:27 +00:00
use Code\Lib\Multibase ;
2022-02-16 04:08:28 +00:00
use Code\Daemon\Run ;
use Code\Import\Friendica ;
use Code\Lib\ServiceClass ;
use Code\Extend\Hook ;
use Code\Render\Theme ;
2022-06-23 07:38:34 +00:00
use Code\Lib\Url ;
2022-02-12 20:43:29 +00:00
2016-04-19 03:38:38 +00:00
require_once ( 'include/import.php' );
2019-05-29 23:29:55 +00:00
require_once ( 'include/photo_factory.php' );
2016-04-19 03:38:38 +00:00
2017-03-23 22:40:12 +00:00
/**
* @ brief Module for channel import .
*
* Import a channel , either by direct file upload or via
* connection to another server .
*/
2021-12-02 23:02:31 +00:00
class Import extends Controller
{
/**
* @ brief Import channel into account .
*
* @ param int $account_id
*/
public function import_account ( $account_id )
{
if ( ! $account_id ) {
logger ( 'No account ID supplied' );
return ;
}
2022-01-25 01:26:12 +00:00
$max_friends = ServiceClass :: account_fetch ( $account_id , 'total_channels' );
$max_feeds = ServiceClass :: account_fetch ( $account_id , 'total_feeds' );
2021-12-02 23:02:31 +00:00
$data = null ;
$seize = (( x ( $_REQUEST , 'make_primary' )) ? intval ( $_REQUEST [ 'make_primary' ]) : 0 );
2022-10-18 19:23:50 +00:00
$import_posts = 0 ;
2021-12-02 23:02:31 +00:00
$src = $_FILES [ 'filename' ][ 'tmp_name' ];
$filename = basename ( $_FILES [ 'filename' ][ 'name' ]);
$filesize = intval ( $_FILES [ 'filename' ][ 'size' ]);
$filetype = $_FILES [ 'filename' ][ 'type' ];
$newname = trim ( strtolower ( $_REQUEST [ 'newname' ]));
// import channel from file
if ( $src ) {
// This is OS specific and could also fail if your tmpdir isn't very
// large mostly used for Diaspora which exports gzipped files.
if ( strpos ( $filename , '.gz' )) {
@ rename ( $src , $src . '.gz' );
@ system ( 'gunzip ' . escapeshellarg ( $src . '.gz' ));
}
if ( $filesize ) {
$data = @ file_get_contents ( $src );
}
unlink ( $src );
}
2022-10-18 19:23:50 +00:00
else {
$import_posts = true ;
}
2021-12-02 23:02:31 +00:00
// import channel from another server
if ( ! $src ) {
$old_address = (( x ( $_REQUEST , 'old_address' )) ? $_REQUEST [ 'old_address' ] : '' );
if ( ! $old_address ) {
logger ( 'Nothing to import.' );
notice ( t ( 'Nothing to import.' ) . EOL );
return ;
} elseif ( strpos ( $old_address , '@ ' )) {
2022-10-18 19:23:50 +00:00
// if you copy the identity address from your profile page, make it work for convenience
// - WARNING: this is a utf-8 variant and NOT an ASCII ampersand. Please do not edit.
2021-12-02 23:02:31 +00:00
$old_address = str_replace ( '@ ' , '@' , $old_address );
}
2022-10-18 19:23:50 +00:00
$split = explode ( '@' , $old_address );
if ( count ( $split ) !== 2 ) {
notice ( t ( 'An invalid channel address was entered. This resembles an email address (xyz@example.com).' ));
return ;
}
$channelname = $split [ 0 ];
$servername = $split [ 1 ];
2021-12-02 23:02:31 +00:00
2022-10-18 19:23:50 +00:00
$password = (( x ( $_REQUEST , 'old_password' )) ? $_REQUEST [ 'old_password' ] : '' );
2021-12-02 23:02:31 +00:00
$api_path = probe_api_path ( $servername );
if ( ! $api_path ) {
2022-10-18 19:23:50 +00:00
notice ( t ( 'Unable to connect to old server' ) . EOL );
2021-12-02 23:02:31 +00:00
return ;
}
2022-10-18 19:23:50 +00:00
$api_path .= 'channel/export/basic?f=&zap_compat=1' ;
$opts = [ 'http_auth' => $channelname . ':' . $password ];
2022-06-23 07:38:34 +00:00
$ret = Url :: get ( $api_path , $opts );
2021-12-02 23:02:31 +00:00
if ( $ret [ 'success' ]) {
$data = $ret [ 'body' ];
} else {
notice ( t ( 'Unable to download data from old server' ) . EOL );
return ;
}
}
if ( ! $data ) {
logger ( 'Empty import file.' );
notice ( t ( 'Imported file is empty.' ) . EOL );
return ;
}
$data = json_decode ( $data , true );
//logger('import: data: ' . print_r($data,true));
//print_r($data);
// handle Friendica export
if ( array_path_exists ( 'user/parent-uid' , $data )) {
2022-08-29 00:36:52 +00:00
$settings = [ 'account_id' => $account_id , 'seize' => 1 , 'newname' => $newname ];
2021-12-02 23:02:31 +00:00
$f = new Friendica ( $data , $settings );
return ;
}
if ( ! array_key_exists ( 'compatibility' , $data )) {
2022-02-12 08:50:48 +00:00
Hook :: call ( 'import_foreign_channel_data' , $data );
2021-12-02 23:02:31 +00:00
if ( $data [ 'handled' ]) {
return ;
}
}
$codebase = 'zap' ;
if (( ! array_path_exists ( 'compatibility/codebase' , $data )) || $data [ 'compatibility' ][ 'codebase' ] !== $codebase ) {
notice ( 'Data export format is not compatible with this software' );
return ;
}
2022-05-06 05:32:09 +00:00
$schema = ( array_path_exists ( 'compatibility/schema' , $data ) && $data [ 'compatibility' ][ 'schema' ]) ? $data [ 'compatibility' ][ 'schema' ] : 'unknown' ;
2022-08-04 22:04:05 +00:00
2021-12-02 23:02:31 +00:00
// import channel
$relocate = (( array_key_exists ( 'relocate' , $data )) ? $data [ 'relocate' ] : null );
if ( array_key_exists ( 'channel' , $data )) {
2022-01-25 01:26:12 +00:00
$max_identities = ServiceClass :: account_fetch ( $account_id , 'total_identities' );
2021-12-02 23:02:31 +00:00
if ( $max_identities !== false ) {
2021-12-03 03:01:39 +00:00
$r = q (
" select channel_id from channel where channel_account_id = %d and channel_removed = 0 " ,
2021-12-02 23:02:31 +00:00
intval ( $account_id )
);
if ( $r && count ( $r ) > $max_identities ) {
notice ( sprintf ( t ( 'Your service plan only allows %d channels.' ), $max_identities ) . EOL );
return ;
}
}
2017-02-06 04:26:06 +00:00
2019-05-29 23:29:55 +00:00
if ( $newname ) {
2021-12-02 23:02:31 +00:00
$x = false ;
if ( get_config ( 'system' , 'unicode_usernames' )) {
$x = punify ( mb_strtolower ( $newname ));
}
if (( ! $x ) || strlen ( $x ) > 64 ) {
$x = strtolower ( URLify :: transliterate ( $newname ));
} else {
$x = $newname ;
}
$newname = $x ;
}
$channel = import_channel ( $data [ 'channel' ], $account_id , $seize , $newname );
2022-11-13 02:27:12 +00:00
}
else {
2021-12-02 23:02:31 +00:00
$channel = App :: get_channel ();
}
if ( ! $channel ) {
logger ( 'Channel not found. ' . print_r ( $channel , true ));
notice ( t ( 'No channel. Import failed.' ) . EOL );
return ;
}
if ( is_array ( $data [ 'config' ])) {
import_config ( $channel , $data [ 'config' ]);
}
logger ( 'import step 2' );
if ( array_key_exists ( 'channel' , $data )) {
2022-03-17 23:57:54 +00:00
if ( isset ( $data [ 'photo' ]) && $data [ 'photo' ]) {
2021-12-02 23:02:31 +00:00
import_channel_photo ( base64url_decode ( $data [ 'photo' ][ 'data' ]), $data [ 'photo' ][ 'type' ], $account_id , $channel [ 'channel_id' ]);
}
if ( is_array ( $data [ 'profile' ])) {
import_profiles ( $channel , $data [ 'profile' ]);
}
}
logger ( 'import step 3' );
// import xchans and contact photos
// This *must* be done before importing hublocs
if ( array_key_exists ( 'channel' , $data ) && $seize ) {
// replace any existing xchan we may have on this site if we're seizing control
2021-12-03 03:01:39 +00:00
$r = q (
" delete from xchan where xchan_hash = '%s' " ,
2021-12-02 23:02:31 +00:00
dbesc ( $channel [ 'channel_hash' ])
);
$r = xchan_store_lowlevel (
[
'xchan_hash' => $channel [ 'channel_hash' ],
'xchan_guid' => $channel [ 'channel_guid' ],
'xchan_guid_sig' => $channel [ 'channel_guid_sig' ],
'xchan_pubkey' => $channel [ 'channel_pubkey' ],
2024-01-02 04:40:43 +00:00
'xchan_epubkey' => ( new Multibase ()) -> publicKey ( $channel [ 'channel_epubkey' ]),
2021-12-02 23:02:31 +00:00
'xchan_photo_l' => z_root () . " /photo/profile/l/ " . $channel [ 'channel_id' ],
'xchan_photo_m' => z_root () . " /photo/profile/m/ " . $channel [ 'channel_id' ],
'xchan_photo_s' => z_root () . " /photo/profile/s/ " . $channel [ 'channel_id' ],
2022-06-29 05:48:02 +00:00
'xchan_photo_mimetype' => $data [ 'photo' ][ 'type' ],
2022-01-25 01:26:12 +00:00
'xchan_addr' => Channel :: get_webfinger ( $channel ),
2021-12-02 23:02:31 +00:00
'xchan_url' => z_root () . '/channel/' . $channel [ 'channel_address' ],
'xchan_connurl' => z_root () . '/poco/' . $channel [ 'channel_address' ],
'xchan_follow' => z_root () . '/follow?f=&url=%s' ,
'xchan_name' => $channel [ 'channel_name' ],
2021-12-06 21:19:19 +00:00
'xchan_network' => 'nomad' ,
2021-12-02 23:02:31 +00:00
'xchan_updated' => datetime_convert (),
'xchan_photo_date' => datetime_convert (),
'xchan_name_date' => datetime_convert ()
]
);
}
logger ( 'import step 4' );
// import xchans
$xchans = $data [ 'xchan' ];
if ( $xchans ) {
foreach ( $xchans as $xchan ) {
// Provide backward compatibility for zot11 based projects
2022-10-24 21:03:04 +00:00
if ( $xchan [ 'xchan_network' ] === 'nomad' && version_compare ( NOMAD_PROTOCOL_VERSION , '10.0' ) <= 0 ) {
2021-12-02 23:02:31 +00:00
$xchan [ 'xchan_network' ] = 'zot6' ;
}
$hash = Libzot :: make_xchan_hash ( $xchan [ 'xchan_guid' ], $xchan [ 'xchan_pubkey' ]);
if ( in_array ( $xchan [ 'xchan_network' ], [ 'nomad' , 'zot6' ]) && $hash !== $xchan [ 'xchan_hash' ]) {
logger ( 'forged xchan: ' . print_r ( $xchan , true ));
continue ;
}
2022-08-04 22:04:05 +00:00
// xchan_pubforum was renamed but still may exist in Hubzilla imports
if ( array_key_exists ( 'xchan_pubforum' , $xchan )) {
$xchan [ 'xchan_type' ] = $xchan [ 'xchan_pubforum' ];
2022-08-04 22:05:50 +00:00
unset ( $xchan [ 'xchan_pubforum' ]);
2022-08-04 22:04:05 +00:00
}
2021-12-03 03:01:39 +00:00
$r = q (
" select xchan_hash from xchan where xchan_hash = '%s' limit 1 " ,
2021-12-02 23:02:31 +00:00
dbesc ( $xchan [ 'xchan_hash' ])
);
if ( $r ) {
continue ;
}
xchan_store_lowlevel ( $xchan );
if ( $xchan [ 'xchan_hash' ] === $channel [ 'channel_hash' ]) {
2021-12-03 03:01:39 +00:00
$r = q (
" update xchan set xchan_updated = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s' where xchan_hash = '%s' " ,
2021-12-02 23:02:31 +00:00
dbesc ( datetime_convert ()),
dbesc ( z_root () . '/photo/profile/l/' . $channel [ 'channel_id' ]),
dbesc ( z_root () . '/photo/profile/m/' . $channel [ 'channel_id' ]),
dbesc ( z_root () . '/photo/profile/s/' . $channel [ 'channel_id' ]),
dbesc ( $xchan [ 'xchan_hash' ])
);
} else {
$photos = import_remote_xchan_photo ( $xchan [ 'xchan_photo_l' ], $xchan [ 'xchan_hash' ]);
if ( $photos ) {
if ( $photos [ 4 ]) {
$photodate = NULL_DATE ;
} else {
$photodate = $xchan [ 'xchan_photo_date' ];
}
2021-12-03 03:01:39 +00:00
$r = q (
" update xchan set xchan_updated = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s' " ,
2021-12-02 23:02:31 +00:00
dbesc ( datetime_convert ()),
dbesc ( $photos [ 0 ]),
dbesc ( $photos [ 1 ]),
dbesc ( $photos [ 2 ]),
dbesc ( $photos [ 3 ]),
dbesc ( $photodate ),
dbesc ( $xchan [ 'xchan_hash' ])
);
}
}
}
logger ( 'import step 5' );
}
logger ( 'import step 6' );
if ( is_array ( $data [ 'hubloc' ])) {
2022-11-13 02:27:12 +00:00
import_hublocs ( $channel , $data [ 'hubloc' ], $seize );
2021-12-02 23:02:31 +00:00
}
logger ( 'import step 7' );
// create new hubloc for the new channel at this site
if ( array_key_exists ( 'channel' , $data )) {
$r = hubloc_store_lowlevel (
[
'hubloc_guid' => $channel [ 'channel_guid' ],
'hubloc_guid_sig' => $channel [ 'channel_guid_sig' ],
2022-01-25 01:26:12 +00:00
'hubloc_id_url' => Channel :: url ( $channel ),
2021-12-02 23:02:31 +00:00
'hubloc_hash' => $channel [ 'channel_hash' ],
2022-01-25 01:26:12 +00:00
'hubloc_addr' => Channel :: get_webfinger ( $channel ),
2021-12-06 21:19:19 +00:00
'hubloc_network' => 'nomad' ,
2021-12-02 23:02:31 +00:00
'hubloc_primary' => (( $seize ) ? 1 : 0 ),
'hubloc_url' => z_root (),
'hubloc_url_sig' => Libzot :: sign ( z_root (), $channel [ 'channel_prvkey' ]),
'hubloc_site_id' => Libzot :: make_xchan_hash ( z_root (), get_config ( 'system' , 'pubkey' )),
'hubloc_host' => App :: get_hostname (),
2022-09-01 20:50:26 +00:00
'hubloc_callback' => z_root () . '/nomad' ,
2021-12-02 23:02:31 +00:00
'hubloc_sitekey' => get_config ( 'system' , 'pubkey' ),
'hubloc_updated' => datetime_convert ()
]
);
// reset the original primary hubloc if it is being seized
if ( $seize ) {
2021-12-03 03:01:39 +00:00
$r = q (
" update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' " ,
2021-12-02 23:02:31 +00:00
dbesc ( $channel [ 'channel_hash' ]),
dbesc ( z_root ())
);
}
}
$friends = 0 ;
$feeds = 0 ;
// import contacts
$abooks = $data [ 'abook' ];
if ( $abooks ) {
foreach ( $abooks as $abook ) {
$abook_copy = $abook ;
$abconfig = null ;
if ( array_key_exists ( 'abconfig' , $abook ) && is_array ( $abook [ 'abconfig' ]) && count ( $abook [ 'abconfig' ])) {
$abconfig = $abook [ 'abconfig' ];
}
unset ( $abook [ 'abook_id' ]);
unset ( $abook [ 'abook_rating' ]);
unset ( $abook [ 'abook_rating_text' ]);
unset ( $abook [ 'abconfig' ]);
unset ( $abook [ 'abook_their_perms' ]);
unset ( $abook [ 'abook_my_perms' ]);
unset ( $abook [ 'abook_not_here' ]);
$abook [ 'abook_account' ] = $account_id ;
$abook [ 'abook_channel' ] = $channel [ 'channel_id' ];
$reconnect = false ;
2022-09-04 01:35:50 +00:00
if ( array_key_exists ( 'abook_instance' , $abook ) && $abook [ 'abook_instance' ] && ! str_contains ( $abook [ 'abook_instance' ], z_root ())) {
2021-12-02 23:02:31 +00:00
$abook [ 'abook_not_here' ] = 1 ;
if ( ! ( $abook [ 'abook_pending' ] || $abook [ 'abook_blocked' ])) {
$reconnect = true ;
}
}
if ( $abook [ 'abook_self' ]) {
$ctype = 0 ;
$role = get_pconfig ( $channel [ 'channel_id' ], 'system' , 'permissions_role' );
if ( strpos ( $role , 'collection' !== false )) {
$ctype = 2 ;
2022-09-04 01:35:50 +00:00
} elseif ( str_contains ( $role , 'group' )) {
2021-12-02 23:02:31 +00:00
$ctype = 1 ;
}
if ( $ctype ) {
2021-12-03 03:01:39 +00:00
q (
" update xchan set xchan_type = %d where xchan_hash = '%s' " ,
2021-12-02 23:02:31 +00:00
intval ( $ctype ),
dbesc ( $abook [ 'abook_xchan' ])
);
}
} else {
if ( $max_friends !== false && $friends > $max_friends ) {
continue ;
}
if ( $max_feeds !== false && intval ( $abook [ 'abook_feed' ]) && ( $feeds > $max_feeds )) {
continue ;
}
}
2021-12-03 03:01:39 +00:00
$r = q (
" select abook_id from abook where abook_xchan = '%s' and abook_channel = %d limit 1 " ,
2021-12-02 23:02:31 +00:00
dbesc ( $abook [ 'abook_xchan' ]),
intval ( $channel [ 'channel_id' ])
);
if ( $r ) {
$columns = db_columns ( 'abook' );
foreach ( $abook as $k => $v ) {
if ( ! in_array ( $k , $columns )) {
continue ;
}
2021-12-03 03:01:39 +00:00
$r = q (
" UPDATE abook SET " . TQUOT . " %s " . TQUOT . " = '%s' WHERE abook_xchan = '%s' AND abook_channel = %d " ,
2021-12-02 23:02:31 +00:00
dbesc ( $k ),
dbesc ( $v ),
dbesc ( $abook [ 'abook_xchan' ]),
intval ( $channel [ 'channel_id' ])
);
}
} else {
abook_store_lowlevel ( $abook );
$friends ++ ;
if ( intval ( $abook [ 'abook_feed' ])) {
$feeds ++ ;
}
}
if ( $abconfig ) {
foreach ( $abconfig as $abc ) {
2022-05-06 05:32:09 +00:00
if ( $abc [ 'cat' ] === 'system' && $abc [ 'k' ] === 'my_perms' && $schema !== 'streams' ) {
$x = explode ( ',' , $abc [ 'v' ]);
if ( in_array ( 'view_stream' , $x ) && ! in_array ( 'deliver_stream' , $x )) {
$x [] = 'deliver_stream' ;
}
set_abconfig ( $channel [ 'channel_id' ], $abc [ 'xchan' ], $abc [ 'cat' ], $abc [ 'k' ], implode ( ',' , $x ));
}
else {
set_abconfig ( $channel [ 'channel_id' ], $abc [ 'xchan' ], $abc [ 'cat' ], $abc [ 'k' ], $abc [ 'v' ]);
}
2021-12-02 23:02:31 +00:00
}
}
if ( $reconnect ) {
Connect :: connect ( $channel , $abook [ 'abook_xchan' ]);
}
}
logger ( 'import step 8' );
}
// import groups
$groups = $data [ 'group' ];
if ( $groups ) {
$saved = [];
foreach ( $groups as $group ) {
$saved [ $group [ 'hash' ]] = [ 'old' => $group [ 'id' ]];
if ( array_key_exists ( 'name' , $group )) {
$group [ 'gname' ] = $group [ 'name' ];
unset ( $group [ 'name' ]);
}
2022-03-16 23:54:32 +00:00
$r = q ( " select * from pgrp where gname = '%s' and uid = %d " ,
dbesc ( $group [ 'gname' ]),
intval ( $channel [ 'channel_id' ])
);
if ( $r ) {
continue ;
}
2021-12-02 23:02:31 +00:00
unset ( $group [ 'id' ]);
$group [ 'uid' ] = $channel [ 'channel_id' ];
create_table_from_array ( 'pgrp' , $group );
}
2022-03-16 23:54:32 +00:00
// create a list of ids that applies to this system so we can map members to them
2021-12-03 03:01:39 +00:00
$r = q (
" select * from pgrp where uid = %d " ,
2021-12-02 23:02:31 +00:00
intval ( $channel [ 'channel_id' ])
);
if ( $r ) {
foreach ( $r as $rr ) {
$saved [ $rr [ 'hash' ]][ 'new' ] = $rr [ 'id' ];
}
}
}
// import group members
$group_members = $data [ 'group_member' ];
if ( $group_members ) {
foreach ( $group_members as $group_member ) {
unset ( $group_member [ 'id' ]);
$group_member [ 'uid' ] = $channel [ 'channel_id' ];
foreach ( $saved as $x ) {
if ( $x [ 'old' ] == $group_member [ 'gid' ]) {
$group_member [ 'gid' ] = $x [ 'new' ];
}
}
2022-03-16 23:54:32 +00:00
// check if it's a duplicate
$r = q ( " select * from pgrp_member where xchan = '%s' and gid = %d " ,
dbesc ( $group_member [ 'xchan' ]),
intval ( $group_member [ 'gid' ])
);
if ( $r ) {
continue ;
}
2021-12-02 23:02:31 +00:00
create_table_from_array ( 'pgrp_member' , $group_member );
}
}
logger ( 'import step 9' );
if ( is_array ( $data [ 'atoken' ])) {
import_atoken ( $channel , $data [ 'atoken' ]);
}
if ( is_array ( $data [ 'xign' ])) {
import_xign ( $channel , $data [ 'xign' ]);
}
if ( is_array ( $data [ 'block' ])) {
import_block ( $channel , $data [ 'block' ]);
}
2022-03-22 19:45:55 +00:00
if ( is_array ( $data [ 'block_xchan' ])) {
import_xchans ( $data [ 'block_xchan' ]);
}
2021-12-02 23:02:31 +00:00
if ( is_array ( $data [ 'obj' ])) {
import_objs ( $channel , $data [ 'obj' ]);
}
if ( is_array ( $data [ 'likes' ])) {
import_likes ( $channel , $data [ 'likes' ]);
}
if ( is_array ( $data [ 'app' ])) {
import_apps ( $channel , $data [ 'app' ]);
}
if ( is_array ( $data [ 'sysapp' ])) {
import_sysapps ( $channel , $data [ 'sysapp' ]);
}
if ( is_array ( $data [ 'chatroom' ])) {
import_chatrooms ( $channel , $data [ 'chatroom' ]);
}
2021-12-03 03:01:39 +00:00
// if (is_array($data['conv'])) {
// import_conv($channel,$data['conv']);
// }
// if (is_array($data['mail'])) {
// import_mail($channel,$data['mail']);
// }
2021-12-02 23:02:31 +00:00
if ( is_array ( $data [ 'event' ])) {
import_events ( $channel , $data [ 'event' ]);
}
if ( is_array ( $data [ 'event_item' ])) {
import_items ( $channel , $data [ 'event_item' ], false , $relocate );
}
2021-12-03 03:01:39 +00:00
// if (is_array($data['menu'])) {
// import_menus($channel,$data['menu']);
// }
// if (is_array($data['wiki'])) {
// import_items($channel,$data['wiki'],false,$relocate);
// }
// if (is_array($data['webpages'])) {
// import_items($channel,$data['webpages'],false,$relocate);
// }
2021-12-02 23:02:31 +00:00
$addon = array ( 'channel' => $channel , 'data' => $data );
2022-02-12 08:50:48 +00:00
Hook :: call ( 'import_channel' , $addon );
2017-03-23 22:40:12 +00:00
2022-01-25 01:26:12 +00:00
$saved_notification_flags = Channel :: notifications_off ( $channel [ 'channel_id' ]);
2021-12-02 23:02:31 +00:00
if ( $import_posts && array_key_exists ( 'item' , $data ) && $data [ 'item' ]) {
import_items ( $channel , $data [ 'item' ], false , $relocate );
}
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
if ( $api_path && $import_posts ) { // we are importing from a server and not a file
$m = parse_url ( $api_path );
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
$hz_server = $m [ 'scheme' ] . '://' . $m [ 'host' ];
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
$since = datetime_convert ( date_default_timezone_get (), date_default_timezone_get (), '0001-01-01 00:00' );
$until = datetime_convert ( date_default_timezone_get (), date_default_timezone_get (), 'now + 1 day' );
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
$poll_interval = get_config ( 'system' , 'poll_interval' , 3 );
$page = 0 ;
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
while ( 1 ) {
$headers = [
'X-API-Token' => random_string (),
'X-API-Request' => $hz_server . '/api/z/1.0/item/export_page?f=&zap_compat=1&since=' . urlencode ( $since ) . '&until=' . urlencode ( $until ) . '&page=' . $page ,
'Host' => $m [ 'host' ],
'(request-target)' => 'get /api/z/1.0/item/export_page?f=&zap_compat=1&since=' . urlencode ( $since ) . '&until=' . urlencode ( $until ) . '&page=' . $page ,
];
2020-12-11 00:32:29 +00:00
2022-01-25 01:26:12 +00:00
$headers = HTTPSig :: create_sig ( $headers , $channel [ 'channel_prvkey' ], Channel :: url ( $channel ), true , 'sha512' );
2020-12-11 00:32:29 +00:00
2022-06-23 07:38:34 +00:00
$x = Url :: get ( $hz_server . '/api/z/1.0/item/export_page?f=&zap_compat=1&since=' . urlencode ( $since ) . '&until=' . urlencode ( $until ) . '&page=' . $page , [ 'headers' => $headers ]);
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
if ( ! $x [ 'success' ]) {
logger ( 'no API response' );
break ;
}
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
$j = json_decode ( $x [ 'body' ], true );
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
if ( ! $j ) {
break ;
}
2020-12-11 00:32:29 +00:00
2022-04-02 08:03:57 +00:00
if ( ! ( isset ( $j [ 'item' ]) && is_array ( $j [ 'item' ]) && count ( $j [ 'item' ]))) {
2021-12-02 23:02:31 +00:00
break ;
}
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
Run :: Summon ([ 'Content_importer' , sprintf ( '%d' , $page ), $since , $until , $channel [ 'channel_address' ], urlencode ( $hz_server )]);
sleep ( $poll_interval );
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
$page ++ ;
continue ;
}
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
$headers = [
'X-API-Token' => random_string (),
'X-API-Request' => $hz_server . '/api/z/1.0/files?f=&zap_compat=1&since=' . urlencode ( $since ) . '&until=' . urlencode ( $until ),
'Host' => $m [ 'host' ],
'(request-target)' => 'get /api/z/1.0/files?f=&zap_compat=1&since=' . urlencode ( $since ) . '&until=' . urlencode ( $until ),
];
2020-12-11 00:32:29 +00:00
2022-01-25 01:26:12 +00:00
$headers = HTTPSig :: create_sig ( $headers , $channel [ 'channel_prvkey' ], Channel :: url ( $channel ), true , 'sha512' );
2020-12-11 00:32:29 +00:00
2022-06-23 07:38:34 +00:00
$x = Url :: get ( $hz_server . '/api/z/1.0/files?f=&zap_compat=1&since=' . urlencode ( $since ) . '&until=' . urlencode ( $until ), [ 'headers' => $headers ]);
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
if ( ! $x [ 'success' ]) {
logger ( 'no API response' );
return ;
}
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
$j = json_decode ( $x [ 'body' ], true );
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
if ( ! $j ) {
return ;
}
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
if ( ! $j [ 'success' ]) {
return ;
}
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
$poll_interval = get_config ( 'system' , 'poll_interval' , 3 );
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
if ( count ( $j [ 'results' ])) {
$todo = count ( $j [ 'results' ]);
logger ( 'total to process: ' . $todo , LOGGER_DEBUG );
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
foreach ( $j [ 'results' ] as $jj ) {
Run :: Summon ([ 'File_importer' , $jj [ 'hash' ], $channel [ 'channel_address' ], urlencode ( $hz_server )]);
sleep ( $poll_interval );
}
}
2020-12-11 00:32:29 +00:00
2021-12-02 23:02:31 +00:00
notice ( t ( 'Files and Posts imported.' ) . EOL );
}
2017-03-23 22:40:12 +00:00
2022-01-25 01:26:12 +00:00
Channel :: notifications_on ( $channel [ 'channel_id' ], $saved_notification_flags );
2017-03-23 22:40:12 +00:00
2021-12-02 23:02:31 +00:00
// send out refresh requests
// notify old server that it may no longer be primary.
2017-03-23 22:40:12 +00:00
2021-12-02 23:02:31 +00:00
Run :: Summon ([ 'Notifier' , 'refresh_all' , $channel [ 'channel_id' ]]);
2017-03-23 22:40:12 +00:00
2021-12-02 23:02:31 +00:00
// This will indirectly perform a refresh_all *and* update the directory
2017-03-23 22:40:12 +00:00
2021-12-02 23:02:31 +00:00
Run :: Summon ([ 'Directory' , $channel [ 'channel_id' ]]);
2017-03-23 22:40:12 +00:00
2021-12-02 23:02:31 +00:00
notice ( t ( 'Import completed.' ) . EOL );
2017-03-23 22:40:12 +00:00
2021-12-02 23:02:31 +00:00
change_channel ( $channel [ 'channel_id' ]);
2017-03-23 22:40:12 +00:00
2021-12-02 23:02:31 +00:00
goaway ( z_root () . '/stream' );
}
2019-05-29 23:29:55 +00:00
2021-12-02 23:02:31 +00:00
/**
* @ brief Handle POST action on channel import page .
*/
2017-03-23 22:40:12 +00:00
2021-12-02 23:02:31 +00:00
public function post ()
{
$account_id = get_account_id ();
if ( ! $account_id ) {
return ;
}
2017-03-23 22:40:12 +00:00
2021-12-02 23:02:31 +00:00
check_form_security_token_redirectOnErr ( '/import' , 'channel_import' );
$this -> import_account ( $account_id );
}
2019-05-29 23:29:55 +00:00
2021-12-02 23:02:31 +00:00
/**
* @ brief Generate channel import page .
*
* @ return string with parsed HTML .
*/
2017-03-23 22:40:12 +00:00
2021-12-02 23:02:31 +00:00
public function get ()
{
2017-03-23 22:40:12 +00:00
2021-12-02 23:02:31 +00:00
if ( ! get_account_id ()) {
notice ( t ( 'You must be logged in to use this feature.' ) . EOL );
return EMPTY_STR ;
}
2018-05-02 02:38:32 +00:00
2022-02-12 20:43:29 +00:00
return replace_macros ( Theme :: get_template ( 'channel_import.tpl' ), [
2021-12-02 23:02:31 +00:00
'$title' => t ( 'Import Channel' ),
2022-10-18 19:23:50 +00:00
'$desc' => t ( 'Use this form to make a copy (clone) of an existing channel from a different site/instance to this site. You may choose to retrieve the channel data from the old site via the network or provide an export file you downloaded previously.' ),
'$label_filename' => t ( 'File to upload' ),
'$choice' => t ( 'Or provide the connection details to an existing site/instance. This information is used immediately to download your existing content and is not saved or stored.' ),
'$old_address' => [ 'old_address' , t ( 'Your old channel address (xyz@example.com)' ), '' , '' ],
'$old_password' => [ 'old_password' , t ( 'Your old login password' ), '' , '' ],
'$common' => t ( 'Your primary location determines which URL or address should be displayed publicly. This should be the location you intend to use most often.' ),
'$make_primary' => [ 'make_primary' , t ( 'Make this instance my primary location' ), false , '' , [ t ( 'No' ), t ( 'Yes' )]],
'$newname' => [ 'newname' , t ( 'Use this channel nickname (optional)' ), '' , t ( 'Leave blank to keep your existing channel nickname. You will be randomly assigned a similar nickname if either name is already allocated on this site.' )],
2018-05-02 02:38:32 +00:00
2021-12-02 23:02:31 +00:00
'$pleasewait' => t ( 'This process may take several minutes to complete and considerably longer if importing a large amount of posts and files. Please submit the form only once and leave this page open until finished.' ),
2017-03-23 22:40:12 +00:00
2021-12-02 23:02:31 +00:00
'$form_security_token' => get_form_security_token ( 'channel_import' ),
'$submit' => t ( 'Submit' )
]);
}
2016-04-19 03:38:38 +00:00
}