aboutsummaryrefslogtreecommitdiffstats
path: root/include/items.php
diff options
context:
space:
mode:
Diffstat (limited to 'include/items.php')
-rwxr-xr-xinclude/items.php633
1 files changed, 565 insertions, 68 deletions
diff --git a/include/items.php b/include/items.php
index 44f9633a9..95822c0ba 100755
--- a/include/items.php
+++ b/include/items.php
@@ -159,7 +159,7 @@ function filter_insecure($channel_id, $arr) {
$ret = array();
- if((! intval(get_pconfig($channel_id, 'system', 'filter_insecure_collections'))) || (! $arr))
+ if((! intval(get_pconfig($channel_id, 'system', 'filter_insecure_privacy_groups'))) || (! $arr))
return $arr;
$str = '';
@@ -274,7 +274,7 @@ function can_comment_on_post($observer_xchan, $item) {
return true;
if(strstr($item['comment_policy'],'network:') && strstr($item['comment_policy'],'diaspora'))
return true;
- if(strstr($item['comment_policy'],'site:') && strstr($item['comment_policy'],get_app()->get_hostname()))
+ if(strstr($item['comment_policy'],'site:') && strstr($item['comment_policy'],App::get_hostname()))
return true;
return false;
@@ -413,8 +413,8 @@ function post_activity_item($arr) {
if(! array_key_exists('item_thread_top',$arr) && (! $is_comment))
$arr['item_thread_top'] = 1;
- $channel = get_app()->get_channel();
- $observer = get_app()->get_observer();
+ $channel = App::get_channel();
+ $observer = App::get_observer();
$arr['aid'] = ((x($arr,'aid')) ? $arr['aid'] : $channel['channel_account_id']);
$arr['uid'] = ((x($arr,'uid')) ? $arr['uid'] : $channel['channel_id']);
@@ -552,6 +552,12 @@ function get_public_feed($channel, $params) {
$params['top'] = ((x($params,'top')) ? intval($params['top']) : 0);
$params['cat'] = ((x($params,'cat')) ? $params['cat'] : '');
+
+ // put a sane lower limit on feed requests if not specified
+
+ if($params['begin'] === NULL_DATE)
+ $params['begin'] = datetime_convert('UTC','UTC','now - 1 month');
+
switch($params['type']) {
case 'json':
header("Content-type: application/atom+json");
@@ -587,8 +593,8 @@ function get_feed_for($channel, $observer_hash, $params) {
}
$items = items_fetch(array(
'wall' => '1',
- 'datequery' => $params['begin'],
- 'datequery2' => $params['end'],
+ 'datequery' => $params['end'],
+ 'datequery2' => $params['begin'],
'start' => $params['start'], // FIXME
'records' => $params['records'], // FIXME
'direction' => $params['direction'], // FIXME
@@ -596,7 +602,7 @@ function get_feed_for($channel, $observer_hash, $params) {
'order' => 'post',
'top' => $params['top'],
'cat' => $params['cat']
- ), $channel, $observer_hash, CLIENT_MODE_NORMAL, get_app()->module);
+ ), $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module);
$feed_template = get_markup_template('atom_feed.tpl');
@@ -604,8 +610,8 @@ function get_feed_for($channel, $observer_hash, $params) {
$atom = '';
$atom .= replace_macros($feed_template, array(
- '$version' => xmlify(RED_VERSION),
- '$red' => xmlify(PLATFORM_NAME),
+ '$version' => xmlify(Zotlabs\Project\System::get_project_version()),
+ '$red' => xmlify(Zotlabs\Project\System::get_platform_name()),
'$feed_id' => xmlify($channel['xchan_url']),
'$feed_title' => xmlify($channel['channel_name']),
'$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', 'now' , ATOM_TIME)) ,
@@ -623,6 +629,7 @@ function get_feed_for($channel, $observer_hash, $params) {
'$community' => '',
));
+
call_hooks('atom_feed', $atom);
if($items) {
@@ -842,7 +849,7 @@ function get_item_elements($x,$allow_code = false) {
if($allow_code)
$arr['body'] = $x['body'];
else
- $arr['body'] = (($x['body']) ? htmlspecialchars($x['body'],ENT_COMPAT,'UTF-8',false) : '');
+ $arr['body'] = (($x['body']) ? htmlspecialchars($x['body'],ENT_COMPAT,'UTF-8',false) : '');
$key = get_config('system','pubkey');
@@ -910,6 +917,7 @@ function get_item_elements($x,$allow_code = false) {
$arr['attach'] = activity_sanitise($x['attach']);
$arr['term'] = decode_tags($x['tags']);
+ $arr['iconfig'] = decode_item_meta($x['meta']);
$arr['item_private'] = ((array_key_exists('flags',$x) && is_array($x['flags']) && in_array('private',$x['flags'])) ? 1 : 0);
@@ -1136,9 +1144,8 @@ function import_author_rss($x) {
$photos = import_xchan_photo($x['photo']['src'],$x['url']);
if($photos) {
- /** @bug $arr is undefined in this SQL query */
$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_url = '%s' and xchan_network = 'rss'",
- dbesc(datetime_convert('UTC', 'UTC', $arr['photo_updated'])),
+ dbesc(datetime_convert()),
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
@@ -1181,9 +1188,8 @@ function import_author_unknown($x) {
$photos = import_xchan_photo($x['photo']['src'],$x['url']);
if($photos) {
- /** @bug $arr is undefined in this SQL query */
$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_url = '%s' and xchan_network = 'unknown'",
- dbesc(datetime_convert('UTC','UTC',$arr['photo_updated'])),
+ dbesc(datetime_convert()),
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
@@ -1317,6 +1323,9 @@ function encode_item($item,$mirror = false) {
if($item['term'])
$x['tags'] = encode_item_terms($item['term'],$mirror);
+ if($item['iconfig'])
+ $x['meta'] = encode_item_meta($item['iconfig'],$mirror);
+
if($item['diaspora_meta']) {
$z = json_decode($item['diaspora_meta'],true);
if($z) {
@@ -1353,7 +1362,7 @@ function map_scope($scope, $strip = false) {
case PERMS_AUTHED:
return 'authenticated';
case PERMS_SITE:
- return 'site: ' . get_app()->get_hostname();
+ return 'site: ' . App::get_hostname();
case PERMS_PENDING:
return 'any connections';
case PERMS_CONTACTS:
@@ -1427,6 +1436,30 @@ function encode_item_terms($terms,$mirror = false) {
return $ret;
}
+function encode_item_meta($meta,$mirror = false) {
+ $ret = array();
+
+ if($meta) {
+ foreach($meta as $m) {
+ if($m['sharing'] || $mirror)
+ $ret[] = array('family' => $m['cat'], 'key' => $m['k'], 'value' => $m['v'], 'sharing' => intval($m['sharing']));
+ }
+ }
+
+ return $ret;
+}
+
+function decode_item_meta($meta) {
+ $ret = array();
+
+ if(is_array($meta) && $meta) {
+ foreach($meta as $m) {
+ $ret[] = array('cat' => escape_tags($m['family']),'k' => escape_tags($m['key']),'v' => $m['value'],'sharing' => $m['sharing']);
+ }
+ }
+ return $ret;
+}
+
/**
* @brief
*
@@ -2058,6 +2091,10 @@ function get_atom_elements($feed, $item, &$author) {
$res['obj_type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data'];
$obj['type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data'];
}
+ if($child[NAMESPACE_ACTIVITY]['object-type'][0]['data']) {
+ $res['obj_type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
+ $obj['type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
+ }
if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'id') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'])
$obj['id'] = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'];
if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'link') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['link'])
@@ -2091,6 +2128,10 @@ function get_atom_elements($feed, $item, &$author) {
$res['tgt_type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data'];
$obj['type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data'];
}
+ if($child[NAMESPACE_ACTIVITY]['object-type'][0]['data']) {
+ $res['tgt_type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
+ $obj['type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
+ }
if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'id') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'])
$obj['id'] = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'];
if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'link') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['link'])
@@ -2115,9 +2156,6 @@ function get_atom_elements($feed, $item, &$author) {
$res['target'] = $obj;
}
- $res['public_policy'] = 'specific';
- $res['comment_policy'] = 'none';
-
$arr = array('feed' => $feed, 'item' => $item, 'result' => $res);
call_hooks('parse_atom', $arr);
@@ -2129,26 +2167,27 @@ function get_atom_elements($feed, $item, &$author) {
}
function encode_rel_links($links) {
- $o = '';
+ $o = array();
if(! ((is_array($links)) && (count($links))))
return $o;
foreach($links as $link) {
- $o .= '<link ';
+ $l = array();
if($link['attribs']['']['rel'])
- $o .= 'rel="' . $link['attribs']['']['rel'] . '" ';
+ $l['rel'] = $link['attribs']['']['rel'];
if($link['attribs']['']['type'])
- $o .= 'type="' . $link['attribs']['']['type'] . '" ';
+ $l['type'] = $link['attribs']['']['type'];
if($link['attribs']['']['href'])
- $o .= 'href="' . $link['attribs']['']['href'] . '" ';
+ $l['href'] = $link['attribs']['']['href'];
if( (x($link['attribs'],NAMESPACE_MEDIA)) && $link['attribs'][NAMESPACE_MEDIA]['width'])
- $o .= 'media:width="' . $link['attribs'][NAMESPACE_MEDIA]['width'] . '" ';
+ $l['width'] = $link['attribs'][NAMESPACE_MEDIA]['width'];
if( (x($link['attribs'],NAMESPACE_MEDIA)) && $link['attribs'][NAMESPACE_MEDIA]['height'])
- $o .= 'media:height="' . $link['attribs'][NAMESPACE_MEDIA]['height'] . '" ';
- $o .= ' />' . "\n" ;
- }
+ $l['height'] = $link['attribs'][NAMESPACE_MEDIA]['height'];
- return xmlify($o);
+ if($l)
+ $o[] = $l;
+ }
+ return $o;
}
/**
@@ -2160,7 +2199,7 @@ function encode_rel_links($links) {
* * \e boolean \b success
* * \e int \b item_id
*/
-function item_store($arr, $allow_exec = false) {
+function item_store($arr, $allow_exec = false, $deliver = true) {
$d = array('item' => $arr, 'allow_exec' => $allow_exec);
call_hooks('item_store', $d );
@@ -2226,7 +2265,7 @@ function item_store($arr, $allow_exec = false) {
$arr['body'] = trim(z_input_filter($arr['uid'],$arr['body'],$arr['mimetype']));
if(local_channel() && (! $arr['sig'])) {
- $channel = get_app()->get_channel();
+ $channel = App::get_channel();
if($channel['channel_hash'] === $arr['author_xchan']) {
$arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey']));
$arr['item_verified'] = 1;
@@ -2439,6 +2478,13 @@ function item_store($arr, $allow_exec = false) {
unset($arr['term']);
}
+ $meta = null;
+ if(array_key_exists('iconfig',$arr)) {
+ $meta = $arr['iconfig'];
+ unset($arr['iconfig']);
+ }
+
+
if(strlen($allow_cid) || strlen($allow_gid) || strlen($deny_cid) || strlen($deny_gid) || strlen($public_policy))
$private = 1;
else
@@ -2516,6 +2562,15 @@ function item_store($arr, $allow_exec = false) {
$arr['term'] = $terms;
}
+ if($meta) {
+ foreach($meta as $m) {
+ set_iconfig($current_post,$m['cat'],$m['k'],$m['v'],$m['sharing']);
+ }
+ $arr['iconfig'] = $meta;
+ }
+
+
+
call_hooks('post_remote_end',$arr);
// update the commented timestamp on the parent
@@ -2537,7 +2592,7 @@ function item_store($arr, $allow_exec = false) {
// so that we have an item in the DB that's marked deleted and won't store a fresh post
// that isn't aware that we were already told to delete it.
- if(! intval($arr['item_deleted'])) {
+ if(($deliver) && (! intval($arr['item_deleted']))) {
send_status_notifications($current_post,$arr);
tag_deliver($arr['uid'],$current_post);
}
@@ -2550,7 +2605,7 @@ function item_store($arr, $allow_exec = false) {
-function item_store_update($arr,$allow_exec = false) {
+function item_store_update($arr,$allow_exec = false, $deliver = true) {
$d = array('item' => $arr, 'allow_exec' => $allow_exec);
call_hooks('item_store_update', $d );
@@ -2606,7 +2661,7 @@ function item_store_update($arr,$allow_exec = false) {
$arr['body'] = trim(z_input_filter($arr['uid'],$arr['body'],$arr['mimetype']));
if(local_channel() && (! $arr['sig'])) {
- $channel = get_app()->get_channel();
+ $channel = App::get_channel();
if($channel['channel_hash'] === $arr['author_xchan']) {
$arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey']));
$arr['item_verified'] = 1;
@@ -2737,6 +2792,13 @@ function item_store_update($arr,$allow_exec = false) {
unset($arr['term']);
}
+ $meta = null;
+ if(array_key_exists('iconfig',$arr)) {
+ $meta = $arr['iconfig'];
+ unset($arr['iconfig']);
+ }
+
+
dbesc_array($arr);
logger('item_store_update: ' . print_r($arr,true), LOGGER_DATA);
@@ -2778,11 +2840,24 @@ function item_store_update($arr,$allow_exec = false) {
$arr['term'] = $terms;
}
+ $r = q("delete from iconfig where iid = %d",
+ intval($orig_post_id)
+ );
+
+ if($meta) {
+ foreach($meta as $m) {
+ set_iconfig($orig_post_id,$m['cat'],$m['k'],$m['v'],$m['sharing']);
+ }
+ $arr['iconfig'] = $meta;
+ }
+
call_hooks('post_remote_update_end',$arr);
- send_status_notifications($orig_post_id,$arr);
+ if($deliver) {
+ send_status_notifications($orig_post_id,$arr);
+ tag_deliver($uid,$orig_post_id);
+ }
- tag_deliver($uid,$orig_post_id);
$ret['success'] = true;
$ret['item_id'] = $orig_post_id;
@@ -2812,17 +2887,17 @@ function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id,
logger('storing diaspora comment signature',LOGGER_DEBUG);
- $diaspora_handle = $channel['channel_address'] . '@' . get_app()->get_hostname();
+ $diaspora_handle = $channel['channel_address'] . '@' . App::get_hostname();
$signed_text = $datarray['mid'] . ';' . $parent_item['mid'] . ';' . $signed_body . ';' . $diaspora_handle;
- /** @FIXME $uprvkey is undefined, do we still need this if-statement? */
- if( $uprvkey !== false )
+
+ if( $channel && $channel['channel_prvkey'] )
$authorsig = base64_encode(rsa_sign($signed_text, $channel['channel_prvkey'], 'sha256'));
else
$authorsig = '';
- $x = array('signer' => $diaspora_handle, 'body' => $signed_body, 'signed_text' => $signed_text, 'signature' => base64_encode($authorsig));
+ $x = array('signer' => $diaspora_handle, 'body' => $signed_body, 'signed_text' => $signed_text, 'signature' => $authorsig);
$y = json_encode($x);
@@ -2831,6 +2906,7 @@ function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id,
intval($post_id)
);
+
if(! $r)
logger('store_diaspora_comment_sig: DB write failed');
@@ -2890,7 +2966,7 @@ function send_status_notifications($post_id,$item) {
if($unfollowed)
return;
- $link = get_app()->get_baseurl() . '/display/' . $item['mid'];
+ $link = z_root() . '/display/' . $item['mid'];
$y = q("select id from notify where link = '%s' and uid = %d limit 1",
dbesc($link),
@@ -3436,6 +3512,7 @@ function check_item_source($uid, $item) {
if(! $r[0]['src_patt'])
return true;
+
require_once('include/html2plain.php');
$text = prepare_text($item['body'],$item['mimetype']);
$text = html2plain($text);
@@ -3651,10 +3728,6 @@ function mail_store($arr) {
/**
* @brief Process atom feed and update anything/everything we might need to update.
*
- * $hub = should we find a hub declation in the feed, pass it back to our calling process, who might (or
- * might not) try and subscribe to it.
- * $datedir sorts in reverse order
- *
* @param array $xml
* The (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds.
* @param $importer
@@ -3685,6 +3758,16 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
return;
}
+ $sys_expire = intval(get_config('system','default_expire_days'));
+ $chn_expire = intval($importer['channel_expire_days']);
+
+ $expire_days = $sys_expire;
+
+ if(($chn_expire != 0) && ($chn_expire < $sys_expire))
+ $expire_days = $chn_expire;
+
+ // logger('expire_days: ' . $expire_days);
+
$feed = new SimplePie();
$feed->set_raw_data($xml);
$feed->init();
@@ -3764,6 +3847,11 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
$author = array();
$datarray = get_atom_elements($feed,$item,$author);
+ if($contact['xchan_network'] === 'rss') {
+ $datarray['public_policy'] = 'specific';
+ $datarray['comment_policy'] = 'none';
+ }
+
if((! x($author,'author_name')) || ($author['author_is_feed']))
$author['author_name'] = $contact['xchan_name'];
if((! x($author,'author_link')) || ($author['author_is_feed']))
@@ -3788,6 +3876,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
intval($importer['channel_id'])
);
+
// Update content if 'updated' changes
if($r) {
@@ -3804,6 +3893,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
}
$datarray['parent_mid'] = $parent_mid;
+ $datarray['aid'] = $importer['channel_account_id'];
$datarray['uid'] = $importer['channel_id'];
logger('consume_feed: ' . print_r($datarray,true),LOGGER_DATA);
@@ -3820,6 +3910,12 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
$author = array();
$datarray = get_atom_elements($feed,$item,$author);
+ if($contact['xchan_network'] === 'rss') {
+ $datarray['public_policy'] = 'specific';
+ $datarray['comment_policy'] = 'none';
+ }
+
+
if(is_array($contact)) {
if((! x($author,'author_name')) || ($author['author_is_feed']))
$author['author_name'] = $contact['xchan_name'];
@@ -3836,6 +3932,16 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
$datarray['author_xchan'] = '';
+ if(activity_match($datarray['verb'],ACTIVITY_FOLLOW) && $datarray['obj_type'] === ACTIVITY_OBJ_PERSON) {
+ $cb = array('item' => $datarray,'channel' => $importer, 'xchan' => null, 'author' => $author, 'caught' => false);
+ call_hooks('follow_from_feed',$cb);
+ if($cb['caught']) {
+ if($cb['return_code'])
+ http_status_exit($cb['return_code']);
+ continue;
+ }
+ }
+
if($author['author_link'] != $contact['xchan_url']) {
$x = import_author_unknown(array('name' => $author['author_name'],'url' => $author['author_link'],'photo' => array('src' => $author['author_photo'])));
if($x)
@@ -3846,6 +3952,17 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
$datarray['owner_xchan'] = $contact['xchan_hash'];
+ if(array_key_exists('created',$datarray) && $datarray['created'] != NULL_DATE && $expire_days) {
+ $t1 = $datarray['created'];
+ $t2 = datetime_convert('UTC','UTC','now - ' . $expire_days . 'days');
+ if($t1 < $t2) {
+ logger('feed content older than expiration. Ignoring.', LOGGER_DEBUG, LOG_INFO);
+ continue;
+ }
+ }
+
+
+
$r = q("SELECT edited FROM item WHERE mid = '%s' AND uid = %d LIMIT 1",
dbesc($item_id),
intval($importer['channel_id'])
@@ -3869,6 +3986,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
$datarray['parent_mid'] = $item_id;
$datarray['uid'] = $importer['channel_id'];
+ $datarray['aid'] = $importer['channel_account_id'];
if(! link_compare($author['owner_link'],$contact['xchan_url'])) {
logger('consume_feed: Correcting item owner.', LOGGER_DEBUG);
@@ -3892,6 +4010,144 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
}
}
+
+/**
+ * @brief Process atom feed and return the first post and structure
+ *
+ * @param array $xml
+ * The (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds.
+ * @param $importer
+ * The contact_record (joined to user_record) of the local user who owns this
+ * relationship. It is this person's stuff that is going to be updated.
+ */
+
+function process_salmon_feed($xml, $importer) {
+
+ $ret = array();
+
+ require_once('library/simplepie/simplepie.inc');
+
+ if(! strlen($xml)) {
+ logger('process_feed: empty input');
+ return;
+ }
+
+ $feed = new SimplePie();
+ $feed->set_raw_data($xml);
+ $feed->init();
+
+ if($feed->error())
+ logger('Error parsing XML: ' . $feed->error());
+
+ $permalink = $feed->get_permalink();
+
+ if($feed->get_item_quantity()) {
+
+ // this should be exactly one
+
+ logger('feed item count = ' . $feed->get_item_quantity(), LOGGER_DEBUG);
+
+ $items = $feed->get_items();
+
+ foreach($items as $item) {
+
+ $item_id = base64url_encode($item->get_id());
+
+ logger('processing ' . $item_id, LOGGER_DEBUG);
+
+ $rawthread = $item->get_item_tags( NAMESPACE_THREAD,'in-reply-to');
+ if(isset($rawthread[0]['attribs']['']['ref'])) {
+ $is_reply = true;
+ $parent_mid = base64url_encode($rawthread[0]['attribs']['']['ref']);
+ }
+
+ if($is_reply)
+ $ret['parent_mid'] = $parent_mid;
+
+ $ret['author'] = array();
+
+ $datarray = get_atom_elements($feed,$item,$ret['author']);
+
+ // reset policies which are restricted by default for RSS connections
+ // This item is likely coming from GNU-social via salmon and allows public interaction
+ $datarray['public_policy'] = '';
+ $datarray['comment_policy'] = '';
+
+ $ret['item'] = $datarray;
+ }
+ }
+
+ return $ret;
+}
+
+/*
+ * Given an xml (atom) feed, find author and hub links
+ */
+
+
+function feed_meta($xml) {
+ require_once('library/simplepie/simplepie.inc');
+
+ $ret = array();
+
+ if(! strlen($xml)) {
+ logger('empty input');
+ return $ret;
+ }
+
+ $feed = new SimplePie();
+ $feed->set_raw_data($xml);
+ $feed->init();
+
+ if($feed->error()) {
+ logger('Error parsing XML: ' . $feed->error());
+ return $ret;
+ }
+
+ $ret['hubs'] = $feed->get_links('hub');
+
+// logger('consume_feed: hubs: ' . print_r($hubs,true), LOGGER_DATA);
+
+ $author = array();
+
+ $found_author = $feed->get_author();
+ if($found_author) {
+ $author['author_name'] = unxmlify($found_author->get_name());
+ $author['author_link'] = unxmlify($found_author->get_link());
+
+ $rawauthor = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
+ logger('rawauthor: ' . print_r($rawauthor,true));
+
+ if($rawauthor) {
+ if($rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
+ $base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
+ foreach($base as $link) {
+ if(!x($author, 'author_photo') || ! $author['author_photo']) {
+ if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar') {
+ $author['author_photo'] = unxmlify($link['attribs']['']['href']);
+ break;
+ }
+ }
+ }
+ }
+ if($rawauthor[0]['child'][NAMESPACE_POCO]['displayName'][0]['data'])
+ $author['full_name'] = unxmlify($rawauthor[0]['child'][NAMESPACE_POCO]['displayName'][0]['data']);
+ if($rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])
+ $author['author_uri'] = unxmlify($rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']);
+
+ }
+ }
+
+ if(substr($author['author_link'],-1,1) == '/')
+ $author['author_link'] = substr($author['author_link'],0,-1);
+
+ $ret['author'] = $author;
+
+ return $ret;
+}
+
+
+
function update_feed_item($uid,$datarray) {
logger('update_feed_item: not implemented! ' . $uid . ' ' . print_r($datarray,true), LOGGER_DATA);
}
@@ -3915,8 +4171,8 @@ function handle_feed($uid,$abook_id,$url) {
//logger('handle_feed:' . print_r($z,true));
if($z['success']) {
- consume_feed($z['body'],$channel,$x[0],0);
consume_feed($z['body'],$channel,$x[0],1);
+ consume_feed($z['body'],$channel,$x[0],2);
}
}
@@ -3972,15 +4228,28 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) {
if(($item['parent'] != $item['id']) || ($item['parent_mid'] !== $item['mid']) || (($item['thr_parent'] !== '') && ($item['thr_parent'] !== $item['mid']))) {
$parent_item = (($item['thr_parent']) ? $item['thr_parent'] : $item['parent_mid']);
- $o .= '<thr:in-reply-to ref="' . xmlify($parent_item) . '" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n";
+ $o .= '<thr:in-reply-to ref="' . z_root() . '/display/' . xmlify($parent_item) . '" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n";
+ }
+
+ if(activity_match($item['obj_type'],ACTIVITY_OBJ_EVENT) && activity_match($item['verb'],ACTIVITY_POST)) {
+ $obj = ((is_array($item['obj'])) ? $item['object'] : json_decode($item['object'],true));
+
+ $o .= '<title>' . xmlify($item['title']) . '</title>' . "\r\n";
+ $o .= '<summary>' . xmlify(bbcode($obj['title'])) . '</summary>' . "\r\n";
+ $o .= '<dtstart xmlns="urn:ietf:params:xml:ns:xcal">' . datetime_convert('UTC','UTC', $obj['start'],'Ymd\\THis' . (($obj['adjust']) ? '\\Z' : '')) . '</dtstart>' . "\r\n";
+ $o .= '<dtend xmlns="urn:ietf:params:xml:ns:xcal">' . datetime_convert('UTC','UTC', $obj['finish'],'Ymd\\THis' . (($obj['adjust']) ? '\\Z' : '')) . '</dtend>' . "\r\n";
+ $o .= '<location>' . bbcode($obj['location']) . '</location>' . "\r\n";
+ $o .= '<content type="' . $type . '" >' . xmlify(bbcode($obj['description'])) . '</content>' . "\r\n";
+ }
+ else {
+ $o .= '<title>' . xmlify($item['title']) . '</title>' . "\r\n";
+ $o .= '<content type="' . $type . '" >' . xmlify(prepare_text($body,$item['mimetype'])) . '</content>' . "\r\n";
}
- $o .= '<id>' . xmlify($item['mid']) . '</id>' . "\r\n";
- $o .= '<title>' . xmlify($item['title']) . '</title>' . "\r\n";
+ $o .= '<id>' . z_root() . '/display/' . xmlify($item['mid']) . '</id>' . "\r\n";
$o .= '<published>' . xmlify(datetime_convert('UTC','UTC',$item['created'] . '+00:00',ATOM_TIME)) . '</published>' . "\r\n";
$o .= '<updated>' . xmlify(datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)) . '</updated>' . "\r\n";
- $o .= '<content type="' . $type . '" >' . xmlify(prepare_text($body,$item['mimetype'])) . '</content>' . "\r\n";
$o .= '<link rel="alternate" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n";
if($item['location']) {
@@ -4029,10 +4298,9 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) {
}
function fix_private_photos($s, $uid, $item = null, $cid = 0) {
- $a = get_app();
logger('fix_private_photos', LOGGER_DEBUG);
- $site = substr($a->get_baseurl(),strpos($a->get_baseurl(),'://'));
+ $site = substr(z_root(),strpos(z_root(),'://'));
$orig_body = $s;
$new_body = '';
@@ -4312,8 +4580,6 @@ function drop_items($items) {
function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = false) {
- $a = get_app();
-
// locate item to be deleted
$r = q("SELECT * FROM item WHERE id = %d LIMIT 1",
@@ -4324,7 +4590,7 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal
if(! $interactive)
return 0;
notice( t('Item not found.') . EOL);
- goaway($a->get_baseurl() . '/' . $_SESSION['return_url']);
+ goaway(z_root() . '/' . $_SESSION['return_url']);
}
$item = $r[0];
@@ -4347,7 +4613,7 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal
$ok_to_delete = true;
// author deletion
- $observer = $a->get_observer();
+ $observer = App::get_observer();
if($observer && $observer['xchan_hash'] && ($observer['xchan_hash'] === $item['author_xchan']))
$ok_to_delete = true;
@@ -4397,13 +4663,13 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal
if((intval($item['item_wall']) && ($stage != DROPITEM_PHASE2)) || ($stage == DROPITEM_PHASE1))
proc_run('php','include/notifier.php','drop',$notify_id);
- goaway($a->get_baseurl() . '/' . $_SESSION['return_url']);
+ goaway(z_root() . '/' . $_SESSION['return_url']);
}
else {
if(! $interactive)
return 0;
notice( t('Permission denied.') . EOL);
- goaway($a->get_baseurl() . '/' . $_SESSION['return_url']);
+ goaway(z_root() . '/' . $_SESSION['return_url']);
}
}
@@ -4643,6 +4909,10 @@ function fetch_post_tags($items,$link = false) {
dbesc($tag_finder_str),
intval(TERM_OBJ_POST)
);
+ $imeta = q("select * from iconfig where iid in ( %s )",
+ dbesc($tag_finder_str)
+ );
+
}
for($x = 0; $x < count($items); $x ++) {
@@ -4666,6 +4936,26 @@ function fetch_post_tags($items,$link = false) {
}
}
}
+ if($imeta) {
+ foreach($imeta as $i) {
+ if(array_key_exists('item_id',$items[$x])) {
+ if($i['iid'] == $items[$x]['item_id']) {
+ if(! is_array($items[$x]['iconfig']))
+ $items[$x]['iconfig'] = array();
+ $i['v'] = ((preg_match('|^a:[0-9]+:{.*}$|s',$i['v'])) ? unserialize($i['v']) : $i['v']);
+ $items[$x]['iconfig'][] = $i;
+ }
+ }
+ else {
+ if($i['iid'] == $items[$x]['id']) {
+ if(! is_array($items[$x]['iconfig']))
+ $items[$x]['iconfig'] = array();
+ $i['v'] = ((preg_match('|^a:[0-9]+:{.*}$|s',$i['v'])) ? unserialize($i['v']) : $i['v']);
+ $items[$x]['iconfig'][] = $i;
+ }
+ }
+ }
+ }
}
return $items;
@@ -4788,8 +5078,6 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$result = array('success' => false);
- $a = get_app();
-
$sql_extra = '';
$sql_nets = '';
$sql_options = '';
@@ -4835,7 +5123,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
intval($uid)
);
if(! $r) {
- $result['message'] = t('Collection not found.');
+ $result['message'] = t('Privacy group not found.');
return $result;
}
@@ -4851,14 +5139,14 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
}
} else {
$contact_str = ' 0 ';
- $result['message'] = t('Collection is empty.');
+ $result['message'] = t('Privacy group is empty.');
return $result;
}
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str)) or allow_gid like '" . protect_sprintf('%<' . dbesc($r[0]['hash']) . '>%') . "' ) and id = parent $item_normal ) ";
$x = group_rec_byhash($uid,$r[0]['hash']);
- $result['headline'] = sprintf( t('Collection: %s'),$x['name']);
+ $result['headline'] = sprintf( t('Privacy group: %s'),$x['name']);
}
elseif($arr['cid'] && $uid) {
@@ -4876,15 +5164,15 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
}
if ($arr['datequery']) {
- $sql_extra3 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$arr['datequery']))));
+ $sql_extra3 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert('UTC','UTC',$arr['datequery']))));
}
if ($arr['datequery2']) {
- $sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$arr['datequery2']))));
+ $sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert('UTC','UTC',$arr['datequery2']))));
}
if(! array_key_exists('nouveau',$arr)) {
$sql_extra2 = " AND item.parent = item.id ";
- $sql_extra3 = '';
+// $sql_extra3 = '';
}
if($arr['search']) {
@@ -4912,8 +5200,8 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$pager_sql = '';
} else {
$itemspage = (($channel) ? get_pconfig($uid,'system','itemspage') : 20);
- $a->set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
- $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(get_app()->pager['itemspage']), intval(get_app()->pager['start']));
+ App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
+ $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
}
if (isset($arr['start']) && isset($arr['records']))
@@ -5183,7 +5471,7 @@ function set_linkified_perms($linkified, &$str_contact_allow, &$str_group_allow,
* @return boolean
*/
function comment_local_origin($item) {
- if(stripos($item['mid'], get_app()->get_hostname()) && ($item['parent'] != $item['id']))
+ if(stripos($item['mid'], App::get_hostname()) && ($item['parent'] != $item['id']))
return true;
return false;
@@ -5274,3 +5562,212 @@ function asencode_person($p) {
return $ret;
}
+
+
+function send_profile_photo_activity($channel,$photo,$profile) {
+
+ // for now only create activities for the default profile
+
+ if(! intval($profile['is_default']))
+ return;
+
+ $arr = array();
+ $arr['item_thread_top'] = 1;
+ $arr['item_origin'] = 1;
+ $arr['item_wall'] = 1;
+ $arr['obj_type'] = ACTIVITY_OBJ_PHOTO;
+ $arr['verb'] = ACTIVITY_UPDATE;
+
+ $arr['object'] = json_encode(array(
+ 'type' => $arr['obj_type'],
+ 'id' => z_root() . '/photo/profile/l/' . $channel['channel_id'],
+ 'link' => array('rel' => 'photo', 'type' => $photo['type'], 'href' => z_root() . '/photo/profile/l/' . $channel['channel_id'])
+ ));
+
+ if(stripos($profile['gender'],t('female')) !== false)
+ $t = t('%1$s updated her %2$s');
+ elseif(stripos($profile['gender'],t('male')) !== false)
+ $t = t('%1$s updated his %2$s');
+ else
+ $t = t('%1$s updated their %2$s');
+
+ $ptext = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . t('profile photo') . '[/zrl]';
+
+ $ltext = '[zrl=' . z_root() . '/profile/' . $channel['channel_address'] . ']' . '[zmg=150x150]' . z_root() . '/photo/' . $photo['resource_id'] . '-4[/zmg][/zrl]';
+
+ $arr['body'] = sprintf($t,$channel['channel_name'],$ptext) . "\n\n" . $ltext;
+
+ $acl = new Zotlabs\Access\AccessList($channel);
+ $x = $acl->get();
+ $arr['allow_cid'] = $x['allow_cid'];
+
+ $arr['allow_gid'] = $x['allow_gid'];
+ $arr['deny_cid'] = $x['deny_cid'];
+ $arr['deny_gid'] = $x['deny_gid'];
+
+ $arr['uid'] = $channel['channel_id'];
+ $arr['aid'] = $channel['channel_account_id'];
+
+ $arr['owner_xchan'] = $channel['channel_hash'];
+ $arr['author_xchan'] = $channel['channel_hash'];
+
+ post_activity_item($arr);
+
+
+}
+
+
+
+
+
+function get_iconfig(&$item, $family, $key) {
+
+ $is_item = false;
+ if(is_array($item)) {
+ $is_item = true;
+ if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
+ $item['iconfig'] = array();
+
+ if(array_key_exists('item_id',$item))
+ $iid = $item['item_id'];
+ else
+ $iid = $item['id'];
+ }
+ elseif(intval($item))
+ $iid = $item;
+
+ if(! $iid)
+ return false;
+
+ if(is_array($item) && array_key_exists('iconfig',$item) && is_array($item['iconfig'])) {
+ foreach($item['iconfig'] as $c) {
+ if($c['iid'] == $iid && $c['cat'] == $family && $c['k'] == $key)
+ return $c['v'];
+ }
+ }
+
+ $r = q("select * from iconfig where iid = %d and cat = '%s' and k = '%s' limit 1",
+ intval($iid),
+ dbesc($family),
+ dbesc($key)
+ );
+ if($r) {
+ $r[0]['v'] = ((preg_match('|^a:[0-9]+:{.*}$|s',$r[0]['v'])) ? unserialize($r[0]['v']) : $r[0]['v']);
+ if($is_item)
+ $item['iconfig'][] = $r[0];
+ return $r[0]['v'];
+ }
+ return false;
+
+}
+
+/**
+ * set_iconfig(&$item, $family, $key, $value, $sharing = false);
+ *
+ * $item - item array or item id. If passed an array the iconfig meta information is
+ * added to the item structure (which will need to be saved with item_store eventually).
+ * If passed an id, the DB is updated, but may not be federated and/or cloned.
+ * $family - namespace of meta variable
+ * $key - key of meta variable
+ * $value - value of meta variable
+ * $sharing - boolean (default false); if true the meta information is propagated with the item
+ * to other sites/channels, mostly useful when $item is an array and has not yet been stored/delivered.
+ * If the meta information is added after delivery and you wish it to be shared, it may be necessary to
+ * alter the item edited timestamp and invoke the delivery process on the updated item. The edited
+ * timestamp needs to be altered in order to trigger an item_store_update() at the receiving end.
+ */
+
+
+function set_iconfig(&$item, $family, $key, $value, $sharing = false) {
+
+ $dbvalue = ((is_array($value)) ? serialize($value) : $value);
+ $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
+
+ $is_item = false;
+ $idx = null;
+
+ if(is_array($item)) {
+ $is_item = true;
+ if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
+ $item['iconfig'] = array();
+ elseif($item['iconfig']) {
+ for($x = 0; $x < count($item['iconfig']); $x ++) {
+ if($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
+ $idx = $x;
+ }
+ }
+ }
+ $entry = array('cat' => $family, 'k' => $key, 'v' => $value, 'sharing' => $sharing);
+
+ if(is_null($idx))
+ $item['iconfig'][] = $entry;
+ else
+ $item['iconfig'][$idx] = $entry;
+ return $value;
+ }
+
+ if(intval($item))
+ $iid = intval($item);
+
+ if(! $iid)
+ return false;
+
+ if(get_iconfig($item, $family, $key) === false) {
+ $r = q("insert into iconfig( iid, cat, k, v, sharing ) values ( %d, '%s', '%s', '%s', %d ) ",
+ intval($iid),
+ dbesc($family),
+ dbesc($key),
+ dbesc($dbvalue),
+ intval($sharing)
+ );
+ }
+ else {
+ $r = q("update iconfig set v = '%s', sharing = %d where iid = %d and cat = '%s' and k = '%s' ",
+ dbesc($dbvalue),
+ intval($sharing),
+ intval($iid),
+ dbesc($family),
+ dbesc($key)
+ );
+ }
+
+ if(! $r)
+ return false;
+
+ return $value;
+}
+
+
+
+function del_iconfig(&$item, $family, $key) {
+
+
+ $is_item = false;
+ $idx = null;
+
+ if(is_array($item)) {
+ $is_item = true;
+ if(is_array($item['iconfig'])) {
+ for($x = 0; $x < count($item['iconfig']); $x ++) {
+ if($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
+ unset($item['iconfig'][$x]);
+ }
+ }
+ }
+ return true;
+ }
+
+ if(intval($item))
+ $iid = intval($item);
+
+ if(! $iid)
+ return false;
+
+ return q("delete from iconfig where iid = %d and cat = '%s' and k = '%s' ",
+ intval($iid),
+ dbesc($family),
+ dbesc($key)
+ );
+
+}
+