aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Zotlabs/Lib/Activity.php38
-rw-r--r--Zotlabs/Module/Uexport.php7
-rw-r--r--boot.php1
-rw-r--r--include/api_zot.php9
-rw-r--r--include/attach.php4
-rw-r--r--include/channel.php118
-rw-r--r--include/items.php62
7 files changed, 173 insertions, 66 deletions
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index d0799bb66..5fefb2979 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -434,7 +434,7 @@ class Activity {
$ret['published'] = datetime_convert('UTC', 'UTC', $i['created'], ATOM_TIME);
if ($i['created'] !== $i['edited'])
$ret['updated'] = datetime_convert('UTC', 'UTC', $i['edited'], ATOM_TIME);
- if ($i['expires'] <= NULL_DATE) {
+ if ($i['expires'] > NULL_DATE) {
$ret['expires'] = datetime_convert('UTC', 'UTC', $i['expires'], ATOM_TIME);
}
@@ -461,7 +461,7 @@ class Activity {
$ret['directMessage'] = true;
}
- if (array_key_exists('comments_closed', $i) && $i['comments_closed'] !== EMPTY_STR && $i['comments_closed'] !== NULL_DATE) {
+ if (array_key_exists('comments_closed', $i) && $i['comments_closed'] !== EMPTY_STR && $i['comments_closed'] > NULL_DATE) {
if ($ret['commentPolicy']) {
$ret['commentPolicy'] .= ' ';
}
@@ -1120,6 +1120,34 @@ class Activity {
return $ret;
}
+ static function encode_item_object($item, $elm = 'obj') {
+ $ret = [];
+
+ if ($item[$elm]) {
+ if (! is_array($item[$elm])) {
+ $item[$elm] = json_decode($item[$elm],true);
+ }
+ if ($item[$elm]['type'] === ACTIVITY_OBJ_PHOTO) {
+ $item[$elm]['id'] = $item['mid'];
+ }
+
+ $obj = self::encode_object($item[$elm]);
+ if ($obj)
+ return $obj;
+ else
+ return [];
+ }
+ else {
+ $obj = self::encode_item($item);
+ if ($obj)
+ return $obj;
+ else
+ return [];
+ }
+
+ }
+
+
static function activity_mapper($verb) {
if (strpos($verb, '/') === false) {
@@ -3303,17 +3331,17 @@ class Activity {
$ret = false;
foreach ($attach as $a) {
- if (strpos($a['type'], 'image') !== false) {
+ if (array_key_exists('type',$a) && stripos($a['type'], 'image') !== false) {
if (self::media_not_in_body($a['href'], $body)) {
$ret .= "\n\n" . '[img]' . $a['href'] . '[/img]';
}
}
- if (array_key_exists('type', $a) && strpos($a['type'], 'video') === 0) {
+ if (array_key_exists('type', $a) && stripos($a['type'], 'video') !== false) {
if (self::media_not_in_body($a['href'], $body)) {
$ret .= "\n\n" . '[video]' . $a['href'] . '[/video]';
}
}
- if (array_key_exists('type', $a) && strpos($a['type'], 'audio') === 0) {
+ if (array_key_exists('type', $a) && stripos($a['type'], 'audio') !== false) {
if (self::media_not_in_body($a['href'], $body)) {
$ret .= "\n\n" . '[audio]' . $a['href'] . '[/audio]';
}
diff --git a/Zotlabs/Module/Uexport.php b/Zotlabs/Module/Uexport.php
index 3d1587b87..55c316317 100644
--- a/Zotlabs/Module/Uexport.php
+++ b/Zotlabs/Module/Uexport.php
@@ -17,6 +17,7 @@ class Uexport extends Controller {
if(argc() > 1) {
$sections = (($_REQUEST['sections']) ? explode(',',$_REQUEST['sections']) : '');
+ $zap_compat = (($_REQUEST['zap_compat']) ? intval($_REQUEST['zap_compat']) : false);
$channel = App::get_channel();
@@ -32,12 +33,12 @@ class Uexport extends Controller {
header('content-disposition: attachment; filename="' . $channel['channel_address'] . (($year) ? '-' . $year : '') . (($month) ? '-' . $month : '') . (($_REQUEST['sections']) ? '-' . $_REQUEST['sections'] : '') . '.json"' );
if($year) {
- echo json_encode(identity_export_year(local_channel(),$year,$month));
+ echo json_encode(identity_export_year(local_channel(),$year,$month, $zap_compat));
killme();
}
if(argc() > 1 && argv(1) === 'basic') {
- echo json_encode(identity_basic_export(local_channel(),$sections));
+ echo json_encode(identity_basic_export(local_channel(),$sections, $zap_compat));
killme();
}
@@ -46,7 +47,7 @@ class Uexport extends Controller {
if(argc() > 1 && argv(1) === 'complete') {
$sections = get_default_export_sections();
$sections[] = 'items';
- echo json_encode(identity_basic_export(local_channel(),$sections));
+ echo json_encode(identity_basic_export(local_channel(),$sections, $zap_compat));
killme();
}
}
diff --git a/boot.php b/boot.php
index 698b077be..74c997f39 100644
--- a/boot.php
+++ b/boot.php
@@ -603,6 +603,7 @@ define ( 'DBTYPE_POSTGRES', 1 );
function sys_boot() {
+
// our central App object
App::init();
diff --git a/include/api_zot.php b/include/api_zot.php
index 8f621d998..9beaaa19c 100644
--- a/include/api_zot.php
+++ b/include/api_zot.php
@@ -87,12 +87,13 @@
return false;
}
$sections = (($_REQUEST['sections']) ? explode(',',$_REQUEST['sections']) : '');
+ $codebase = ((isset($_REQUEST['zap_compat']) && $_REQUEST['zap_compat']) ? true : false);
if($_REQUEST['posts']) {
$sections = get_default_export_sections();
$sections[] = 'items';
}
- json_return_and_die(identity_basic_export(api_user(),$sections));
+ json_return_and_die(identity_basic_export(api_user(),$sections,$codebase));
}
function api_item_export_page($type) {
@@ -111,8 +112,9 @@
$start = datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['since']);
}
$finish = datetime_convert(date_default_timezone_get(),'UTC', (($_REQUEST['until']) ? $_REQUEST['until'] : 'now'));
+ $codebase = ((isset($_REQUEST['zap_compat']) && $_REQUEST['zap_compat']) ? true : false);
- json_return_and_die(channel_export_items_page(api_user(),$start,$finish,$page,$records));
+ json_return_and_die(channel_export_items_page(api_user(),$start,$finish,$page,$records,$codebase));
}
@@ -289,10 +291,11 @@
return false;
if(! $_REQUEST['file_id'])
return false;
+ $codebase = ((isset($_REQUEST['zap_compat']) && $_REQUEST['zap_compat']) ? true : false);
$channel = channelx_by_n(api_user());
- $ret = attach_export_data($channel,$_REQUEST['file_id']);
+ $ret = attach_export_data($channel,$_REQUEST['file_id'],false,$codebase);
if($ret) {
json_return_and_die($ret);
diff --git a/include/attach.php b/include/attach.php
index 9ba6be109..db7046ef0 100644
--- a/include/attach.php
+++ b/include/attach.php
@@ -2339,7 +2339,7 @@ function filepath_macro($s) {
}
-function attach_export_data($channel, $resource_id, $deleted = false) {
+function attach_export_data($channel, $resource_id, $deleted = false, $zap_compat = false) {
$ret = array();
@@ -2429,7 +2429,7 @@ function attach_export_data($channel, $resource_id, $deleted = false) {
xchan_query($items);
$items = fetch_post_tags($items,true);
foreach($items as $rr)
- $ret['item'][] = encode_item($rr,true);
+ $ret['item'][] = encode_item($rr,true,$zap_compat);
}
}
}
diff --git a/include/channel.php b/include/channel.php
index 08b5ee889..5843dacf9 100644
--- a/include/channel.php
+++ b/include/channel.php
@@ -903,8 +903,20 @@ function identity_basic_export($channel_id, $sections = null, $zap_compat = fals
$r = q("select * from profile where uid = %d",
intval($channel_id)
);
- if($r)
+
+ if($r) {
$ret['profile'] = $r;
+ if ($zap_compat) {
+ // zap only supports one profile
+ foreach ($r as $rv) {
+ if ($rv['is_default']) {
+ $ret['profile'] = [ $rv ];
+ break;
+ }
+ }
+ }
+ }
+
$r = q("select mimetype, content, os_storage from photo
where imgscale = 4 and photo_usage = %d and uid = %d limit 1",
@@ -937,50 +949,47 @@ function identity_basic_export($channel_id, $sections = null, $zap_compat = fals
$newconfig = [];
$abconfig = load_abconfig($channel_id,$ret['abook'][$x]['abook_xchan']);
- // Partly revert of commit 85cf25a2a8bfbbfe10de485d4affd54626fbbfa4
if($abconfig) {
- $ret['abook'][$x]['abconfig'] = $abconfig;
- }
+ if ($zap_compat) {
+ foreach ($abconfig as $abc) {
+
+ if ($abc['cat'] === 'my_perms') {
+ if (intval($abc['v'])) {
+ $my_perms[] = $abc['k'];
+ }
+ continue;
+ }
+ if ($abc['cat'] === 'their_perms') {
+ if (intval($abc['v'])) {
+ $their_perms[] = $abc['k'];
+ }
+ continue;
+ }
+ if (preg_match('|^a:[0-9]+:{.*}$|s', $abc['v'])) {
+ $abc['v'] = serialise(unserialize($abc['v']));
+ }
+ $newconfig[] = $abc;
+ }
- /* This was added in commit 85cf25a2a8bfbbfe10de485d4affd54626fbbfa4
- * Seems unfinished work on zap compatibility for cloning.
- * It breaks cloning of abconfig for hubzilla - reverted to the above code.
+ $ret['abook'][$x]['abconfig'] = $newconfig;
- if($abconfig) {
- foreach ($abconfig as $abc) {
+ $ret['abook'][$x]['abconfig'][] = [ 'chan' => $channel_id, 'xchan' => $ret['abook'][$x]['abook_xchan'], 'cat' => 'system', 'k' => 'my_perms', 'v' => implode(',',$my_perms) ];
+ $ret['abook'][$x]['abconfig'][] = [ 'chan' => $channel_id, 'xchan' => $ret['abook'][$x]['abook_xchan'], 'cat' => 'system', 'k' => 'their_perms', 'v' => implode(',',$their_perms) ];
- if ($abc['cat'] === 'my_perms' && intval($abc['v'])) {
- $my_perms[] = $abc['k'];
- continue;
- }
- if ($abc['cat'] === 'their_perms' && intval($abc['v'])) {
- $their_perms[] = $abc['k'];
- continue;
- }
- if ($zap_compat && preg_match('|^a:[0-9]+:{.*}$|s', $abc['v'])) {
- $abc['v'] = serialise(unserialize($abc['v']));
- }
- $newconfig[] = $abc;
}
-
- $ret['abook'][$x]['abconfig'] = $newconfig;
-
- if ($zap_compat) {
- $ret['abook'][$x]['abconfig'][] = [ 'chan' => $channel_id, 'xchan' => $ret['abook'][$x]['abook_chan'], 'cat' => 'system', 'k' => 'my_perms', 'v' => implode(',',$my_perms) ];
- $ret['abook'][$x]['abconfig'][] = [ 'chan' => $channel_id, 'xchan' => $ret['abook'][$x]['abook_chan'], 'cat' => 'system', 'k' => 'their_perms', 'v' => implode(',',$their_perms) ];
+ else {
+ $ret['abook'][$x]['abconfig'] = $abconfig;
}
}
- */
+
translate_abook_perms_outbound($ret['abook'][$x]);
}
-
-
// pick up the zot xchan and hublocs also
- if($ret['channel']['channel_portable_id']) {
+ if($ret['channel']['channel_portable_id'] && ! $zot_compat) {
$xchans[] = $ret['channel']['channel_portable_id'];
}
@@ -1091,13 +1100,24 @@ function identity_basic_export($channel_id, $sections = null, $zap_compat = fals
}
if(in_array('events',$sections)) {
- $r = q("select * from event where uid = %d",
+
+ // @fixme - Not totally certain how to handle $zot_compat for the event timezone which exists
+ // in Hubzilla but is stored with the item and not the event. In Zap, stored information is
+ // always UTC and localised on access as per standard conventions for working with global time data.
+
+ // Older Zot (pre-Zot6) records aren't translated correctly w/r/t AS2 so only include events for the last year or so if
+ // migrating to Zap.
+
+ $sqle = (($zap_compat) ? " and created > '2020-01-01 00:00:00' " : '');
+
+ $r = q("select * from event where uid = %d $sqle",
intval($channel_id)
);
- if($r)
+ if ($r) {
$ret['event'] = $r;
+ }
- $r = q("select * from item where resource_type = 'event' and uid = %d",
+ $r = q("select * from item where resource_type = 'event' and uid = %d $sqle",
intval($channel_id)
);
if($r) {
@@ -1105,7 +1125,7 @@ function identity_basic_export($channel_id, $sections = null, $zap_compat = fals
xchan_query($r);
$r = fetch_post_tags($r,true);
foreach($r as $rr)
- $ret['event_item'][] = encode_item($rr,true);
+ $ret['event_item'][] = encode_item($rr,true, $zap_compat);
}
}
@@ -1128,7 +1148,7 @@ function identity_basic_export($channel_id, $sections = null, $zap_compat = fals
xchan_query($r);
$r = fetch_post_tags($r,true);
foreach($r as $rr)
- $ret['webpages'][] = encode_item($rr,true);
+ $ret['webpages'][] = encode_item($rr,true, $zap_compat);
}
}
@@ -1165,7 +1185,7 @@ function identity_basic_export($channel_id, $sections = null, $zap_compat = fals
xchan_query($r);
$r = fetch_post_tags($r,true);
foreach($r as $rv) {
- $ret['wiki'][] = encode_item($rv,true);
+ $ret['wiki'][] = encode_item($rv,true, $zap_compat);
}
}
}
@@ -1190,7 +1210,7 @@ function identity_basic_export($channel_id, $sections = null, $zap_compat = fals
xchan_query($r);
$r = fetch_post_tags($r,true);
foreach($r as $rr)
- $ret['item'][] = encode_item($rr,true);
+ $ret['item'][] = encode_item($rr,true, $zap_compat);
}
}
@@ -1223,7 +1243,7 @@ function identity_basic_export($channel_id, $sections = null, $zap_compat = fals
* * \e array \b relocate - (optional)
* * \e array \b item - array with items encoded_item()
*/
-function identity_export_year($channel_id, $year, $month = 0) {
+function identity_export_year($channel_id, $year, $month = 0, $zap_compat = false) {
if(! $year)
return array();
@@ -1241,7 +1261,7 @@ function identity_export_year($channel_id, $year, $month = 0) {
else
$maxdate = datetime_convert('UTC', 'UTC', $year+1 . '-01-01 00:00:00');
- return channel_export_items_date($channel_id,$mindate,$maxdate);
+ return channel_export_items_date($channel_id,$mindate,$maxdate, $zap_compat);
}
@@ -1256,7 +1276,7 @@ function identity_export_year($channel_id, $year, $month = 0) {
* @return array
*/
-function channel_export_items_date($channel_id, $start, $finish) {
+function channel_export_items_date($channel_id, $start, $finish, $zap_compat = false) {
if(! $start)
return array();
@@ -1274,6 +1294,11 @@ function channel_export_items_date($channel_id, $start, $finish) {
$ret['relocate'] = [ 'channel_address' => $ch['channel_address'], 'url' => z_root()];
}
+ if ($zap_compat) {
+ $ret['compatibility']['codebase'] = 'zap';
+ }
+
+
$r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and created >= '%s' and created <= '%s' and resource_type != 'photo' order by created",
intval(ITEM_TYPE_POST),
intval($channel_id),
@@ -1286,7 +1311,7 @@ function channel_export_items_date($channel_id, $start, $finish) {
xchan_query($r);
$r = fetch_post_tags($r, true);
foreach($r as $rr)
- $ret['item'][] = encode_item($rr, true);
+ $ret['item'][] = encode_item($rr, true, $zap_compat);
}
return $ret;
@@ -1304,7 +1329,7 @@ function channel_export_items_date($channel_id, $start, $finish) {
* @return array
*/
-function channel_export_items_page($channel_id, $start, $finish, $page = 0, $limit = 50) {
+function channel_export_items_page($channel_id, $start, $finish, $page = 0, $limit = 50, $zap_compat = false) {
if(intval($page) < 1) {
$page = 0;
@@ -1336,6 +1361,11 @@ function channel_export_items_page($channel_id, $start, $finish, $page = 0, $lim
$ret['relocate'] = [ 'channel_address' => $ch['channel_address'], 'url' => z_root()];
}
+ if ($zap_compat) {
+ $ret['compatibility']['codebase'] = 'zap';
+ }
+
+
$r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and resource_type != 'photo' and created >= '%s' and created <= '%s' order by created limit %d offset %d",
intval(ITEM_TYPE_POST),
intval($channel_id),
@@ -1350,7 +1380,7 @@ function channel_export_items_page($channel_id, $start, $finish, $page = 0, $lim
xchan_query($r);
$r = fetch_post_tags($r, true);
foreach($r as $rr)
- $ret['item'][] = encode_item($rr, true);
+ $ret['item'][] = encode_item($rr, true, $zap_compat);
}
return $ret;
diff --git a/include/items.php b/include/items.php
index ce1461aba..88f100e60 100644
--- a/include/items.php
+++ b/include/items.php
@@ -1089,7 +1089,7 @@ function empty_acl($item) {
return (($item['allow_cid'] === EMPTY_STR && $item['allow_gid'] === EMPTY_STR && $item['deny_cid'] === EMPTY_STR && $item['deny_gid'] === EMPTY_STR) ? true : false);
}
-function encode_item($item,$mirror = false) {
+function encode_item($item,$mirror = false,$zap_compat = false) {
$x = [];
$x['type'] = 'activity';
$x['encoding'] = 'zot';
@@ -1167,9 +1167,9 @@ function encode_item($item,$mirror = false) {
$x['summary'] = $item['summary'];
$x['body'] = $item['body'];
$x['app'] = $item['app'];
- $x['verb'] = $item['verb'];
- $x['object_type'] = $item['obj_type'];
- $x['target_type'] = $item['tgt_type'];
+ $x['verb'] = (($zap_compat) ? Activity::activity_mapper($item['verb']) : $item['verb']);
+ $x['object_type'] = (($zap_compat && $item['obj_type']) ? Activity::activity_obj_mapper($item['obj_type']) : $item['obj_type']);
+ $x['target_type'] = (($zap_compat && $item['tgt_type']) ? Activity::activity_obj_mapper($item['tgt_type']) : $item['tgt_type']);
$x['permalink'] = $item['plink'];
$x['location'] = $item['location'];
$x['longlat'] = $item['coord'];
@@ -1178,10 +1178,19 @@ function encode_item($item,$mirror = false) {
$x['owner'] = encode_item_xchan($item['owner']);
$x['author'] = encode_item_xchan($item['author']);
- if($item['obj'])
- $x['object'] = json_decode($item['obj'],true);
+ if ($zap_compat) {
+ $x['object'] = Activity::encode_item_object($item,'obj');
+ }
+ else {
+ if ($item['obj']) {
+ $x['object'] = json_decode($item['obj'],true);
+ }
+ }
+
if($item['target'])
- $x['target'] = json_decode($item['target'],true);
+ $x['target'] = (($zap_compat)
+ ? Activity::encode_item_object($item,'target')
+ : json_decode($item['target'],true)) ;
if($item['attach'])
$x['attach'] = json_decode($item['attach'],true);
if($y = encode_item_flags($item))
@@ -1200,9 +1209,16 @@ function encode_item($item,$mirror = false) {
if($item['term'])
$x['tags'] = encode_item_terms($item['term'],$mirror);
- if($item['iconfig'])
+ if($item['iconfig']) {
+ if ($zap_compat) {
+ for ($y = 0; $y < count($item['iconfig']); $y ++) {
+ if (preg_match('|^a:[0-9]+:{.*}$|s', $item['iconfig'][$y]['v'])) {
+ $item['iconfig'][$y]['v'] = serialise(unserialize($item['iconfig'][$y]['v']));
+ }
+ }
+ }
$x['meta'] = encode_item_meta($item['iconfig'],$mirror);
-
+ }
logger('encode_item: ' . print_r($x,true), LOGGER_DATA);
@@ -1400,6 +1416,30 @@ function decode_tags($t) {
return '';
}
+
+function purify_imported_object($obj) {
+ $ret = null;
+ if (is_array($obj)) {
+ foreach ( $obj as $k => $v ) {
+ if (is_array($v)) {
+ $ret[$k] = purify_imported_object($v);
+ }
+ elseif (is_string($v)) {
+ $ret[$k] = purify_html($v);
+ }
+ }
+ }
+ elseif (is_string($obj)) {
+ $ret = purify_html($obj);
+ }
+
+ return $ret;
+}
+
+
+
+
+
/**
* @brief Santise a potentially complex array.
*
@@ -1411,6 +1451,10 @@ function activity_sanitise($arr) {
if(is_array($arr)) {
$ret = array();
foreach($arr as $k => $x) {
+ if (in_array($k, [ 'content', 'summary', 'contentMap', 'summaryMap' ])) {
+ $ret[$k] = purify_imported_object($arr[$k]);
+ continue;
+ }
if(is_array($x))
$ret[$k] = activity_sanitise($x);
else