2013-02-26 01:09:40 +00:00
< ? php /** @file */
2010-07-18 13:02:55 +00:00
2011-08-20 11:53:11 +00:00
require_once ( 'include/bbcode.php' );
require_once ( 'include/oembed.php' );
require_once ( 'include/crypto.php' );
2013-04-26 03:01:24 +00:00
require_once ( 'include/photo/photo_driver.php' );
2013-01-14 02:35:12 +00:00
require_once ( 'include/permissions.php' );
2010-07-18 13:02:55 +00:00
2012-11-16 05:52:05 +00:00
2012-11-19 03:19:16 +00:00
function collect_recipients ( $item , & $private ) {
2012-11-16 05:52:05 +00:00
2013-02-14 22:07:00 +00:00
// FIXME - this needs a revision to handle public scope (this site, this network, etc.)
// We'll be changing this to return an array of
// - recipients
// - private
// - scope if message is public ('global', 'network: red', 'site: $sitename', 'connections')
// The receiving site will need to check the scope before creating a list of local recipients
2012-12-08 22:18:02 +00:00
require_once ( 'include/group.php' );
2014-01-23 06:07:47 +00:00
$private = (( intval ( $item [ 'item_private' ])) ? true : false );
$recipients = array ();
// if the post is marked private but there are no recipients, only add the author and owner
// as recipients. The ACL for the post may live on the hub of a different clone. We need to
// get the post to that hub.
2013-09-13 11:51:55 +00:00
2012-11-16 05:52:05 +00:00
if ( $item [ 'allow_cid' ] || $item [ 'allow_gid' ] || $item [ 'deny_cid' ] || $item [ 'deny_gid' ]) {
2014-01-23 06:07:47 +00:00
// it is private
2012-11-16 05:52:05 +00:00
$allow_people = expand_acl ( $item [ 'allow_cid' ]);
$allow_groups = expand_groups ( expand_acl ( $item [ 'allow_gid' ]));
2013-09-23 03:55:55 +00:00
$recipients = array_unique ( array_merge ( $allow_people , $allow_groups ));
// if you specifically deny somebody but haven't allowed anybody, we'll allow everybody in your
// address book minus the denied connections. The post is still private and can't be seen publicly
// as that would allow the denied person to see the post by logging out.
if (( ! $item [ 'allow_cid' ]) && ( ! $item [ 'allow_gid' ])) {
$r = q ( " select * from abook where abook_channel = %d and not (abook_flags & %d) and not (abook_flags & %d) and not (abook_flags & %d) " ,
intval ( $item [ 'uid' ]),
intval ( ABOOK_FLAG_SELF ),
intval ( ABOOK_FLAG_PENDING ),
intval ( ABOOK_FLAG_ARCHIVED )
);
if ( $r ) {
foreach ( $r as $rr ) {
$recipients [] = $rr [ 'abook_xchan' ];
}
}
}
2012-11-16 05:52:05 +00:00
$deny_people = expand_acl ( $item [ 'deny_cid' ]);
$deny_groups = expand_groups ( expand_acl ( $item [ 'deny_gid' ]));
$deny = array_unique ( array_merge ( $deny_people , $deny_groups ));
$recipients = array_diff ( $recipients , $deny );
2012-11-19 03:19:16 +00:00
$private = true ;
2012-11-16 05:52:05 +00:00
}
else {
2014-01-23 06:07:47 +00:00
if ( ! $private ) {
$r = q ( " select abook_xchan from abook where abook_channel = %d and not (abook_flags & %d) and not (abook_flags & %d) and not (abook_flags & %d) " ,
intval ( $item [ 'uid' ]),
intval ( ABOOK_FLAG_SELF ),
intval ( ABOOK_FLAG_PENDING ),
intval ( ABOOK_FLAG_ARCHIVED )
);
if ( $r ) {
foreach ( $r as $rr ) {
$recipients [] = $rr [ 'abook_xchan' ];
}
2012-11-16 05:52:05 +00:00
}
}
}
2013-01-14 02:35:12 +00:00
// This is a somewhat expensive operation but important.
// Don't send this item to anybody who isn't allowed to see it
$recipients = check_list_permissions ( $item [ 'uid' ], $recipients , 'view_stream' );
2013-07-14 08:12:05 +00:00
// add ourself just in case we have nomadic clones that need to get a copy.
$recipients [] = $item [ 'author_xchan' ];
if ( $item [ 'owner_xchan' ] != $item [ 'author_xchan' ])
$recipients [] = $item [ 'owner_xchan' ];
2012-11-16 05:52:05 +00:00
return $recipients ;
2013-01-14 02:35:12 +00:00
2012-11-16 05:52:05 +00:00
}
2013-09-28 11:41:12 +00:00
/**
* @ function can_comment_on_post ( $observer_xchan , $item );
*
* This function examines the comment_policy attached to an item and decides if the current observer has
* sufficient privileges to comment . This will normally be called on a remote site where perm_is_allowed ()
* will not be suitable because the post owner does not have a local channel_id .
* Generally we should look at the item - in particular the author [ 'book_flags' ] and see if ABOOK_FLAG_SELF is set .
* If it is , you should be able to use perm_is_allowed ( ... 'post_comments' ), and if it isn ' t you need to call
* can_comment_on_post ()
2013-09-28 12:03:58 +00:00
*/
2013-06-17 03:44:29 +00:00
function can_comment_on_post ( $observer_xchan , $item ) {
2013-09-28 11:41:12 +00:00
// logger('can_comment_on_post: comment_policy: ' . $item['comment_policy'], LOGGER_DEBUG);
2013-06-17 03:44:29 +00:00
if ( ! $observer_xchan )
return false ;
if ( $item [ 'comment_policy' ] === 'none' )
return false ;
2013-09-21 00:58:11 +00:00
if ( $observer_xchan === $item [ 'author_xchan' ] || $observer_xchan === $item [ 'owner_xchan' ])
return true ;
2013-06-17 03:44:29 +00:00
switch ( $item [ 'comment_policy' ]) {
case 'self' :
if ( $observer_xchan === $item [ 'author_xchan' ] || $observer_xchan === $item [ 'owner_xchan' ])
return true ;
break ;
case 'public' :
2013-09-28 11:41:12 +00:00
// We don't allow public comments yet, until a policy
// for dealing with anonymous comments is in place with
// a means to moderate comments. Until that time, return
// false.
2013-06-17 03:44:29 +00:00
return false ;
break ;
case 'contacts' :
case '' :
2013-09-21 02:14:57 +00:00
if ( array_key_exists ( 'owner' , $item )) {
if (( $item [ 'owner' ][ 'abook_xchan' ]) && ( $item [ 'owner' ][ 'abook_their_perms' ] & PERMS_W_COMMENT ))
return true ;
}
2013-06-17 03:44:29 +00:00
break ;
default :
break ;
}
2013-06-17 06:07:04 +00:00
if ( strstr ( $item [ 'comment_policy' ], 'network:' ) && strstr ( $item [ 'comment_policy' ], 'red' ))
2013-06-17 03:44:29 +00:00
return true ;
2013-06-17 06:07:04 +00:00
if ( strstr ( $item [ 'comment_policy' ], 'site:' ) && strstr ( $item [ 'comment_policy' ], get_app () -> get_hostname ()))
2013-06-17 03:44:29 +00:00
return true ;
return false ;
}
2013-04-19 00:55:35 +00:00
/**
* @ function red_zrl_callback
* preg_match function when fixing 'naked' links in mod item . php
* Check if we 've got a hubloc for the site and use a zrl if we do, a url if we don' t .
2014-02-16 22:13:26 +00:00
* Remove any existing zid = param which may have been pasted by mistake - and will have
* the author 's credentials. zid' s are dynamic and can ' t really be passed around like
* that .
2013-04-19 00:55:35 +00:00
*/
function red_zrl_callback ( $matches ) {
$m = @ parse_url ( $matches [ 2 ]);
$zrl = false ;
if ( $m [ 'host' ]) {
$r = q ( " select hubloc_url from hubloc where hubloc_host = '%s' limit 1 " ,
dbesc ( $m [ 'host' ])
);
if ( $r )
$zrl = true ;
}
2014-02-16 22:13:26 +00:00
$t = strip_zids ( $matches [ 2 ]);
if ( $t !== $matches [ 2 ]) {
$zrl = true ;
$matches [ 2 ] = $t ;
}
2014-02-08 20:08:07 +00:00
if ( $matches [ 1 ] === '#^' )
$matches [ 1 ] = '' ;
2013-04-19 00:55:35 +00:00
if ( $zrl )
2014-02-06 21:54:39 +00:00
return $matches [ 1 ] . '#^[zrl=' . $matches [ 2 ] . ']' . $matches [ 2 ] . '[/zrl]' ;
2014-02-07 00:22:40 +00:00
return $matches [ 1 ] . '#^[url=' . $matches [ 2 ] . ']' . $matches [ 2 ] . '[/url]' ;
2013-04-19 00:55:35 +00:00
}
2014-02-09 08:30:43 +00:00
// If we've got a url or zrl tag with a naked url somewhere in the link text,
// escape it with quotes unless the naked url is a linked photo.
function red_escape_zrl_callback ( $matches ) {
2014-02-09 21:46:40 +00:00
// Uncertain why the url/zrl forms weren't picked up by the non-greedy regex.
if (( strpos ( $matches [ 3 ], 'zmg' ) !== false ) || ( strpos ( $matches [ 3 ], 'img' ) !== false ) || ( strpos ( $matches [ 3 ], 'zrl' ) !== false ) || ( strpos ( $matches [ 3 ], 'url' ) !== false ))
2014-02-09 08:30:43 +00:00
return $matches [ 0 ];
return '[' . $matches [ 1 ] . 'rl' . $matches [ 2 ] . ']' . $matches [ 3 ] . '"' . $matches [ 4 ] . '"' . $matches [ 5 ] . '[/' . $matches [ 6 ] . 'rl]' ;
}
2013-04-19 00:55:35 +00:00
2014-02-10 09:11:59 +00:00
function red_escape_codeblock ( $m ) {
2014-02-10 09:44:21 +00:00
return '[$b64' . $m [ 2 ] . base64_encode ( $m [ 1 ]) . '[/' . $m [ 2 ] . ']' ;
2014-02-10 09:11:59 +00:00
}
function red_unescape_codeblock ( $m ) {
2014-02-10 09:44:21 +00:00
return '[' . $m [ 2 ] . base64_decode ( $m [ 1 ]) . '[/' . $m [ 2 ] . ']' ;
2014-02-10 09:11:59 +00:00
}
2013-04-05 01:54:24 +00:00
/**
* @ function post_activity_item ( $arr )
*
* post an activity
*
* @ param array $arr
*
* In its simplest form one needs only to set $arr [ 'body' ] to post a note to the logged in channel ' s wall .
* Much more complex activities can be created . Permissions are checked . No filtering , tag expansion
* or other processing is performed .
*
* @ returns array
* 'success' => true or false
* 'activity' => the resulting activity if successful
*/
function post_activity_item ( $arr ) {
$ret = array ( 'success' => false );
2013-06-05 03:07:13 +00:00
$is_comment = false ;
if ((( $arr [ 'parent' ]) && $arr [ 'parent' ] != $arr [ 'id' ]) || (( $arr [ 'parent_mid' ]) && $arr [ 'parent_mid' ] != $arr [ 'mid' ]))
$is_comment = true ;
2013-04-05 01:54:24 +00:00
if ( ! x ( $arr , 'item_flags' )) {
2013-06-05 03:07:13 +00:00
if ( $is_comment )
$arr [ 'item_flags' ] = ITEM_ORIGIN ;
else
$arr [ 'item_flags' ] = ITEM_ORIGIN | ITEM_WALL | ITEM_THREAD_TOP ;
2013-04-05 01:54:24 +00:00
}
2013-06-05 03:07:13 +00:00
2013-04-05 01:54:24 +00:00
$channel = get_app () -> get_channel ();
$observer = get_app () -> get_observer ();
$arr [ 'aid' ] = (( x ( $arr , 'aid' )) ? $arr [ 'aid' ] : $channel [ 'channel_account_id' ]);
$arr [ 'uid' ] = (( x ( $arr , 'uid' )) ? $arr [ 'uid' ] : $channel [ 'channel_id' ]);
2013-06-05 03:07:13 +00:00
if ( ! perm_is_allowed ( $arr [ 'uid' ], $observer [ 'xchan_hash' ],(( $is_comment ) ? 'post_comments' : 'post_wall' ))) {
2013-04-05 01:54:24 +00:00
$ret [ 'message' ] = t ( 'Permission denied' );
return $ret ;
}
2013-05-23 01:22:41 +00:00
2013-12-08 07:29:26 +00:00
if ( ! array_key_exists ( 'mimetype' , $arr ))
$arr [ 'mimetype' ] = 'text/bbcode' ;
if ( array_key_exists ( 'item_private' , $arr ) && $arr [ 'item_private' ]) {
$arr [ 'body' ] = z_input_filter ( $arr [ 'uid' ], $arr [ 'body' ], $arr [ 'mimetype' ]);
if ( $channel ) {
if ( $channel [ 'channel_hash' ] === $arr [ 'author_xchan' ]) {
$arr [ 'sig' ] = base64url_encode ( rsa_sign ( $arr [ 'body' ], $channel [ 'channel_prvkey' ]));
$arr [ 'item_flags' ] = $arr [ 'item_flags' ] | ITEM_VERIFIED ;
}
}
logger ( 'Encrypting local storage' );
$key = get_config ( 'system' , 'pubkey' );
$arr [ 'item_flags' ] = $arr [ 'item_flags' ] | ITEM_OBSCURED ;
if ( $arr [ 'title' ])
$arr [ 'title' ] = json_encode ( aes_encapsulate ( $arr [ 'title' ], $key ));
if ( $arr [ 'body' ])
$arr [ 'body' ] = json_encode ( aes_encapsulate ( $arr [ 'body' ], $key ));
}
2013-05-23 01:22:41 +00:00
2013-04-05 01:54:24 +00:00
$arr [ 'mid' ] = (( x ( $arr , 'mid' )) ? $arr [ 'mid' ] : item_message_id ());
$arr [ 'parent_mid' ] = (( x ( $arr , 'parent_mid' )) ? $arr [ 'parent_mid' ] : $arr [ 'mid' ]);
$arr [ 'thr_parent' ] = (( x ( $arr , 'thr_parent' )) ? $arr [ 'thr_parent' ] : $arr [ 'mid' ]);
2013-04-18 04:40:40 +00:00
$arr [ 'owner_xchan' ] = (( x ( $arr , 'owner_xchan' )) ? $arr [ 'owner_xchan' ] : $channel [ 'channel_hash' ]);
2013-04-05 01:54:24 +00:00
$arr [ 'author_xchan' ] = (( x ( $arr , 'author_xchan' )) ? $arr [ 'author_xchan' ] : $observer [ 'xchan_hash' ]);
$arr [ 'verb' ] = (( x ( $arr , 'verb' )) ? $arr [ 'verb' ] : ACTIVITY_POST );
$arr [ 'obj_type' ] = (( x ( $arr , 'obj_type' )) ? $arr [ 'obj_type' ] : ACTIVITY_OBJ_NOTE );
$arr [ 'allow_cid' ] = (( x ( $arr , 'allow_cid' )) ? $arr [ 'allow_cid' ] : $channel [ 'channel_allow_cid' ]);
$arr [ 'allow_gid' ] = (( x ( $arr , 'allow_gid' )) ? $arr [ 'allow_gid' ] : $channel [ 'channel_allow_gid' ]);
$arr [ 'deny_cid' ] = (( x ( $arr , 'deny_cid' )) ? $arr [ 'deny_cid' ] : $channel [ 'channel_deny_cid' ]);
$arr [ 'deny_gid' ] = (( x ( $arr , 'deny_gid' )) ? $arr [ 'deny_gid' ] : $channel [ 'channel_deny_gid' ]);
2013-06-17 06:08:52 +00:00
$arr [ 'comment_policy' ] = map_scope ( $channel [ 'channel_w_comment' ]);
2013-05-22 04:51:02 +00:00
2014-01-09 23:45:17 +00:00
if (( ! $arr [ 'plink' ]) && ( $arr [ 'item_flags' ] & ITEM_THREAD_TOP )) {
$arr [ 'plink' ] = z_root () . '/channel/' . $channel [ 'channel_address' ] . '/?f=&mid=' . $arr [ 'mid' ];
}
2013-05-22 04:51:02 +00:00
// for the benefit of plugins, we will behave as if this is an API call rather than a normal online post
$_REQUEST [ 'api_source' ] = 1 ;
2013-05-22 04:54:21 +00:00
call_hooks ( 'post_local' , $arr );
2013-05-22 04:51:02 +00:00
if ( x ( $arr , 'cancel' )) {
logger ( 'post_activity_item: post cancelled by plugin.' );
return $ret ;
}
2013-09-11 02:06:06 +00:00
$post = item_store ( $arr );
2013-12-08 07:29:26 +00:00
if ( $post [ 'success' ])
2013-09-11 02:06:06 +00:00
$post_id = $post [ 'item_id' ];
2013-04-05 01:54:24 +00:00
if ( $post_id ) {
$arr [ 'id' ] = $post_id ;
call_hooks ( 'post_local_end' , $arr );
proc_run ( 'php' , 'include/notifier.php' , 'activity' , $post_id );
$ret [ 'success' ] = true ;
2013-05-22 03:52:18 +00:00
$r = q ( " select * from item where id = %d limit 1 " ,
intval ( $post_id )
);
if ( $r )
$ret [ 'activity' ] = $r [ 0 ];
2013-04-05 01:54:24 +00:00
}
return $ret ;
}
2012-09-21 00:04:22 +00:00
function get_public_feed ( $channel , $params ) {
$type = 'xml' ;
$begin = '0000-00-00 00:00:00' ;
$end = '' ;
$start = 0 ;
$records = 40 ;
$direction = 'desc' ;
2013-09-06 02:31:26 +00:00
$pages = 0 ;
2012-09-21 00:04:22 +00:00
2013-06-13 03:03:04 +00:00
if ( ! $params )
$params = array ();
2013-09-06 02:31:26 +00:00
$params [ 'type' ] = (( x ( $params , 'type' )) ? $params [ 'type' ] : 'xml' );
$params [ 'begin' ] = (( x ( $params , 'begin' )) ? $params [ 'begin' ] : '0000-00-00 00:00:00' );
$params [ 'end' ] = (( x ( $params , 'end' )) ? $params [ 'end' ] : datetime_convert ( 'UTC' , 'UTC' , 'now' ));
$params [ 'start' ] = (( x ( $params , 'start' )) ? $params [ 'start' ] : 0 );
$params [ 'records' ] = (( x ( $params , 'records' )) ? $params [ 'records' ] : 40 );
$params [ 'direction' ] = (( x ( $params , 'direction' )) ? $params [ 'direction' ] : 'desc' );
$params [ 'pages' ] = (( x ( $params , 'pages' )) ? intval ( $params [ 'pages' ]) : 0 );
2012-09-21 00:04:22 +00:00
2013-06-13 03:03:04 +00:00
switch ( $params [ 'type' ]) {
2012-09-21 00:04:22 +00:00
case 'json' :
header ( " Content-type: application/atom+json " );
break ;
case 'xml' :
default :
header ( " Content-type: application/atom+xml " );
break ;
}
2012-04-14 11:19:41 +00:00
2013-06-13 04:12:27 +00:00
return get_feed_for ( $channel , get_observer_hash (), $params );
2013-06-13 03:03:04 +00:00
}
2010-07-18 13:02:55 +00:00
2013-06-13 03:03:04 +00:00
function get_feed_for ( $channel , $observer_hash , $params ) {
2010-09-10 08:45:58 +00:00
2013-06-13 03:03:04 +00:00
if ( ! channel )
http_status_exit ( 401 );
2010-09-21 02:34:44 +00:00
2012-04-14 11:19:41 +00:00
2013-09-06 02:31:26 +00:00
if ( $params [ 'pages' ]) {
if ( ! perm_is_allowed ( $channel [ 'channel_id' ], $observer_hash , 'view_pages' ))
http_status_exit ( 403 );
}
else {
if ( ! perm_is_allowed ( $channel [ 'channel_id' ], $observer_hash , 'view_stream' ))
http_status_exit ( 403 );
}
2013-06-13 03:03:04 +00:00
$items = items_fetch ( array (
'wall' => '1' ,
'datequery' => $params [ 'begin' ],
'datequery2' => $params [ 'end' ],
'start' => $params [ 'start' ], // FIXME
'records' => $params [ 'records' ], // FIXME
'direction' => $params [ 'direction' ], // FIXME
2013-09-06 02:31:26 +00:00
'pages' => $params [ 'pages' ],
2013-06-13 03:03:04 +00:00
'order' => 'post'
), $channel , $observer_hash , CLIENT_MODE_NORMAL , get_app () -> module );
2010-09-21 02:34:44 +00:00
2010-07-18 13:02:55 +00:00
2013-06-13 03:03:04 +00:00
$feed_template = get_markup_template ( 'atom_feed.tpl' );
2010-07-18 13:02:55 +00:00
$atom = '' ;
$atom .= replace_macros ( $feed_template , array (
2013-04-15 05:24:47 +00:00
'$version' => xmlify ( RED_VERSION ),
2013-06-13 04:12:27 +00:00
'$red' => xmlify ( RED_PLATFORM ),
2013-06-13 03:03:04 +00:00
'$feed_id' => xmlify ( $channel [ 'channel_url' ]),
'$feed_title' => xmlify ( $channel [ 'channel_name' ]),
2010-10-31 23:38:22 +00:00
'$feed_updated' => xmlify ( datetime_convert ( 'UTC' , 'UTC' , 'now' , ATOM_TIME )) ,
2013-06-13 04:12:27 +00:00
'$hub' => '' , // feed_hublinks(),
'$salmon' => '' , // feed_salmonlinks($channel['channel_address']),
2013-06-13 03:03:04 +00:00
'$name' => xmlify ( $channel [ 'channel_name' ]),
'$profile_page' => xmlify ( $channel [ 'channel_url' ]),
2013-06-13 04:12:27 +00:00
'$mimephoto' => xmlify ( $channel [ 'xchan_photo_mimetype' ]),
'$photo' => xmlify ( $channel [ 'xchan_photo_l' ]),
'$thumb' => xmlify ( $channel [ 'xchan_photo_m' ]),
2013-06-13 03:03:04 +00:00
'$picdate' => '' ,
'$uridate' => '' ,
'$namdate' => '' ,
'$birthday' => '' ,
'$community' => '' ,
2010-07-18 13:02:55 +00:00
));
2010-12-25 02:32:23 +00:00
call_hooks ( 'atom_feed' , $atom );
2013-06-13 03:03:04 +00:00
if ( $items ) {
$type = 'html' ;
foreach ( $items as $item ) {
if ( $item [ 'item_private' ])
2011-08-11 04:46:19 +00:00
continue ;
2010-09-09 03:14:17 +00:00
2013-06-13 03:03:04 +00:00
$atom .= atom_entry ( $item , $type , null , $owner , true );
}
2010-07-18 13:02:55 +00:00
}
2010-12-25 02:32:23 +00:00
call_hooks ( 'atom_feed_end' , $atom );
2010-08-14 14:55:18 +00:00
$atom .= '</feed>' . " \r \n " ;
2010-12-25 03:04:40 +00:00
2010-07-18 13:02:55 +00:00
return $atom ;
2010-09-09 03:14:17 +00:00
}
function construct_verb ( $item ) {
if ( $item [ 'verb' ])
return $item [ 'verb' ];
return ACTIVITY_POST ;
}
2010-11-03 23:48:21 +00:00
function construct_activity_object ( $item ) {
2010-09-09 03:14:17 +00:00
2010-09-17 10:10:19 +00:00
if ( $item [ 'object' ]) {
$o = '<as:object>' . " \r \n " ;
2013-06-13 04:12:27 +00:00
$r = json_decode ( $item [ 'object' ], false );
2011-06-10 08:51:14 +00:00
if ( ! $r )
return '' ;
2010-09-17 10:10:19 +00:00
if ( $r -> type )
2012-08-16 05:33:37 +00:00
$o .= '<as:obj_type>' . xmlify ( $r -> type ) . '</as:obj_type>' . " \r \n " ;
2010-09-17 10:10:19 +00:00
if ( $r -> id )
2010-10-11 03:02:29 +00:00
$o .= '<id>' . xmlify ( $r -> id ) . '</id>' . " \r \n " ;
2010-11-05 03:47:44 +00:00
if ( $r -> title )
$o .= '<title>' . xmlify ( $r -> title ) . '</title>' . " \r \n " ;
2013-06-13 04:12:27 +00:00
if ( $r -> links ) {
// FIXME!!
2011-06-10 08:51:14 +00:00
if ( substr ( $r -> link , 0 , 1 ) === '<' ) {
$r -> link = preg_replace ( '/\<link(.*?)\"\>/' , '<link$1"/>' , $r -> link );
2010-11-05 03:47:44 +00:00
$o .= $r -> link ;
2011-06-10 08:51:14 +00:00
}
2010-11-03 23:48:21 +00:00
else
$o .= '<link rel="alternate" type="text/html" href="' . xmlify ( $r -> link ) . '" />' . " \r \n " ;
}
2010-09-17 10:10:19 +00:00
if ( $r -> content )
2010-10-11 03:02:29 +00:00
$o .= '<content type="html" >' . xmlify ( bbcode ( $r -> content )) . '</content>' . " \r \n " ;
2010-09-17 10:10:19 +00:00
$o .= '</as:object>' . " \r \n " ;
return $o ;
2010-09-09 03:14:17 +00:00
}
2010-09-17 10:10:19 +00:00
2010-09-09 03:14:17 +00:00
return '' ;
2010-07-19 03:49:10 +00:00
}
2010-11-03 23:48:21 +00:00
function construct_activity_target ( $item ) {
if ( $item [ 'target' ]) {
$o = '<as:target>' . " \r \n " ;
2013-06-13 04:12:27 +00:00
$r = json_decode ( $item [ 'target' ], false );
2011-06-10 08:51:14 +00:00
if ( ! $r )
return '' ;
2010-11-03 23:48:21 +00:00
if ( $r -> type )
2012-08-16 05:33:37 +00:00
$o .= '<as:obj_type>' . xmlify ( $r -> type ) . '</as:obj_type>' . " \r \n " ;
2010-11-03 23:48:21 +00:00
if ( $r -> id )
$o .= '<id>' . xmlify ( $r -> id ) . '</id>' . " \r \n " ;
2010-11-05 03:47:44 +00:00
if ( $r -> title )
$o .= '<title>' . xmlify ( $r -> title ) . '</title>' . " \r \n " ;
2013-06-13 04:12:27 +00:00
if ( $r -> links ) {
// FIXME !!!
2011-06-10 08:51:14 +00:00
if ( substr ( $r -> link , 0 , 1 ) === '<' ) {
if ( strstr ( $r -> link , '&' ) && ( ! strstr ( $r -> link , '&' )))
$r -> link = str_replace ( '&' , '&' , $r -> link );
$r -> link = preg_replace ( '/\<link(.*?)\"\>/' , '<link$1"/>' , $r -> link );
2010-11-05 03:47:44 +00:00
$o .= $r -> link ;
2011-06-10 08:51:14 +00:00
}
2010-11-03 23:48:21 +00:00
else
$o .= '<link rel="alternate" type="text/html" href="' . xmlify ( $r -> link ) . '" />' . " \r \n " ;
}
if ( $r -> content )
$o .= '<content type="html" >' . xmlify ( bbcode ( $r -> content )) . '</content>' . " \r \n " ;
$o .= '</as:target>' . " \r \n " ;
return $o ;
}
return '' ;
2012-07-06 23:09:23 +00:00
}
/* limit_body_size ()
*
* The purpose of this function is to apply system message length limits to
* imported messages without including any embedded photos in the length
*/
2013-04-04 01:04:48 +00:00
2012-07-06 23:09:23 +00:00
function limit_body_size ( $body ) {
$maxlen = get_max_import_size ();
// If the length of the body, including the embedded images, is smaller
2012-07-07 22:20:24 +00:00
// than the maximum, then don't waste time looking for the images
2012-07-06 23:09:23 +00:00
if ( $maxlen && ( strlen ( $body ) > $maxlen )) {
2012-07-07 22:20:24 +00:00
$orig_body = $body ;
$new_body = '' ;
$textlen = 0 ;
$max_found = false ;
2012-07-06 23:09:23 +00:00
2012-07-07 22:20:24 +00:00
$img_start = strpos ( $orig_body , '[img' );
$img_st_close = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), ']' ) : false );
$img_end = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), '[/img]' ) : false );
while (( $img_st_close !== false ) && ( $img_end !== false )) {
2012-07-06 23:09:23 +00:00
2012-07-07 22:20:24 +00:00
$img_st_close ++ ; // make it point to AFTER the closing bracket
$img_end += $img_start ;
$img_end += strlen ( '[/img]' );
2012-07-06 23:09:23 +00:00
2012-07-07 22:20:24 +00:00
if ( ! strcmp ( substr ( $orig_body , $img_start + $img_st_close , 5 ), 'data:' )) {
// This is an embedded image
2012-07-06 23:09:23 +00:00
2012-07-07 22:20:24 +00:00
if ( ( $textlen + $img_start ) > $maxlen ) {
if ( $textlen < $maxlen ) {
logger ( 'limit_body_size: the limit happens before an embedded image' , LOGGER_DEBUG );
$new_body = $new_body . substr ( $orig_body , 0 , $maxlen - $textlen );
$textlen = $maxlen ;
}
2012-07-06 23:09:23 +00:00
}
2012-07-07 22:20:24 +00:00
else {
$new_body = $new_body . substr ( $orig_body , 0 , $img_start );
2012-07-08 00:47:13 +00:00
$textlen += $img_start ;
2012-07-07 22:20:24 +00:00
}
$new_body = $new_body . substr ( $orig_body , $img_start , $img_end - $img_start );
2012-07-06 23:09:23 +00:00
}
else {
2012-07-07 22:20:24 +00:00
if ( ( $textlen + $img_end ) > $maxlen ) {
if ( $textlen < $maxlen ) {
$new_body = $new_body . substr ( $orig_body , 0 , $maxlen - $textlen );
$textlen = $maxlen ;
}
}
else {
$new_body = $new_body . substr ( $orig_body , 0 , $img_end );
$textlen += $img_end ;
}
2012-07-06 23:09:23 +00:00
}
2012-07-07 22:20:24 +00:00
$orig_body = substr ( $orig_body , $img_end );
2012-07-06 23:09:23 +00:00
2012-07-07 22:20:24 +00:00
if ( $orig_body === false ) // in case the body ends on a closing image tag
$orig_body = '' ;
2012-07-06 23:09:23 +00:00
2012-07-07 22:20:24 +00:00
$img_start = strpos ( $orig_body , '[img' );
$img_st_close = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), ']' ) : false );
$img_end = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), '[/img]' ) : false );
}
2012-07-06 23:09:23 +00:00
2012-07-07 22:20:24 +00:00
if ( ( $textlen + strlen ( $orig_body )) > $maxlen ) {
if ( $textlen < $maxlen ) {
$new_body = $new_body . substr ( $orig_body , 0 , $maxlen - $textlen );
$textlen = $maxlen ;
}
2012-07-06 23:09:23 +00:00
}
else {
2012-07-07 22:20:24 +00:00
$new_body = $new_body . $orig_body ;
$textlen += strlen ( $orig_body );
2012-07-06 23:09:23 +00:00
}
2012-07-07 22:20:24 +00:00
return $new_body ;
2012-07-06 23:09:23 +00:00
}
else
return $body ;
2013-04-04 01:04:48 +00:00
}
2010-11-03 23:48:21 +00:00
2012-07-19 00:08:03 +00:00
function title_is_body ( $title , $body ) {
$title = strip_tags ( $title );
$title = trim ( $title );
$title = str_replace ( array ( " \n " , " \r " , " \t " , " " ), array ( " " , " " , " " , " " ), $title );
$body = strip_tags ( $body );
$body = trim ( $body );
$body = str_replace ( array ( " \n " , " \r " , " \t " , " " ), array ( " " , " " , " " , " " ), $body );
if ( strlen ( $title ) < strlen ( $body ))
$body = substr ( $body , 0 , strlen ( $title ));
if (( $title != $body ) and ( substr ( $title , - 3 ) == " ... " )) {
$pos = strrpos ( $title , " ... " );
if ( $pos > 0 ) {
$title = substr ( $title , 0 , $pos );
$body = substr ( $body , 0 , $pos );
}
}
return ( $title == $body );
}
2010-07-19 03:49:10 +00:00
2012-11-17 10:29:02 +00:00
function get_item_elements ( $x ) {
2012-07-30 05:43:51 +00:00
2013-12-12 07:13:36 +00:00
2012-07-30 05:43:51 +00:00
$arr = array ();
2013-12-12 07:13:36 +00:00
$arr [ 'body' ] = (( $x [ 'body' ]) ? htmlspecialchars ( $x [ 'body' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
2012-07-30 05:43:51 +00:00
2012-11-17 10:29:02 +00:00
$arr [ 'created' ] = datetime_convert ( 'UTC' , 'UTC' , $x [ 'created' ]);
$arr [ 'edited' ] = datetime_convert ( 'UTC' , 'UTC' , $x [ 'edited' ]);
2012-07-30 05:43:51 +00:00
if ( $arr [ 'created' ] > datetime_convert ())
2012-11-17 10:29:02 +00:00
$arr [ 'created' ] = datetime_convert ();
2012-07-30 05:43:51 +00:00
if ( $arr [ 'edited' ] > datetime_convert ())
2012-11-17 10:29:02 +00:00
$arr [ 'edited' ] = datetime_convert ();
2013-11-18 03:22:24 +00:00
$arr [ 'expires' ] = (( x ( $x , 'expires' ) && $x [ 'expires' ])
? datetime_convert ( 'UTC' , 'UTC' , $x [ 'expires' ])
: '0000-00-00 00:00:00' );
$arr [ 'commented' ] = (( x ( $x , 'commented' ) && $x [ 'commented' ])
? datetime_convert ( 'UTC' , 'UTC' , $x [ 'commented' ])
: $arr [ 'created' ]);
2013-12-12 07:13:36 +00:00
$arr [ 'title' ] = (( $x [ 'title' ]) ? htmlspecialchars ( $x [ 'title' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
2013-07-30 00:30:46 +00:00
if ( mb_strlen ( $arr [ 'title' ]) > 255 )
$arr [ 'title' ] = mb_substr ( $arr [ 'title' ], 0 , 255 );
2013-12-12 07:13:36 +00:00
$arr [ 'app' ] = (( $x [ 'app' ]) ? htmlspecialchars ( $x [ 'app' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'mid' ] = (( $x [ 'message_id' ]) ? htmlspecialchars ( $x [ 'message_id' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'parent_mid' ] = (( $x [ 'message_top' ]) ? htmlspecialchars ( $x [ 'message_top' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'thr_parent' ] = (( $x [ 'message_parent' ]) ? htmlspecialchars ( $x [ 'message_parent' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
2012-11-17 10:29:02 +00:00
2013-12-12 07:13:36 +00:00
$arr [ 'plink' ] = (( $x [ 'permalink' ]) ? htmlspecialchars ( $x [ 'permalink' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'location' ] = (( $x [ 'location' ]) ? htmlspecialchars ( $x [ 'location' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'coord' ] = (( $x [ 'longlat' ]) ? htmlspecialchars ( $x [ 'longlat' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'verb' ] = (( $x [ 'verb' ]) ? htmlspecialchars ( $x [ 'verb' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'mimetype' ] = (( $x [ 'mimetype' ]) ? htmlspecialchars ( $x [ 'mimetype' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'obj_type' ] = (( $x [ 'object_type' ]) ? htmlspecialchars ( $x [ 'object_type' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'tgt_type' ] = (( $x [ 'target_type' ]) ? htmlspecialchars ( $x [ 'target_type' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'comment_policy' ] = (( $x [ 'comment_scope' ]) ? htmlspecialchars ( $x [ 'comment_scope' ], ENT_COMPAT , 'UTF-8' , false ) : 'contacts' );
2013-10-03 04:04:48 +00:00
2013-12-12 07:13:36 +00:00
$arr [ 'sig' ] = (( $x [ 'signature' ]) ? htmlspecialchars ( $x [ 'signature' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
2013-10-03 04:04:48 +00:00
2013-06-17 03:44:29 +00:00
2012-11-17 20:55:59 +00:00
$arr [ 'object' ] = activity_sanitise ( $x [ 'object' ]);
$arr [ 'target' ] = activity_sanitise ( $x [ 'target' ]);
2012-07-30 05:43:51 +00:00
2013-02-01 08:49:07 +00:00
$arr [ 'attach' ] = activity_sanitise ( $x [ 'attach' ]);
2012-11-17 20:55:59 +00:00
$arr [ 'term' ] = decode_tags ( $x [ 'tags' ]);
2012-07-30 05:43:51 +00:00
2012-11-27 01:07:23 +00:00
$arr [ 'item_private' ] = (( array_key_exists ( 'flags' , $x ) && is_array ( $x [ 'flags' ]) && in_array ( 'private' , $x [ 'flags' ])) ? 1 : 0 );
2013-08-01 01:57:14 +00:00
$arr [ 'item_flags' ] = 0 ;
2012-11-27 05:20:16 +00:00
if ( array_key_exists ( 'flags' , $x ) && in_array ( 'deleted' , $x [ 'flags' ]))
$arr [ 'item_restrict' ] = ITEM_DELETED ;
2012-11-27 01:07:23 +00:00
2012-11-17 20:55:59 +00:00
// Here's the deal - the site might be down or whatever but if there's a new person you've never
// seen before sending stuff to your stream, we MUST be able to look them up and import their data from their
// hub and verify that they are legit - or else we're going to toss the post. We only need to do this
// once, and after that your hub knows them. Sure some info is in the post, but it's only a transit identifier
// and not enough info to be able to look you up from your hash - which is the only thing stored with the post.
2012-07-30 05:43:51 +00:00
2013-12-04 08:19:29 +00:00
if (( $xchan_hash = import_author_xchan ( $x [ 'author' ])) !== false )
$arr [ 'author_xchan' ] = $xchan_hash ;
2012-11-17 20:55:59 +00:00
else
return array ();
2012-07-30 05:43:51 +00:00
2013-01-29 04:51:37 +00:00
// save a potentially expensive lookup if author == owner
if ( $arr [ 'author_xchan' ] === base64url_encode ( hash ( 'whirlpool' , $x [ 'owner' ][ 'guid' ] . $x [ 'owner' ][ 'guid_sig' ], true )))
$arr [ 'owner_xchan' ] = $arr [ 'author_xchan' ];
else {
2013-12-04 08:19:29 +00:00
if (( $xchan_hash = import_author_xchan ( $x [ 'owner' ])) !== false )
$arr [ 'owner_xchan' ] = $xchan_hash ;
2013-01-29 04:51:37 +00:00
else
return array ();
}
2012-07-30 05:43:51 +00:00
2013-10-03 04:04:48 +00:00
if ( $arr [ 'sig' ]) {
$r = q ( " select xchan_pubkey from xchan where xchan_hash = '%s' limit 1 " ,
dbesc ( $arr [ 'author_xchan' ])
);
if ( $r && rsa_verify ( $x [ 'body' ], base64url_decode ( $arr [ 'sig' ]), $r [ 0 ][ 'xchan_pubkey' ]))
$arr [ 'item_flags' ] |= ITEM_VERIFIED ;
else
logger ( 'get_item_elements: message verification failed.' );
}
// if it's a private post, encrypt it in the DB.
// We have to do that here because we need to cleanse the input and prevent bad stuff from getting in,
// and we need plaintext to do that.
if ( intval ( $arr [ 'item_private' ])) {
$arr [ 'item_flags' ] = $arr [ 'item_flags' ] | ITEM_OBSCURED ;
$key = get_config ( 'system' , 'pubkey' );
if ( $arr [ 'title' ])
2013-11-20 23:20:12 +00:00
$arr [ 'title' ] = json_encode ( crypto_encapsulate ( $arr [ 'title' ], $key ));
2013-10-03 04:04:48 +00:00
if ( $arr [ 'body' ])
2013-11-20 23:20:12 +00:00
$arr [ 'body' ] = json_encode ( crypto_encapsulate ( $arr [ 'body' ], $key ));
2013-10-03 04:04:48 +00:00
}
2012-07-30 05:43:51 +00:00
return $arr ;
}
2012-12-06 00:44:07 +00:00
2012-11-17 20:55:59 +00:00
function import_author_xchan ( $x ) {
2013-01-29 04:51:37 +00:00
2013-12-04 08:19:29 +00:00
$arr = array ( 'xchan' => $x , 'xchan_hash' => '' );
call_hooks ( 'import_author_xchan' , $arr );
if ( $arr [ 'xchan_hash' ])
return $arr [ 'xchan_hash' ];
2013-01-29 04:51:37 +00:00
2013-12-04 08:19:29 +00:00
if (( ! array_key_exists ( 'network' , $x )) || ( $x [ 'network' ] === 'zot' )) {
2014-02-17 22:30:02 +00:00
$y = import_author_zot ( $x );
2013-01-29 04:51:37 +00:00
}
2014-02-17 22:30:02 +00:00
if ( $x [ 'network' ] === 'rss' ) {
$y = import_author_rss ( $x );
}
return (( $y ) ? $y : false );
}
function import_author_rss ( $x ) {
if ( ! $x [ 'url' ])
return false ;
$r = q ( " select xchan_hash from xchan where xchan_network = 'rss' and xchan_url = '%s' limit 1 " ,
dbesc ( $x [ 'url' ])
);
if ( $r ) {
logger ( 'import_author_rss: in cache' , LOGGER_DEBUG );
return $r [ 0 ][ 'xchan_hash' ];
}
$name = trim ( $x [ 'name' ]);
$r = q ( " insert into xchan ( xchan_hash, xchan_url, xchan_name, xchan_network )
values ( '%s' , '%s' , '%s' , '%s' ) " ,
dbesc ( $x [ 'url' ]),
dbesc ( $x [ 'url' ]),
2014-02-22 22:58:12 +00:00
dbesc (( $name ) ? $name : t ( '(Unknown)' )),
2014-02-17 22:30:02 +00:00
dbesc ( 'rss' )
);
if ( $r ) {
$photos = import_profile_photo ( $x [ 'photo' ], $x [ 'url' ]);
if ( $photos ) {
$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' limit 1 " ,
dbesc ( datetime_convert ( 'UTC' , 'UTC' , $arr [ 'photo_updated' ])),
dbesc ( $photos [ 0 ]),
dbesc ( $photos [ 1 ]),
dbesc ( $photos [ 2 ]),
dbesc ( $photos [ 3 ]),
dbesc ( $x [ 'url' ])
);
if ( $r )
return $x [ 'url' ];
}
}
2013-01-29 04:51:37 +00:00
2013-12-04 08:19:29 +00:00
return false ;
2014-02-17 22:30:02 +00:00
2012-11-17 20:55:59 +00:00
}
2012-07-30 05:43:51 +00:00
2014-02-17 22:30:02 +00:00
2012-08-16 06:15:29 +00:00
function encode_item ( $item ) {
2012-11-15 07:09:25 +00:00
$x = array ();
2012-11-20 04:45:12 +00:00
$x [ 'type' ] = 'activity' ;
2012-11-15 07:09:25 +00:00
2013-10-03 04:04:48 +00:00
// logger('encode_item: ' . print_r($item,true));
2012-11-16 05:52:05 +00:00
2013-06-17 06:20:36 +00:00
$r = q ( " select channel_r_stream, channel_w_comment from channel where channel_id = %d limit 1 " ,
2013-02-15 04:17:30 +00:00
intval ( $item [ 'uid' ])
);
2013-06-17 02:14:01 +00:00
if ( $r ) {
2013-02-15 04:17:30 +00:00
$public_scope = $r [ 0 ][ 'channel_r_stream' ];
2013-06-17 02:14:01 +00:00
$comment_scope = $r [ 0 ][ 'channel_w_comment' ];
}
else {
2013-02-15 04:17:30 +00:00
$public_scope = 0 ;
2013-06-17 02:14:01 +00:00
$comment_scope = 0 ;
}
2013-02-15 04:17:30 +00:00
$scope = map_scope ( $public_scope );
2013-06-17 02:14:01 +00:00
$c_scope = map_scope ( $comment_scope );
2013-02-15 04:17:30 +00:00
2013-07-29 04:04:03 +00:00
if ( array_key_exists ( 'item_flags' , $item ) && ( $item [ 'item_flags' ] & ITEM_OBSCURED )) {
$key = get_config ( 'system' , 'prvkey' );
if ( $item [ 'title' ])
2013-11-20 23:20:12 +00:00
$item [ 'title' ] = crypto_unencapsulate ( json_decode_plus ( $item [ 'title' ]), $key );
2013-07-29 04:04:03 +00:00
if ( $item [ 'body' ])
2013-11-20 23:20:12 +00:00
$item [ 'body' ] = crypto_unencapsulate ( json_decode_plus ( $item [ 'body' ]), $key );
2013-07-29 04:04:03 +00:00
}
2012-11-16 21:57:55 +00:00
if ( $item [ 'item_restrict' ] & ITEM_DELETED ) {
2013-03-22 01:25:41 +00:00
$x [ 'message_id' ] = $item [ 'mid' ];
2013-01-27 06:24:08 +00:00
$x [ 'created' ] = $item [ 'created' ];
$x [ 'flags' ] = array ( 'deleted' );
2013-01-27 21:43:43 +00:00
$x [ 'owner' ] = encode_item_xchan ( $item [ 'owner' ]);
$x [ 'author' ] = encode_item_xchan ( $item [ 'author' ]);
2012-11-16 21:57:55 +00:00
return $x ;
}
2013-03-22 01:25:41 +00:00
$x [ 'message_id' ] = $item [ 'mid' ];
$x [ 'message_top' ] = $item [ 'parent_mid' ];
2012-11-15 07:09:25 +00:00
$x [ 'message_parent' ] = $item [ 'thr_parent' ];
$x [ 'created' ] = $item [ 'created' ];
$x [ 'edited' ] = $item [ 'edited' ];
2012-12-30 08:41:08 +00:00
$x [ 'expires' ] = $item [ 'expires' ];
2013-11-18 03:22:24 +00:00
$x [ 'commented' ] = $item [ 'commented' ];
2013-02-11 03:08:19 +00:00
$x [ 'mimetype' ] = $item [ 'mimetype' ];
2012-11-15 07:09:25 +00:00
$x [ 'title' ] = $item [ 'title' ];
$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 [ 'permalink' ] = $item [ 'plink' ];
$x [ 'location' ] = $item [ 'location' ];
$x [ 'longlat' ] = $item [ 'coord' ];
2013-10-03 04:04:48 +00:00
$x [ 'signature' ] = $item [ 'sig' ];
2012-11-15 07:09:25 +00:00
2012-11-16 05:52:05 +00:00
$x [ 'owner' ] = encode_item_xchan ( $item [ 'owner' ]);
$x [ 'author' ] = encode_item_xchan ( $item [ 'author' ]);
if ( $item [ 'object' ])
2013-08-06 10:54:49 +00:00
$x [ 'object' ] = json_decode_plus ( $item [ 'object' ]);
2012-11-16 05:52:05 +00:00
if ( $item [ 'target' ])
2013-08-06 10:54:49 +00:00
$x [ 'target' ] = json_decode_plus ( $item [ 'target' ]);
2012-11-16 05:52:05 +00:00
if ( $item [ 'attach' ])
2013-08-06 10:54:49 +00:00
$x [ 'attach' ] = json_decode_plus ( $item [ 'attach' ]);
2012-11-16 21:57:55 +00:00
if ( $y = encode_item_flags ( $item ))
$x [ 'flags' ] = $y ;
2013-02-15 04:17:30 +00:00
2013-02-16 01:18:07 +00:00
if ( ! in_array ( 'private' , $y ))
2013-02-15 04:17:30 +00:00
$x [ 'public_scope' ] = $scope ;
2013-06-17 02:14:01 +00:00
if ( $item [ 'item_flags' ] & ITEM_NOCOMMENT )
$x [ 'comment_scope' ] = 'none' ;
else
$x [ 'comment_scope' ] = $c_scope ;
2012-11-16 05:52:05 +00:00
if ( $item [ 'term' ])
$x [ 'tags' ] = encode_item_terms ( $item [ 'term' ]);
2012-11-15 07:09:25 +00:00
2013-10-03 04:04:48 +00:00
logger ( 'encode_item: ' . print_r ( $x , true ));
2012-11-15 07:09:25 +00:00
return $x ;
2012-08-16 06:15:29 +00:00
}
2013-02-15 04:17:30 +00:00
function map_scope ( $scope ) {
switch ( $scope ) {
2013-02-15 22:13:58 +00:00
case 0 :
return 'self' ;
2013-02-15 04:17:30 +00:00
case PERMS_PUBLIC :
return 'public' ;
case PERMS_NETWORK :
return 'network: red' ;
case PERMS_SITE :
return 'site: ' . get_app () -> get_hostname ();
case PERMS_CONTACTS :
default :
return 'contacts' ;
}
}
2012-11-16 05:52:05 +00:00
function encode_item_xchan ( $xchan ) {
2012-08-16 06:15:29 +00:00
2012-11-16 05:52:05 +00:00
$ret = array ();
$ret [ 'name' ] = $xchan [ 'xchan_name' ];
$ret [ 'address' ] = $xchan [ 'xchan_addr' ];
$ret [ 'url' ] = $xchan [ 'hubloc_url' ];
2013-12-04 08:19:29 +00:00
$ret [ 'network' ] = $xchan [ 'xchan_network' ];
2012-11-16 05:52:05 +00:00
$ret [ 'photo' ] = array ( 'mimetype' => $xchan [ 'xchan_photo_mimetype' ], 'src' => $xchan [ 'xchan_photo_m' ]);
$ret [ 'guid' ] = $xchan [ 'xchan_guid' ];
$ret [ 'guid_sig' ] = $xchan [ 'xchan_guid_sig' ];
return $ret ;
}
2012-08-16 06:15:29 +00:00
2012-11-16 05:52:05 +00:00
function encode_item_terms ( $terms ) {
$ret = array ();
2014-02-04 03:38:15 +00:00
$allowed_export_terms = array ( TERM_UNKNOWN , TERM_HASHTAG , TERM_MENTION , TERM_CATEGORY , TERM_BOOKMARK );
2012-11-16 05:52:05 +00:00
if ( $terms ) {
foreach ( $terms as $term ) {
if ( in_array ( $term [ 'type' ], $allowed_export_terms ))
2012-11-17 20:55:59 +00:00
$ret [] = array ( 'tag' => $term [ 'term' ], 'url' => $term [ 'url' ], 'type' => termtype ( $term [ 'type' ]));
2012-11-16 05:52:05 +00:00
}
}
return $ret ;
}
function termtype ( $t ) {
2014-02-04 03:38:15 +00:00
$types = array ( 'unknown' , 'hashtag' , 'mention' , 'category' , 'private_category' , 'file' , 'search' , 'thing' , 'bookmark' );
2012-11-16 05:52:05 +00:00
return (( $types [ $t ]) ? $types [ $t ] : 'unknown' );
}
2010-07-19 03:49:10 +00:00
2012-11-17 20:55:59 +00:00
function decode_tags ( $t ) {
if ( $t ) {
$ret = array ();
foreach ( $t as $x ) {
$tag = array ();
2013-12-12 07:13:36 +00:00
$tag [ 'term' ] = htmlspecialchars ( $x [ 'tag' ], ENT_COMPAT , 'UTF-8' , false );
$tag [ 'url' ] = htmlspecialchars ( $x [ 'url' ], ENT_COMPAT , 'UTF-8' , false );
2012-11-17 20:55:59 +00:00
switch ( $x [ 'type' ]) {
case 'hashtag' :
$tag [ 'type' ] = TERM_HASHTAG ;
break ;
case 'mention' :
$tag [ 'type' ] = TERM_MENTION ;
break ;
case 'category' :
$tag [ 'type' ] = TERM_CATEGORY ;
break ;
case 'private_category' :
$tag [ 'type' ] = TERM_PCATEGORY ;
break ;
case 'file' :
$tag [ 'type' ] = TERM_FILE ;
break ;
case 'search' :
$tag [ 'type' ] = TERM_SEARCH ;
break ;
2014-02-04 03:38:15 +00:00
case 'thing' :
$tag [ 'type' ] = TERM_THING ;
break ;
case 'bookmark' :
$tag [ 'type' ] = TERM_BOOKMARK ;
break ;
2012-11-17 20:55:59 +00:00
default :
case 'unknown' :
$tag [ 'type' ] = TERM_UNKNOWN ;
break ;
}
$ret [] = $tag ;
}
return $ret ;
}
return '' ;
}
2012-12-22 12:33:32 +00:00
// santise a potentially complex array
2012-11-17 20:55:59 +00:00
function activity_sanitise ( $arr ) {
if ( $arr ) {
2013-08-18 07:04:38 +00:00
if ( is_array ( $arr )) {
$ret = array ();
foreach ( $arr as $k => $x ) {
if ( is_array ( $x ))
$ret [ $k ] = activity_sanitise ( $x );
else
2013-12-12 07:13:36 +00:00
$ret [ $k ] = htmlspecialchars ( $x , ENT_COMPAT , 'UTF-8' , false );
2013-08-18 07:04:38 +00:00
}
return $ret ;
}
else {
2013-12-12 07:13:36 +00:00
return htmlspecialchars ( $arr , ENT_COMPAT , 'UTF-8' , false );
2012-11-17 20:55:59 +00:00
}
}
return '' ;
}
2012-11-16 21:57:55 +00:00
2012-12-22 12:33:32 +00:00
// sanitise a simple linear array
function array_sanitise ( $arr ) {
if ( $arr ) {
$ret = array ();
foreach ( $arr as $x ) {
2013-12-12 07:13:36 +00:00
$ret [] = htmlspecialchars ( $x , ENT_COMPAT , 'UTF-8' , false );
2012-12-22 12:33:32 +00:00
}
return $ret ;
}
return '' ;
}
2012-11-16 21:57:55 +00:00
function encode_item_flags ( $item ) {
// most of item_flags and item_restrict are local settings which don't apply when transmitted.
// We may need those for the case of syncing other hub locations which you are attached to.
// ITEM_DELETED is handled in encode_item directly so we don't need to handle it here.
$ret = array ();
2012-11-27 00:48:04 +00:00
if ( $item [ 'item_flags' ] & ITEM_THREAD_TOP )
2012-11-16 21:57:55 +00:00
$ret [] = 'thread_parent' ;
2012-11-27 00:48:04 +00:00
if ( $item [ 'item_flags' ] & ITEM_NSFW )
2012-11-16 21:57:55 +00:00
$ret [] = 'nsfw' ;
2012-11-27 01:07:23 +00:00
if ( $item [ 'item_private' ])
2012-11-17 10:29:02 +00:00
$ret [] = 'private' ;
2012-11-16 21:57:55 +00:00
return $ret ;
}
2012-12-06 00:44:07 +00:00
function encode_mail ( $item ) {
$x = array ();
$x [ 'type' ] = 'mail' ;
2013-07-31 09:32:41 +00:00
if ( array_key_exists ( 'mail_flags' , $item ) && ( $item [ 'mail_flags' ] & MAIL_OBSCURED )) {
$key = get_config ( 'system' , 'prvkey' );
if ( $item [ 'title' ])
2013-11-20 23:20:12 +00:00
$item [ 'title' ] = crypto_unencapsulate ( json_decode_plus ( $item [ 'title' ]), $key );
2013-07-31 09:32:41 +00:00
if ( $item [ 'body' ])
2013-11-20 23:20:12 +00:00
$item [ 'body' ] = crypto_unencapsulate ( json_decode_plus ( $item [ 'body' ]), $key );
2013-07-31 09:32:41 +00:00
}
2012-12-06 00:44:07 +00:00
2013-03-22 01:25:41 +00:00
$x [ 'message_id' ] = $item [ 'mid' ];
$x [ 'message_parent' ] = $item [ 'parent_mid' ];
2012-12-06 00:44:07 +00:00
$x [ 'created' ] = $item [ 'created' ];
2013-11-07 02:28:36 +00:00
$x [ 'expires' ] = $item [ 'expires' ];
2012-12-06 00:44:07 +00:00
$x [ 'title' ] = $item [ 'title' ];
$x [ 'body' ] = $item [ 'body' ];
$x [ 'from' ] = encode_item_xchan ( $item [ 'from' ]);
$x [ 'to' ] = encode_item_xchan ( $item [ 'to' ]);
2013-08-20 04:19:39 +00:00
if ( $item [ 'attach' ])
$x [ 'attach' ] = json_decode_plus ( $item [ 'attach' ]);
2013-07-19 09:45:44 +00:00
$x [ 'flags' ] = array ();
2013-02-28 04:38:33 +00:00
if ( $item [ 'mail_flags' ] & MAIL_RECALLED ) {
2013-07-19 09:45:44 +00:00
$x [ 'flags' ][] = 'recalled' ;
2013-02-28 04:38:33 +00:00
$x [ 'title' ] = '' ;
$x [ 'body' ] = '' ;
}
2012-12-06 00:44:07 +00:00
return $x ;
}
function get_mail_elements ( $x ) {
$arr = array ();
2013-12-12 07:13:36 +00:00
$arr [ 'body' ] = (( $x [ 'body' ]) ? htmlspecialchars ( $x [ 'body' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'title' ] = (( $x [ 'title' ]) ? htmlspecialchars ( $x [ 'title' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
2012-12-06 00:44:07 +00:00
$arr [ 'created' ] = datetime_convert ( 'UTC' , 'UTC' , $x [ 'created' ]);
2013-11-07 02:28:36 +00:00
if (( ! array_key_exists ( 'expires' , $x )) || ( $x [ 'expires' ] === '0000-00-00 00:00:00' ))
$arr [ 'expires' ] = '0000-00-00 00:00:00' ;
else
$arr [ 'expires' ] = datetime_convert ( 'UTC' , 'UTC' , $x [ 'expires' ]);
2012-12-06 00:44:07 +00:00
2013-02-28 04:38:33 +00:00
$arr [ 'mail_flags' ] = 0 ;
if ( $x [ 'flags' ] && is_array ( $x [ 'flags' ])) {
if ( in_array ( 'recalled' , $x [ 'flags' ])) {
2013-07-19 09:45:44 +00:00
$arr [ 'mail_flags' ] |= MAIL_RECALLED ;
}
2013-02-28 04:38:33 +00:00
}
2013-07-31 09:32:41 +00:00
$key = get_config ( 'system' , 'pubkey' );
$arr [ 'mail_flags' ] |= MAIL_OBSCURED ;
2013-12-12 07:13:36 +00:00
$arr [ 'body' ] = htmlspecialchars ( $arr [ 'body' ], ENT_COMPAT , 'UTF-8' , false );
2013-07-31 09:32:41 +00:00
if ( $arr [ 'body' ])
2013-11-20 23:20:12 +00:00
$arr [ 'body' ] = json_encode ( crypto_encapsulate ( $arr [ 'body' ], $key ));
2013-12-12 07:13:36 +00:00
$arr [ 'title' ] = htmlspecialchars ( $arr [ 'title' ], ENT_COMPAT , 'UTF-8' , false );
2013-07-31 09:32:41 +00:00
if ( $arr [ 'title' ])
2013-11-20 23:20:12 +00:00
$arr [ 'title' ] = json_encode ( crypto_encapsulate ( $arr [ 'title' ], $key ));
2013-02-28 04:38:33 +00:00
2012-12-06 00:44:07 +00:00
if ( $arr [ 'created' ] > datetime_convert ())
$arr [ 'created' ] = datetime_convert ();
2013-12-12 07:13:36 +00:00
$arr [ 'mid' ] = (( $x [ 'message_id' ]) ? htmlspecialchars ( $x [ 'message_id' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'parent_mid' ] = (( $x [ 'message_parent' ]) ? htmlspecialchars ( $x [ 'message_parent' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
2012-12-06 00:44:07 +00:00
2013-08-20 04:19:39 +00:00
if ( $x [ 'attach' ])
$arr [ 'attach' ] = activity_sanitise ( $x [ 'attach' ]);
2013-12-04 08:19:29 +00:00
if (( $xchan_hash = import_author_xchan ( $x [ 'from' ])) !== false )
$arr [ 'from_xchan' ] = $xchan_hash ;
2012-12-06 00:44:07 +00:00
else
return array ();
2013-12-04 08:19:29 +00:00
if (( $xchan_hash = import_author_xchan ( $x [ 'to' ])) !== false )
$arr [ 'to_xchan' ] = $xchan_hash ;
2012-12-06 00:44:07 +00:00
else
return array ();
return $arr ;
}
2012-12-22 12:33:32 +00:00
function get_profile_elements ( $x ) {
$arr = array ();
2013-12-04 08:19:29 +00:00
if (( $xchan_hash = import_author_xchan ( $x [ 'from' ])) !== false )
$arr [ 'xprof_hash' ] = $xchan_hash ;
2012-12-22 12:33:32 +00:00
else
return array ();
2013-12-12 07:13:36 +00:00
$arr [ 'desc' ] = (( $x [ 'title' ]) ? htmlspecialchars ( $x [ 'title' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
2012-12-22 12:33:32 +00:00
$arr [ 'dob' ] = datetime_convert ( 'UTC' , 'UTC' , $x [ 'birthday' ], 'Y-m-d' );
2013-06-30 07:38:02 +00:00
$arr [ 'age' ] = (( $x [ 'age' ]) ? intval ( $x [ 'age' ]) : 0 );
2012-12-22 12:33:32 +00:00
2013-12-12 07:13:36 +00:00
$arr [ 'gender' ] = (( $x [ 'gender' ]) ? htmlspecialchars ( $x [ 'gender' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'marital' ] = (( $x [ 'marital' ]) ? htmlspecialchars ( $x [ 'marital' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'sexual' ] = (( $x [ 'sexual' ]) ? htmlspecialchars ( $x [ 'sexual' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'locale' ] = (( $x [ 'locale' ]) ? htmlspecialchars ( $x [ 'locale' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'region' ] = (( $x [ 'region' ]) ? htmlspecialchars ( $x [ 'region' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'postcode' ] = (( $x [ 'postcode' ]) ? htmlspecialchars ( $x [ 'postcode' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
$arr [ 'country' ] = (( $x [ 'country' ]) ? htmlspecialchars ( $x [ 'country' ], ENT_COMPAT , 'UTF-8' , false ) : '' );
2012-12-22 12:33:32 +00:00
$arr [ 'keywords' ] = (( $x [ 'keywords' ] && is_array ( $x [ 'keywords' ])) ? array_sanitise ( $x [ 'keywords' ]) : array ());
return $arr ;
}
2012-12-06 00:44:07 +00:00
2010-10-25 03:39:24 +00:00
function get_atom_elements ( $feed , $item ) {
2010-07-19 03:49:10 +00:00
2010-09-09 03:14:17 +00:00
2010-10-25 03:39:24 +00:00
$best_photo = array ();
2010-07-19 03:49:10 +00:00
2010-10-25 03:39:24 +00:00
$res = array ();
2010-09-09 03:14:17 +00:00
2010-07-19 03:49:10 +00:00
$author = $item -> get_author ();
2011-04-05 02:36:18 +00:00
if ( $author ) {
$res [ 'author-name' ] = unxmlify ( $author -> get_name ());
$res [ 'author-link' ] = unxmlify ( $author -> get_link ());
}
else {
$res [ 'author-name' ] = unxmlify ( $feed -> get_title ());
$res [ 'author-link' ] = unxmlify ( $feed -> get_permalink ());
}
2013-03-22 01:25:41 +00:00
$res [ 'mid' ] = unxmlify ( $item -> get_id ());
2010-07-19 03:49:10 +00:00
$res [ 'title' ] = unxmlify ( $item -> get_title ());
$res [ 'body' ] = unxmlify ( $item -> get_content ());
2011-02-16 10:07:11 +00:00
$res [ 'plink' ] = unxmlify ( $item -> get_link ( 0 ));
2010-10-25 03:39:24 +00:00
2012-07-19 00:08:03 +00:00
// removing the content of the title if its identically to the body
// This helps with auto generated titles e.g. from tumblr
2013-05-28 08:40:27 +00:00
2012-07-19 00:08:03 +00:00
if ( title_is_body ( $res [ " title " ], $res [ " body " ]))
$res [ 'title' ] = " " ;
2012-01-18 00:30:32 +00:00
if ( $res [ 'plink' ])
$base_url = implode ( '/' , array_slice ( explode ( '/' , $res [ 'plink' ]), 0 , 3 ));
else
$base_url = '' ;
2010-10-25 03:39:24 +00:00
// look for a photo. We should check media size and find the best one,
// but for now let's just find any author photo
$rawauthor = $item -> get_item_tags ( SIMPLEPIE_NAMESPACE_ATOM_10 , 'author' );
if ( $rawauthor && $rawauthor [ 0 ][ 'child' ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'link' ]) {
$base = $rawauthor [ 0 ][ 'child' ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'link' ];
foreach ( $base as $link ) {
2012-02-26 20:43:51 +00:00
if ( ! x ( $res , 'author-avatar' ) || ! $res [ 'author-avatar' ]) {
2010-10-25 03:39:24 +00:00
if ( $link [ 'attribs' ][ '' ][ 'rel' ] === 'photo' || $link [ 'attribs' ][ '' ][ 'rel' ] === 'avatar' )
$res [ 'author-avatar' ] = unxmlify ( $link [ 'attribs' ][ '' ][ 'href' ]);
}
}
2012-07-19 00:08:03 +00:00
}
2010-10-25 03:39:24 +00:00
$rawactor = $item -> get_item_tags ( NAMESPACE_ACTIVITY , 'actor' );
2012-08-16 05:33:37 +00:00
if ( $rawactor && activity_match ( $rawactor [ 0 ][ 'child' ][ NAMESPACE_ACTIVITY ][ 'obj_type' ][ 0 ][ 'data' ], ACTIVITY_OBJ_PERSON )) {
2010-10-25 03:39:24 +00:00
$base = $rawactor [ 0 ][ 'child' ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'link' ];
if ( $base && count ( $base )) {
foreach ( $base as $link ) {
if ( $link [ 'attribs' ][ '' ][ 'rel' ] === 'alternate' && ( ! $res [ 'author-link' ]))
$res [ 'author-link' ] = unxmlify ( $link [ 'attribs' ][ '' ][ 'href' ]);
2012-02-26 20:43:51 +00:00
if ( ! x ( $res , 'author-avatar' ) || ! $res [ 'author-avatar' ]) {
2010-10-25 03:39:24 +00:00
if ( $link [ 'attribs' ][ '' ][ 'rel' ] === 'avatar' || $link [ 'attribs' ][ '' ][ 'rel' ] === 'photo' )
$res [ 'author-avatar' ] = unxmlify ( $link [ 'attribs' ][ '' ][ 'href' ]);
}
}
}
}
// No photo/profile-link on the item - look at the feed level
2010-11-10 04:38:24 +00:00
if (( ! ( x ( $res , 'author-link' ))) || ( ! ( x ( $res , 'author-avatar' )))) {
2010-10-25 03:39:24 +00:00
$rawauthor = $feed -> get_feed_tags ( SIMPLEPIE_NAMESPACE_ATOM_10 , 'author' );
if ( $rawauthor && $rawauthor [ 0 ][ 'child' ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'link' ]) {
$base = $rawauthor [ 0 ][ 'child' ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'link' ];
foreach ( $base as $link ) {
if ( $link [ 'attribs' ][ '' ][ 'rel' ] === 'alternate' && ( ! $res [ 'author-link' ]))
$res [ 'author-link' ] = unxmlify ( $link [ 'attribs' ][ '' ][ 'href' ]);
if ( ! $res [ 'author-avatar' ]) {
if ( $link [ 'attribs' ][ '' ][ 'rel' ] === 'photo' || $link [ 'attribs' ][ '' ][ 'rel' ] === 'avatar' )
$res [ 'author-avatar' ] = unxmlify ( $link [ 'attribs' ][ '' ][ 'href' ]);
}
}
2012-07-19 00:08:03 +00:00
}
2010-10-25 03:39:24 +00:00
$rawactor = $feed -> get_feed_tags ( NAMESPACE_ACTIVITY , 'subject' );
2012-08-16 05:33:37 +00:00
if ( $rawactor && activity_match ( $rawactor [ 0 ][ 'child' ][ NAMESPACE_ACTIVITY ][ 'obj_type' ][ 0 ][ 'data' ], ACTIVITY_OBJ_PERSON )) {
2010-10-25 03:39:24 +00:00
$base = $rawactor [ 0 ][ 'child' ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'link' ];
if ( $base && count ( $base )) {
foreach ( $base as $link ) {
if ( $link [ 'attribs' ][ '' ][ 'rel' ] === 'alternate' && ( ! $res [ 'author-link' ]))
$res [ 'author-link' ] = unxmlify ( $link [ 'attribs' ][ '' ][ 'href' ]);
2010-11-10 04:38:24 +00:00
if ( ! ( x ( $res , 'author-avatar' ))) {
2010-10-25 03:39:24 +00:00
if ( $link [ 'attribs' ][ '' ][ 'rel' ] === 'avatar' || $link [ 'attribs' ][ '' ][ 'rel' ] === 'photo' )
$res [ 'author-avatar' ] = unxmlify ( $link [ 'attribs' ][ '' ][ 'href' ]);
}
}
}
}
}
2011-06-21 02:08:40 +00:00
$apps = $item -> get_item_tags ( NAMESPACE_STATUSNET , 'notice_info' );
if ( $apps && $apps [ 0 ][ 'attribs' ][ '' ][ 'source' ]) {
2011-06-23 22:58:43 +00:00
$res [ 'app' ] = strip_tags ( unxmlify ( $apps [ 0 ][ 'attribs' ][ '' ][ 'source' ]));
2011-06-21 02:08:40 +00:00
}
2010-10-25 03:39:24 +00:00
2011-02-01 13:10:04 +00:00
/**
* If there ' s a copy of the body content which is guaranteed to have survived mangling in transit , use it .
*/
$have_real_body = false ;
$rawenv = $item -> get_item_tags ( NAMESPACE_DFRN , 'env' );
if ( $rawenv ) {
$have_real_body = true ;
$res [ 'body' ] = $rawenv [ 0 ][ 'data' ];
$res [ 'body' ] = str_replace ( array ( ' ' , " \t " , " \r " , " \n " ), array ( '' , '' , '' , '' ), $res [ 'body' ]);
2011-02-02 01:50:49 +00:00
// make sure nobody is trying to sneak some html tags by us
$res [ 'body' ] = notags ( base64url_decode ( $res [ 'body' ]));
2011-02-01 13:10:04 +00:00
}
2012-07-06 23:09:23 +00:00
$res [ 'body' ] = limit_body_size ( $res [ 'body' ]);
2010-07-19 03:49:10 +00:00
2010-09-09 03:14:17 +00:00
// It isn't certain at this point whether our content is plaintext or html and we'd be foolish to trust
// the content type. Our own network only emits text normally, though it might have been converted to
2011-01-18 03:50:18 +00:00
// html if we used a pubsubhubbub transport. But if we see even one html tag in our text, we will
2010-09-09 03:14:17 +00:00
// have to assume it is all html and needs to be purified.
// It doesn't matter all that much security wise - because before this content is used anywhere, we are
// going to escape any tags we find regardless, but this lets us import a limited subset of html from
// the wild, by sanitising it and converting supported tags to bbcode before we rip out any remaining
// html.
2012-04-01 10:19:37 +00:00
if (( strpos ( $res [ 'body' ], '<' ) !== false ) && ( strpos ( $res [ 'body' ], '>' ) !== false )) {
2010-09-09 03:14:17 +00:00
2012-01-18 00:30:32 +00:00
$res [ 'body' ] = reltoabs ( $res [ 'body' ], $base_url );
2011-10-12 01:24:37 +00:00
$res [ 'body' ] = html2bb_video ( $res [ 'body' ]);
2011-05-20 22:46:41 +00:00
2011-02-02 02:20:25 +00:00
$res [ 'body' ] = oembed_html2bbcode ( $res [ 'body' ]);
2011-02-17 01:32:15 +00:00
2013-05-28 08:40:27 +00:00
$res [ 'body' ] = purify_html ( $res [ 'body' ]);
2010-09-09 09:00:54 +00:00
2012-04-01 10:19:37 +00:00
$res [ 'body' ] = @ html2bbcode ( $res [ 'body' ]);
2012-06-20 12:04:51 +00:00
2011-01-18 03:50:18 +00:00
}
2012-04-01 22:43:57 +00:00
elseif ( ! $have_real_body ) {
// it's not one of our messages and it has no tags
// so it's probably just text. We'll escape it just to be safe.
$res [ 'body' ] = escape_tags ( $res [ 'body' ]);
}
2010-12-08 04:47:53 +00:00
$private = $item -> get_item_tags ( NAMESPACE_DFRN , 'private' );
2012-06-29 00:43:29 +00:00
if ( $private && intval ( $private [ 0 ][ 'data' ]) > 0 )
$res [ 'private' ] = intval ( $private [ 0 ][ 'data' ]);
2010-12-08 04:47:53 +00:00
else
$res [ 'private' ] = 0 ;
2010-08-24 23:25:02 +00:00
$rawlocation = $item -> get_item_tags ( NAMESPACE_DFRN , 'location' );
2010-08-20 21:33:15 +00:00
if ( $rawlocation )
$res [ 'location' ] = unxmlify ( $rawlocation [ 0 ][ 'data' ]);
2011-01-25 03:36:20 +00:00
$rawcreated = $item -> get_item_tags ( SIMPLEPIE_NAMESPACE_ATOM_10 , 'published' );
if ( $rawcreated )
$res [ 'created' ] = unxmlify ( $rawcreated [ 0 ][ 'data' ]);
2010-07-19 03:49:10 +00:00
$rawedited = $item -> get_item_tags ( SIMPLEPIE_NAMESPACE_ATOM_10 , 'updated' );
if ( $rawedited )
2011-02-02 00:50:19 +00:00
$res [ 'edited' ] = unxmlify ( $rawedited [ 0 ][ 'data' ]);
2010-07-19 03:49:10 +00:00
2011-02-02 00:50:19 +00:00
if (( x ( $res , 'edited' )) && ( ! ( x ( $res , 'created' ))))
2011-02-02 01:05:17 +00:00
$res [ 'created' ] = $res [ 'edited' ];
2011-01-25 03:36:20 +00:00
if ( ! $res [ 'created' ])
2011-02-02 00:50:19 +00:00
$res [ 'created' ] = $item -> get_date ( 'c' );
2011-01-25 03:36:20 +00:00
if ( ! $res [ 'edited' ])
2011-02-02 00:50:19 +00:00
$res [ 'edited' ] = $item -> get_date ( 'c' );
2011-01-25 03:36:20 +00:00
2011-03-15 01:34:58 +00:00
// Disallow time travelling posts
$d1 = strtotime ( $res [ 'created' ]);
$d2 = strtotime ( $res [ 'edited' ]);
$d3 = strtotime ( 'now' );
if ( $d1 > $d3 )
$res [ 'created' ] = datetime_convert ();
if ( $d2 > $d3 )
$res [ 'edited' ] = datetime_convert ();
2010-08-03 02:06:36 +00:00
$rawowner = $item -> get_item_tags ( NAMESPACE_DFRN , 'owner' );
2010-09-09 03:14:17 +00:00
if ( $rawowner [ 0 ][ 'child' ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'name' ][ 0 ][ 'data' ])
$res [ 'owner-name' ] = unxmlify ( $rawowner [ 0 ][ 'child' ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'name' ][ 0 ][ 'data' ]);
elseif ( $rawowner [ 0 ][ 'child' ][ NAMESPACE_DFRN ][ 'name' ][ 0 ][ 'data' ])
2010-08-03 02:06:36 +00:00
$res [ 'owner-name' ] = unxmlify ( $rawowner [ 0 ][ 'child' ][ NAMESPACE_DFRN ][ 'name' ][ 0 ][ 'data' ]);
2010-09-09 03:14:17 +00:00
if ( $rawowner [ 0 ][ 'child' ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'uri' ][ 0 ][ 'data' ])
$res [ 'owner-link' ] = unxmlify ( $rawowner [ 0 ][ 'child' ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'uri' ][ 0 ][ 'data' ]);
elseif ( $rawowner [ 0 ][ 'child' ][ NAMESPACE_DFRN ][ 'uri' ][ 0 ][ 'data' ])
2010-08-03 02:06:36 +00:00
$res [ 'owner-link' ] = unxmlify ( $rawowner [ 0 ][ 'child' ][ NAMESPACE_DFRN ][ 'uri' ][ 0 ][ 'data' ]);
2010-09-09 03:14:17 +00:00
2010-10-25 03:39:24 +00:00
if ( $rawowner [ 0 ][ 'child' ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'link' ]) {
$base = $rawowner [ 0 ][ 'child' ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'link' ];
foreach ( $base as $link ) {
2012-02-26 20:43:51 +00:00
if ( ! x ( $res , 'owner-avatar' ) || ! $res [ 'owner-avatar' ]) {
2012-07-19 00:08:03 +00:00
if ( $link [ 'attribs' ][ '' ][ 'rel' ] === 'photo' || $link [ 'attribs' ][ '' ][ 'rel' ] === 'avatar' )
2010-10-25 03:39:24 +00:00
$res [ 'owner-avatar' ] = unxmlify ( $link [ 'attribs' ][ '' ][ 'href' ]);
}
}
}
2010-07-19 03:49:10 +00:00
2010-10-20 03:52:05 +00:00
$rawgeo = $item -> get_item_tags ( NAMESPACE_GEORSS , 'point' );
if ( $rawgeo )
$res [ 'coord' ] = unxmlify ( $rawgeo [ 0 ][ 'data' ]);
2010-10-22 04:48:22 +00:00
2010-09-09 03:14:17 +00:00
$rawverb = $item -> get_item_tags ( NAMESPACE_ACTIVITY , 'verb' );
2011-01-04 10:20:00 +00:00
2010-09-09 03:14:17 +00:00
// select between supported verbs
2011-01-04 10:20:00 +00:00
if ( $rawverb ) {
2010-09-09 03:14:17 +00:00
$res [ 'verb' ] = unxmlify ( $rawverb [ 0 ][ 'data' ]);
2011-01-04 10:20:00 +00:00
}
// translate OStatus unfollow to activity streams if it happened to get selected
if (( x ( $res , 'verb' )) && ( $res [ 'verb' ] === 'http://ostatus.org/schema/1.0/unfollow' ))
$res [ 'verb' ] = ACTIVITY_UNFOLLOW ;
2011-04-06 00:41:02 +00:00
$cats = $item -> get_categories ();
if ( $cats ) {
2012-07-11 11:29:47 +00:00
$terms = array ();
2011-04-06 00:41:02 +00:00
foreach ( $cats as $cat ) {
$term = $cat -> get_term ();
if ( ! $term )
$term = $cat -> get_label ();
$scheme = $cat -> get_scheme ();
2012-07-11 11:29:47 +00:00
$termurl = '' ;
if ( $scheme && $term && stristr ( $scheme , 'X-DFRN:' )) {
$termtype = (( substr ( $scheme , 7 , 1 ) === '#' ) ? TERM_HASHTAG : TERM_MENTION );
$termurl = unxmlify ( substr ( $scheme , 9 ));
}
else {
$termtype = TERM_UNKNOWN ;
}
$termterm = notags ( trim ( unxmlify ( $term )));
if ( $termterm ) {
$terms = array (
'otype' => TERM_OBJ_POST ,
'type' => $termtype ,
'url' => $termurl ,
'term' => $termterm ,
);
}
2011-04-06 00:41:02 +00:00
}
2012-07-11 11:29:47 +00:00
$res [ 'term' ] = implode ( ',' , $tag_arr );
2011-04-06 00:41:02 +00:00
}
2010-09-09 03:14:17 +00:00
2011-04-07 02:41:16 +00:00
$attach = $item -> get_enclosures ();
if ( $attach ) {
$att_arr = array ();
foreach ( $attach as $att ) {
2011-04-13 08:53:40 +00:00
$len = intval ( $att -> get_length ());
$link = str_replace ( array ( ',' , '"' ), array ( '%2D' , '%22' ), notags ( trim ( unxmlify ( $att -> get_link ()))));
$title = str_replace ( array ( ',' , '"' ), array ( '%2D' , '%22' ), notags ( trim ( unxmlify ( $att -> get_title ()))));
$type = str_replace ( array ( ',' , '"' ), array ( '%2D' , '%22' ), notags ( trim ( unxmlify ( $att -> get_type ()))));
if ( strpos ( $type , ';' ))
$type = substr ( $type , 0 , strpos ( $type , ';' ));
2011-04-07 02:41:16 +00:00
if (( ! $link ) || ( strpos ( $link , 'http' ) !== 0 ))
continue ;
if ( ! $title )
$title = ' ' ;
if ( ! $type )
$type = 'application/octet-stream' ;
2011-08-04 02:18:58 +00:00
$att_arr [] = '[attach]href="' . $link . '" length="' . $len . '" type="' . $type . '" title="' . $title . '"[/attach]' ;
2011-04-07 02:41:16 +00:00
}
$res [ 'attach' ] = implode ( ',' , $att_arr );
}
2010-09-09 03:14:17 +00:00
$rawobj = $item -> get_item_tags ( NAMESPACE_ACTIVITY , 'object' );
2010-09-17 10:10:19 +00:00
2010-09-09 03:14:17 +00:00
if ( $rawobj ) {
2010-09-17 10:10:19 +00:00
$res [ 'object' ] = '<object>' . " \n " ;
2012-04-17 11:33:50 +00:00
$child = $rawobj [ 0 ][ 'child' ];
2012-08-16 05:33:37 +00:00
if ( $child [ NAMESPACE_ACTIVITY ][ 'obj_type' ][ 0 ][ 'data' ]) {
$res [ 'obj_type' ] = $child [ NAMESPACE_ACTIVITY ][ 'obj_type' ][ 0 ][ 'data' ];
$res [ 'object' ] .= '<type>' . $child [ NAMESPACE_ACTIVITY ][ 'obj_type' ][ 0 ][ 'data' ] . '</type>' . " \n " ;
2010-09-17 10:10:19 +00:00
}
2012-04-17 11:33:50 +00:00
if ( x ( $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ], 'id' ) && $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'id' ][ 0 ][ 'data' ])
$res [ 'object' ] .= '<id>' . $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'id' ][ 0 ][ 'data' ] . '</id>' . " \n " ;
if ( x ( $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ], 'link' ) && $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'link' ])
$res [ 'object' ] .= '<link>' . encode_rel_links ( $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'link' ]) . '</link>' . " \n " ;
if ( x ( $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ], 'title' ) && $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'title' ][ 0 ][ 'data' ])
$res [ 'object' ] .= '<title>' . $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'title' ][ 0 ][ 'data' ] . '</title>' . " \n " ;
if ( x ( $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ], 'content' ) && $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'content' ][ 0 ][ 'data' ]) {
$body = $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'content' ][ 0 ][ 'data' ];
2010-09-17 10:10:19 +00:00
if ( ! $body )
2012-04-17 11:33:50 +00:00
$body = $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'summary' ][ 0 ][ 'data' ];
2011-01-12 21:21:37 +00:00
// preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events
$res [ 'object' ] .= '<orig>' . xmlify ( $body ) . '</orig>' . " \n " ;
2011-02-02 02:20:25 +00:00
if (( strpos ( $body , '<' ) !== false ) || ( strpos ( $body , '>' ) !== false )) {
2010-09-17 10:10:19 +00:00
2013-09-30 03:34:05 +00:00
$body = purify_html ( $body );
2011-01-18 03:50:18 +00:00
$body = html2bbcode ( $body );
2013-09-30 03:34:05 +00:00
2010-09-17 10:10:19 +00:00
}
$res [ 'object' ] .= '<content>' . $body . '</content>' . " \n " ;
}
$res [ 'object' ] .= '</object>' . " \n " ;
2010-09-09 03:14:17 +00:00
}
2010-11-03 23:48:21 +00:00
$rawobj = $item -> get_item_tags ( NAMESPACE_ACTIVITY , 'target' );
if ( $rawobj ) {
$res [ 'target' ] = '<target>' . " \n " ;
2012-04-17 11:33:50 +00:00
$child = $rawobj [ 0 ][ 'child' ];
2012-08-16 05:33:37 +00:00
if ( $child [ NAMESPACE_ACTIVITY ][ 'obj_type' ][ 0 ][ 'data' ]) {
$res [ 'target' ] .= '<type>' . $child [ NAMESPACE_ACTIVITY ][ 'obj_type' ][ 0 ][ 'data' ] . '</type>' . " \n " ;
2010-11-03 23:48:21 +00:00
}
2012-04-17 11:33:50 +00:00
if ( x ( $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ], 'id' ) && $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'id' ][ 0 ][ 'data' ])
$res [ 'target' ] .= '<id>' . $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'id' ][ 0 ][ 'data' ] . '</id>' . " \n " ;
if ( x ( $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ], 'link' ) && $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'link' ])
$res [ 'target' ] .= '<link>' . encode_rel_links ( $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'link' ]) . '</link>' . " \n " ;
if ( x ( $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ], 'data' ) && $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'title' ][ 0 ][ 'data' ])
$res [ 'target' ] .= '<title>' . $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'title' ][ 0 ][ 'data' ] . '</title>' . " \n " ;
if ( x ( $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ], 'data' ) && $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'content' ][ 0 ][ 'data' ]) {
$body = $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'content' ][ 0 ][ 'data' ];
2010-11-03 23:48:21 +00:00
if ( ! $body )
2012-04-17 11:33:50 +00:00
$body = $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ 'summary' ][ 0 ][ 'data' ];
2011-01-12 21:21:37 +00:00
// preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events
2011-10-23 07:24:37 +00:00
$res [ 'target' ] .= '<orig>' . xmlify ( $body ) . '</orig>' . " \n " ;
2011-02-02 02:20:25 +00:00
if (( strpos ( $body , '<' ) !== false ) || ( strpos ( $body , '>' ) !== false )) {
2010-11-03 23:48:21 +00:00
2013-09-30 03:34:05 +00:00
$body = purify_html ( $body );
2011-01-18 03:50:18 +00:00
$body = html2bbcode ( $body );
2010-11-03 23:48:21 +00:00
}
$res [ 'target' ] .= '<content>' . $body . '</content>' . " \n " ;
}
$res [ 'target' ] .= '</target>' . " \n " ;
}
2012-07-19 00:08:03 +00:00
// This is some experimental stuff. By now retweets are shown with "RT:"
// But: There is data so that the message could be shown similar to native retweets
// There is some better way to parse this array - but it didn't worked for me.
2013-05-28 08:40:27 +00:00
2012-07-19 00:08:03 +00:00
$child = $item -> feed -> data [ " child " ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ " feed " ][ 0 ][ " child " ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ " entry " ][ 0 ][ " child " ][ " http://activitystrea.ms/spec/1.0/ " ][ object ][ 0 ][ " child " ];
if ( is_array ( $child )) {
$message = $child [ " http://activitystrea.ms/spec/1.0/ " ][ " object " ][ 0 ][ " child " ][ SIMPLEPIE_NAMESPACE_ATOM_10 ][ " content " ][ 0 ][ " data " ];
$author = $child [ SIMPLEPIE_NAMESPACE_ATOM_10 ][ " author " ][ 0 ][ " child " ][ SIMPLEPIE_NAMESPACE_ATOM_10 ];
$uri = $author [ " uri " ][ 0 ][ " data " ];
$name = $author [ " name " ][ 0 ][ " data " ];
$avatar = @ array_shift ( $author [ " link " ][ 2 ][ " attribs " ]);
$avatar = $avatar [ " href " ];
if (( $name != " " ) and ( $uri != " " ) and ( $avatar != " " ) and ( $message != " " )) {
$res [ " owner-name " ] = $res [ " author-name " ];
$res [ " owner-link " ] = $res [ " author-link " ];
$res [ " owner-avatar " ] = $res [ " author-avatar " ];
$res [ " author-name " ] = $name ;
$res [ " author-link " ] = $uri ;
$res [ " author-avatar " ] = $avatar ;
$res [ " body " ] = html2bbcode ( $message );
}
}
2010-12-25 23:01:02 +00:00
$arr = array ( 'feed' => $feed , 'item' => $item , 'result' => $res );
call_hooks ( 'parse_atom' , $arr );
2013-09-30 03:34:05 +00:00
logger ( 'get_atom_elements: ' . print_r ( $res , true ));
2010-12-25 02:32:23 +00:00
2010-07-19 03:49:10 +00:00
return $res ;
}
2010-11-03 23:48:21 +00:00
function encode_rel_links ( $links ) {
$o = '' ;
if ( ! (( is_array ( $links )) && ( count ( $links ))))
return $o ;
foreach ( $links as $link ) {
$o .= '<link ' ;
if ( $link [ 'attribs' ][ '' ][ 'rel' ])
$o .= 'rel="' . $link [ 'attribs' ][ '' ][ 'rel' ] . '" ' ;
if ( $link [ 'attribs' ][ '' ][ 'type' ])
$o .= 'type="' . $link [ 'attribs' ][ '' ][ 'type' ] . '" ' ;
if ( $link [ 'attribs' ][ '' ][ 'href' ])
2011-01-18 00:06:22 +00:00
$o .= 'href="' . $link [ 'attribs' ][ '' ][ 'href' ] . '" ' ;
2010-11-04 07:37:29 +00:00
if ( ( x ( $link [ 'attribs' ], NAMESPACE_MEDIA )) && $link [ 'attribs' ][ NAMESPACE_MEDIA ][ 'width' ])
2010-11-03 23:48:21 +00:00
$o .= 'media:width="' . $link [ 'attribs' ][ NAMESPACE_MEDIA ][ 'width' ] . '" ' ;
2010-11-04 07:37:29 +00:00
if ( ( x ( $link [ 'attribs' ], NAMESPACE_MEDIA )) && $link [ 'attribs' ][ NAMESPACE_MEDIA ][ 'height' ])
2010-11-03 23:48:21 +00:00
$o .= 'media:height="' . $link [ 'attribs' ][ NAMESPACE_MEDIA ][ 'height' ] . '" ' ;
$o .= ' />' . " \n " ;
}
return xmlify ( $o );
}
2013-08-11 23:56:06 +00:00
function item_store ( $arr , $allow_exec = false ) {
2010-07-19 03:49:10 +00:00
2013-11-29 02:10:04 +00:00
$d = array ( 'item' => $arr , 'allow_exec' => $allow_exec );
call_hooks ( 'item_store' , $d );
$arr = $d [ 'item' ];
$allow_exec = $d [ 'allow_exec' ];
2014-03-05 03:57:54 +00:00
$ret = array ( 'success' => false , 'item_id' => 0 );
2013-09-11 02:06:06 +00:00
2012-07-16 10:32:42 +00:00
if ( ! $arr [ 'uid' ]) {
logger ( 'item_store: no uid' );
2013-09-11 02:06:06 +00:00
$ret [ 'message' ] = 'No uid.' ;
return ret ;
2012-07-16 10:32:42 +00:00
}
2013-10-14 01:36:28 +00:00
$uplinked_comment = false ;
2013-09-02 02:15:08 +00:00
// If a page layout is provided, ensure it exists and belongs to us.
if ( array_key_exists ( 'layout_mid' , $arr ) && $arr [ 'layout_mid' ]) {
$l = q ( " select item_restrict from item where mid = '%s' and uid = %d limit 1 " ,
dbesc ( $arr [ 'layout_mid' ]),
intval ( $arr [ 'uid' ])
);
if (( ! $l ) || ( ! ( $l [ 0 ][ 'item_restrict' ] & ITEM_PDL )))
unset ( $arr [ 'layout_mid' ]);
}
2013-07-16 01:07:23 +00:00
// Don't let anybody set these, either intentionally or accidentally
if ( array_key_exists ( 'id' , $arr ))
unset ( $arr [ 'id' ]);
if ( array_key_exists ( 'parent' , $arr ))
unset ( $arr [ 'parent' ]);
2013-08-02 02:18:05 +00:00
$arr [ 'mimetype' ] = (( x ( $arr , 'mimetype' )) ? notags ( trim ( $arr [ 'mimetype' ])) : 'text/bbcode' );
2013-08-11 23:56:06 +00:00
if (( $arr [ 'mimetype' ] == 'application/x-php' ) && ( ! $allow_exec )) {
logger ( 'item_store: php mimetype but allow_exec is denied.' );
2013-09-11 02:06:06 +00:00
$ret [ 'message' ] = 'exec denied.' ;
return $ret ;
2013-08-11 23:56:06 +00:00
}
2014-02-20 23:00:29 +00:00
$arr [ 'title' ] = (( x ( $arr , 'title' )) ? trim ( $arr [ 'title' ]) : '' );
2013-08-02 02:18:05 +00:00
$arr [ 'body' ] = (( x ( $arr , 'body' )) ? trim ( $arr [ 'body' ]) : '' );
$arr [ 'allow_cid' ] = (( x ( $arr , 'allow_cid' )) ? trim ( $arr [ 'allow_cid' ]) : '' );
$arr [ 'allow_gid' ] = (( x ( $arr , 'allow_gid' )) ? trim ( $arr [ 'allow_gid' ]) : '' );
$arr [ 'deny_cid' ] = (( x ( $arr , 'deny_cid' )) ? trim ( $arr [ 'deny_cid' ]) : '' );
$arr [ 'deny_gid' ] = (( x ( $arr , 'deny_gid' )) ? trim ( $arr [ 'deny_gid' ]) : '' );
$arr [ 'item_private' ] = (( x ( $arr , 'item_private' )) ? intval ( $arr [ 'item_private' ]) : 0 );
$arr [ 'item_flags' ] = (( x ( $arr , 'item_flags' )) ? intval ( $arr [ 'item_flags' ]) : 0 );
2013-09-02 08:38:17 +00:00
2013-10-03 04:04:48 +00:00
2013-08-02 01:50:36 +00:00
// only detect language if we have text content, and if the post is private but not yet
// obscured, make it so.
if ( ! ( $arr [ 'item_flags' ] & ITEM_OBSCURED )) {
2013-10-03 04:04:48 +00:00
2013-08-02 01:50:36 +00:00
$arr [ 'lang' ] = detect_language ( $arr [ 'body' ]);
2013-09-04 05:48:08 +00:00
// apply the input filter here - if it is obscured it has been filtered already
$arr [ 'body' ] = z_input_filter ( $arr [ 'uid' ], $arr [ 'body' ], $arr [ 'mimetype' ]);
2013-08-02 01:50:36 +00:00
2013-10-03 04:04:48 +00:00
if ( local_user () && ( ! $arr [ 'sig' ])) {
$channel = get_app () -> get_channel ();
if ( $channel [ 'channel_hash' ] === $arr [ 'author_xchan' ]) {
$arr [ 'sig' ] = base64url_encode ( rsa_sign ( $arr [ 'body' ], $channel [ 'channel_prvkey' ]));
$arr [ 'item_flags' ] |= ITEM_VERIFIED ;
}
}
2013-08-02 01:50:36 +00:00
$allowed_languages = get_pconfig ( $arr [ 'uid' ], 'system' , 'allowed_languages' );
2012-07-16 10:32:42 +00:00
2013-08-02 01:50:36 +00:00
if (( is_array ( $allowed_languages )) && ( $arr [ 'lang' ]) && ( ! array_key_exists ( $arr [ 'lang' ], $allowed_languages ))) {
$translate = array ( 'item' => $arr , 'from' => $arr [ 'lang' ], 'to' => $allowed_languages , 'translated' => false );
call_hooks ( 'item_translate' , $translate );
if (( ! $translate [ 'translated' ]) && ( intval ( get_pconfig ( $arr [ 'uid' ], 'system' , 'reject_disallowed_languages' )))) {
logger ( 'item_store: language ' . $arr [ 'lang' ] . ' not accepted for uid ' . $arr [ 'uid' ]);
2013-09-11 02:06:06 +00:00
$ret [ 'message' ] = 'language not accepted' ;
return $ret ;
2013-08-02 01:50:36 +00:00
}
$arr = $translate [ 'item' ];
2012-07-16 10:32:42 +00:00
}
2013-08-02 01:50:36 +00:00
if ( $arr [ 'item_private' ]) {
$key = get_config ( 'system' , 'pubkey' );
$arr [ 'item_flags' ] = $arr [ 'item_flags' ] | ITEM_OBSCURED ;
if ( $arr [ 'title' ])
2013-11-20 23:20:12 +00:00
$arr [ 'title' ] = json_encode ( crypto_encapsulate ( $arr [ 'title' ], $key ));
2013-08-02 01:50:36 +00:00
if ( $arr [ 'body' ])
2013-11-20 23:20:12 +00:00
$arr [ 'body' ] = json_encode ( crypto_encapsulate ( $arr [ 'body' ], $key ));
2013-08-02 01:50:36 +00:00
}
2012-07-16 10:32:42 +00:00
}
2011-02-02 02:20:25 +00:00
2013-01-07 21:58:25 +00:00
if (( x ( $arr , 'object' )) && is_array ( $arr [ 'object' ])) {
activity_sanitise ( $arr [ 'object' ]);
$arr [ 'object' ] = json_encode ( $arr [ 'object' ]);
}
if (( x ( $arr , 'target' )) && is_array ( $arr [ 'target' ])) {
activity_sanitise ( $arr [ 'target' ]);
$arr [ 'target' ] = json_encode ( $arr [ 'target' ]);
}
2013-02-01 08:49:07 +00:00
if (( x ( $arr , 'attach' )) && is_array ( $arr [ 'attach' ])) {
activity_sanitise ( $arr [ 'attach' ]);
$arr [ 'attach' ] = json_encode ( $arr [ 'attach' ]);
}
2012-10-04 05:28:19 +00:00
$arr [ 'aid' ] = (( x ( $arr , 'aid' )) ? intval ( $arr [ 'aid' ]) : 0 );
2013-03-22 01:25:41 +00:00
$arr [ 'mid' ] = (( x ( $arr , 'mid' )) ? notags ( trim ( $arr [ 'mid' ])) : random_string ());
2012-10-04 05:28:19 +00:00
$arr [ 'author_xchan' ] = (( x ( $arr , 'author_xchan' )) ? notags ( trim ( $arr [ 'author_xchan' ])) : '' );
$arr [ 'owner_xchan' ] = (( x ( $arr , 'owner_xchan' )) ? notags ( trim ( $arr [ 'owner_xchan' ])) : '' );
2010-11-10 04:38:24 +00:00
$arr [ 'created' ] = (( x ( $arr , 'created' ) !== false ) ? datetime_convert ( 'UTC' , 'UTC' , $arr [ 'created' ]) : datetime_convert ());
$arr [ 'edited' ] = (( x ( $arr , 'edited' ) !== false ) ? datetime_convert ( 'UTC' , 'UTC' , $arr [ 'edited' ]) : datetime_convert ());
2013-11-18 03:22:24 +00:00
$arr [ 'expires' ] = (( x ( $arr , 'expires' ) !== false ) ? datetime_convert ( 'UTC' , 'UTC' , $arr [ 'expires' ]) : '0000-00-00 00:00:00' );
$arr [ 'commented' ] = (( x ( $arr , 'commented' ) !== false ) ? datetime_convert ( 'UTC' , 'UTC' , $arr [ 'commented' ]) : datetime_convert ());
2011-06-24 00:56:59 +00:00
$arr [ 'received' ] = datetime_convert ();
2010-11-10 04:38:24 +00:00
$arr [ 'changed' ] = datetime_convert ();
$arr [ 'location' ] = (( x ( $arr , 'location' )) ? notags ( trim ( $arr [ 'location' ])) : '' );
$arr [ 'coord' ] = (( x ( $arr , 'coord' )) ? notags ( trim ( $arr [ 'coord' ])) : '' );
2013-09-11 05:45:04 +00:00
$arr [ 'parent_mid' ] = (( x ( $arr , 'parent_mid' )) ? notags ( trim ( $arr [ 'parent_mid' ])) : '' );
2013-04-04 01:04:48 +00:00
$arr [ 'thr_parent' ] = (( x ( $arr , 'thr_parent' )) ? notags ( trim ( $arr [ 'thr_parent' ])) : $arr [ 'parent_mid' ]);
2010-11-10 04:38:24 +00:00
$arr [ 'verb' ] = (( x ( $arr , 'verb' )) ? notags ( trim ( $arr [ 'verb' ])) : '' );
2012-10-06 08:17:25 +00:00
$arr [ 'obj_type' ] = (( x ( $arr , 'obj_type' )) ? notags ( trim ( $arr [ 'obj_type' ])) : '' );
2010-11-10 04:38:24 +00:00
$arr [ 'object' ] = (( x ( $arr , 'object' )) ? trim ( $arr [ 'object' ]) : '' );
2012-10-06 08:17:25 +00:00
$arr [ 'tgt_type' ] = (( x ( $arr , 'tgt_type' )) ? notags ( trim ( $arr [ 'tgt_type' ])) : '' );
2010-11-10 04:38:24 +00:00
$arr [ 'target' ] = (( x ( $arr , 'target' )) ? trim ( $arr [ 'target' ]) : '' );
2011-02-16 10:07:11 +00:00
$arr [ 'plink' ] = (( x ( $arr , 'plink' )) ? notags ( trim ( $arr [ 'plink' ])) : '' );
2011-04-07 04:59:07 +00:00
$arr [ 'attach' ] = (( x ( $arr , 'attach' )) ? notags ( trim ( $arr [ 'attach' ])) : '' );
2011-06-21 02:08:40 +00:00
$arr [ 'app' ] = (( x ( $arr , 'app' )) ? notags ( trim ( $arr [ 'app' ])) : '' );
2012-10-07 23:39:29 +00:00
$arr [ 'item_restrict' ] = (( x ( $arr , 'item_restrict' )) ? intval ( $arr [ 'item_restrict' ]) : 0 );
2013-06-17 03:44:29 +00:00
$arr [ 'comment_policy' ] = (( x ( $arr , 'comment_policy' )) ? notags ( trim ( $arr [ 'comment_policy' ])) : 'contacts' );
2012-10-06 08:17:25 +00:00
2012-11-30 04:46:45 +00:00
$arr [ 'item_flags' ] = $arr [ 'item_flags' ] | ITEM_UNSEEN ;
2012-12-16 10:18:26 +00:00
2013-06-17 03:44:29 +00:00
if ( $arr [ 'comment_policy' ] == 'none' )
$arr [ 'item_flags' ] = $arr [ 'item_flags' ] | ITEM_NOCOMMENT ;
2013-05-24 00:24:15 +00:00
// handle time travelers
// Allow a bit of fudge in case somebody just has a slightly slow/fast clock
2013-05-30 04:11:30 +00:00
$d1 = new DateTime ( 'now +10 minutes' , new DateTimeZone ( 'UTC' ));
$d2 = new DateTime ( $arr [ 'created' ] . '+00:00' );
2013-05-24 00:24:15 +00:00
if ( $d2 > $d1 )
$arr [ 'item_restrict' ] = $arr [ 'item_restrict' ] | ITEM_DELAYED_PUBLISH ;
2013-03-22 01:25:41 +00:00
$arr [ 'llink' ] = z_root () . '/display/' . $arr [ 'mid' ];
2012-12-16 10:18:26 +00:00
2014-01-09 23:45:17 +00:00
if ( ! $arr [ 'plink' ])
$arr [ 'plink' ] = $arr [ 'llink' ];
2012-12-16 10:18:26 +00:00
2013-03-22 01:25:41 +00:00
if ( $arr [ 'parent_mid' ] === $arr [ 'mid' ]) {
2010-11-12 04:32:20 +00:00
$parent_id = 0 ;
2012-02-28 12:56:16 +00:00
$parent_deleted = 0 ;
2010-11-12 04:32:20 +00:00
$allow_cid = $arr [ 'allow_cid' ];
$allow_gid = $arr [ 'allow_gid' ];
$deny_cid = $arr [ 'deny_cid' ];
$deny_gid = $arr [ 'deny_gid' ];
2012-11-27 07:52:16 +00:00
$arr [ 'item_flags' ] = $arr [ 'item_flags' ] | ITEM_THREAD_TOP ;
2010-11-12 04:32:20 +00:00
}
else {
// find the parent and snarf the item id and ACL's
2011-03-08 22:40:33 +00:00
// and anything else we need to inherit
2010-11-12 04:32:20 +00:00
2013-03-22 01:25:41 +00:00
$r = q ( " SELECT * FROM `item` WHERE `mid` = '%s' AND `uid` = %d ORDER BY `id` ASC LIMIT 1 " ,
dbesc ( $arr [ 'parent_mid' ]),
2010-11-12 04:32:20 +00:00
intval ( $arr [ 'uid' ])
);
2013-07-22 05:39:21 +00:00
if ( $r ) {
2010-12-05 07:16:16 +00:00
// is the new message multi-level threaded?
// even though we don't support it now, preserve the info
// and re-attach to the conversation parent.
2013-03-22 01:25:41 +00:00
if ( $r [ 0 ][ 'mid' ] != $r [ 0 ][ 'parent_mid' ]) {
$arr [ 'parent_mid' ] = $r [ 0 ][ 'parent_mid' ];
$z = q ( " SELECT * FROM `item` WHERE `mid` = '%s' AND `parent_mid` = '%s' AND `uid` = %d
2011-10-12 09:21:18 +00:00
ORDER BY `id` ASC LIMIT 1 " ,
2013-03-22 01:25:41 +00:00
dbesc ( $r [ 0 ][ 'parent_mid' ]),
dbesc ( $r [ 0 ][ 'parent_mid' ]),
2011-08-09 02:10:36 +00:00
intval ( $arr [ 'uid' ])
);
if ( $z && count ( $z ))
$r = $z ;
2010-12-05 07:16:16 +00:00
}
2011-02-04 12:25:53 +00:00
$parent_id = $r [ 0 ][ 'id' ];
2012-10-06 08:17:25 +00:00
$parent_deleted = $r [ 0 ][ 'item_restrict' ] & ITEM_DELETED ;
2011-02-04 12:25:53 +00:00
$allow_cid = $r [ 0 ][ 'allow_cid' ];
$allow_gid = $r [ 0 ][ 'allow_gid' ];
$deny_cid = $r [ 0 ][ 'deny_cid' ];
$deny_gid = $r [ 0 ][ 'deny_gid' ];
2012-10-06 08:17:25 +00:00
2012-10-07 23:39:29 +00:00
if ( $r [ 0 ][ 'item_flags' ] & ITEM_WALL )
2012-10-06 08:17:25 +00:00
$arr [ 'item_flags' ] = $arr [ 'item_flags' ] | ITEM_WALL ;
2012-06-11 12:28:08 +00:00
2013-10-14 01:36:28 +00:00
// An uplinked comment might arrive with a downstream owner.
// Fix it.
if ( $r [ 0 ][ 'owner_xchan' ] !== $arr [ 'owner_xchan' ]) {
$arr [ 'owner_xchan' ] = $r [ 0 ][ 'owner_xchan' ];
$uplinked_comment = true ;
}
2012-06-11 12:28:08 +00:00
// if the parent is private, force privacy for the entire conversation
// This differs from the above settings as it subtly allows comments from
// email correspondents to be private even if the overall thread is not.
2012-10-08 01:44:06 +00:00
if ( $r [ 0 ][ 'item_private' ])
$arr [ 'item_private' ] = $r [ 0 ][ 'item_private' ];
2012-06-11 12:28:08 +00:00
2012-06-19 00:19:56 +00:00
// Edge case. We host a public forum that was originally posted to privately.
// The original author commented, but as this is a comment, the permissions
// weren't fixed up so it will still show the comment as private unless we fix it here.
2012-10-08 01:44:06 +00:00
if (( intval ( $r [ 0 ][ 'item_flags' ]) & ITEM_UPLINK ) && ( ! $r [ 0 ][ 'item_private' ]))
$arr [ 'item_private' ] = 0 ;
2010-11-12 04:32:20 +00:00
}
else {
2013-03-28 02:02:01 +00:00
logger ( 'item_store: item parent was not found - ignoring item' );
2013-09-11 02:06:06 +00:00
$ret [ 'message' ] = 'parent not found.' ;
return $ret ;
2010-11-12 04:32:20 +00:00
}
}
2010-07-19 03:49:10 +00:00
2012-10-06 08:17:25 +00:00
if ( $parent_deleted )
$arr [ 'item_restrict' ] = $arr [ 'item_restrict' ] | ITEM_DELETED ;
2013-03-22 01:25:41 +00:00
$r = q ( " SELECT `id` FROM `item` WHERE `mid` = '%s' AND `uid` = %d LIMIT 1 " ,
dbesc ( $arr [ 'mid' ]),
2011-10-12 09:21:18 +00:00
intval ( $arr [ 'uid' ])
2011-10-03 13:04:17 +00:00
);
2012-11-28 01:09:01 +00:00
if ( $r ) {
2013-09-11 04:10:56 +00:00
logger ( 'item_store: duplicate item ignored. ' . print_r ( $arr , true ));
2013-09-11 02:06:06 +00:00
$ret [ 'message' ] = 'duplicate post.' ;
return $ret ;
2011-10-03 13:04:17 +00:00
}
2011-08-08 00:29:26 +00:00
2010-12-22 22:16:22 +00:00
call_hooks ( 'post_remote' , $arr );
2012-01-31 04:49:54 +00:00
if ( x ( $arr , 'cancel' )) {
logger ( 'item_store: post cancelled by plugin.' );
2013-09-11 02:06:06 +00:00
$ret [ 'message' ] = 'cancelled.' ;
return $ret ;
2012-01-31 04:49:54 +00:00
}
2012-07-11 11:29:47 +00:00
// pull out all the taxonomy stuff for separate storage
$terms = null ;
2012-11-27 05:20:16 +00:00
if ( array_key_exists ( 'term' , $arr )) {
2012-07-11 11:29:47 +00:00
$terms = $arr [ 'term' ];
unset ( $arr [ 'term' ]);
}
2010-11-04 02:47:07 +00:00
logger ( 'item_store: ' . print_r ( $arr , true ), LOGGER_DATA );
2013-08-18 07:04:38 +00:00
dbesc_array ( $arr );
2010-11-09 23:11:47 +00:00
$r = dbq ( " INSERT INTO `item` (` "
2010-07-19 03:49:10 +00:00
. implode ( " `, ` " , array_keys ( $arr ))
. " `) VALUES (' "
. implode ( " ', ' " , array_values ( $arr ))
. " ') " );
2010-11-12 04:32:20 +00:00
// find the item we just created
2010-07-19 03:49:10 +00:00
2013-09-11 06:25:56 +00:00
$r = q ( " SELECT * FROM `item` WHERE `mid` = '%s' AND `uid` = %d ORDER BY `id` ASC " ,
2013-03-22 01:25:41 +00:00
$arr [ 'mid' ], // already dbesc'd
2010-07-19 03:49:10 +00:00
intval ( $arr [ 'uid' ])
);
2011-05-30 05:50:36 +00:00
2013-09-11 06:25:56 +00:00
2012-10-08 07:23:43 +00:00
if ( $r && count ( $r )) {
2010-07-19 03:49:10 +00:00
$current_post = $r [ 0 ][ 'id' ];
2013-09-11 04:10:56 +00:00
$arr = $r [ 0 ]; // This will gives us a fresh copy of what's now in the DB and undo the db escaping, which really messes up the notifications
2012-10-08 07:23:43 +00:00
logger ( 'item_store: created item ' . $current_post , LOGGER_DEBUG );
2010-11-04 02:47:07 +00:00
}
2010-11-12 04:32:20 +00:00
else {
2013-09-11 03:14:12 +00:00
logger ( 'item_store: could not locate stored item' );
2013-09-11 02:06:06 +00:00
$ret [ 'message' ] = 'unable to retrieve.' ;
return $ret ;
2010-09-09 03:14:17 +00:00
}
2011-10-12 09:21:18 +00:00
if ( count ( $r ) > 1 ) {
logger ( 'item_store: duplicated post occurred. Removing duplicates.' );
2013-03-22 01:25:41 +00:00
q ( " DELETE FROM `item` WHERE `mid` = '%s' AND `uid` = %d AND `id` != %d " ,
$arr [ 'mid' ],
2011-10-12 09:21:18 +00:00
intval ( $arr [ 'uid' ]),
intval ( $current_post )
);
}
2010-07-19 03:49:10 +00:00
2013-03-22 01:25:41 +00:00
if (( ! $parent_id ) || ( $arr [ 'parent_mid' ] === $arr [ 'mid' ]))
2010-11-12 04:32:20 +00:00
$parent_id = $current_post ;
2011-02-04 21:37:04 +00:00
if ( strlen ( $allow_cid ) || strlen ( $allow_gid ) || strlen ( $deny_cid ) || strlen ( $deny_gid ))
2010-12-08 04:47:53 +00:00
$private = 1 ;
else
2013-07-29 04:04:03 +00:00
$private = $arr [ 'item_private' ];
2010-12-08 04:47:53 +00:00
2010-11-12 04:32:20 +00:00
// Set parent id - and also make sure to inherit the parent's ACL's.
2010-09-29 05:32:48 +00:00
2013-05-28 08:40:27 +00:00
$r = q ( " UPDATE item SET parent = %d, allow_cid = '%s', allow_gid = '%s',
deny_cid = '%s' , deny_gid = '%s' , item_private = % d WHERE id = % d LIMIT 1 " ,
2010-07-19 03:49:10 +00:00
intval ( $parent_id ),
2010-09-29 05:32:48 +00:00
dbesc ( $allow_cid ),
dbesc ( $allow_gid ),
dbesc ( $deny_cid ),
dbesc ( $deny_gid ),
2010-12-08 04:47:53 +00:00
intval ( $private ),
2010-07-19 03:49:10 +00:00
intval ( $current_post )
);
2013-09-11 04:10:56 +00:00
// These are probably redundant now that we've queried the just stored post
2012-10-08 07:23:43 +00:00
$arr [ 'id' ] = $current_post ;
$arr [ 'parent' ] = $parent_id ;
2012-07-11 11:29:47 +00:00
$arr [ 'allow_cid' ] = $allow_cid ;
$arr [ 'allow_gid' ] = $allow_gid ;
2012-10-08 07:23:43 +00:00
$arr [ 'deny_cid' ] = $deny_cid ;
$arr [ 'deny_gid' ] = $deny_gid ;
2013-07-29 04:04:03 +00:00
$arr [ 'item_private' ] = $private ;
2012-10-08 07:23:43 +00:00
// Store taxonomy
2013-02-11 08:20:14 +00:00
2012-07-11 11:29:47 +00:00
if (( $terms ) && ( is_array ( $terms ))) {
foreach ( $terms as $t ) {
q ( " insert into term (uid,oid,otype,type,term,url)
values ( % d , % d , % d , % d , '%s' , '%s' ) " ,
intval ( $arr [ 'uid' ]),
intval ( $current_post ),
2013-02-11 08:20:14 +00:00
intval ( TERM_OBJ_POST ),
2012-07-11 11:29:47 +00:00
intval ( $t [ 'type' ]),
dbesc ( $t [ 'term' ]),
dbesc ( $t [ 'url' ])
);
}
$arr [ 'term' ] = $terms ;
}
2012-06-12 05:09:50 +00:00
call_hooks ( 'post_remote_end' , $arr );
2011-09-19 02:04:11 +00:00
// update the commented timestamp on the parent
2011-09-16 13:49:24 +00:00
2013-11-18 07:12:34 +00:00
$z = q ( " select max(created) as commented from item where parent_mid = '%s' and uid = %d " ,
2013-11-18 03:22:24 +00:00
dbesc ( $arr [ 'parent_mid' ]),
2013-11-18 03:49:48 +00:00
intval ( $arr [ 'uid' ])
2013-11-18 03:22:24 +00:00
);
2013-11-18 04:09:40 +00:00
q ( " UPDATE item set commented = '%s', changed = '%s' WHERE id = %d LIMIT 1 " ,
dbesc (( $z ) ? $z [ 0 ][ 'commented' ] : ( datetime_convert ())),
dbesc ( datetime_convert ()),
2011-09-16 13:49:24 +00:00
intval ( $parent_id )
);
2013-02-07 04:29:17 +00:00
send_status_notifications ( $current_post , $arr );
2012-02-10 05:18:50 +00:00
tag_deliver ( $arr [ 'uid' ], $current_post );
2013-09-11 02:06:06 +00:00
$ret [ 'success' ] = true ;
$ret [ 'item_id' ] = $current_post ;
2011-11-16 04:30:34 +00:00
2013-09-11 02:06:06 +00:00
return $ret ;
2010-07-19 03:49:10 +00:00
}
2010-09-26 23:30:21 +00:00
2013-02-07 04:29:17 +00:00
2013-03-01 02:20:42 +00:00
2013-08-11 23:56:06 +00:00
function item_store_update ( $arr , $allow_exec = false ) {
2013-03-01 02:20:42 +00:00
2013-11-29 02:10:04 +00:00
$d = array ( 'item' => $arr , 'allow_exec' => $allow_exec );
call_hooks ( 'item_store_update' , $d );
$arr = $d [ 'item' ];
$allow_exec = $d [ 'allow_exec' ];
2014-03-05 03:57:54 +00:00
$ret = array ( 'success' => false , 'item_id' => 0 );
2013-03-01 02:20:42 +00:00
if ( ! intval ( $arr [ 'uid' ])) {
logger ( 'item_store_update: no uid' );
2013-09-11 02:06:06 +00:00
$ret [ 'message' ] = 'no uid.' ;
return $ret ;
2013-03-01 02:20:42 +00:00
}
if ( ! intval ( $arr [ 'id' ])) {
logger ( 'item_store_update: no id' );
2013-09-11 02:06:06 +00:00
$ret [ 'message' ] = 'no id.' ;
return $ret ;
2013-03-01 02:20:42 +00:00
}
$orig_post_id = $arr [ 'id' ];
$uid = $arr [ 'uid' ];
2013-10-04 11:47:41 +00:00
$orig = q ( " select * from item where id = %d and uid = %d limit 1 " ,
intval ( $orig_post_id ),
intval ( $uid )
);
if ( ! $orig ) {
logger ( 'item_store_update: original post not found: ' . $orig_post_id );
$ret [ 'message' ] = 'no original' ;
return $ret ;
}
2013-10-20 06:38:07 +00:00
// override the unseen flag with the original
if ( $arr [ 'item_flags' ] & ITEM_UNSEEN )
$arr [ 'item_flags' ] = $arr [ 'item_flags' ] ^ ITEM_UNSEEN ;
2013-10-04 11:47:41 +00:00
if ( $orig [ 0 ][ 'item_flags' ] & ITEM_VERIFIED )
$orig [ 0 ][ 'item_flags' ] = $orig [ 0 ][ 'item_flags' ] ^ ITEM_VERIFIED ;
$arr [ 'item_flags' ] = intval ( $arr [ 'item_flags' ]) | $orig [ 0 ][ 'item_flags' ];
$arr [ 'item_restrict' ] = intval ( $arr [ 'item_restrict' ]) | $orig [ 0 ][ 'item_restrict' ];
2013-10-14 03:09:11 +00:00
2013-10-04 11:47:41 +00:00
if ( array_key_exists ( 'edit' , $arr ))
unset ( $arr [ 'edit' ]);
2013-08-11 23:56:06 +00:00
$arr [ 'mimetype' ] = (( x ( $arr , 'mimetype' )) ? notags ( trim ( $arr [ 'mimetype' ])) : 'text/bbcode' );
if (( $arr [ 'mimetype' ] == 'application/x-php' ) && ( ! $allow_exec )) {
logger ( 'item_store: php mimetype but allow_exec is denied.' );
2013-09-11 02:06:06 +00:00
$ret [ 'message' ] = 'exec denied.' ;
return $ret ;
2013-08-11 23:56:06 +00:00
}
2013-10-03 04:04:48 +00:00
if ( ! ( $arr [ 'item_flags' ] & ITEM_OBSCURED )) {
2013-08-11 23:56:06 +00:00
2013-10-03 04:04:48 +00:00
$arr [ 'lang' ] = detect_language ( $arr [ 'body' ]);
// apply the input filter here - if it is obscured it has been filtered already
$arr [ 'body' ] = z_input_filter ( $arr [ 'uid' ], $arr [ 'body' ], $arr [ 'mimetype' ]);
2013-03-01 02:20:42 +00:00
2013-10-03 04:04:48 +00:00
if ( local_user () && ( ! $arr [ 'sig' ])) {
$channel = get_app () -> get_channel ();
if ( $channel [ 'channel_hash' ] === $arr [ 'author_xchan' ]) {
$arr [ 'sig' ] = base64url_encode ( rsa_sign ( $arr [ 'body' ], $channel [ 'channel_prvkey' ]));
$arr [ 'item_flags' ] |= ITEM_VERIFIED ;
}
}
2013-03-01 02:20:42 +00:00
2013-10-03 04:04:48 +00:00
$allowed_languages = get_pconfig ( $arr [ 'uid' ], 'system' , 'allowed_languages' );
if (( is_array ( $allowed_languages )) && ( $arr [ 'lang' ]) && ( ! array_key_exists ( $arr [ 'lang' ], $allowed_languages ))) {
$translate = array ( 'item' => $arr , 'from' => $arr [ 'lang' ], 'to' => $allowed_languages , 'translated' => false );
call_hooks ( 'item_translate' , $translate );
if (( ! $translate [ 'translated' ]) && ( intval ( get_pconfig ( $arr [ 'uid' ], 'system' , 'reject_disallowed_languages' )))) {
logger ( 'item_store: language ' . $arr [ 'lang' ] . ' not accepted for uid ' . $arr [ 'uid' ]);
$ret [ 'message' ] = 'language not accepted' ;
return $ret ;
}
$arr = $translate [ 'item' ];
2013-08-11 23:56:06 +00:00
}
2013-10-03 04:04:48 +00:00
if ( $arr [ 'item_private' ]) {
$key = get_config ( 'system' , 'pubkey' );
$arr [ 'item_flags' ] = $arr [ 'item_flags' ] | ITEM_OBSCURED ;
if ( $arr [ 'title' ])
2013-11-20 23:20:12 +00:00
$arr [ 'title' ] = json_encode ( crypto_encapsulate ( $arr [ 'title' ], $key ));
2013-10-03 04:04:48 +00:00
if ( $arr [ 'body' ])
2013-11-20 23:20:12 +00:00
$arr [ 'body' ] = json_encode ( crypto_encapsulate ( $arr [ 'body' ], $key ));
2013-10-03 04:04:48 +00:00
}
2013-03-01 02:20:42 +00:00
2013-10-03 04:04:48 +00:00
}
2013-08-11 23:56:06 +00:00
2013-10-03 04:04:48 +00:00
if (( x ( $arr , 'object' )) && is_array ( $arr [ 'object' ])) {
activity_sanitise ( $arr [ 'object' ]);
$arr [ 'object' ] = json_encode ( $arr [ 'object' ]);
}
if (( x ( $arr , 'target' )) && is_array ( $arr [ 'target' ])) {
activity_sanitise ( $arr [ 'target' ]);
$arr [ 'target' ] = json_encode ( $arr [ 'target' ]);
}
if (( x ( $arr , 'attach' )) && is_array ( $arr [ 'attach' ])) {
activity_sanitise ( $arr [ 'attach' ]);
$arr [ 'attach' ] = json_encode ( $arr [ 'attach' ]);
2013-03-01 02:20:42 +00:00
}
2013-10-03 04:04:48 +00:00
2013-11-21 00:20:32 +00:00
unset ( $arr [ 'id' ]);
unset ( $arr [ 'uid' ]);
2013-03-01 02:20:42 +00:00
unset ( $arr [ 'aid' ]);
2013-03-22 01:25:41 +00:00
unset ( $arr [ 'mid' ]);
2013-03-01 02:20:42 +00:00
unset ( $arr [ 'parent' ]);
2013-03-22 01:25:41 +00:00
unset ( $arr [ 'parent_mid' ]);
2013-03-01 02:20:42 +00:00
unset ( $arr [ 'created' ]);
unset ( $arr [ 'author_xchan' ]);
unset ( $arr [ 'owner_xchan' ]);
unset ( $arr [ 'thr_parent' ]);
unset ( $arr [ 'llink' ]);
$arr [ 'edited' ] = (( x ( $arr , 'edited' ) !== false ) ? datetime_convert ( 'UTC' , 'UTC' , $arr [ 'edited' ]) : datetime_convert ());
$arr [ 'expires' ] = (( x ( $arr , 'expires' ) !== false ) ? datetime_convert ( 'UTC' , 'UTC' , $arr [ 'expires' ]) : $orig [ 0 ][ 'expires' ]);
2013-10-20 06:38:07 +00:00
$arr [ 'commented' ] = $orig [ 0 ][ 'commented' ];
2013-03-01 02:20:42 +00:00
$arr [ 'received' ] = datetime_convert ();
$arr [ 'changed' ] = datetime_convert ();
$arr [ 'title' ] = (( x ( $arr , 'title' )) ? notags ( trim ( $arr [ 'title' ])) : '' );
2013-10-04 11:47:41 +00:00
$arr [ 'location' ] = (( x ( $arr , 'location' )) ? notags ( trim ( $arr [ 'location' ])) : $orig [ 0 ][ 'location' ]);
$arr [ 'coord' ] = (( x ( $arr , 'coord' )) ? notags ( trim ( $arr [ 'coord' ])) : $orig [ 0 ][ 'coord' ]);
$arr [ 'verb' ] = (( x ( $arr , 'verb' )) ? notags ( trim ( $arr [ 'verb' ])) : $orig [ 0 ][ 'verb' ]);
$arr [ 'obj_type' ] = (( x ( $arr , 'obj_type' )) ? notags ( trim ( $arr [ 'obj_type' ])) : $orig [ 0 ][ 'obj_type' ]);
$arr [ 'object' ] = (( x ( $arr , 'object' )) ? trim ( $arr [ 'object' ]) : $orig [ 0 ][ 'object' ]);
$arr [ 'tgt_type' ] = (( x ( $arr , 'tgt_type' )) ? notags ( trim ( $arr [ 'tgt_type' ])) : $orig [ 0 ][ 'tgt_type' ]);
$arr [ 'target' ] = (( x ( $arr , 'target' )) ? trim ( $arr [ 'target' ]) : $orig [ 0 ][ 'target' ]);
2013-03-01 02:20:42 +00:00
$arr [ 'plink' ] = (( x ( $arr , 'plink' )) ? notags ( trim ( $arr [ 'plink' ])) : $orig [ 0 ][ 'plink' ]);
$arr [ 'allow_cid' ] = (( x ( $arr , 'allow_cid' )) ? trim ( $arr [ 'allow_cid' ]) : $orig [ 0 ][ 'allow_cid' ]);
$arr [ 'allow_gid' ] = (( x ( $arr , 'allow_gid' )) ? trim ( $arr [ 'allow_gid' ]) : $orig [ 0 ][ 'allow_gid' ]);
$arr [ 'deny_cid' ] = (( x ( $arr , 'deny_cid' )) ? trim ( $arr [ 'deny_cid' ]) : $orig [ 0 ][ 'deny_cid' ]);
$arr [ 'deny_gid' ] = (( x ( $arr , 'deny_gid' )) ? trim ( $arr [ 'deny_gid' ]) : $orig [ 0 ][ 'deny_gid' ]);
$arr [ 'item_private' ] = (( x ( $arr , 'item_private' )) ? intval ( $arr [ 'item_private' ]) : $orig [ 0 ][ 'item_private' ]);
$arr [ 'body' ] = (( x ( $arr , 'body' )) ? trim ( $arr [ 'body' ]) : '' );
2013-10-04 11:47:41 +00:00
$arr [ 'attach' ] = (( x ( $arr , 'attach' )) ? notags ( trim ( $arr [ 'attach' ])) : $orig [ 0 ][ 'attach' ]);
$arr [ 'app' ] = (( x ( $arr , 'app' )) ? notags ( trim ( $arr [ 'app' ])) : $orig [ 0 ][ 'app' ]);
// $arr['item_restrict'] = ((x($arr,'item_restrict')) ? intval($arr['item_restrict']) : $orig[0]['item_restrict'] );
// $arr['item_flags'] = ((x($arr,'item_flags')) ? intval($arr['item_flags']) : $orig[0]['item_flags'] );
2013-03-01 02:20:42 +00:00
2013-10-04 11:47:41 +00:00
$arr [ 'sig' ] = (( x ( $arr , 'sig' )) ? $arr [ 'sig' ] : '' );
$arr [ 'layout_mid' ] = (( x ( $arr , 'layout_mid' )) ? dbesc ( $arr [ 'layout_mid' ]) : $orig [ 0 ][ 'layout_mid' ] );
2013-03-01 02:20:42 +00:00
call_hooks ( 'post_remote_update' , $arr );
if ( x ( $arr , 'cancel' )) {
logger ( 'item_store_update: post cancelled by plugin.' );
2013-09-11 02:06:06 +00:00
$ret [ 'message' ] = 'cancelled.' ;
return $ret ;
2013-03-01 02:20:42 +00:00
}
// pull out all the taxonomy stuff for separate storage
$terms = null ;
if ( array_key_exists ( 'term' , $arr )) {
$terms = $arr [ 'term' ];
unset ( $arr [ 'term' ]);
}
dbesc_array ( $arr );
logger ( 'item_store_update: ' . print_r ( $arr , true ), LOGGER_DATA );
$str = '' ;
foreach ( $arr as $k => $v ) {
if ( $str )
$str .= " , " ;
$str .= " ` " . $k . " ` = ' " . $v . " ' " ;
}
$r = dbq ( " update `item` set " . $str . " where id = " . $orig_post_id . " limit 1 " );
if ( $r )
logger ( 'item_store_update: updated item ' . $orig_post_id , LOGGER_DEBUG );
else {
logger ( 'item_store_update: could not update item' );
2013-09-11 02:06:06 +00:00
$ret [ 'message' ] = 'DB update failed.' ;
return $ret ;
2013-03-01 02:20:42 +00:00
}
$r = q ( " delete from term where oid = %d and otype = %d " ,
intval ( $orig_post_id ),
intval ( TERM_OBJ_POST )
);
if (( $terms ) && ( is_array ( $terms ))) {
foreach ( $terms as $t ) {
q ( " insert into term (uid,oid,otype,type,term,url)
values ( % d , % d , % d , % d , '%s' , '%s' ) " ,
intval ( $uid ),
intval ( $orig_post_id ),
intval ( TERM_OBJ_POST ),
intval ( $t [ 'type' ]),
dbesc ( $t [ 'term' ]),
dbesc ( $t [ 'url' ])
);
}
$arr [ 'term' ] = $terms ;
}
call_hooks ( 'post_remote_update_end' , $arr );
send_status_notifications ( $orig_post_id , $arr );
tag_deliver ( $uid , $orig_post_id );
2013-09-11 02:06:06 +00:00
$ret [ 'success' ] = true ;
$ret [ 'item_id' ] = $orig_post_id ;
2013-03-01 02:20:42 +00:00
2013-09-11 02:06:06 +00:00
return $ret ;
2013-03-01 02:20:42 +00:00
}
2013-02-07 04:29:17 +00:00
function send_status_notifications ( $post_id , $item ) {
$notify = false ;
$parent = 0 ;
$r = q ( " select channel_hash from channel where channel_id = %d limit 1 " ,
intval ( $item [ 'uid' ])
);
if ( ! $r )
return ;
// my own post - no notification needed
if ( $item [ 'author_xchan' ] === $r [ 0 ][ 'channel_hash' ])
return ;
// I'm the owner - notify me
if ( $item [ 'owner_hash' ] === $r [ 0 ][ 'channel_hash' ])
$notify = true ;
// Was I involved in this conversation?
2013-03-22 01:25:41 +00:00
$x = q ( " select * from item where parent_mid = '%s' and uid = %d " ,
dbesc ( $item [ 'parent_mid' ]),
2013-02-07 04:29:17 +00:00
intval ( $item [ 'uid' ])
);
if ( $x ) {
foreach ( $x as $xx ) {
if ( $xx [ 'author_xchan' ] === $r [ 0 ][ 'channel_hash' ]) {
$notify = true ;
2013-02-15 04:17:30 +00:00
}
if ( $xx [ 'id' ] == $xx [ 'parent' ]) {
$parent = $xx [ 'parent' ];
2013-02-07 04:29:17 +00:00
}
}
}
2014-02-05 23:01:53 +00:00
$link = get_app () -> get_baseurl () . '/display/' . $item [ 'mid' ];
2014-02-06 21:32:29 +00:00
$y = q ( " select id from notify where link = '%s' and uid = %d limit 1 " ,
2014-02-05 23:01:53 +00:00
dbesc ( $link ),
intval ( $item [ 'uid' ])
);
2014-02-06 21:32:29 +00:00
if ( $y )
2014-02-05 23:01:53 +00:00
$notify = false ;
2013-02-07 04:29:17 +00:00
if ( ! $notify )
return ;
require_once ( 'include/enotify.php' );
notification ( array (
'type' => NOTIFY_COMMENT ,
'from_xchan' => $item [ 'author_xchan' ],
'to_xchan' => $r [ 0 ][ 'channel_hash' ],
'item' => $item ,
2014-02-05 23:01:53 +00:00
'link' => $link ,
2013-02-07 04:29:17 +00:00
'verb' => ACTIVITY_POST ,
'otype' => 'item' ,
'parent' => $parent ,
2013-03-22 01:25:41 +00:00
'parent_mid' => $item [ 'parent_mid' ]
2013-02-07 04:29:17 +00:00
));
return ;
}
2010-09-26 23:30:21 +00:00
function get_item_contact ( $item , $contacts ) {
if ( ! count ( $contacts ) || ( ! is_array ( $item )))
return false ;
foreach ( $contacts as $contact ) {
if ( $contact [ 'id' ] == $item [ 'contact-id' ]) {
return $contact ;
break ; // NOTREACHED
}
}
return false ;
}
2012-02-10 05:18:50 +00:00
function tag_deliver ( $uid , $item_id ) {
2011-11-16 04:30:34 +00:00
2013-06-05 05:52:17 +00:00
// Called when we deliver things that might be tagged in ways that require delivery processing.
// Handles community tagging of posts and also look for mention tags
// and sets up a second delivery chain if appropriate
2011-11-19 06:20:08 +00:00
2011-11-16 04:30:34 +00:00
$a = get_app ();
2012-02-10 05:18:50 +00:00
$mention = false ;
2011-11-16 04:30:34 +00:00
2012-10-08 07:23:43 +00:00
$u = q ( " select * from channel where channel_id = %d limit 1 " ,
2012-02-10 05:18:50 +00:00
intval ( $uid )
2011-11-16 04:30:34 +00:00
);
2013-02-11 08:20:14 +00:00
if ( ! $u )
2011-11-16 04:30:34 +00:00
return ;
2012-10-08 07:23:43 +00:00
2011-11-19 11:13:46 +00:00
$i = q ( " select * from item where id = %d and uid = %d limit 1 " ,
2011-11-16 04:30:34 +00:00
intval ( $item_id ),
intval ( $uid )
);
2013-06-05 05:52:17 +00:00
if ( ! $i )
2011-11-16 04:30:34 +00:00
return ;
2013-01-13 02:06:34 +00:00
$i = fetch_post_tags ( $i );
2011-11-16 04:30:34 +00:00
$item = $i [ 0 ];
2014-02-05 00:06:56 +00:00
$terms = get_terms_oftype ( $item [ 'term' ], TERM_BOOKMARK );
2014-02-06 00:01:02 +00:00
if ( $terms && ( ! $item [ 'item_restrict' ])) {
2014-02-05 00:06:56 +00:00
logger ( 'tag_deliver: found bookmark' );
2014-02-05 23:56:18 +00:00
$bookmark_self = intval ( get_pconfig ( $uid , 'system' , 'bookmark_self' ));
2014-02-06 00:01:02 +00:00
if ( perm_is_allowed ( $u [ 0 ][ 'channel_id' ], $item [ 'author_xchan' ], 'bookmark' ) && (( $item [ 'author_xchan' ] != $u [ 0 ][ 'channel_hash' ]) || ( $bookmark_self ))) {
2014-02-05 00:06:56 +00:00
require_once ( 'include/bookmarks.php' );
require_once ( 'include/Contact.php' );
2014-02-05 23:56:18 +00:00
$s = q ( " select * from xchan where xchan_hash = '%s' limit 1 " ,
dbesc ( $item [ 'author_xchan' ])
);
if ( $s ) {
foreach ( $terms as $t ) {
2014-02-06 00:01:02 +00:00
bookmark_add ( $u [ 0 ], $s [ 0 ], $t , $item [ 'item_private' ]);
2014-02-05 23:56:18 +00:00
}
2014-02-05 00:06:56 +00:00
}
}
}
2013-12-20 04:23:19 +00:00
if (( $item [ 'source_xchan' ]) && ( $item [ 'item_flags' ] & ITEM_UPLINK ) && ( $item [ 'item_flags' ] & ITEM_THREAD_TOP ) && ( $item [ 'edited' ] != $item [ 'created' ])) {
// this is an update to a post which was already processed by us and has a second delivery chain
// Just start the second delivery chain to deliver the updated post
proc_run ( 'php' , 'include/notifier.php' , 'tgroup' , $item [ 'id' ]);
return ;
}
2013-06-05 05:52:17 +00:00
if ( $item [ 'obj_type' ] === ACTIVITY_OBJ_TAGTERM ) {
// We received a community tag activity for a post.
// See if we are the owner of the parent item and have given permission to tag our posts.
// If so tag the parent post.
2013-06-21 04:19:22 +00:00
logger ( 'tag_deliver: community tag activity received' );
2013-06-05 05:52:17 +00:00
if (( $item [ 'owner_xchan' ] === $u [ 0 ][ 'channel_hash' ]) && ( ! get_pconfig ( $u [ 0 ][ 'channel_id' ], 'system' , 'blocktags' ))) {
2013-08-06 10:54:49 +00:00
$j_tgt = json_decode_plus ( $item [ 'target' ]);
2013-06-21 04:19:22 +00:00
if ( $j_tgt && $j_tgt [ 'id' ]) {
2013-06-05 05:52:17 +00:00
$p = q ( " select * from item where mid = '%s' and uid = %d limit 1 " ,
2013-06-21 04:19:22 +00:00
dbesc ( $j_tgt [ 'id' ]),
2013-06-05 05:52:17 +00:00
intval ( $u [ 0 ][ 'channel_id' ])
);
if ( $p ) {
2013-08-06 10:54:49 +00:00
$j_obj = json_decode_plus ( $item [ 'object' ]);
2013-06-21 04:19:22 +00:00
logger ( 'tag_deliver: tag object: ' . print_r ( $j_obj , true ), LOGGER_DATA );
2013-06-05 05:52:17 +00:00
if ( $j_obj && $j_obj [ 'id' ] && $j_obj [ 'title' ]) {
2013-07-01 06:04:27 +00:00
if ( is_array ( $j_obj [ 'link' ]))
$taglink = get_rel_link ( $j_obj [ 'link' ], 'alternate' );
store_item_tag ( $u [ 0 ][ 'channel_id' ], $p [ 0 ][ 'id' ], TERM_OBJ_POST , TERM_HASHTAG , $j_obj [ 'title' ], $j_obj [ 'id' ]);
2014-02-17 00:04:46 +00:00
$x = q ( " update item set edited = '%s', received = '%s', changed = '%s' where mid = '%s' and uid = %d limit 1 " ,
dbesc ( datetime_convert ()),
dbesc ( datetime_convert ()),
dbesc ( datetime_convert ()),
dbesc ( $j_tgt [ 'id' ]),
intval ( $u [ 0 ][ 'channel_id' ])
);
2013-06-05 05:52:17 +00:00
proc_run ( 'php' , 'include/notifier.php' , 'edit_post' , $p [ 0 ][ 'id' ]);
}
}
}
}
2013-06-21 04:19:22 +00:00
else
logger ( 'tag_deliver: tag permission denied for ' . $u [ 0 ][ 'channel_address' ]);
2013-06-05 05:52:17 +00:00
}
2013-09-27 02:34:45 +00:00
$union = check_item_source ( $uid , $item );
if ( $union )
logger ( 'check_item_source returns true' );
2014-02-13 22:20:23 +00:00
// This might be a followup (e.g. comment) by the original post author to a tagged forum
2013-06-29 09:04:44 +00:00
// If so setup a second delivery chain
$r = null ;
if ( ! ( $item [ 'item_flags' ] & ITEM_THREAD_TOP )) {
$x = q ( " select * from item where id = parent and parent = %d and uid = %d limit 1 " ,
intval ( $item [ 'parent' ]),
intval ( $uid )
);
2013-09-05 06:15:53 +00:00
2013-10-14 01:36:28 +00:00
2013-09-05 06:15:53 +00:00
if (( $x ) && ( $x [ 0 ][ 'item_flags' ] & ITEM_UPLINK )) {
2013-10-14 01:36:28 +00:00
2013-09-05 06:15:53 +00:00
logger ( 'tag_deliver: creating second delivery chain for comment to tagged post.' );
2013-06-29 09:04:44 +00:00
// now change this copy of the post to a forum head message and deliver to all the tgroup members
// also reset all the privacy bits to the forum default permissions
2014-02-13 22:20:23 +00:00
$private = (( $u [ 0 ][ 'channel_allow_cid' ] || $u [ 0 ][ 'channel_allow_gid' ] || $u [ 0 ][ 'channel_deny_cid' ] || $u [ 0 ][ 'channel_deny_gid' ]) ? 1 : 0 );
2013-06-29 09:04:44 +00:00
$flag_bits = ITEM_WALL | ITEM_ORIGIN ;
2013-10-14 01:36:28 +00:00
// maintain the original source, which will be the original item owner and was stored in source_xchan
// when we created the delivery fork
$r = q ( " update item set source_xchan = '%s' where id = %d limit 1 " ,
dbesc ( $x [ 0 ][ 'source_xchan' ]),
intval ( $item_id )
);
2013-06-29 09:04:44 +00:00
$r = q ( " update item set item_flags = ( item_flags | %d ), owner_xchan = '%s', allow_cid = '%s', allow_gid = '%s',
deny_cid = '%s' , deny_gid = '%s' , item_private = % d where id = % d limit 1 " ,
intval ( $flag_bits ),
dbesc ( $u [ 0 ][ 'channel_hash' ]),
2014-02-13 22:20:23 +00:00
dbesc ( $u [ 0 ][ 'channel_allow_cid' ]),
dbesc ( $u [ 0 ][ 'channel_allow_gid' ]),
dbesc ( $u [ 0 ][ 'channel_deny_cid' ]),
dbesc ( $u [ 0 ][ 'channel_deny_gid' ]),
2013-06-29 09:04:44 +00:00
intval ( $private ),
intval ( $item_id )
);
if ( $r )
proc_run ( 'php' , 'include/notifier.php' , 'tgroup' , $item_id );
else
logger ( 'tag_deliver: failed to update item' );
}
}
2013-01-13 02:06:34 +00:00
$terms = get_terms_oftype ( $item [ 'term' ], TERM_MENTION );
2013-06-29 09:04:44 +00:00
if ( $terms )
logger ( 'tag_deliver: post mentions: ' . print_r ( $terms , true ), LOGGER_DATA );
2013-01-13 02:06:34 +00:00
2013-02-11 07:19:52 +00:00
$link = normalise_link ( $a -> get_baseurl () . '/channel/' . $u [ 0 ][ 'channel_address' ]);
2011-11-16 04:30:34 +00:00
2013-01-13 02:06:34 +00:00
if ( $terms ) {
foreach ( $terms as $term ) {
2014-01-15 11:12:47 +00:00
if (( strcasecmp ( $term [ 'term' ], $u [ 0 ][ 'channel_name' ]) == 0 ) && link_compare ( $term [ 'url' ], $link )) {
2012-02-10 05:18:50 +00:00
$mention = true ;
2013-01-13 02:06:34 +00:00
break ;
2011-11-16 04:30:34 +00:00
}
}
2013-01-13 02:06:34 +00:00
}
2011-11-16 04:30:34 +00:00
2013-01-13 02:06:34 +00:00
if ( $mention ) {
2013-02-11 07:19:52 +00:00
logger ( 'tag_deliver: mention found for ' . $u [ 0 ][ 'channel_name' ]);
2013-01-13 02:06:34 +00:00
$r = q ( " update item set item_flags = ( item_flags | %d ) where id = %d limit 1 " ,
intval ( ITEM_MENTIONSME ),
intval ( $item_id )
);
2011-11-16 04:30:34 +00:00
2013-11-05 00:44:23 +00:00
2013-09-27 02:34:45 +00:00
// At this point we've determined that the person receiving this post was mentioned in it or it is a union.
// Now let's check if this mention was inside a reshare so we don't spam a forum
2013-11-05 00:44:23 +00:00
// If it's private we may have to unobscure it momentarily so that we can parse it.
$body = '' ;
if ( $item [ 'item_flags' ] & ITEM_OBSCURED ) {
$key = get_config ( 'system' , 'prvkey' );
if ( $item [ 'body' ])
2013-11-20 23:20:12 +00:00
$body = crypto_unencapsulate ( json_decode_plus ( $item [ 'body' ]), $key );
2013-11-05 00:44:23 +00:00
}
else
$body = $item [ 'body' ];
2013-01-13 02:35:27 +00:00
2013-11-05 00:44:23 +00:00
$body = preg_replace ( '/\[share(.*?)\[\/share\]/' , '' , $body );
2013-01-13 02:35:27 +00:00
2013-12-30 03:45:54 +00:00
$pattern = '/@\!?\[zrl\=' . preg_quote ( $term [ 'url' ], '/' ) . '\]' . preg_quote ( $u [ 0 ][ 'channel_name' ], '/' ) . '\[\/zrl\]/' ;
2013-02-11 23:51:43 +00:00
2013-09-27 02:34:45 +00:00
if ( ! preg_match ( $pattern , $body , $matches )) {
logger ( 'tag_deliver: mention was in a reshare - ignoring' );
return ;
}
2013-01-13 02:35:27 +00:00
2013-09-27 02:34:45 +00:00
// All good.
// Send a notification
2012-05-18 05:44:52 +00:00
2013-09-27 02:34:45 +00:00
require_once ( 'include/enotify.php' );
notification ( array (
'to_xchan' => $u [ 0 ][ 'channel_hash' ],
'from_xchan' => $item [ 'author_xchan' ],
'type' => NOTIFY_TAGSELF ,
'item' => $item ,
'link' => $i [ 0 ][ 'llink' ],
'verb' => ACTIVITY_TAG ,
'otype' => 'item'
));
2012-05-18 02:35:24 +00:00
2013-01-13 02:06:34 +00:00
2013-09-27 02:34:45 +00:00
if ( ! perm_is_allowed ( $uid , $item [ 'author_xchan' ], 'tag_deliver' )) {
logger ( 'tag_delivery denied for uid ' . $uid . ' and xchan ' . $item [ 'author_xchan' ]);
return ;
}
2013-08-06 04:42:55 +00:00
}
2012-05-18 02:35:24 +00:00
2014-01-15 11:12:47 +00:00
if (( ! $mention ) && ( ! $union )) {
logger ( 'tag_deliver: no mention and no union.' );
2013-09-27 02:34:45 +00:00
return ;
2014-01-15 11:12:47 +00:00
}
2013-09-27 02:34:45 +00:00
2011-11-19 06:20:08 +00:00
2012-02-10 08:08:23 +00:00
// tgroup delivery - setup a second delivery chain
// prevent delivery looping - only proceed
// if the message originated elsewhere and is a top-level post
2011-11-19 06:20:08 +00:00
2013-08-06 04:42:55 +00:00
if (( $item [ 'item_flags' ] & ITEM_WALL ) || ( $item [ 'item_flags' ] & ITEM_ORIGIN ) || ( ! ( $item [ 'item_flags' ] & ITEM_THREAD_TOP )) || ( $item [ 'id' ] != $item [ 'parent' ])) {
logger ( 'tag_deliver: item was local or a comment. rejected.' );
2013-01-14 02:35:12 +00:00
return ;
2013-08-06 04:42:55 +00:00
}
2011-11-16 04:30:34 +00:00
2013-02-12 00:59:48 +00:00
logger ( 'tag_deliver: creating second delivery chain.' );
2012-02-17 02:29:09 +00:00
2013-01-14 02:35:12 +00:00
// now change this copy of the post to a forum head message and deliver to all the tgroup members
2012-05-07 06:06:21 +00:00
// also reset all the privacy bits to the forum default permissions
2014-02-13 22:20:23 +00:00
$private = (( $u [ 0 ][ 'channel_allow_cid' ] || $u [ 0 ][ 'channel_allow_gid' ] || $u [ 0 ][ 'channel_deny_cid' ] || $u [ 0 ][ 'channel_deny_gid' ]) ? 1 : 0 );
2012-05-07 06:06:21 +00:00
2013-01-14 02:35:12 +00:00
$flag_bits = ITEM_WALL | ITEM_ORIGIN | ITEM_UPLINK ;
2013-10-14 01:36:28 +00:00
// preserve the source
$r = q ( " update item set source_xchan = owner_xchan where id = %d limit 1 " ,
intval ( $item_id )
);
2013-02-12 01:03:06 +00:00
$r = q ( " update item set item_flags = ( item_flags | %d ), owner_xchan = '%s', allow_cid = '%s', allow_gid = '%s',
2013-01-20 06:21:00 +00:00
deny_cid = '%s' , deny_gid = '%s' , item_private = % d where id = % d limit 1 " ,
2013-01-14 02:35:12 +00:00
intval ( $flag_bits ),
dbesc ( $u [ 0 ][ 'channel_hash' ]),
2014-02-13 22:20:23 +00:00
dbesc ( $u [ 0 ][ 'channel_allow_cid' ]),
dbesc ( $u [ 0 ][ 'channel_allow_gid' ]),
dbesc ( $u [ 0 ][ 'channel_deny_cid' ]),
dbesc ( $u [ 0 ][ 'channel_deny_gid' ]),
2013-01-20 06:21:00 +00:00
intval ( $private ),
2013-01-14 02:35:12 +00:00
intval ( $item_id )
);
if ( $r )
proc_run ( 'php' , 'include/notifier.php' , 'tgroup' , $item_id );
else
logger ( 'tag_deliver: failed to update item' );
2012-02-10 08:08:23 +00:00
2011-11-16 04:30:34 +00:00
}
2012-09-21 00:04:22 +00:00
function tgroup_check ( $uid , $item ) {
$a = get_app ();
$mention = false ;
// check that the message originated elsewhere and is a top-level post
2013-12-17 02:07:41 +00:00
// or is a followup and we have already accepted the top level post as an uplink
2012-09-21 00:04:22 +00:00
2013-08-02 04:24:55 +00:00
if ( $item [ 'mid' ] != $item [ 'parent_mid' ]) {
2013-12-17 02:07:41 +00:00
$r = q ( " select id from item where mid = '%s' and uid = %d and ( item_flags & %d ) limit 1 " ,
2013-08-02 04:24:55 +00:00
dbesc ( $item [ 'parent_mid' ]),
2013-12-17 02:07:41 +00:00
intval ( $uid ),
intval ( ITEM_UPLINK )
2013-07-29 23:51:44 +00:00
);
if ( $r )
return true ;
2012-09-21 00:04:22 +00:00
return false ;
2013-07-29 23:51:44 +00:00
}
2013-06-16 07:57:39 +00:00
if ( ! perm_is_allowed ( $uid , $item [ 'author_xchan' ], 'tag_deliver' ))
return false ;
2012-09-21 00:04:22 +00:00
2013-06-16 07:57:39 +00:00
$u = q ( " select * from channel where channel_id = %d limit 1 " ,
2012-09-21 00:04:22 +00:00
intval ( $uid )
);
2013-06-16 07:57:39 +00:00
if ( ! $u )
return false ;
2012-09-21 00:04:22 +00:00
2013-06-16 07:57:39 +00:00
$terms = get_terms_oftype ( $item [ 'term' ], TERM_MENTION );
2012-09-21 00:04:22 +00:00
2013-07-16 02:04:23 +00:00
if ( $terms )
logger ( 'tgroup_check: post mentions: ' . print_r ( $terms , true ), LOGGER_DATA );
2012-09-21 00:04:22 +00:00
2013-06-16 07:57:39 +00:00
$link = normalise_link ( $a -> get_baseurl () . '/channel/' . $u [ 0 ][ 'channel_address' ]);
2012-09-21 00:04:22 +00:00
2013-06-16 07:57:39 +00:00
if ( $terms ) {
foreach ( $terms as $term ) {
if (( $term [ 'term' ] == $u [ 0 ][ 'channel_name' ]) && link_compare ( $term [ 'url' ], $link )) {
2012-09-21 00:04:22 +00:00
$mention = true ;
2013-06-16 07:57:39 +00:00
break ;
2012-09-21 00:04:22 +00:00
}
}
2013-06-16 07:57:39 +00:00
}
2012-09-21 00:04:22 +00:00
2013-06-16 07:57:39 +00:00
if ( $mention ) {
logger ( 'tgroup_check: mention found for ' . $u [ 0 ][ 'channel_name' ]);
}
else
2012-09-21 00:04:22 +00:00
return false ;
2013-06-16 07:57:39 +00:00
// At this point we've determined that the person receiving this post was mentioned in it.
// Now let's check if this mention was inside a reshare so we don't spam a forum
2012-09-21 00:04:22 +00:00
2013-06-16 07:57:39 +00:00
$body = preg_replace ( '/\[share(.*?)\[\/share\]/' , '' , $item [ 'body' ]);
2013-12-30 03:45:54 +00:00
$pattern = '/@\!?\[zrl\=' . preg_quote ( $term [ 'url' ], '/' ) . '\]' . preg_quote ( $u [ 0 ][ 'channel_name' ], '/' ) . '\[\/zrl\]/' ;
2013-06-16 07:57:39 +00:00
if ( ! preg_match ( $pattern , $body , $matches )) {
logger ( 'tgroup_check: mention was in a reshare - ignoring' );
return false ;
}
2012-09-21 00:04:22 +00:00
return true ;
}
2013-09-27 02:34:45 +00:00
/**
* @ function check_item_source ( $uid , $item )
* @ param $uid
* @ param $item
*
* @ description
* Checks to see if this item owner is referenced as a source for this channel and if the post
* matches the rules for inclusion in this channel . Returns true if we should create a second delivery
* chain and false if none of the rules apply , or if the item is private .
*/
function check_item_source ( $uid , $item ) {
if ( $item [ 'item_private' ])
return false ;
2014-02-01 04:02:59 +00:00
$r = q ( " select * from source where src_channel_id = %d and ( src_xchan = '%s' || src_xchan = '*' ) limit 1 " ,
2013-09-27 02:34:45 +00:00
intval ( $uid ),
2013-12-20 04:23:19 +00:00
dbesc (( $item [ 'source_xchan' ]) ? $item [ 'source_xchan' ] : $item [ 'owner_xchan' ])
2013-09-27 02:34:45 +00:00
);
if ( ! $r )
return false ;
2013-10-01 04:49:26 +00:00
$x = q ( " select abook_their_perms from abook where abook_channel = %d and abook_xchan = '%s' limit 1 " ,
intval ( $uid ),
dbesc ( $item [ 'owner_xchan' ])
);
if ( ! $x )
return false ;
if ( ! ( $x [ 0 ][ 'abook_their_perms' ] & PERMS_A_REPUBLISH ))
return false ;
2013-09-27 02:34:45 +00:00
if ( $r [ 0 ][ 'src_channel_xchan' ] === $item [ 'owner_xchan' ])
return false ;
if ( ! $r [ 0 ][ 'src_patt' ])
return true ;
2013-09-27 02:58:24 +00:00
require_once ( 'include/html2plain.php' );
$text = prepare_text ( $item [ 'body' ], $item [ 'mimetype' ]);
$text = html2plain ( $text );
2013-09-27 02:34:45 +00:00
$tags = (( count ( $items [ 'term' ])) ? $items [ 'term' ] : false );
$words = explode ( " \n " , $r [ 0 ][ 'src_patt' ]);
if ( $words ) {
foreach ( $words as $word ) {
if ( substr ( $word , 0 , 1 ) === '#' && $tags ) {
foreach ( $tags as $t )
2014-02-01 04:02:59 +00:00
if (( $t [ 'type' ] == TERM_HASHTAG ) && (( substr ( $t , 1 ) === substr ( $word , 1 )) || ( substr ( $word , 1 ) === '*' )))
2013-09-27 02:34:45 +00:00
return true ;
}
2013-09-27 02:58:24 +00:00
if ( stristr ( $text , $word ) !== false )
2013-09-27 02:34:45 +00:00
return true ;
}
}
return false ;
}
2012-12-06 00:44:07 +00:00
function mail_store ( $arr ) {
if ( ! $arr [ 'channel_id' ]) {
logger ( 'mail_store: no uid' );
return 0 ;
}
if (( strpos ( $arr [ 'body' ], '<' ) !== false ) || ( strpos ( $arr [ 'body' ], '>' ) !== false ))
$arr [ 'body' ] = escape_tags ( $arr [ 'body' ]);
2013-08-20 04:19:39 +00:00
if ( array_key_exists ( 'attach' , $arr ) && is_array ( $arr [ 'attach' ]))
$arr [ 'attach' ] = json_encode ( $arr [ 'attach' ]);
2012-12-06 00:44:07 +00:00
$arr [ 'account_id' ] = (( x ( $arr , 'account_id' )) ? intval ( $arr [ 'account_id' ]) : 0 );
2013-03-22 01:25:41 +00:00
$arr [ 'mid' ] = (( x ( $arr , 'mid' )) ? notags ( trim ( $arr [ 'mid' ])) : random_string ());
2012-12-06 00:44:07 +00:00
$arr [ 'from_xchan' ] = (( x ( $arr , 'from_xchan' )) ? notags ( trim ( $arr [ 'from_xchan' ])) : '' );
$arr [ 'to_xchan' ] = (( x ( $arr , 'to_xchan' )) ? notags ( trim ( $arr [ 'to_xchan' ])) : '' );
$arr [ 'created' ] = (( x ( $arr , 'created' ) !== false ) ? datetime_convert ( 'UTC' , 'UTC' , $arr [ 'created' ]) : datetime_convert ());
2013-11-07 02:28:36 +00:00
$arr [ 'expires' ] = (( x ( $arr , 'expires' ) !== false ) ? datetime_convert ( 'UTC' , 'UTC' , $arr [ 'expires' ]) : '0000-00-00 00:00:00' );
2012-12-06 00:44:07 +00:00
$arr [ 'title' ] = (( x ( $arr , 'title' )) ? notags ( trim ( $arr [ 'title' ])) : '' );
2013-03-22 01:25:41 +00:00
$arr [ 'parent_mid' ] = (( x ( $arr , 'parent_mid' )) ? notags ( trim ( $arr [ 'parent_mid' ])) : '' );
2012-12-06 00:44:07 +00:00
$arr [ 'body' ] = (( x ( $arr , 'body' )) ? trim ( $arr [ 'body' ]) : '' );
2013-08-20 04:19:39 +00:00
2012-12-06 00:44:07 +00:00
$arr [ 'mail_flags' ] = (( x ( $arr , 'mail_flags' )) ? intval ( $arr [ 'mail_flags' ]) : 0 );
2012-12-06 01:11:38 +00:00
2013-03-22 01:25:41 +00:00
if ( ! $arr [ 'parent_mid' ]) {
2012-12-06 01:11:38 +00:00
logger ( 'mail_store: missing parent' );
2013-03-22 01:25:41 +00:00
$arr [ 'parent_mid' ] = $arr [ 'mid' ];
2012-12-06 01:11:38 +00:00
}
2013-03-22 01:25:41 +00:00
$r = q ( " SELECT `id` FROM mail WHERE `mid` = '%s' AND channel_id = %d LIMIT 1 " ,
dbesc ( $arr [ 'mid' ]),
2012-12-06 00:44:07 +00:00
intval ( $arr [ 'channel_id' ])
);
if ( $r ) {
logger ( 'mail_store: duplicate item ignored. ' . print_r ( $arr , true ));
return 0 ;
}
call_hooks ( 'post_mail' , $arr );
if ( x ( $arr , 'cancel' )) {
logger ( 'mail_store: post cancelled by plugin.' );
return 0 ;
}
dbesc_array ( $arr );
logger ( 'mail_store: ' . print_r ( $arr , true ), LOGGER_DATA );
$r = dbq ( " INSERT INTO mail (` "
. implode ( " `, ` " , array_keys ( $arr ))
. " `) VALUES (' "
. implode ( " ', ' " , array_values ( $arr ))
. " ') " );
// find the item we just created
2013-03-22 01:25:41 +00:00
$r = q ( " SELECT `id` FROM mail WHERE `mid` = '%s' AND `channel_id` = %d ORDER BY `id` ASC " ,
$arr [ 'mid' ], // already dbesc'd
2012-12-06 00:44:07 +00:00
intval ( $arr [ 'channel_id' ])
);
if ( $r ) {
$current_post = $r [ 0 ][ 'id' ];
logger ( 'mail_store: created item ' . $current_post , LOGGER_DEBUG );
2013-01-06 02:08:06 +00:00
$arr [ 'id' ] = $current_post ; // for notification
2012-12-06 00:44:07 +00:00
}
else {
logger ( 'mail_store: could not locate created item' );
return 0 ;
}
if ( count ( $r ) > 1 ) {
logger ( 'mail_store: duplicated post occurred. Removing duplicates.' );
2013-03-22 01:25:41 +00:00
q ( " DELETE FROM mail WHERE `mid` = '%s' AND `channel_id` = %d AND `id` != %d " ,
$arr [ 'mid' ],
2012-12-06 00:44:07 +00:00
intval ( $arr [ 'channel_id' ]),
intval ( $current_post )
);
}
2013-01-06 02:08:06 +00:00
else {
require_once ( 'include/enotify.php' );
$notif_params = array (
'from_xchan' => $arr [ 'from_xchan' ],
'to_xchan' => $arr [ 'to_xchan' ],
'type' => NOTIFY_MAIL ,
'item' => $arr ,
'verb' => ACTIVITY_POST ,
'otype' => 'mail'
);
notification ( $notif_params );
}
2012-12-06 00:44:07 +00:00
call_hooks ( 'post_mail_end' , $arr );
return $current_post ;
}
2012-09-21 00:04:22 +00:00
2011-02-08 05:16:39 +00:00
/**
2010-10-22 04:48:22 +00:00
*
* consume_feed - process atom feed and update anything / everything we might need to update
*
2011-02-08 05:16:39 +00:00
* $xml = the ( atom ) feed to consume - RSS isn ' t as fully supported but may work for simple feeds .
*
2010-10-22 04:48:22 +00:00
* $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 .
* $contact = the person who is sending us stuff . If not set , we MAY be processing a " follow " activity
* from an external network and MAY create an appropriate contact record . Otherwise , we MUST
* have a contact record .
2010-12-01 21:39:00 +00:00
* $hub = should we find a hub declation in the feed , pass it back to our calling process , who might ( or
2010-10-22 04:48:22 +00:00
* might not ) try and subscribe to it .
2011-10-04 11:38:58 +00:00
* $datedir sorts in reverse order
* $pass - by default ( $pass = 0 ) we cannot guarantee that a parent item has been
* imported prior to its children being seen in the stream unless we are certain
* of how the feed is arranged / ordered .
* With $pass = 1 , we only pull parent items out of the stream .
* With $pass = 2 , we only pull children ( comments / likes ) .
2010-10-22 04:48:22 +00:00
*
2011-10-04 11:38:58 +00:00
* So running this twice , first with pass 1 and then with pass 2 will do the right
* thing regardless of feed ordering . This won ' t be adequate in a fully - threaded
* model where comments can have sub - threads . That would require some massive sorting
* to get all the feed items into a mostly linear ordering , and might still require
* recursion .
2010-10-22 04:48:22 +00:00
*/
2011-10-04 10:06:34 +00:00
function consume_feed ( $xml , $importer , & $contact , & $hub , $datedir = 0 , $pass = 0 ) {
2010-10-01 02:41:22 +00:00
2011-06-29 04:11:52 +00:00
require_once ( 'library/simplepie/simplepie.inc' );
2010-10-01 02:41:22 +00:00
2011-08-04 04:05:39 +00:00
if ( ! strlen ( $xml )) {
logger ( 'consume_feed: empty input' );
return ;
}
2013-09-30 03:34:05 +00:00
// Want to see this work as a content source for the matrix?
// Read this: https://github.com/friendica/red/wiki/Service_Federation
2011-08-04 04:05:39 +00:00
2010-10-01 02:41:22 +00:00
$feed = new SimplePie ();
$feed -> set_raw_data ( $xml );
2010-11-08 09:11:50 +00:00
if ( $datedir )
$feed -> enable_order_by_date ( true );
else
$feed -> enable_order_by_date ( false );
2010-10-01 02:41:22 +00:00
$feed -> init ();
2011-01-31 03:38:03 +00:00
if ( $feed -> error ())
logger ( 'consume_feed: Error parsing XML: ' . $feed -> error ());
2011-04-05 02:36:18 +00:00
$permalink = $feed -> get_permalink ();
2011-01-31 03:38:03 +00:00
2010-10-01 02:41:22 +00:00
// Check at the feed level for updated contact name and/or photo
2011-01-07 22:31:05 +00:00
2011-02-08 12:25:27 +00:00
// process any deleted entries
2010-10-01 02:41:22 +00:00
2011-02-08 12:25:27 +00:00
$del_entries = $feed -> get_feed_tags ( NAMESPACE_TOMB , 'deleted-entry' );
2011-10-04 10:06:34 +00:00
if ( is_array ( $del_entries ) && count ( $del_entries ) && $pass != 2 ) {
2011-02-08 12:25:27 +00:00
foreach ( $del_entries as $dentry ) {
2010-10-01 02:41:22 +00:00
$deleted = false ;
2011-02-08 12:25:27 +00:00
if ( isset ( $dentry [ 'attribs' ][ '' ][ 'ref' ])) {
2013-03-22 01:25:41 +00:00
$mid = $dentry [ 'attribs' ][ '' ][ 'ref' ];
2010-10-01 02:41:22 +00:00
$deleted = true ;
2011-02-08 12:25:27 +00:00
if ( isset ( $dentry [ 'attribs' ][ '' ][ 'when' ])) {
$when = $dentry [ 'attribs' ][ '' ][ 'when' ];
2010-10-01 02:41:22 +00:00
$when = datetime_convert ( 'UTC' , 'UTC' , $when , 'Y-m-d H:i:s' );
}
else
$when = datetime_convert ( 'UTC' , 'UTC' , 'now' , 'Y-m-d H:i:s' );
}
2010-10-22 04:48:22 +00:00
if ( $deleted && is_array ( $contact )) {
2013-08-07 10:54:47 +00:00
/* $r = q ( " SELECT `item`.*, `contact`.`self` FROM `item` left join `contact` on `item`.`contact-id` = `contact`.`id`
2013-03-22 01:25:41 +00:00
WHERE `mid` = '%s' AND `item` . `uid` = % d AND `contact-id` = % d AND NOT `item` . `file` LIKE '%%[%%' LIMIT 1 " ,
dbesc ( $mid ),
2013-09-30 03:34:05 +00:00
intval ( $importer [ 'channel_id' ]),
2010-10-22 04:48:22 +00:00
intval ( $contact [ 'id' ])
2010-10-01 02:41:22 +00:00
);
2013-08-07 10:54:47 +00:00
*/
2010-10-01 02:41:22 +00:00
if ( count ( $r )) {
$item = $r [ 0 ];
2011-02-08 12:25:27 +00:00
if ( ! $item [ 'deleted' ])
2013-03-22 01:25:41 +00:00
logger ( 'consume_feed: deleting item ' . $item [ 'id' ] . ' mid=' . $item [ 'mid' ], LOGGER_DEBUG );
2011-02-08 12:25:27 +00:00
2013-03-22 01:25:41 +00:00
if ( $item [ 'mid' ] == $item [ 'parent_mid' ]) {
2013-08-07 10:54:47 +00:00
$r = q ( " UPDATE `item` SET item_restrict = (item_restrict | %d), `edited` = '%s', `changed` = '%s',
2010-10-01 02:41:22 +00:00
`body` = '' , `title` = ''
2013-03-22 01:25:41 +00:00
WHERE `parent_mid` = '%s' AND `uid` = % d " ,
2013-08-07 10:54:47 +00:00
intval ( ITEM_DELETED ),
2010-10-01 02:41:22 +00:00
dbesc ( $when ),
dbesc ( datetime_convert ()),
2013-03-22 01:25:41 +00:00
dbesc ( $item [ 'mid' ]),
2013-09-30 03:34:05 +00:00
intval ( $importer [ 'channel_id' ])
2010-10-01 02:41:22 +00:00
);
}
else {
2013-08-07 10:54:47 +00:00
$r = q ( " UPDATE `item` SET item_restrict = ( item_restrict | %d ), `edited` = '%s', `changed` = '%s',
2010-10-01 02:41:22 +00:00
`body` = '' , `title` = ''
2013-03-22 01:25:41 +00:00
WHERE `mid` = '%s' AND `uid` = % d LIMIT 1 " ,
2013-08-07 10:54:47 +00:00
intval ( ITEM_DELETED ),
2010-10-01 02:41:22 +00:00
dbesc ( $when ),
dbesc ( datetime_convert ()),
2013-03-22 01:25:41 +00:00
dbesc ( $mid ),
2013-09-30 03:34:05 +00:00
intval ( $importer [ 'channel_id' ])
2010-10-01 02:41:22 +00:00
);
}
}
}
2011-02-08 12:25:27 +00:00
}
}
// Now process the feed
2012-07-19 00:08:03 +00:00
if ( $feed -> get_item_quantity ()) {
2011-02-08 12:25:27 +00:00
logger ( 'consume_feed: feed item count = ' . $feed -> get_item_quantity ());
// in inverse date order
if ( $datedir )
$items = array_reverse ( $feed -> get_items ());
else
$items = $feed -> get_items ();
2010-10-01 02:41:22 +00:00
2011-02-08 12:25:27 +00:00
foreach ( $items as $item ) {
2012-07-19 00:08:03 +00:00
$is_reply = false ;
2010-10-01 02:41:22 +00:00
$item_id = $item -> get_id ();
2013-09-30 03:34:05 +00:00
logger ( 'consume_feed: processing ' . $item_id );
2010-10-01 02:41:22 +00:00
$rawthread = $item -> get_item_tags ( NAMESPACE_THREAD , 'in-reply-to' );
if ( isset ( $rawthread [ 0 ][ 'attribs' ][ '' ][ 'ref' ])) {
$is_reply = true ;
2013-03-22 01:25:41 +00:00
$parent_mid = $rawthread [ 0 ][ 'attribs' ][ '' ][ 'ref' ];
2010-10-01 02:41:22 +00:00
}
2013-08-07 10:54:47 +00:00
if ( $is_reply ) {
2011-10-20 04:54:33 +00:00
if ( $pass == 1 )
continue ;
2011-02-09 02:44:30 +00:00
2012-09-21 00:04:22 +00:00
2010-10-01 02:41:22 +00:00
// Have we seen it? If not, import it.
2012-07-19 00:08:03 +00:00
2011-03-01 02:24:32 +00:00
$item_id = $item -> get_id ();
$datarray = get_atom_elements ( $feed , $item );
2011-02-09 02:44:30 +00:00
2012-02-25 04:03:13 +00:00
if (( ! x ( $datarray , 'author-name' )) && ( $contact [ 'network' ] != NETWORK_DFRN ))
2011-05-06 13:30:33 +00:00
$datarray [ 'author-name' ] = $contact [ 'name' ];
2012-02-25 04:03:13 +00:00
if (( ! x ( $datarray , 'author-link' )) && ( $contact [ 'network' ] != NETWORK_DFRN ))
2011-05-06 13:30:33 +00:00
$datarray [ 'author-link' ] = $contact [ 'url' ];
2012-02-25 04:03:13 +00:00
if (( ! x ( $datarray , 'author-avatar' )) && ( $contact [ 'network' ] != NETWORK_DFRN ))
2011-05-06 13:30:33 +00:00
$datarray [ 'author-avatar' ] = $contact [ 'thumb' ];
2012-02-25 04:03:13 +00:00
if (( ! x ( $datarray , 'author-name' )) || ( ! x ( $datarray , 'author-link' ))) {
logger ( 'consume_feed: no author information! ' . print_r ( $datarray , true ));
continue ;
}
2011-07-06 02:55:09 +00:00
2012-06-28 23:04:00 +00:00
2013-03-22 01:25:41 +00:00
$r = q ( " SELECT `uid`, `edited`, `body` FROM `item` WHERE `mid` = '%s' AND `uid` = %d LIMIT 1 " ,
2010-10-01 02:41:22 +00:00
dbesc ( $item_id ),
2013-09-30 03:34:05 +00:00
intval ( $importer [ 'channel_id' ])
2010-10-01 02:41:22 +00:00
);
2011-02-09 02:44:30 +00:00
2011-03-01 02:24:32 +00:00
// Update content if 'updated' changes
2013-09-30 03:34:05 +00:00
if ( $r ) {
2011-03-01 02:24:32 +00:00
if (( x ( $datarray , 'edited' ) !== false ) && ( datetime_convert ( 'UTC' , 'UTC' , $datarray [ 'edited' ]) !== $r [ 0 ][ 'edited' ])) {
2012-06-12 01:14:49 +00:00
// do not accept (ignore) an earlier edit than one we currently have.
2012-06-12 09:47:05 +00:00
if ( datetime_convert ( 'UTC' , 'UTC' , $datarray [ 'edited' ]) < $r [ 0 ][ 'edited' ])
2012-06-12 01:14:49 +00:00
continue ;
2013-03-22 01:25:41 +00:00
$r = q ( " UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `mid` = '%s' AND `uid` = %d LIMIT 1 " ,
2012-02-09 23:58:26 +00:00
dbesc ( $datarray [ 'title' ]),
2011-03-01 02:24:32 +00:00
dbesc ( $datarray [ 'body' ]),
dbesc ( datetime_convert ( 'UTC' , 'UTC' , $datarray [ 'edited' ])),
dbesc ( $item_id ),
2013-09-30 03:34:05 +00:00
intval ( $importer [ 'channel_id' ])
2011-03-01 02:24:32 +00:00
);
}
2010-10-01 02:41:22 +00:00
continue ;
}
2011-02-09 02:44:30 +00:00
2011-01-26 10:32:00 +00:00
2013-03-22 01:25:41 +00:00
$datarray [ 'parent_mid' ] = $parent_mid ;
2013-09-30 03:34:05 +00:00
$datarray [ 'uid' ] = $importer [ 'channel_id' ];
2010-10-01 02:41:22 +00:00
$datarray [ 'contact-id' ] = $contact [ 'id' ];
2010-10-27 22:50:44 +00:00
if (( activity_match ( $datarray [ 'verb' ], ACTIVITY_LIKE )) || ( activity_match ( $datarray [ 'verb' ], ACTIVITY_DISLIKE ))) {
2010-10-01 02:41:22 +00:00
$datarray [ 'type' ] = 'activity' ;
$datarray [ 'gravity' ] = GRAVITY_LIKE ;
2012-03-06 10:17:55 +00:00
// only one like or dislike per person
2013-03-22 01:25:41 +00:00
$r = q ( " select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 and (`parent_mid` = '%s' OR `thr_parent` = '%s') limit 1 " ,
2012-03-06 10:17:55 +00:00
intval ( $datarray [ 'uid' ]),
intval ( $datarray [ 'contact-id' ]),
2012-06-24 04:11:18 +00:00
dbesc ( $datarray [ 'verb' ]),
2013-03-22 01:25:41 +00:00
dbesc ( $parent_mid ),
dbesc ( $parent_mid )
2012-03-06 10:17:55 +00:00
);
if ( $r && count ( $r ))
continue ;
2010-10-01 02:41:22 +00:00
}
2012-08-16 05:33:37 +00:00
if (( $datarray [ 'verb' ] === ACTIVITY_TAG ) && ( $datarray [ 'obj_type' ] === ACTIVITY_OBJ_TAGTERM )) {
2011-10-24 11:17:46 +00:00
$xo = parse_xml_string ( $datarray [ 'object' ], false );
$xt = parse_xml_string ( $datarray [ 'target' ], false );
if ( $xt -> type == ACTIVITY_OBJ_NOTE ) {
2013-03-22 01:25:41 +00:00
$r = q ( " select * from item where `mid` = '%s' AND `uid` = %d limit 1 " ,
2011-10-24 11:17:46 +00:00
dbesc ( $xt -> id ),
2013-09-30 03:34:05 +00:00
intval ( $importer [ 'channel_id' ])
2011-10-24 11:17:46 +00:00
);
if ( ! count ( $r ))
continue ;
// extract tag, if not duplicate, add to parent item
2011-11-17 01:09:58 +00:00
if ( $xo -> id && $xo -> content ) {
2013-04-15 10:00:08 +00:00
$newtag = '#[zrl=' . $xo -> id . ']' . $xo -> content . '[/zrl]' ;
2011-11-17 01:09:58 +00:00
if ( ! ( stristr ( $r [ 0 ][ 'tag' ], $newtag ))) {
2011-10-24 11:17:46 +00:00
q ( " UPDATE item SET tag = '%s' WHERE id = %d LIMIT 1 " ,
2011-11-17 01:09:58 +00:00
dbesc ( $r [ 0 ][ 'tag' ] . ( strlen ( $r [ 0 ][ 'tag' ]) ? ',' : '' ) . $newtag ),
2011-10-24 11:17:46 +00:00
intval ( $r [ 0 ][ 'id' ])
);
}
}
}
}
2013-09-30 03:34:05 +00:00
logger ( 'consume_feed: ' . print_r ( $datarray , true ));
// $xx = item_store($datarray);
2013-09-11 02:06:06 +00:00
$r = $xx [ 'item_id' ];
2010-10-01 02:41:22 +00:00
continue ;
}
else {
2011-03-01 02:24:32 +00:00
2010-10-01 02:41:22 +00:00
// Head post of a conversation. Have we seen it? If not, import it.
2011-03-01 02:24:32 +00:00
$item_id = $item -> get_id ();
2011-04-05 02:36:18 +00:00
2011-03-01 02:24:32 +00:00
$datarray = get_atom_elements ( $feed , $item );
2011-05-06 13:30:33 +00:00
if ( is_array ( $contact )) {
2012-02-25 04:03:13 +00:00
if (( ! x ( $datarray , 'author-name' )) && ( $contact [ 'network' ] != NETWORK_DFRN ))
2011-05-06 13:30:33 +00:00
$datarray [ 'author-name' ] = $contact [ 'name' ];
2012-02-25 04:03:13 +00:00
if (( ! x ( $datarray , 'author-link' )) && ( $contact [ 'network' ] != NETWORK_DFRN ))
2011-05-06 13:30:33 +00:00
$datarray [ 'author-link' ] = $contact [ 'url' ];
2012-02-25 04:03:13 +00:00
if (( ! x ( $datarray , 'author-avatar' )) && ( $contact [ 'network' ] != NETWORK_DFRN ))
2011-05-06 13:30:33 +00:00
$datarray [ 'author-avatar' ] = $contact [ 'thumb' ];
}
2012-02-25 04:03:13 +00:00
if (( ! x ( $datarray , 'author-name' )) || ( ! x ( $datarray , 'author-link' ))) {
logger ( 'consume_feed: no author information! ' . print_r ( $datarray , true ));
continue ;
}
2011-10-04 10:06:34 +00:00
// special handling for events
2012-08-16 05:33:37 +00:00
if (( x ( $datarray , 'obj_type' )) && ( $datarray [ 'obj_type' ] === ACTIVITY_OBJ_EVENT )) {
2011-06-11 03:39:46 +00:00
$ev = bbtoevent ( $datarray [ 'body' ]);
if ( x ( $ev , 'desc' ) && x ( $ev , 'start' )) {
2013-09-30 03:34:05 +00:00
$ev [ 'uid' ] = $importer [ 'channel_id' ];
2013-03-22 01:25:41 +00:00
$ev [ 'mid' ] = $item_id ;
2011-06-24 01:25:33 +00:00
$ev [ 'edited' ] = $datarray [ 'edited' ];
2011-07-27 09:21:55 +00:00
$ev [ 'private' ] = $datarray [ 'private' ];
2011-06-14 03:42:37 +00:00
2011-06-14 02:06:49 +00:00
if ( is_array ( $contact ))
$ev [ 'cid' ] = $contact [ 'id' ];
2013-03-22 01:25:41 +00:00
$r = q ( " SELECT * FROM `event` WHERE `mid` = '%s' AND `uid` = %d LIMIT 1 " ,
2011-06-11 03:39:46 +00:00
dbesc ( $item_id ),
2013-09-30 03:34:05 +00:00
intval ( $importer [ 'channel_id' ])
2011-06-11 03:39:46 +00:00
);
2011-06-14 02:06:49 +00:00
if ( count ( $r ))
$ev [ 'id' ] = $r [ 0 ][ 'id' ];
2013-09-30 03:34:05 +00:00
// $xyz = event_store($ev);
2011-06-14 02:06:49 +00:00
continue ;
2011-06-11 03:39:46 +00:00
}
}
2011-06-14 02:06:49 +00:00
2013-03-22 01:25:41 +00:00
$r = q ( " SELECT `uid`, `edited`, `body` FROM `item` WHERE `mid` = '%s' AND `uid` = %d LIMIT 1 " ,
2010-10-01 02:41:22 +00:00
dbesc ( $item_id ),
2013-09-30 03:34:05 +00:00
intval ( $importer [ 'channel_id' ])
2010-10-01 02:41:22 +00:00
);
2011-03-01 02:24:32 +00:00
// Update content if 'updated' changes
2013-09-30 03:34:05 +00:00
if ( $r ) {
2011-03-01 02:24:32 +00:00
if (( x ( $datarray , 'edited' ) !== false ) && ( datetime_convert ( 'UTC' , 'UTC' , $datarray [ 'edited' ]) !== $r [ 0 ][ 'edited' ])) {
2012-06-12 01:14:49 +00:00
// do not accept (ignore) an earlier edit than one we currently have.
2012-06-12 09:47:05 +00:00
if ( datetime_convert ( 'UTC' , 'UTC' , $datarray [ 'edited' ]) < $r [ 0 ][ 'edited' ])
2012-06-12 01:14:49 +00:00
continue ;
2013-03-22 01:25:41 +00:00
$r = q ( " UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `mid` = '%s' AND `uid` = %d LIMIT 1 " ,
2012-02-09 23:58:26 +00:00
dbesc ( $datarray [ 'title' ]),
2011-03-01 02:24:32 +00:00
dbesc ( $datarray [ 'body' ]),
dbesc ( datetime_convert ( 'UTC' , 'UTC' , $datarray [ 'edited' ])),
dbesc ( $item_id ),
2013-09-30 03:34:05 +00:00
intval ( $importer [ 'channel_id' ])
2011-03-01 02:24:32 +00:00
);
}
2010-10-01 02:41:22 +00:00
continue ;
}
2010-10-25 03:39:24 +00:00
2010-10-27 22:50:44 +00:00
if ( activity_match ( $datarray [ 'verb' ], ACTIVITY_FOLLOW )) {
2010-10-27 05:09:13 +00:00
logger ( 'consume-feed: New follower' );
2010-10-25 03:39:24 +00:00
new_follower ( $importer , $contact , $datarray , $item );
2010-10-22 04:48:22 +00:00
return ;
}
2010-10-27 22:50:44 +00:00
if ( activity_match ( $datarray [ 'verb' ], ACTIVITY_UNFOLLOW )) {
2010-10-25 03:39:24 +00:00
lose_follower ( $importer , $contact , $datarray , $item );
2010-10-22 04:48:22 +00:00
return ;
}
2011-10-02 23:18:01 +00:00
if ( activity_match ( $datarray [ 'verb' ], ACTIVITY_REQ_FRIEND )) {
logger ( 'consume-feed: New friend request' );
new_follower ( $importer , $contact , $datarray , $item , true );
return ;
}
if ( activity_match ( $datarray [ 'verb' ], ACTIVITY_UNFRIEND )) {
lose_sharer ( $importer , $contact , $datarray , $item );
return ;
}
2013-09-30 03:34:05 +00:00
// if(! is_array($contact))
// return;
2010-10-25 03:39:24 +00:00
2010-11-09 04:56:09 +00:00
2011-07-06 02:55:09 +00:00
// This is my contact on another system, but it's really me.
// Turn this into a wall post.
2012-06-29 01:52:49 +00:00
if ( $contact [ 'remote_self' ]) {
2011-07-06 02:55:09 +00:00
$datarray [ 'wall' ] = 1 ;
2012-06-29 01:52:49 +00:00
}
2011-07-06 02:55:09 +00:00
2013-03-22 01:25:41 +00:00
$datarray [ 'parent_mid' ] = $item_id ;
2013-09-30 03:34:05 +00:00
$datarray [ 'uid' ] = $importer [ 'channel_id' ];
2010-10-01 02:41:22 +00:00
$datarray [ 'contact-id' ] = $contact [ 'id' ];
2012-03-05 02:50:32 +00:00
2012-03-08 02:23:55 +00:00
if ( ! link_compare ( $datarray [ 'owner-link' ], $contact [ 'url' ])) {
2012-03-05 02:50:32 +00:00
// The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery,
// but otherwise there's a possible data mixup on the sender's system.
// the tgroup delivery code called from item_store will correct it if it's a forum,
// but we're going to unconditionally correct it here so that the post will always be owned by our contact.
2012-03-22 23:17:10 +00:00
logger ( 'consume_feed: Correcting item owner.' , LOGGER_DEBUG );
2012-03-05 02:50:32 +00:00
$datarray [ 'owner-name' ] = $contact [ 'name' ];
$datarray [ 'owner-link' ] = $contact [ 'url' ];
$datarray [ 'owner-avatar' ] = $contact [ 'thumb' ];
}
2012-09-21 00:04:22 +00:00
// We've allowed "followers" to reach this point so we can decide if they are
// posting an @-tag delivery, which followers are allowed to do for certain
// page types. Now that we've parsed the post, let's check if it is legit. Otherwise ignore it.
2013-09-30 03:34:05 +00:00
if (( $contact [ 'rel' ] == CONTACT_IS_FOLLOWER ) && ( ! tgroup_check ( $importer [ 'channel_id' ], $datarray )))
2012-09-21 00:04:22 +00:00
continue ;
2013-09-30 03:34:05 +00:00
logger ( 'consume_feed: ' . print_r ( $datarray , true ));
2012-09-21 00:04:22 +00:00
2013-09-30 03:34:05 +00:00
// $xx = item_store($datarray);
2013-09-11 02:06:06 +00:00
$r = $xx [ 'item_id' ];
2010-10-01 02:41:22 +00:00
continue ;
}
}
}
2013-09-30 03:34:05 +00:00
2010-10-01 04:38:45 +00:00
}
2011-10-02 23:18:01 +00:00
2010-10-01 04:38:45 +00:00
2013-06-13 04:12:27 +00:00
function atom_author ( $tag , $name , $uri , $h , $w , $type , $photo ) {
2010-11-02 00:56:36 +00:00
$o = '' ;
if ( ! $tag )
return $o ;
$name = xmlify ( $name );
$uri = xmlify ( $uri );
$h = intval ( $h );
$w = intval ( $w );
$photo = xmlify ( $photo );
$o .= " < $tag > \r \n " ;
$o .= " <name> $name </name> \r \n " ;
$o .= " <uri> $uri </uri> \r \n " ;
2013-06-13 04:12:27 +00:00
$o .= '<link rel="photo" type="' . $type . '" media:width="' . $w . '" media:height="' . $h . '" href="' . $photo . '" />' . " \r \n " ;
$o .= '<link rel="avatar" type="' . $type . '" media:width="' . $w . '" media:height="' . $h . '" href="' . $photo . '" />' . " \r \n " ;
2010-12-25 02:32:23 +00:00
call_hooks ( 'atom_author' , $o );
2010-11-02 00:56:36 +00:00
$o .= " </ $tag > \r \n " ;
return $o ;
}
2012-05-28 04:01:58 +00:00
function atom_entry ( $item , $type , $author , $owner , $comment = false , $cid = 0 ) {
2010-11-02 00:56:36 +00:00
2011-05-01 00:24:37 +00:00
$a = get_app ();
2011-10-15 10:26:37 +00:00
if ( ! $item [ 'parent' ])
return ;
2010-11-02 00:56:36 +00:00
if ( $item [ 'deleted' ])
2013-03-22 01:25:41 +00:00
return '<at:deleted-entry ref="' . xmlify ( $item [ 'mid' ]) . '" when="' . xmlify ( datetime_convert ( 'UTC' , 'UTC' , $item [ 'edited' ] . '+00:00' , ATOM_TIME )) . '" />' . " \r \n " ;
2010-11-02 00:56:36 +00:00
2011-05-01 00:24:37 +00:00
if ( $item [ 'allow_cid' ] || $item [ 'allow_gid' ] || $item [ 'deny_cid' ] || $item [ 'deny_gid' ])
2012-05-28 04:01:58 +00:00
$body = fix_private_photos ( $item [ 'body' ], $owner [ 'uid' ], $item , $cid );
2011-05-01 00:24:37 +00:00
else
$body = $item [ 'body' ];
2010-11-02 00:56:36 +00:00
2010-11-02 06:42:26 +00:00
$o = " \r \n \r \n <entry> \r \n " ;
2010-11-02 00:56:36 +00:00
if ( is_array ( $author ))
2013-06-13 04:12:27 +00:00
$o .= atom_author ( 'author' , $author [ 'xchan_name' ], $author [ 'xchan_url' ], 80 , 80 , $author [ 'xchan_photo_mimetype' ], $author [ 'xchan_photo_m' ]);
2010-11-02 00:56:36 +00:00
else
2013-06-13 04:12:27 +00:00
$o .= atom_author ( 'author' , $item [ 'author' ][ 'xchan_name' ], $item [ 'author' ][ 'xchan_url' ], 80 , 80 , $item [ 'author' ][ 'xchan_photo_mimetype' ], $item [ 'author' ][ 'xchan_photo_m' ]);
$o .= atom_author ( 'zot:owner' , $item [ 'owner' ][ 'xchan_name' ], $item [ 'owner' ][ 'xchan_url' ], 80 , 80 , $item [ 'owner' ][ 'xchan_photo_mimetype' ], $item [ 'owner' ][ 'xchan_photo_m' ]);
2010-11-02 00:56:36 +00:00
2013-03-22 01:25:41 +00:00
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' ]);
2013-06-13 04:12:27 +00:00
$o .= '<thr:in-reply-to ref="' . xmlify ( $parent_item ) . '" type="text/html" href="' . xmlify ( $item [ 'plink' ]) . '" />' . " \r \n " ;
2012-06-23 13:04:56 +00:00
}
2010-11-02 00:56:36 +00:00
2013-03-22 01:25:41 +00:00
$o .= '<id>' . xmlify ( $item [ 'mid' ]) . '</id>' . " \r \n " ;
2010-11-02 00:56:36 +00:00
$o .= '<title>' . xmlify ( $item [ 'title' ]) . '</title>' . " \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 " ;
2013-09-06 02:31:26 +00:00
$o .= '<content type="' . $type . '" >' . xmlify ( prepare_text ( $body , $item [ 'mimetype' ])) . '</content>' . " \r \n " ;
2013-06-13 04:12:27 +00:00
$o .= '<link rel="alternate" type="text/html" href="' . xmlify ( $item [ 'plink' ]) . '" />' . " \r \n " ;
2010-11-10 04:38:24 +00:00
if ( $item [ 'location' ]) {
2013-06-13 04:12:27 +00:00
$o .= '<zot:location>' . xmlify ( $item [ 'location' ]) . '</zot:location>' . " \r \n " ;
2010-11-10 04:38:24 +00:00
$o .= '<poco:address><poco:formatted>' . xmlify ( $item [ 'location' ]) . '</poco:formatted></poco:address>' . " \r \n " ;
}
2010-11-02 00:56:36 +00:00
if ( $item [ 'coord' ])
$o .= '<georss:point>' . xmlify ( $item [ 'coord' ]) . '</georss:point>' . " \r \n " ;
2013-06-13 04:12:27 +00:00
if (( $item [ 'item_private' ]) || strlen ( $item [ 'allow_cid' ]) || strlen ( $item [ 'allow_gid' ]) || strlen ( $item [ 'deny_cid' ]) || strlen ( $item [ 'deny_gid' ]))
$o .= '<zot:private>' . (( $item [ 'item_private' ]) ? $item [ 'item_private' ] : 1 ) . '</zot:private>' . " \r \n " ;
2010-12-08 04:47:53 +00:00
2011-05-23 01:40:00 +00:00
2011-06-21 02:08:40 +00:00
if ( $item [ 'app' ])
2011-08-29 02:22:27 +00:00
$o .= '<statusnet:notice_info local_id="' . $item [ 'id' ] . '" source="' . xmlify ( $item [ 'app' ]) . '" ></statusnet:notice_info>' . " \r \n " ;
2010-11-02 00:56:36 +00:00
$verb = construct_verb ( $item );
$o .= '<as:verb>' . xmlify ( $verb ) . '</as:verb>' . " \r \n " ;
2010-11-03 23:48:21 +00:00
$actobj = construct_activity_object ( $item );
2010-11-02 00:56:36 +00:00
if ( strlen ( $actobj ))
$o .= $actobj ;
2010-11-03 23:48:21 +00:00
$actarg = construct_activity_target ( $item );
if ( strlen ( $actarg ))
$o .= $actarg ;
2010-11-02 00:56:36 +00:00
2013-06-13 04:12:27 +00:00
// FIXME
// $tags = item_getfeedtags($item);
// if(count($tags)) {
// foreach($tags as $t) {
// $o .= '<category scheme="X-DFRN:' . xmlify($t[0]) . ':' . xmlify($t[1]) . '" term="' . xmlify($t[2]) . '" />' . "\r\n";
// }
// }
2011-04-06 00:41:02 +00:00
2013-06-13 04:12:27 +00:00
// FIXME
// $o .= item_getfeedattach($item);
2011-04-07 02:41:16 +00:00
2013-06-13 04:12:27 +00:00
// $mentioned = get_mentions($item,$tags);
// if($mentioned)
// $o .= $mentioned;
2010-11-02 00:56:36 +00:00
2010-12-25 02:32:23 +00:00
call_hooks ( 'atom_entry' , $o );
2010-11-02 00:56:36 +00:00
$o .= '</entry>' . " \r \n " ;
return $o ;
}
2011-04-06 00:41:02 +00:00
2012-07-07 22:20:24 +00:00
function fix_private_photos ( $s , $uid , $item = null , $cid = 0 ) {
2011-05-01 00:24:37 +00:00
$a = get_app ();
2012-05-28 04:01:58 +00:00
logger ( 'fix_private_photos' , LOGGER_DEBUG );
2012-05-29 23:44:02 +00:00
$site = substr ( $a -> get_baseurl (), strpos ( $a -> get_baseurl (), '://' ));
2011-05-01 00:24:37 +00:00
2012-07-07 22:20:24 +00:00
$orig_body = $s ;
$new_body = '' ;
2013-05-28 11:50:16 +00:00
$img_start = strpos ( $orig_body , '[zmg' );
2012-07-07 22:20:24 +00:00
$img_st_close = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), ']' ) : false );
2013-05-28 11:50:16 +00:00
$img_len = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start + $img_st_close + 1 ), '[/zmg]' ) : false );
2012-07-07 22:20:24 +00:00
while ( ( $img_st_close !== false ) && ( $img_len !== false ) ) {
$img_st_close ++ ; // make it point to AFTER the closing bracket
$image = substr ( $orig_body , $img_start + $img_st_close , $img_len );
2012-05-28 04:01:58 +00:00
logger ( 'fix_private_photos: found photo ' . $image , LOGGER_DEBUG );
2012-07-07 22:20:24 +00:00
2012-05-28 04:01:58 +00:00
if ( stristr ( $image , $site . '/photo/' )) {
2012-07-07 22:20:24 +00:00
// Only embed locally hosted photos
2012-05-28 04:01:58 +00:00
$replace = false ;
2011-05-01 00:24:37 +00:00
$i = basename ( $image );
$x = strpos ( $i , '-' );
2012-07-07 22:20:24 +00:00
2011-05-01 00:24:37 +00:00
if ( $x ) {
$res = substr ( $i , $x + 1 );
$i = substr ( $i , 0 , $x );
2012-10-02 01:02:11 +00:00
$r = q ( " SELECT * FROM `photo` WHERE `resource_id` = '%s' AND `scale` = %d AND `uid` = %d " ,
2011-05-01 00:24:37 +00:00
dbesc ( $i ),
intval ( $res ),
intval ( $uid )
);
if ( count ( $r )) {
2012-05-28 04:01:58 +00:00
// Check to see if we should replace this photo link with an embedded image
// 1. No need to do so if the photo is public
// 2. If there's a contact-id provided, see if they're in the access list
// for the photo. If so, embed it.
// 3. Otherwise, if we have an item, see if the item permissions match the photo
// permissions, regardless of order but first check to see if they're an exact
// match to save some processing overhead.
if ( has_permissions ( $r [ 0 ])) {
if ( $cid ) {
$recips = enumerate_permissions ( $r [ 0 ]);
if ( in_array ( $cid , $recips )) {
$replace = true ;
}
}
elseif ( $item ) {
if ( compare_permissions ( $item , $r [ 0 ]))
$replace = true ;
}
}
if ( $replace ) {
2012-07-07 22:20:24 +00:00
$data = $r [ 0 ][ 'data' ];
$type = $r [ 0 ][ 'type' ];
// If a custom width and height were specified, apply before embedding
2013-05-28 11:50:16 +00:00
if ( preg_match ( " / \ [zmg \ =([0-9]*)x([0-9]*) \ ]/is " , substr ( $orig_body , $img_start , $img_st_close ), $match )) {
2012-07-07 22:20:24 +00:00
logger ( 'fix_private_photos: scaling photo' , LOGGER_DEBUG );
$width = intval ( $match [ 1 ]);
$height = intval ( $match [ 2 ]);
2013-04-26 03:01:24 +00:00
$ph = photo_factory ( $data , $type );
2012-07-07 22:20:24 +00:00
if ( $ph -> is_valid ()) {
$ph -> scaleImage ( max ( $width , $height ));
$data = $ph -> imageString ();
$type = $ph -> getType ();
}
}
2012-05-28 23:51:52 +00:00
logger ( 'fix_private_photos: replacing photo' , LOGGER_DEBUG );
2012-07-07 22:20:24 +00:00
$image = 'data:' . $type . ';base64,' . base64_encode ( $data );
logger ( 'fix_private_photos: replaced: ' . $image , LOGGER_DATA );
2012-05-28 04:01:58 +00:00
}
2011-05-01 00:24:37 +00:00
}
}
}
2012-07-07 22:20:24 +00:00
2013-05-28 11:50:16 +00:00
$new_body = $new_body . substr ( $orig_body , 0 , $img_start + $img_st_close ) . $image . '[/zmg]' ;
$orig_body = substr ( $orig_body , $img_start + $img_st_close + $img_len + strlen ( '[/zmg]' ));
2012-07-07 22:20:24 +00:00
if ( $orig_body === false )
$orig_body = '' ;
2013-05-28 11:50:16 +00:00
$img_start = strpos ( $orig_body , '[zmg' );
2012-07-07 22:20:24 +00:00
$img_st_close = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), ']' ) : false );
2013-05-28 11:50:16 +00:00
$img_len = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start + $img_st_close + 1 ), '[/zmg]' ) : false );
2011-05-01 00:24:37 +00:00
}
2012-07-07 22:20:24 +00:00
2012-07-08 00:47:13 +00:00
$new_body = $new_body . $orig_body ;
2012-07-07 22:20:24 +00:00
return ( $new_body );
2011-05-01 00:24:37 +00:00
}
2012-05-28 04:01:58 +00:00
function has_permissions ( $obj ) {
if (( $obj [ 'allow_cid' ] != '' ) || ( $obj [ 'allow_gid' ] != '' ) || ( $obj [ 'deny_cid' ] != '' ) || ( $obj [ 'deny_gid' ] != '' ))
return true ;
return false ;
}
function compare_permissions ( $obj1 , $obj2 ) {
// first part is easy. Check that these are exactly the same.
if (( $obj1 [ 'allow_cid' ] == $obj2 [ 'allow_cid' ])
&& ( $obj1 [ 'allow_gid' ] == $obj2 [ 'allow_gid' ])
&& ( $obj1 [ 'deny_cid' ] == $obj2 [ 'deny_cid' ])
&& ( $obj1 [ 'deny_gid' ] == $obj2 [ 'deny_gid' ]))
return true ;
// This is harder. Parse all the permissions and compare the resulting set.
$recipients1 = enumerate_permissions ( $obj1 );
$recipients2 = enumerate_permissions ( $obj2 );
sort ( $recipients1 );
sort ( $recipients2 );
if ( $recipients1 == $recipients2 )
return true ;
return false ;
}
// returns an array of contact-ids that are allowed to see this object
function enumerate_permissions ( $obj ) {
require_once ( 'include/group.php' );
$allow_people = expand_acl ( $obj [ 'allow_cid' ]);
$allow_groups = expand_groups ( expand_acl ( $obj [ 'allow_gid' ]));
$deny_people = expand_acl ( $obj [ 'deny_cid' ]);
$deny_groups = expand_groups ( expand_acl ( $obj [ 'deny_gid' ]));
$recipients = array_unique ( array_merge ( $allow_people , $allow_groups ));
$deny = array_unique ( array_merge ( $deny_people , $deny_groups ));
$recipients = array_diff ( $recipients , $deny );
return $recipients ;
}
2011-05-01 00:24:37 +00:00
2011-04-06 00:41:02 +00:00
function item_getfeedtags ( $item ) {
2012-07-11 11:29:47 +00:00
$terms = get_terms_oftype ( $item [ 'term' ], array ( TERM_HASHTAG , TERM_MENTION ));
2011-04-06 00:41:02 +00:00
$ret = array ();
2012-07-11 11:29:47 +00:00
if ( count ( $terms )) {
foreach ( $terms as $term ) {
if ( $term [ 'type' ] == TERM_HASHTAG )
$ret [] = array ( '#' , $term [ 'url' ], $term [ 'term' ]);
else
$ret [] = array ( '@' , $term [ 'url' ], $term [ 'term' ]);
2011-04-06 00:41:02 +00:00
}
}
return $ret ;
}
2011-04-07 02:41:16 +00:00
function item_getfeedattach ( $item ) {
2011-04-07 03:03:06 +00:00
$ret = '' ;
2011-04-07 02:41:16 +00:00
$arr = explode ( ',' , $item [ 'attach' ]);
if ( count ( $arr )) {
foreach ( $arr as $r ) {
$matches = false ;
2011-08-04 02:18:58 +00:00
$cnt = preg_match ( '|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"\[\/attach\]|' , $r , $matches );
2011-04-07 02:41:16 +00:00
if ( $cnt ) {
2011-04-07 03:36:24 +00:00
$ret .= '<link rel="enclosure" href="' . xmlify ( $matches [ 1 ]) . '" type="' . xmlify ( $matches [ 3 ]) . '" ' ;
2011-04-07 02:41:16 +00:00
if ( intval ( $matches [ 2 ]))
2011-08-04 02:18:58 +00:00
$ret .= 'length="' . intval ( $matches [ 2 ]) . '" ' ;
2011-04-07 02:41:16 +00:00
if ( $matches [ 4 ] !== ' ' )
2011-04-13 08:53:40 +00:00
$ret .= 'title="' . xmlify ( trim ( $matches [ 4 ])) . '" ' ;
2011-04-07 02:41:16 +00:00
$ret .= ' />' . " \r \n " ;
}
}
}
return $ret ;
}
2011-04-06 00:41:02 +00:00
2011-01-03 09:04:54 +00:00
2011-03-16 00:31:49 +00:00
function item_expire ( $uid , $days ) {
2012-05-29 06:24:10 +00:00
if (( ! $uid ) || ( $days < 1 ))
2011-03-16 00:31:49 +00:00
return ;
2012-05-29 06:24:10 +00:00
// $expire_network_only = save your own wall posts
// and just expire conversations started by others
2014-03-04 03:15:11 +00:00
// do not enable this until we can pass bulk delete messages through zot
// $expire_network_only = get_pconfig($uid,'expire','network_only');
$expire_network_only = 1 ;
2012-05-29 06:24:10 +00:00
2013-08-14 12:26:17 +00:00
$sql_extra = (( intval ( $expire_network_only )) ? " AND not (item_flags & " . intval ( ITEM_WALL ) . " ) " : " " );
2012-05-29 06:24:10 +00:00
2011-03-16 00:31:49 +00:00
$r = q ( " SELECT * FROM `item`
WHERE `uid` = % d
AND `created` < UTC_TIMESTAMP () - INTERVAL % d DAY
AND `id` = `parent`
2012-05-29 06:24:10 +00:00
$sql_extra
2014-03-04 03:15:11 +00:00
AND NOT ( item_flags & % d )
AND ( item_restrict = 0 ) " ,
2011-03-16 00:31:49 +00:00
intval ( $uid ),
2013-08-14 12:26:17 +00:00
intval ( $days ),
2014-03-04 03:15:11 +00:00
intval ( ITEM_RETAINED )
2011-03-16 00:31:49 +00:00
);
2013-08-14 12:26:17 +00:00
if ( ! $r )
2011-03-16 00:31:49 +00:00
return ;
2011-11-17 14:53:59 +00:00
2013-08-14 12:26:17 +00:00
$r = fetch_post_tags ( $r , true );
2011-03-16 00:31:49 +00:00
foreach ( $r as $item ) {
2012-03-27 07:54:34 +00:00
// don't expire filed items
2013-08-14 12:26:17 +00:00
$terms = get_terms_oftype ( $item [ 'term' ], TERM_FILE );
2014-03-04 03:15:11 +00:00
if ( $terms ) {
retain_item ( $item [ 'id' ]);
2012-03-27 07:54:34 +00:00
continue ;
2014-03-04 03:15:11 +00:00
}
2012-03-27 07:54:34 +00:00
2011-03-16 00:31:49 +00:00
// Only expire posts, not photos and photo comments
2014-03-04 03:15:11 +00:00
if ( $item [ 'resource_type' ] === 'photo' ) {
retain_item ( $item [ 'id' ]);
2011-03-16 00:31:49 +00:00
continue ;
2014-03-04 03:15:11 +00:00
}
if ( $item [ 'item_flags' ] & ITEM_STARRED ) {
retain_item ( $item [ 'id' ]);
2011-11-17 14:53:59 +00:00
continue ;
2014-03-04 03:15:11 +00:00
}
2011-11-17 14:53:59 +00:00
2012-05-05 14:05:32 +00:00
drop_item ( $item [ 'id' ], false );
2011-03-16 00:31:49 +00:00
}
2014-03-04 03:15:11 +00:00
// proc_run('php',"include/notifier.php","expire","$uid");
2011-11-17 14:53:59 +00:00
2011-06-11 03:39:46 +00:00
}
2014-03-04 03:15:11 +00:00
function retain_item ( $id ) {
$r = q ( " update item set item_flags = (item_flags | %d ) where id = %d limit 1 " ,
intval ( ITEM_RETAINED ),
intval ( $id )
);
}
2011-06-16 03:43:39 +00:00
function drop_items ( $items ) {
$uid = 0 ;
2012-04-17 11:33:50 +00:00
if ( ! local_user () && ! remote_user ())
2012-01-25 02:59:55 +00:00
return ;
2011-06-16 03:43:39 +00:00
if ( count ( $items )) {
foreach ( $items as $item ) {
$owner = drop_item ( $item , false );
if ( $owner && ! $uid )
$uid = $owner ;
}
}
// multiple threads may have been deleted, send an expire notification
if ( $uid )
proc_run ( 'php' , " include/notifier.php " , " expire " , " $uid " );
}
2013-01-25 00:44:10 +00:00
// Delete item with given item $id. $interactive means we're running interactively, and must check
// permissions to carry out this act. If it is non-interactive, we are deleting something at the
// system's request and do not check permission. This is very important to know.
2011-06-16 03:43:39 +00:00
function drop_item ( $id , $interactive = true ) {
$a = get_app ();
// locate item to be deleted
2013-01-25 00:44:10 +00:00
$r = q ( " SELECT * FROM item WHERE id = %d LIMIT 1 " ,
2011-06-16 03:43:39 +00:00
intval ( $id )
);
2013-11-27 07:00:32 +00:00
if (( ! $r ) || ( $r [ 0 ][ 'item_restrict' ] & ITEM_DELETED )) {
2011-06-16 03:43:39 +00:00
if ( ! $interactive )
return 0 ;
notice ( t ( 'Item not found.' ) . EOL );
goaway ( $a -> get_baseurl () . '/' . $_SESSION [ 'return_url' ]);
}
$item = $r [ 0 ];
2013-01-25 00:44:10 +00:00
$ok_to_delete = false ;
2012-09-10 04:17:06 +00:00
2013-01-25 00:44:10 +00:00
// system deletion
if ( ! $interactive )
$ok_to_delete = true ;
2011-06-16 03:43:39 +00:00
2013-01-25 00:44:10 +00:00
// owner deletion
if ( local_user () && local_user () == $item [ 'uid' ])
$ok_to_delete = true ;
2013-01-23 12:50:57 +00:00
2013-01-25 00:44:10 +00:00
// author deletion
$observer = $a -> get_observer ();
if ( $observer && $observer [ 'xchan_hash' ] && ( $observer [ 'xchan_hash' ] === $item [ 'author_xchan' ]))
$ok_to_delete = true ;
2013-01-23 12:50:57 +00:00
2013-01-25 00:44:10 +00:00
if ( $ok_to_delete ) {
2012-05-05 14:05:32 +00:00
2013-11-27 07:10:10 +00:00
// set the deleted flag immediately on this item just in case the
// hook calls a remote process which loops. We'll delete it properly in a second.
$r = q ( " UPDATE item SET item_restrict = ( item_restrict | %d ) WHERE id = %d LIMIT 1 " ,
intval ( ITEM_DELETED ),
intval ( $item [ 'id' ])
);
2013-11-26 23:26:11 +00:00
$arr = array ( 'item' => $item );
call_hooks ( 'drop_item' , $arr );
2013-01-25 00:44:10 +00:00
$notify_id = intval ( $item [ 'id' ]);
2012-05-05 14:05:32 +00:00
2013-01-25 00:44:10 +00:00
$items = q ( " select * from item where parent = %d and uid = %d " ,
2012-05-05 14:05:32 +00:00
intval ( $item [ 'id' ]),
intval ( $item [ 'uid' ])
);
2013-01-25 00:44:10 +00:00
if ( $items ) {
foreach ( $items as $i )
delete_item_lowlevel ( $i );
2011-06-16 03:43:39 +00:00
}
2013-01-27 21:43:43 +00:00
else
delete_item_lowlevel ( $item );
2012-06-01 01:40:12 +00:00
2013-01-25 00:44:10 +00:00
if ( ! $interactive )
return 1 ;
2012-05-05 14:05:32 +00:00
2011-06-16 03:43:39 +00:00
// send the notification upstream/downstream as the case may be
2013-01-25 00:44:10 +00:00
// only send notifications to others if this is the owner's wall item.
2011-06-16 03:43:39 +00:00
2013-01-25 00:44:10 +00:00
if ( $item [ 'item_flags' ] & ITEM_WALL )
proc_run ( 'php' , 'include/notifier.php' , 'drop' , $notify_id );
2011-06-16 03:43:39 +00:00
goaway ( $a -> get_baseurl () . '/' . $_SESSION [ 'return_url' ]);
2013-01-25 00:44:10 +00:00
2011-06-16 03:43:39 +00:00
}
else {
if ( ! $interactive )
return 0 ;
notice ( t ( 'Permission denied.' ) . EOL );
goaway ( $a -> get_baseurl () . '/' . $_SESSION [ 'return_url' ]);
}
2011-10-23 07:24:37 +00:00
}
2012-06-13 03:46:30 +00:00
2013-01-25 00:44:10 +00:00
// This function does not check for permission and does not send notifications and does not check recursion.
// It merely destroys all resources associated with an item.
// Please do not use without a suitable wrapper.
function delete_item_lowlevel ( $item ) {
$r = q ( " UPDATE item SET item_restrict = ( item_restrict | %d ), title = '', body = '',
changed = '%s' , edited = '%s' WHERE id = % d LIMIT 1 " ,
intval ( ITEM_DELETED ),
dbesc ( datetime_convert ()),
dbesc ( datetime_convert ()),
intval ( $item [ 'id' ])
);
$r = q ( " delete from term where otype = %d and oid = %d limit 1 " ,
intval ( TERM_OBJ_POST ),
intval ( $item [ 'id' ])
);
// If item is a link to a photo resource, nuke all the associated photos
// This only applies to photos uploaded from the photos page. Photos inserted into a post do not
// generate a resource_id and therefore aren't intimately linked to the item.
if ( strlen ( $item [ 'resource_id' ])) {
if ( $item [ 'resource_type' ] === 'event' ) {
q ( " delete from event where event_hash = '%s' and uid = %d limit 1 " ,
dbesc ( $item [ 'resource_id' ]),
intval ( $item [ 'uid' ])
);
}
elseif ( $item [ 'resource_type' ] === 'photo' ) {
q ( " DELETE FROM `photo` WHERE `resource_id` = '%s' AND `uid` = %d " ,
dbesc ( $item [ 'resource_id' ]),
intval ( $item [ 'uid' ])
);
}
}
q ( " delete from item_id where iid = %d and uid = %d limit 1 " ,
intval ( $item [ 'id' ]),
intval ( $item [ 'uid' ])
);
2013-02-18 23:15:55 +00:00
q ( " delete from term where oid = %d and otype = %d " ,
intval ( $item [ 'id' ]),
intval ( TERM_OBJ_POST )
);
// FIXME remove notifications for this item
2013-01-25 00:44:10 +00:00
return true ;
}
2012-06-13 03:46:30 +00:00
function first_post_date ( $uid , $wall = false ) {
2012-10-08 01:44:06 +00:00
$wall_sql = (( $wall ) ? sprintf ( " and item_flags & %d " , ITEM_WALL ) : " " );
$r = q ( " select id, created from item
where item_restrict = % d and uid = % d and id = parent $wall_sql
2012-06-13 03:46:30 +00:00
order by created asc limit 1 " ,
2012-10-08 01:44:06 +00:00
intval ( ITEM_VISIBLE ),
intval ( $uid )
2012-06-13 03:46:30 +00:00
);
2012-06-13 04:34:28 +00:00
if ( count ( $r )) {
2012-06-13 04:39:39 +00:00
// logger('first_post_date: ' . $r[0]['id'] . ' ' . $r[0]['created'], LOGGER_DATA);
2012-06-13 05:52:34 +00:00
return substr ( datetime_convert ( '' , date_default_timezone_get (), $r [ 0 ][ 'created' ]), 0 , 10 );
2012-06-13 04:34:28 +00:00
}
2012-06-13 03:46:30 +00:00
return false ;
}
function posted_dates ( $uid , $wall ) {
2012-06-13 05:52:34 +00:00
$dnow = datetime_convert ( '' , date_default_timezone_get (), 'now' , 'Y-m-d' );
2012-06-13 03:46:30 +00:00
$dthen = first_post_date ( $uid , $wall );
if ( ! $dthen )
return array ();
2012-06-13 05:52:34 +00:00
// If it's near the end of a long month, backup to the 28th so that in
// consecutive loops we'll always get a whole month difference.
if ( intval ( substr ( $dnow , 8 )) > 28 )
$dnow = substr ( $dnow , 0 , 8 ) . '28' ;
if ( intval ( substr ( $dthen , 8 )) > 28 )
$dnow = substr ( $dthen , 0 , 8 ) . '28' ;
2012-06-13 03:46:30 +00:00
$ret = array ();
2012-07-10 13:28:02 +00:00
// Starting with the current month, get the first and last days of every
// month down to and including the month of the first post
while ( substr ( $dnow , 0 , 7 ) >= substr ( $dthen , 0 , 7 )) {
2012-06-14 03:59:19 +00:00
$dstart = substr ( $dnow , 0 , 8 ) . '01' ;
$dend = substr ( $dnow , 0 , 8 ) . get_dim ( intval ( $dnow ), intval ( substr ( $dnow , 5 )));
$start_month = datetime_convert ( '' , '' , $dstart , 'Y-m-d' );
$end_month = datetime_convert ( '' , '' , $dend , 'Y-m-d' );
2012-06-13 03:46:30 +00:00
$str = day_translate ( datetime_convert ( '' , '' , $dnow , 'F Y' ));
$ret [] = array ( $str , $end_month , $start_month );
$dnow = datetime_convert ( '' , '' , $dnow . ' -1 month' , 'Y-m-d' );
}
return $ret ;
}
2013-02-11 08:20:14 +00:00
function fetch_post_tags ( $items , $link = false ) {
2012-07-11 02:28:02 +00:00
$tag_finder = array ();
2012-11-16 05:52:05 +00:00
if ( $items ) {
foreach ( $items as $item ) {
2013-01-03 00:28:47 +00:00
if ( is_array ( $item )) {
if ( array_key_exists ( 'item_id' , $item )) {
if ( ! in_array ( $item [ 'item_id' ], $tag_finder ))
$tag_finder [] = $item [ 'item_id' ];
}
else {
if ( ! in_array ( $item [ 'id' ], $tag_finder ))
$tag_finder [] = $item [ 'id' ];
}
2012-11-16 05:52:05 +00:00
}
}
}
2012-07-11 02:28:02 +00:00
$tag_finder_str = implode ( ', ' , $tag_finder );
2012-11-16 05:52:05 +00:00
2012-07-17 12:30:32 +00:00
if ( strlen ( $tag_finder_str )) {
$tags = q ( " select * from term where oid in ( %s ) and otype = %d " ,
dbesc ( $tag_finder_str ),
intval ( TERM_OBJ_POST )
);
}
2012-07-11 02:28:02 +00:00
2012-11-16 05:52:05 +00:00
2012-07-11 02:28:02 +00:00
for ( $x = 0 ; $x < count ( $items ); $x ++ ) {
2013-01-03 00:28:47 +00:00
if ( $tags ) {
2012-07-11 02:28:02 +00:00
foreach ( $tags as $t ) {
2013-02-11 08:20:14 +00:00
if (( $link ) && ( $t [ 'type' ] == TERM_MENTION ))
$t [ 'url' ] = chanlink_url ( $t [ 'url' ]);
2012-11-16 05:52:05 +00:00
if ( array_key_exists ( 'item_id' , $items [ $x ])) {
if ( $t [ 'oid' ] == $items [ $x ][ 'item_id' ]) {
if ( ! is_array ( $items [ $x ][ 'term' ]))
$items [ $x ][ 'term' ] = array ();
$items [ $x ][ 'term' ][] = $t ;
}
}
else {
if ( $t [ 'oid' ] == $items [ $x ][ 'id' ]) {
if ( ! is_array ( $items [ $x ][ 'term' ]))
$items [ $x ][ 'term' ] = array ();
$items [ $x ][ 'term' ][] = $t ;
}
2012-07-11 02:28:02 +00:00
}
}
}
}
return $items ;
}
2013-01-04 03:34:04 +00:00
2013-01-24 22:31:57 +00:00
function zot_feed ( $uid , $observer_xchan , $mindate ) {
2013-01-04 03:34:04 +00:00
2013-11-18 00:50:32 +00:00
2013-01-04 03:34:04 +00:00
$result = array ();
$mindate = datetime_convert ( 'UTC' , 'UTC' , $mindate );
if ( ! $mindate )
$mindate = '0000-00-00 00:00:00' ;
2013-07-30 03:39:12 +00:00
$mindate = dbesc ( $mindate );
2013-11-18 00:50:32 +00:00
logger ( 'zot_feed: ' . $uid );
2013-01-24 22:31:57 +00:00
if ( ! perm_is_allowed ( $uid , $observer_xchan , 'view_stream' )) {
2013-11-18 00:50:32 +00:00
logger ( 'zot_feed: permission denied.' );
2013-01-04 03:34:04 +00:00
return $result ;
}
2013-11-18 00:50:32 +00:00
require_once ( 'include/security.php' );
2013-07-30 03:39:12 +00:00
$sql_extra = item_permissions_sql ( $uid );
2013-01-04 03:34:04 +00:00
2013-07-30 03:39:12 +00:00
if ( $mindate != '0000-00-00 00:00:00' ) {
2013-01-04 03:34:04 +00:00
$sql_extra .= " and created > ' $mindate ' " ;
2013-07-30 03:39:12 +00:00
$limit = " " ;
}
else
$limit = " limit 0, 50 " ;
2013-01-04 03:34:04 +00:00
2013-07-30 03:31:02 +00:00
$items = array ();
2013-01-04 03:34:04 +00:00
2013-07-30 03:31:02 +00:00
$r = q ( " SELECT item.*, item.id as item_id from item
WHERE uid = % d AND item_restrict = 0 and id = parent
2013-01-04 03:34:04 +00:00
AND ( item_flags & % d )
2013-07-30 03:39:12 +00:00
$sql_extra ORDER BY created ASC $limit " ,
2013-01-04 03:34:04 +00:00
intval ( $uid ),
intval ( ITEM_WALL )
);
2013-07-30 03:31:02 +00:00
if ( $r ) {
$parents_str = ids_to_querystr ( $r , 'id' );
$items = q ( " SELECT `item`.*, `item`.`id` AS `item_id` FROM `item`
WHERE `item` . `uid` = % d AND `item` . `item_restrict` = 0
AND `item` . `parent` IN ( % s ) " ,
intval ( $uid ),
dbesc ( $parents_str )
);
}
2013-01-04 03:34:04 +00:00
if ( $items ) {
xchan_query ( $items );
$items = fetch_post_tags ( $items );
2013-07-30 03:31:58 +00:00
require_once ( 'include/conversation.php' );
2013-07-30 03:31:02 +00:00
$items = conv_sort ( $items , 'ascending' );
2013-01-04 03:34:04 +00:00
}
2013-07-30 03:31:02 +00:00
else
$items = array ();
2013-01-04 03:34:04 +00:00
foreach ( $items as $item )
$result [] = encode_item ( $item );
return $result ;
}
2013-05-23 04:54:02 +00:00
2013-06-13 03:03:04 +00:00
function items_fetch ( $arr , $channel = null , $observer_hash = null , $client_mode = CLIENT_MODE_NORMAL , $module = 'network' ) {
2013-05-23 04:54:02 +00:00
$result = array ( 'success' => false );
2013-06-13 03:03:04 +00:00
$a = get_app ();
2013-05-23 04:54:02 +00:00
$sql_extra = '' ;
$sql_nets = '' ;
$sql_options = '' ;
$sql_extra2 = '' ;
$sql_extra3 = '' ;
2013-12-09 04:08:50 +00:00
$def_acl = '' ;
2013-05-24 01:50:27 +00:00
$item_uids = ' true ' ;
2014-01-25 02:50:47 +00:00
if ( $arr [ 'uid' ]) $uid = $arr [ 'uid' ];
2013-05-24 01:50:27 +00:00
if ( $channel ) {
$uid = $channel [ 'channel_id' ];
$uidhash = $channel [ 'channel_hash' ];
$item_uids = " item.uid = " . intval ( $uid ) . " " ;
}
2014-01-22 22:15:42 +00:00
2013-05-23 04:54:02 +00:00
if ( $arr [ 'star' ])
2013-06-13 03:03:04 +00:00
$sql_options .= " and (item_flags & " . intval ( ITEM_STARRED ) . " ) " ;
if ( $arr [ 'wall' ])
$sql_options .= " and (item_flags & " . intval ( ITEM_WALL ) . " ) " ;
2014-01-25 02:50:47 +00:00
2013-05-23 04:54:02 +00:00
$sql_extra = " AND item.parent IN ( SELECT parent FROM item WHERE (item_flags & " . intval ( ITEM_THREAD_TOP ) . " ) $sql_options ) " ;
2014-01-22 22:15:42 +00:00
if ( $arr [ 'since_id' ])
$sql_extra .= " and item.id > " . $since_id . " " ;
2013-12-09 04:08:50 +00:00
if ( $arr [ 'gid' ] && $uid ) {
2013-12-23 02:37:39 +00:00
$r = q ( " SELECT * FROM `groups` WHERE id = %d AND uid = %d LIMIT 1 " ,
2013-05-23 04:54:02 +00:00
intval ( $arr [ 'group' ]),
2013-05-24 01:50:27 +00:00
intval ( $uid )
2013-05-23 04:54:02 +00:00
);
if ( ! $r ) {
$result [ 'message' ] = t ( 'Collection not found.' );
return $result ;
}
2013-09-19 08:01:51 +00:00
$contact_str = '' ;
$contacts = group_get_members ( $group );
if ( $contacts ) {
foreach ( $contacts as $c ) {
if ( $contact_str )
$contact_str .= ',' ;
$contact_str .= " ' " . $c [ 'xchan' ] . " ' " ;
}
2013-05-23 04:54:02 +00:00
}
else {
2013-09-19 08:01:51 +00:00
$contact_str = ' 0 ' ;
2013-12-09 04:08:50 +00:00
$result [ 'message' ] = t ( 'Collection is empty.' );
return $result ;
2013-05-23 04:54:02 +00:00
}
2013-09-21 00:58:11 +00:00
$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 and item_restrict = 0 ) " ;
2013-05-23 04:54:02 +00:00
2013-12-09 04:08:50 +00:00
$x = group_rec_byhash ( $uid , $r [ 0 ][ 'hash' ]);
$result [ 'headline' ] = sprintf ( t ( 'Collection: %s' ), $x [ 'name' ]);
2013-05-23 04:54:02 +00:00
}
2013-05-24 01:50:27 +00:00
elseif ( $arr [ 'cid' ] && $uid ) {
2013-05-23 04:54:02 +00:00
2013-09-29 09:47:36 +00:00
$r = q ( " SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and not ( abook_flags & " . intval ( ABOOK_FLAG_BLOCKED ) . " ) limit 1 " ,
2013-05-23 04:54:02 +00:00
intval ( $arr [ 'cid' ]),
2013-09-29 09:47:36 +00:00
intval ( local_user ())
2013-05-23 04:54:02 +00:00
);
if ( $r ) {
2013-06-28 04:40:56 +00:00
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval ( $arr [ 'uid' ]) . " AND ( author_xchan = ' " . dbesc ( $r [ 0 ][ 'abook_xchan' ]) . " ' or owner_xchan = ' " . dbesc ( $r [ 0 ][ 'abook_xchan' ]) . " ' ) and item_restrict = 0 ) " ;
2013-12-09 04:08:50 +00:00
$result [ 'headline' ] = sprintf ( t ( 'Connection: %s' ), $r [ 0 ][ 'xchan_name' ]);
2013-05-23 04:54:02 +00:00
}
else {
$result [ 'message' ] = t ( 'Connection not found.' );
return $result ;
}
}
if ( $arr [ 'datequery' ]) {
$sql_extra3 .= protect_sprintf ( sprintf ( " AND item.created <= '%s' " , dbesc ( datetime_convert ( date_default_timezone_get (), '' , $arr [ 'datequery' ]))));
}
if ( $arr [ 'datequery2' ]) {
$sql_extra3 .= protect_sprintf ( sprintf ( " AND item.created >= '%s' " , dbesc ( datetime_convert ( date_default_timezone_get (), '' , $arr [ 'datequery2' ]))));
}
if ( ! array_key_exists ( 'nouveau' , $arr )) {
$sql_extra2 = " AND item.parent = item.id " ;
$sql_extra3 = '' ;
}
if ( $arr [ 'search' ]) {
if ( strpos ( $arr [ 'search' ], '#' ) === 0 )
$sql_extra .= term_query ( 'item' , substr ( $arr [ 'search' ], 1 ), TERM_HASHTAG );
else
$sql_extra .= sprintf ( " AND item.body like '%s' " ,
dbesc ( protect_sprintf ( '%' . $arr [ 'search' ] . '%' ))
);
}
if ( strlen ( $arr [ 'file' ])) {
$sql_extra .= term_query ( 'item' , $arr [ 'files' ], TERM_FILE );
}
2013-05-24 01:50:27 +00:00
if ( $arr [ 'conv' ] && $channel ) {
2013-05-23 04:54:02 +00:00
$sql_extra .= sprintf ( " AND parent IN (SELECT distinct parent from item where ( author_xchan like '%s' or ( item_flags & %d ))) " ,
2013-05-24 01:50:27 +00:00
dbesc ( protect_sprintf ( $uidhash )),
2013-05-23 04:54:02 +00:00
intval ( ITEM_MENTIONSME )
);
}
2014-01-25 23:51:10 +00:00
2013-05-24 01:50:27 +00:00
if (( $client_mode & CLIENT_MODE_UPDATE ) && ( ! ( $client_mode & CLIENT_MODE_LOAD ))) {
2013-05-23 04:54:02 +00:00
// only setup pagination on initial page view
$pager_sql = '' ;
}
else {
2013-05-24 01:50:27 +00:00
$itemspage = (( $channel ) ? get_pconfig ( $uid , 'system' , 'itemspage' ) : 20 );
2013-05-23 04:54:02 +00:00
$a -> set_pager_itemspage ((( intval ( $itemspage )) ? $itemspage : 20 ));
2013-05-24 01:50:27 +00:00
$pager_sql = sprintf ( " LIMIT %d, %d " , intval ( get_app () -> pager [ 'start' ]), intval ( get_app () -> pager [ 'itemspage' ]));
2013-05-23 04:54:02 +00:00
}
2014-01-25 23:51:10 +00:00
if ( isset ( $arr [ 'start' ]) && isset ( $arr [ 'records' ]))
$pager_sql = sprintf ( " LIMIT %d, %d " , intval ( $arr [ 'start' ]), intval ( $arr [ 'records' ]));
2013-05-23 04:54:02 +00:00
2013-05-24 01:50:27 +00:00
if (( $arr [ 'cmin' ] != 0 ) || ( $arr [ 'cmax' ] != 99 )) {
2013-05-23 04:54:02 +00:00
// Not everybody who shows up in the network stream will be in your address book.
// By default those that aren't are assumed to have closeness = 99; but this isn't
// recorded anywhere. So if cmax is 99, we'll open the search up to anybody in
// the stream with a NULL address book entry.
$sql_nets .= " AND " ;
2013-05-24 01:50:27 +00:00
if ( $arr [ 'cmax' ] == 99 )
2013-05-23 04:54:02 +00:00
$sql_nets .= " ( " ;
2013-05-24 01:50:27 +00:00
$sql_nets .= " ( abook.abook_closeness >= " . intval ( $arr [ 'cmin' ]) . " " ;
$sql_nets .= " AND abook.abook_closeness <= " . intval ( $arr [ 'cmax' ]) . " ) " ;
if ( $cmax == 99 )
2013-05-23 04:54:02 +00:00
$sql_nets .= " OR abook.abook_closeness IS NULL ) " ;
}
2013-05-24 01:50:27 +00:00
$simple_update = (( $client_mode & CLIENT_MODE_UPDATE ) ? " and ( item.item_flags & " . intval ( ITEM_UNSEEN ) . " ) " : '' );
if ( $client_mode & CLIENT_MODE_LOAD )
2013-05-23 04:54:02 +00:00
$simple_update = '' ;
$start = dba_timer ();
2013-06-14 00:53:16 +00:00
require_once ( 'include/security.php' );
2013-06-13 03:03:04 +00:00
$sql_extra .= item_permissions_sql ( $channel [ 'channel_id' ]);
2013-09-06 02:31:26 +00:00
if ( $arr [ 'pages' ])
$item_restrict = " AND (item_restrict & " . ITEM_WEBPAGE . " ) " ;
else
$item_restrict = " AND item_restrict = 0 " ;
2014-01-25 23:51:10 +00:00
if ( $arr [ 'nouveau' ] && ( $client_mode & CLIENT_MODE_LOAD ) && $channel ) {
2013-05-23 04:54:02 +00:00
// "New Item View" - show all items unthreaded in reverse created date order
2013-05-24 01:50:27 +00:00
$items = q ( " SELECT item.*, item.id AS item_id FROM item
2013-09-06 02:31:26 +00:00
WHERE $item_uids $item_restrict
2013-05-23 04:54:02 +00:00
$simple_update
$sql_extra $sql_nets
2013-05-24 01:50:27 +00:00
ORDER BY item . received DESC $pager_sql "
2013-05-23 04:54:02 +00:00
);
require_once ( 'include/items.php' );
xchan_query ( $items );
$items = fetch_post_tags ( $items , true );
}
2013-06-13 03:03:04 +00:00
else {
2013-05-23 04:54:02 +00:00
// Normal conversation view
2013-05-24 01:50:27 +00:00
if ( $arr [ 'order' ] === 'post' )
$ordering = " created " ;
2013-05-23 04:54:02 +00:00
else
2013-05-24 01:50:27 +00:00
$ordering = " commented " ;
2013-05-23 04:54:02 +00:00
2014-01-25 23:51:10 +00:00
if (( $client_mode & CLIENT_MODE_LOAD ) || ( $client_mode == CLIENT_MODE_NORMAL )) {
2013-05-23 04:54:02 +00:00
// Fetch a page full of parent items for this page
$r = q ( " SELECT distinct item.id AS item_id FROM item
left join abook on item . author_xchan = abook . abook_xchan
2013-09-06 02:31:26 +00:00
WHERE $item_uids $item_restrict
2013-05-23 04:54:02 +00:00
AND item . parent = item . id
and (( abook . abook_flags & % d ) = 0 or abook . abook_flags is null )
$sql_extra3 $sql_extra $sql_nets
ORDER BY item . $ordering DESC $pager_sql " ,
intval ( ABOOK_FLAG_BLOCKED )
);
2014-01-25 02:50:47 +00:00
2013-05-23 04:54:02 +00:00
}
else {
// update
$r = q ( " SELECT item.parent AS item_id FROM item
left join abook on item . author_xchan = abook . abook_xchan
2013-09-06 02:31:26 +00:00
WHERE $item_uids $item_restrict $simple_update
2013-05-23 04:54:02 +00:00
and (( abook . abook_flags & % d ) = 0 or abook . abook_flags is null )
$sql_extra3 $sql_extra $sql_nets " ,
intval ( ABOOK_FLAG_BLOCKED )
);
}
$first = dba_timer ();
// Then fetch all the children of the parents that are on this page
if ( $r ) {
$parents_str = ids_to_querystr ( $r , 'item_id' );
2013-05-24 01:50:27 +00:00
$items = q ( " SELECT item.*, item.id AS item_id FROM item
2013-09-06 02:31:26 +00:00
WHERE $item_uids $item_restrict
2013-05-24 01:50:27 +00:00
AND item . parent IN ( % s )
2013-05-23 04:54:02 +00:00
$sql_extra " ,
dbesc ( $parents_str )
);
$second = dba_timer ();
xchan_query ( $items );
$third = dba_timer ();
$items = fetch_post_tags ( $items , true );
$fourth = dba_timer ();
2013-06-13 03:03:04 +00:00
require_once ( 'include/conversation.php' );
2013-05-23 04:54:02 +00:00
$items = conv_sort ( $items , $ordering );
//logger('items: ' . print_r($items,true));
}
else {
$items = array ();
}
2013-06-13 03:03:04 +00:00
if ( $parents_str && $arr [ 'mark_seen' ])
2013-05-23 04:54:02 +00:00
$update_unseen = ' AND parent IN ( ' . dbesc ( $parents_str ) . ' )' ;
2013-06-13 03:03:04 +00:00
// FIXME finish mark unseen sql
2013-05-23 04:54:02 +00:00
}
2013-06-13 03:03:04 +00:00
return $items ;
2013-09-25 19:43:21 +00:00
}
2014-01-04 21:44:43 +00:00
function update_remote_id ( $channel , $post_id , $webpage , $pagetitle , $namespace , $remote_id , $mid ) {
$page_type = '' ;
if ( $webpage & ITEM_WEBPAGE )
$page_type = 'WEBPAGE' ;
elseif ( $webpage & ITEM_BUILDBLOCK )
$page_type = 'BUILDBLOCK' ;
elseif ( $webpage & ITEM_PDL )
$page_type = 'PDL' ;
elseif ( $namespace && $remote_id ) {
$page_type = $namespace ;
$pagetitle = $remote_id ;
}
if ( $page_type ) {
// store page info as an alternate message_id so we can access it via
// https://sitename/page/$channelname/$pagetitle
// if no pagetitle was given or it couldn't be transliterated into a url, use the first
// sixteen bytes of the mid - which makes the link portable and not quite as daunting
// as the entire mid. If it were the post_id the link would be less portable.
$r = q ( " select * from item_id where iid = %d and uid = %d and service = '%s' limit 1 " ,
intval ( $post_id ),
intval ( $channel [ 'channel_id' ]),
dbesc ( $page_type )
);
if ( $r ) {
q ( " update item_id set sid = '%s' where id = %d limit 1 " ,
dbesc (( $pagetitle ) ? $pagetitle : substr ( $mid , 0 , 16 )),
intval ( $r [ 0 ][ 'id' ])
);
}
else {
q ( " insert into item_id ( iid, uid, sid, service ) values ( %d, %d, '%s','%s' ) " ,
intval ( $post_id ),
intval ( $channel [ 'channel_id' ]),
dbesc (( $pagetitle ) ? $pagetitle : substr ( $mid , 0 , 16 )),
dbesc ( $page_type )
);
}
}
}