X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fitems.php;h=15fd262f4c0d35958f545f476d28c5698c893844;hb=97b608db38edac6e4989c7343e9de8f32f46f263;hp=04b86ab3fe55605226c3cf98ee21743e7738c885;hpb=9513f1f1668a33be3fc2b241fe3662e9de42d84b;p=friendica.git diff --git a/include/items.php b/include/items.php index 04b86ab3fe..15fd262f4c 100644 --- a/include/items.php +++ b/include/items.php @@ -1,8 +1,10 @@ '%s' OR `item`.`changed` > '%s' ) $sql_extra @@ -143,6 +185,7 @@ function get_feed_for(&$a, $dfrn_id, $owner_id, $last_update, $direction = 0) { $atom .= replace_macros($feed_template, array( + '$version' => xmlify(FRIENDIKA_VERSION), '$feed_id' => xmlify($a->get_baseurl() . '/profile/' . $owner_nick), '$feed_title' => xmlify($owner['name']), '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', 'now' , ATOM_TIME)) , @@ -154,11 +197,16 @@ function get_feed_for(&$a, $dfrn_id, $owner_id, $last_update, $direction = 0) { '$thumb' => xmlify($owner['thumb']), '$picdate' => xmlify(datetime_convert('UTC','UTC',$owner['avatar-date'] . '+00:00' , ATOM_TIME)) , '$uridate' => xmlify(datetime_convert('UTC','UTC',$owner['uri-date'] . '+00:00' , ATOM_TIME)) , - '$namdate' => xmlify(datetime_convert('UTC','UTC',$owner['name-date'] . '+00:00' , ATOM_TIME)) + '$namdate' => xmlify(datetime_convert('UTC','UTC',$owner['name-date'] . '+00:00' , ATOM_TIME)) , + '$birthday' => ((strlen($birthday)) ? '' . xmlify($birthday) . '' : '') )); + call_hooks('atom_feed', $atom); if(! count($items)) { + + call_hooks('atom_feed_end', $atom); + $atom .= '' . "\r\n"; return $atom; } @@ -177,7 +225,10 @@ function get_feed_for(&$a, $dfrn_id, $owner_id, $last_update, $direction = 0) { $atom .= atom_entry($item,$type,null,$owner,true); } + call_hooks('atom_feed_end', $atom); + $atom .= '' . "\r\n"; + return $atom; } @@ -326,13 +377,28 @@ function get_atom_elements($feed,$item) { } + /** + * 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']); + // make sure nobody is trying to sneak some html tags by us + $res['body'] = notags(base64url_decode($res['body'])); + } + $maxlen = get_max_import_size(); if($maxlen && (strlen($res['body']) > $maxlen)) $res['body'] = substr($res['body'],0, $maxlen); // 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 - // html if we used a pubsubhubbub transport. But if we see even one html open tag in our text, we will + // html if we used a pubsubhubbub transport. But if we see even one html tag in our text, we will // 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 @@ -341,11 +407,13 @@ function get_atom_elements($feed,$item) { // html. - if(strpos($res['body'],'<')) { + if((strpos($res['body'],'<') !== false) || (strpos($res['body'],'>') !== false)) { $res['body'] = preg_replace('#]+>.+?' . 'http://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?#s', '[youtube]$1[/youtube]', $res['body']); + $res['body'] = oembed_html2bbcode($res['body']); + $config = HTMLPurifier_Config::createDefault(); $config->set('Cache.DefinitionImpl', null); @@ -355,30 +423,46 @@ function get_atom_elements($feed,$item) { $purifier = new HTMLPurifier($config); $res['body'] = $purifier->purify($res['body']); - } + $res['body'] = html2bbcode($res['body']); + } - $res['body'] = html2bbcode($res['body']); - - $allow = $item->get_item_tags(NAMESPACE_DFRN,'comment-allow'); if($allow && $allow[0]['data'] == 1) $res['last-child'] = 1; else $res['last-child'] = 0; - $rawcreated = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'published'); - if($rawcreated) - $res['created'] = unxmlify($rawcreated[0]['data']); + $private = $item->get_item_tags(NAMESPACE_DFRN,'private'); + if($private && $private[0]['data'] == 1) + $res['private'] = 1; + else + $res['private'] = 0; + $rawlocation = $item->get_item_tags(NAMESPACE_DFRN, 'location'); if($rawlocation) $res['location'] = unxmlify($rawlocation[0]['data']); + $rawcreated = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'published'); + if($rawcreated) + $res['created'] = unxmlify($rawcreated[0]['data']); + + $rawedited = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'updated'); if($rawedited) - $res['edited'] = unxmlify($rawcreated[0]['data']); + $res['edited'] = unxmlify($rawedited[0]['data']); + + if((x($res,'edited')) && (! (x($res,'created')))) + $res['created'] = $res['edited']; + + if(! $res['created']) + $res['created'] = $item->get_date('c'); + + if(! $res['edited']) + $res['edited'] = $item->get_date('c'); + $rawowner = $item->get_item_tags(NAMESPACE_DFRN, 'owner'); if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']) @@ -407,9 +491,19 @@ function get_atom_elements($feed,$item) { $rawverb = $item->get_item_tags(NAMESPACE_ACTIVITY, 'verb'); + // select between supported verbs - if($rawverb) + + if($rawverb) { $res['verb'] = unxmlify($rawverb[0]['data']); + } + + // 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; + + $rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'object'); @@ -429,7 +523,9 @@ function get_atom_elements($feed,$item) { $body = $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']; if(! $body) $body = $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data']; - if(strpos($body,'<')) { + // preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events + $res['object'] .= '' . xmlify($body) . '' . "\n"; + if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) { $body = preg_replace('#]+>.+?' . 'http://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?#s', '[youtube]$1[/youtube]', $body); @@ -439,9 +535,9 @@ function get_atom_elements($feed,$item) { $purifier = new HTMLPurifier($config); $body = $purifier->purify($body); + $body = html2bbcode($body); } - $body = html2bbcode($body); $res['object'] .= '' . $body . '' . "\n"; } @@ -466,7 +562,9 @@ function get_atom_elements($feed,$item) { $body = $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']; if(! $body) $body = $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data']; - if(strpos($body,'<')) { + // preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events + $res['object'] .= '' . xmlify($body) . '' . "\n"; + if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) { $body = preg_replace('#]+>.+?' . 'http://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?#s', '[youtube]$1[/youtube]', $body); @@ -476,15 +574,19 @@ function get_atom_elements($feed,$item) { $purifier = new HTMLPurifier($config); $body = $purifier->purify($body); + $body = html2bbcode($body); } - $body = html2bbcode($body); $res['target'] .= '' . $body . '' . "\n"; } $res['target'] .= '' . "\n"; } + $arr = array('feed' => $feed, 'item' => $item, 'result' => $res); + + call_hooks('parse_atom', $arr); + return $res; } @@ -499,7 +601,7 @@ function encode_rel_links($links) { if($link['attribs']['']['type']) $o .= 'type="' . $link['attribs']['']['type'] . '" '; if($link['attribs']['']['href']) - $o .= 'type="' . $link['attribs']['']['href'] . '" '; + $o .= 'href="' . $link['attribs']['']['href'] . '" '; if( (x($link['attribs'],NAMESPACE_MEDIA)) && $link['attribs'][NAMESPACE_MEDIA]['width']) $o .= 'media:width="' . $link['attribs'][NAMESPACE_MEDIA]['width'] . '" '; if( (x($link['attribs'],NAMESPACE_MEDIA)) && $link['attribs'][NAMESPACE_MEDIA]['height']) @@ -509,7 +611,7 @@ function encode_rel_links($links) { return xmlify($o); } -function item_store($arr) { +function item_store($arr,$force_parent = false) { if($arr['gravity']) $arr['gravity'] = intval($arr['gravity']); @@ -522,6 +624,13 @@ function item_store($arr) { if(! x($arr,'type')) $arr['type'] = 'remote'; + + // Shouldn't happen but we want to make absolutely sure it doesn't leak from a plugin. + + if((strpos($arr['body'],'<') !== false) || (strpos($arr['body'],'>') !== false)) + $arr['body'] = strip_tags($arr['body']); + + $arr['wall'] = ((x($arr,'wall')) ? intval($arr['wall']) : 0); $arr['uri'] = ((x($arr,'uri')) ? notags(trim($arr['uri'])) : random_string()); $arr['author-name'] = ((x($arr,'author-name')) ? notags(trim($arr['author-name'])) : ''); @@ -549,15 +658,8 @@ function item_store($arr) { $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['body'] = ((x($arr,'body')) ? escape_tags(trim($arr['body'])) : ''); - - // The content body has been through a lot of filtering and transport escaping by now. - // We don't want to skip any filters, however a side effect of all this filtering - // is that ampersands will have been double encoded. - - $arr['body'] = str_replace('&amp;','&',$arr['body']); - - + $arr['private'] = ((x($arr,'private')) ? intval($arr['private']) : 0 ); + $arr['body'] = ((x($arr,'body')) ? trim($arr['body']) : ''); if($arr['parent-uri'] === $arr['uri']) { $parent_id = 0; @@ -576,18 +678,43 @@ function item_store($arr) { ); if(count($r)) { - $parent_id = $r[0]['id']; - $allow_cid = $r[0]['allow_cid']; - $allow_gid = $r[0]['allow_gid']; - $deny_cid = $r[0]['deny_cid']; - $deny_gid = $r[0]['deny_gid']; + + // 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. + + if($r[0]['uri'] != $r[0]['parent-uri']) { + $arr['thr-parent'] = $arr['parent-uri']; + $arr['parent-uri'] = $r[0]['parent-uri']; + } + + $parent_id = $r[0]['id']; + $parent_deleted = $r[0]['deleted']; + $allow_cid = $r[0]['allow_cid']; + $allow_gid = $r[0]['allow_gid']; + $deny_cid = $r[0]['deny_cid']; + $deny_gid = $r[0]['deny_gid']; } else { - logger('item_store: item parent was not found - ignoring item'); - return 0; + + // Allow one to see reply tweets from status.net even when + // we don't have or can't see the original post. + + if($force_parent) { + logger('item_store: $force_parent=true, reply converted to top-level post.'); + $parent_id = 0; + $arr['thr-parent'] = $arr['parent-uri']; + $arr['parent-uri'] = $arr['uri']; + } + else { + logger('item_store: item parent was not found - ignoring item'); + return 0; + } } } + call_hooks('post_remote',$arr); + dbesc_array($arr); logger('item_store: ' . print_r($arr,true), LOGGER_DATA); @@ -613,18 +740,25 @@ function item_store($arr) { return 0; } - if($arr['parent-uri'] === $arr['uri']) + if((! $parent_id) || ($arr['parent-uri'] === $arr['uri'])) $parent_id = $current_post; - + + if(strlen($allow_cid) || strlen($allow_gid) || strlen($deny_cid) || strlen($deny_gid)) + $private = 1; + else + $private = $arr['private']; + // Set parent id - and also make sure to inherit the parent's ACL's. $r = q("UPDATE `item` SET `parent` = %d, `allow_cid` = '%s', `allow_gid` = '%s', - `deny_cid` = '%s', `deny_gid` = '%s' WHERE `id` = %d LIMIT 1", + `deny_cid` = '%s', `deny_gid` = '%s', `private` = %d, `deleted` = %d WHERE `id` = %d LIMIT 1", intval($parent_id), dbesc($allow_cid), dbesc($allow_gid), dbesc($deny_cid), dbesc($deny_gid), + intval($private), + intval($parent_deleted), intval($current_post) ); @@ -644,11 +778,11 @@ function get_item_contact($item,$contacts) { } -function dfrn_deliver($owner,$contact,$atom) { +function dfrn_deliver($owner,$contact,$atom, $dissolve = false) { $a = get_app(); - if((! strlen($contact['dfrn-id'])) && (! $contact['duplex']) && (! ($owner['page-flags'] == PAGE_COMMUNITY))) + if((! strlen($contact['issued-id'])) && (! $contact['duplex']) && (! ($owner['page-flags'] == PAGE_COMMUNITY))) return 3; $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']); @@ -680,27 +814,34 @@ function dfrn_deliver($owner,$contact,$atom) { if(! $xml) return 3; + if(strpos($xml,'status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id))) return (($res->status) ? $res->status : 3); $postvars = array(); - $sent_dfrn_id = hex2bin($res->dfrn_id); - $challenge = hex2bin($res->challenge); + $sent_dfrn_id = hex2bin((string) $res->dfrn_id); + $challenge = hex2bin((string) $res->challenge); + $dfrn_version = (float) (($res->dfrn_version) ? $res->dfrn_version : 2.0); $rino_allowed = ((intval($res->rino) === 1) ? 1 : 0); $final_dfrn_id = ''; - if(($contact['duplex'] && strlen($contact['prvkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) { - openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']); - openssl_private_decrypt($challenge,$postvars['challenge'],$contact['prvkey']); - } - else { + if(($contact['duplex'] && strlen($contact['pubkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) { openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']); openssl_public_decrypt($challenge,$postvars['challenge'],$contact['pubkey']); } + else { + openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']); + openssl_private_decrypt($challenge,$postvars['challenge'],$contact['prvkey']); + } $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.')); @@ -715,6 +856,8 @@ function dfrn_deliver($owner,$contact,$atom) { $postvars['dfrn_id'] = $idtosend; $postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION; + if($dissolve) + $postvars['dissolve'] = '1'; if(($contact['rel']) && ($contact['rel'] != REL_FAN) && (! $contact['blocked']) && (! $contact['readonly'])) { $postvars['data'] = $atom; @@ -726,17 +869,28 @@ function dfrn_deliver($owner,$contact,$atom) { $postvars['data'] = str_replace('1','0',$atom); } - if($rino && $rino_allowed) { + if($rino && $rino_allowed && (! $dissolve)) { $key = substr(random_string(),0,16); $data = bin2hex(aes_encrypt($postvars['data'],$key)); $postvars['data'] = $data; logger('rino: sent key = ' . $key); - if(($contact['duplex'] && strlen($contact['prvkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) { - openssl_private_encrypt($key,$postvars['key'],$contact['prvkey']); + + if($dfrn_version >= 2.1) { + if(($contact['duplex'] && strlen($contact['pubkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) { + openssl_public_encrypt($key,$postvars['key'],$contact['pubkey']); + } + else { + openssl_private_encrypt($key,$postvars['key'],$contact['prvkey']); + } } else { - openssl_public_encrypt($key,$postvars['key'],$contact['pubkey']); + if(($contact['duplex'] && strlen($contact['prvkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) { + openssl_private_encrypt($key,$postvars['key'],$contact['prvkey']); + } + else { + openssl_public_encrypt($key,$postvars['key'],$contact['pubkey']); + } } logger('md5 rawkey ' . md5($postvars['key'])); @@ -754,6 +908,13 @@ function dfrn_deliver($owner,$contact,$atom) { if((! $curl_stat) || (! strlen($xml))) return(-1); // timed out + + if(strpos($xml,'status; @@ -777,7 +938,7 @@ function dfrn_deliver($owner,$contact,$atom) { * */ -function consume_feed($xml,$importer,$contact, &$hub, $datedir = 0) { +function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0) { require_once('simplepie/simplepie.inc'); @@ -789,13 +950,17 @@ function consume_feed($xml,$importer,$contact, &$hub, $datedir = 0) { $feed->enable_order_by_date(false); $feed->init(); + if($feed->error()) + logger('consume_feed: Error parsing XML: ' . $feed->error()); + + // Check at the feed level for updated contact name and/or photo $name_updated = ''; $new_name = ''; $photo_timestamp = ''; $photo_url = ''; - + $birthday = ''; $hubs = $feed->get_links('hub'); @@ -813,10 +978,14 @@ function consume_feed($xml,$importer,$contact, &$hub, $datedir = 0) { $photo_timestamp = datetime_convert('UTC','UTC',$elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated']); $photo_url = $elems['link'][0]['attribs']['']['href']; } + + if((x($rawtags[0]['child'], NAMESPACE_DFRN)) && (x($rawtags[0]['child'][NAMESPACE_DFRN],'birthday'))) { + $birthday = datetime_convert('UTC','UTC', $rawtags[0]['child'][NAMESPACE_DFRN]['birthday'][0]['data']); + } } if((is_array($contact)) && ($photo_timestamp) && (strlen($photo_url)) && ($photo_timestamp > $contact['avatar-date'])) { - logger('Consume feed: Updating photo for ' . $contact['name']); + logger('consume_feed: Updating photo for ' . $contact['name']); require_once("Photo.php"); $photo_failure = false; $have_photo = false; @@ -878,9 +1047,63 @@ function consume_feed($xml,$importer,$contact, &$hub, $datedir = 0) { ); } + if(strlen($birthday)) { + if(substr($birthday,0,4) != $contact['bdyear']) { + logger('consume_feed: updating birthday: ' . $birthday); + + /** + * + * Add new birthday event for this person + * + * $bdtext is just a readable placeholder in case the event is shared + * with others. We will replace it during presentation to our $importer + * to contain a sparkle link and perhaps a photo. + * + */ + + $bdtext = t('Birthday:') . ' [url=' . $contact['url'] . ']' . $contact['name'] . '[/url]' ; + + + $r = q("INSERT INTO `event` (`uid`,`cid`,`created`,`edited`,`start`,`finish`,`desc`,`type`) + VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s' ) ", + intval($contact['uid']), + intval($contact['id']), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc(datetime_convert('UTC','UTC', $birthday)), + dbesc(datetime_convert('UTC','UTC', $birthday . ' + 1 day ')), + dbesc($bdtext), + dbesc('birthday') + ); + + + // update bdyear + + q("UPDATE `contact` SET `bdyear` = '%s' WHERE `uid` = %d AND `id` = %d LIMIT 1", + dbesc(substr($birthday,0,4)), + intval($contact['uid']), + intval($contact['id']) + ); + + // This function is called twice without reloading the contact + // Make sure we only create one event. This is why &$contact + // is a reference var in this function + + $contact['bdyear'] = substr($birthday,0,4); + } + + } + // Now process the feed if($feed->get_item_quantity()) { - foreach($feed->get_items() as $item) { + + // in inverse date order + if ($datedir) + $items = array_reverse($feed->get_items()); + else + $items = $feed->get_items(); + + foreach($items as $item) { $deleted = false; @@ -985,7 +1208,9 @@ function consume_feed($xml,$importer,$contact, &$hub, $datedir = 0) { continue; } $datarray = get_atom_elements($feed,$item); + $force_parent = false; if($contact['network'] === 'stat') { + $force_parent = true; if(strlen($datarray['title'])) unset($datarray['title']); $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d", @@ -995,6 +1220,11 @@ function consume_feed($xml,$importer,$contact, &$hub, $datedir = 0) { ); $datarray['last-child'] = 1; } + + if(($contact['network'] === 'feed') || (! strlen($contact['notify']))) { + // one way feed - no remote comment ability + $datarray['last-child'] = 0; + } $datarray['parent-uri'] = $parent_uri; $datarray['uid'] = $importer['uid']; $datarray['contact-id'] = $contact['id']; @@ -1003,7 +1233,7 @@ function consume_feed($xml,$importer,$contact, &$hub, $datedir = 0) { $datarray['gravity'] = GRAVITY_LIKE; } - $r = item_store($datarray); + $r = item_store($datarray,$force_parent); continue; } @@ -1047,6 +1277,11 @@ function consume_feed($xml,$importer,$contact, &$hub, $datedir = 0) { $datarray['last-child'] = 1; } + if(($contact['network'] === 'feed') || (! strlen($contact['notify']))) { + // one way feed - no remote comment ability + $datarray['last-child'] = 0; + } + $datarray['parent-uri'] = $item_id; $datarray['uid'] = $importer['uid']; $datarray['contact-id'] = $contact['id']; @@ -1056,7 +1291,6 @@ function consume_feed($xml,$importer,$contact, &$hub, $datedir = 0) { } } } - } function new_follower($importer,$contact,$datarray,$item) { @@ -1118,6 +1352,7 @@ function new_follower($importer,$contact,$datarray,$item) { $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer['uid']) ); + $a = get_app(); if(count($r)) { if(($r[0]['notify-flags'] & NOTIFY_INTRO) && ($r[0]['page-flags'] == PAGE_NORMAL)) { $email_tpl = load_view_file('view/follow_notify_eml.tpl'); @@ -1201,6 +1436,9 @@ function atom_author($tag,$name,$uri,$h,$w,$photo) { $o .= "$uri\r\n"; $o .= '' . "\r\n"; $o .= '' . "\r\n"; + + call_hooks('atom_author', $o); + $o .= "\r\n"; return $o; } @@ -1228,6 +1466,7 @@ function atom_entry($item,$type,$author,$owner,$comment = false) { $o .= '' . xmlify($item['title']) . '' . "\r\n"; $o .= '' . xmlify(datetime_convert('UTC','UTC',$item['created'] . '+00:00',ATOM_TIME)) . '' . "\r\n"; $o .= '' . xmlify(datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)) . '' . "\r\n"; + $o .= '' . base64url_encode($item['body'], true) . '' . "\r\n"; $o .= '' . xmlify(($type === 'html') ? bbcode($item['body']) : $item['body']) . '' . "\r\n"; $o .= '' . "\r\n"; if($comment) @@ -1241,6 +1480,9 @@ function atom_entry($item,$type,$author,$owner,$comment = false) { if($item['coord']) $o .= '' . xmlify($item['coord']) . '' . "\r\n"; + if(($item['private']) || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) + $o .= '1' . "\r\n"; + $verb = construct_verb($item); $o .= '' . xmlify($verb) . '' . "\r\n"; $actobj = construct_activity_object($item); @@ -1254,8 +1496,10 @@ function atom_entry($item,$type,$author,$owner,$comment = false) { if($mentioned) $o .= $mentioned; + call_hooks('atom_entry', $o); + $o .= '' . "\r\n"; return $o; } - \ No newline at end of file +