Exemplo n.º 1
0
function bb2diaspora($Text, $preserve_nl = false, $fordiaspora = true)
{
    $a = get_app();
    $OriginalText = $Text;
    // Since Diaspora is creating a summary for links, this function removes them before posting
    if ($fordiaspora) {
        $Text = bb_remove_share_information($Text);
    }
    /**
     * Transform #tags, strip off the [url] and replace spaces with underscore
     */
    $URLSearchString = "^\\[\\]";
    $Text = preg_replace_callback("/#\\[url\\=([{$URLSearchString}]*)\\](.*?)\\[\\/url\\]/i", create_function('$match', 'return \'#\'. str_replace(\' \', \'_\', $match[2]);'), $Text);
    // Converting images with size parameters to simple images. Markdown doesn't know it.
    $Text = preg_replace("/\\[img\\=([0-9]*)x([0-9]*)\\](.*?)\\[\\/img\\]/ism", '[img]$3[/img]', $Text);
    // Convert it to HTML - don't try oembed
    if ($fordiaspora) {
        $Text = bbcode($Text, $preserve_nl, false, 3);
        // Add all tags that maybe were removed
        if (preg_match_all("/#\\[url\\=([{$URLSearchString}]*)\\](.*?)\\[\\/url\\]/ism", $OriginalText, $tags)) {
            $tagline = "";
            foreach ($tags[2] as $tag) {
                $tag = html_entity_decode($tag, ENT_QUOTES, 'UTF-8');
                if (!strpos(html_entity_decode($Text, ENT_QUOTES, 'UTF-8'), "#" . $tag)) {
                    $tagline .= "#" . $tag . " ";
                }
            }
            $Text = $Text . " " . $tagline;
        }
    } else {
        $Text = bbcode($Text, $preserve_nl, false, 4);
    }
    // mask some special HTML chars from conversation to markdown
    $Text = str_replace(array('<', '>', '&'), array('&_lt_;', '&_gt_;', '&_amp_;'), $Text);
    // If a link is followed by a quote then there should be a newline before it
    // Maybe we should make this newline at every time before a quote.
    $Text = str_replace(array("</a><blockquote>"), array("</a><br><blockquote>"), $Text);
    $stamp1 = microtime(true);
    // Now convert HTML to Markdown
    $Text = new HTML_To_Markdown($Text);
    // unmask the special chars back to HTML
    $Text = str_replace(array('&_lt_;', '&_gt_;', '&_amp_;'), array('&lt;', '&gt;', '&amp;'), $Text);
    $a->save_timestamp($stamp1, "parser");
    // Libertree has a problem with escaped hashtags.
    $Text = str_replace(array('\\#'), array('#'), $Text);
    // Remove any leading or trailing whitespace, as this will mess up
    // the Diaspora signature verification and cause the item to disappear
    $Text = trim($Text);
    call_hooks('bb2diaspora', $Text);
    return $Text;
}
Exemplo n.º 2
0
function bb2diaspora($Text, $preserve_nl = false, $fordiaspora = true)
{
    // Since Diaspora is creating a summary for links, this function removes them before posting
    if ($fordiaspora) {
        $Text = bb_remove_share_information($Text);
    }
    /**
     * Transform #tags, strip off the [url] and replace spaces with underscore
     */
    $URLSearchString = "^\\[\\]";
    $Text = preg_replace_callback("/#\\[url\\=([{$URLSearchString}]*)\\](.*?)\\[\\/url\\]/i", create_function('$match', 'return \'#\'. str_replace(\' \', \'_\', $match[2]);'), $Text);
    // Converting images with size parameters to simple images. Markdown doesn't know it.
    $Text = preg_replace("/\\[img\\=([0-9]*)x([0-9]*)\\](.*?)\\[\\/img\\]/ism", '[img]$3[/img]', $Text);
    // Convert it to HTML - don't try oembed
    if ($fordiaspora) {
        $Text = bbcode($Text, $preserve_nl, false, 3);
    } else {
        $Text = bbcode($Text, $preserve_nl, false, 4);
        // Libertree doesn't convert a harizontal rule if there isn't a linefeed
        $Text = str_replace("<hr />", "<br /><hr />", $Text);
    }
    // Now convert HTML to Markdown
    $md = new Markdownify(false, false, false);
    $Text = $md->parseString($Text);
    // The Markdownify converter converts underscores '_' in URLs to '\_', which
    // messes up the URL. Manually fix these
    $count = 1;
    $pos = bb_find_open_close($Text, '[', ']', $count);
    while ($pos !== false) {
        $start = substr($Text, 0, $pos['start']);
        $subject = substr($Text, $pos['start'], $pos['end'] - $pos['start'] + 1);
        $end = substr($Text, $pos['end'] + 1);
        $subject = str_replace('\\_', '_', $subject);
        $Text = $start . $subject . $end;
        $count++;
        $pos = bb_find_open_close($Text, '[', ']', $count);
    }
    // If the text going into bbcode() has a plain URL in it, i.e.
    // with no [url] tags around it, it will come out of parseString()
    // looking like: <http://url.com>, which gets removed by strip_tags().
    // So take off the angle brackets of any such URL
    $Text = preg_replace("/<http(.*?)>/is", "http\$1", $Text);
    // Remove all unconverted tags
    $Text = strip_tags($Text);
    // Remove any leading or trailing whitespace, as this will mess up
    // the Diaspora signature verification and cause the item to disappear
    $Text = trim($Text);
    call_hooks('bb2diaspora', $Text);
    return $Text;
}
Exemplo n.º 3
0
function gpluspost_feeditem($pid, $uid)
{
    global $a;
    require_once 'include/api.php';
    require_once 'include/bbcode.php';
    require_once "include/html2plain.php";
    require_once "include/network.php";
    $skipwithoutlink = get_pconfig($uid, 'gpluspost', 'skip_without_link');
    $items = q("SELECT `uri`, `plink`, `author-link`, `author-name`, `created`, `edited`, `id`, `title`, `body` from `item` WHERE id=%d", intval($pid));
    foreach ($items as $item) {
        $item['body'] = bb_CleanPictureLinks($item['body']);
        $item['body'] = bb_remove_share_information($item['body'], true);
        if ($item["title"] != "") {
            $item['body'] = "*" . $item["title"] . "*\n\n" . $item['body'];
        }
        // Looking for the first image
        $image = '';
        if (preg_match("/\\[img\\=([0-9]*)x([0-9]*)\\](.*?)\\[\\/img\\]/is", $item['body'], $matches)) {
            $image = $matches[3];
        }
        if ($image == '') {
            if (preg_match("/\\[img\\](.*?)\\[\\/img\\]/is", $item['body'], $matches)) {
                $image = $matches[1];
            }
        }
        $multipleimages = strpos($item['body'], "[img") != strrpos($item['body'], "[img");
        // When saved into the database the content is sent through htmlspecialchars
        // That means that we have to decode all image-urls
        $image = htmlspecialchars_decode($image);
        $link = '';
        // look for bookmark-bbcode and handle it with priority
        if (preg_match("/\\[bookmark\\=([^\\]]*)\\](.*?)\\[\\/bookmark\\]/is", $item['body'], $matches)) {
            $link = $matches[1];
        }
        $multiplelinks = strpos($item['body'], "[bookmark") != strrpos($item['body'], "[bookmark");
        $body = $item['body'];
        $body = preg_replace("(\\[b\\](.*?)\\[\\/b\\])ism", '*$1*', $body);
        $body = preg_replace("(\\[i\\](.*?)\\[\\/i\\])ism", '_$1_', $body);
        $body = preg_replace("(\\[s\\](.*?)\\[\\/s\\])ism", '-$1-', $body);
        // At first convert the text to html
        $html = bbcode(api_clean_plain_items($body), false, false, 2);
        // Then convert it to plain text
        $msg = trim(html2plain($html, 0, true));
        $msg = html_entity_decode($msg, ENT_QUOTES, 'UTF-8');
        // If there is no bookmark element then take the first link
        if ($link == '') {
            $links = collecturls($html);
            if (sizeof($links) > 0) {
                reset($links);
                $link = current($links);
            }
            $multiplelinks = sizeof($links) > 1;
            if ($multiplelinks) {
                $html2 = bbcode($msg, false, false);
                $links2 = collecturls($html2);
                if (sizeof($links2) > 0) {
                    reset($links2);
                    $link = current($links2);
                    $multiplelinks = sizeof($links2) > 1;
                }
            }
        }
        $msglink = "";
        if ($multiplelinks) {
            $msglink = $item["plink"];
        } else {
            if ($link != "") {
                $msglink = $link;
            } else {
                if ($multipleimages) {
                    $msglink = $item["plink"];
                } else {
                    if ($image != "") {
                        $msglink = $image;
                    }
                }
            }
        }
        if ($msglink == "" and $skipwithoutlink) {
            continue;
        } else {
            if ($msglink == "") {
                $msglink = $item["plink"];
            }
        }
        // Fetching the title - or the first line
        if ($item["title"] != "") {
            $title = $item["title"];
        } else {
            $lines = explode("\n", $msg);
            $title = $lines[0];
        }
        //if ($image != $msglink)
        //	$html = trim(str_replace($msglink, "", $html));
        $title = trim(str_replace($msglink, "", $title));
        $msglink = original_url($msglink);
        if ($uid == 0) {
            $title = $item["author-name"] . ": " . $title;
        }
        $msglink = htmlspecialchars(html_entity_decode($msglink));
        if (strpos($msg, $msglink) == 0) {
            $msg .= "\n" . $msglink;
        }
        $msg = nl2br($msg);
        $title = str_replace("&", "&amp;", $title);
        //$html = str_replace("&", "&amp;", $html);
        echo "\t" . '<entry xmlns="http://www.w3.org/2005/Atom">' . "\n";
        echo "\t\t" . '<title type="html" xml:space="preserve"><![CDATA[' . $title . "]]></title>\n";
        echo "\t\t" . '<link rel="alternate" type="text/html" href="' . $msglink . '" />' . "\n";
        // <link rel="enclosure" type="audio/mpeg" length="1337" href="http://example.org/audio/ph34r_my_podcast.mp3"/>
        echo "\t\t<id>" . $item["uri"] . "</id>\n";
        echo "\t\t<updated>" . date("c", strtotime($item["edited"])) . "</updated>\n";
        echo "\t\t<published>" . date("c", strtotime($item["created"])) . "</published>\n";
        echo "\t\t<author>\n\t\t\t<name><![CDATA[" . $item["author-name"] . "]]></name>\n";
        echo "\t\t\t<uri>" . $item["author-link"] . "</uri>\n\t\t</author>\n";
        //echo '<content type="image/png" src="http://media.example.org/the_beach.png"/>';
        echo "\t\t" . '<content type="html" xml:space="preserve" xml:base="' . $item["plink"] . '"><![CDATA[' . $msg . "]]></content>\n";
        echo "\t</entry>\n";
    }
}
Exemplo n.º 4
0
function appnet_create_entities($a, $b, $postdata)
{
    require_once "include/bbcode.php";
    require_once "include/plaintext.php";
    $bbcode = $b["body"];
    $bbcode = bb_remove_share_information($bbcode, false, true);
    // Change pure links in text to bbcode uris
    $bbcode = preg_replace("/([^\\]\\='" . '"' . "]|^)(https?\\:\\/\\/[a-zA-Z0-9\\:\\/\\-\\?\\&\\;\\.\\=\\_\\~\\#\\%\$\\!\\+\\,]+)/ism", '$1[url=$2]$2[/url]', $bbcode);
    $URLSearchString = "^\\[\\]";
    $bbcode = preg_replace("/#\\[url\\=([{$URLSearchString}]*)\\](.*?)\\[\\/url\\]/ism", '#$2', $bbcode);
    $bbcode = preg_replace("/@\\[url\\=([{$URLSearchString}]*)\\](.*?)\\[\\/url\\]/ism", '@$2', $bbcode);
    $bbcode = preg_replace("/\\[bookmark\\=([{$URLSearchString}]*)\\](.*?)\\[\\/bookmark\\]/ism", '[url=$1]$2[/url]', $bbcode);
    $bbcode = preg_replace("/\\[video\\](.*?)\\[\\/video\\]/ism", '[url=$1]$1[/url]', $bbcode);
    $bbcode = preg_replace("/\\[youtube\\]https?:\\/\\/(.*?)\\[\\/youtube\\]/ism", '[url=https://$1]https://$1[/url]', $bbcode);
    $bbcode = preg_replace("/\\[youtube\\]([A-Za-z0-9\\-_=]+)(.*?)\\[\\/youtube\\]/ism", '[url=https://www.youtube.com/watch?v=$1]https://www.youtube.com/watch?v=$1[/url]', $bbcode);
    $bbcode = preg_replace("/\\[vimeo\\]https?:\\/\\/(.*?)\\[\\/vimeo\\]/ism", '[url=https://$1]https://$1[/url]', $bbcode);
    $bbcode = preg_replace("/\\[vimeo\\]([0-9]+)(.*?)\\[\\/vimeo\\]/ism", '[url=https://vimeo.com/$1]https://vimeo.com/$1[/url]', $bbcode);
    //$bbcode = preg_replace("/\[vimeo\](.*?)\[\/vimeo\]/ism",'[url=$1]$1[/url]',$bbcode);
    $bbcode = preg_replace("/\\[img\\=([0-9]*)x([0-9]*)\\](.*?)\\[\\/img\\]/ism", '[img]$3[/img]', $bbcode);
    preg_match_all("/\\[url\\=([{$URLSearchString}]*)\\](.*?)\\[\\/url\\]/ism", $bbcode, $urls, PREG_SET_ORDER);
    $bbcode = preg_replace("/\\[url\\=([{$URLSearchString}]*)\\](.*?)\\[\\/url\\]/ism", '$1', $bbcode);
    $b["body"] = $bbcode;
    // To-Do:
    // Bilder
    // https://alpha.app.net/heluecht/post/32424376
    // https://alpha.app.net/heluecht/post/32424307
    $plaintext = plaintext($a, $b, 0, false, 6);
    $text = $plaintext["text"];
    $start = 0;
    $entities = array();
    foreach ($urls as $url) {
        $lenurl = iconv_strlen($url[1], "UTF-8");
        $len = iconv_strlen($url[2], "UTF-8");
        $pos = iconv_strpos($text, $url[1], $start, "UTF-8");
        $pre = iconv_substr($text, 0, $pos, "UTF-8");
        $post = iconv_substr($text, $pos + $lenurl, 1000000, "UTF-8");
        $mid = $url[2];
        $html = bbcode($mid, false, false, 6);
        $mid = html2plain($html, 0, true);
        $mid = trim(html_entity_decode($mid, ENT_QUOTES, 'UTF-8'));
        $text = $pre . $mid . $post;
        if ($mid != "") {
            $entities[] = array("pos" => $pos, "len" => $len, "url" => $url[1], "text" => $mid);
        }
        $start = $pos + 1;
    }
    if (isset($postdata["url"]) and isset($postdata["title"]) and $postdata["type"] != "photo") {
        $postdata["title"] = shortenmsg($postdata["title"], 90);
        $max = 256 - strlen($postdata["title"]);
        $text = shortenmsg($text, $max);
        $text .= "\n[" . $postdata["title"] . "](" . $postdata["url"] . ")";
    } elseif (isset($postdata["url"]) and $postdata["type"] != "photo") {
        $postdata["url"] = short_link($postdata["url"]);
        $max = 240;
        $text = shortenmsg($text, $max);
        $text .= " [" . $postdata["url"] . "](" . $postdata["url"] . ")";
    } else {
        $max = 256;
        $text = shortenmsg($text, $max);
    }
    if (iconv_strlen($text, "UTF-8") < $max) {
        $max = iconv_strlen($text, "UTF-8");
    }
    krsort($entities);
    foreach ($entities as $entity) {
        //if (iconv_strlen($text, "UTF-8") >= $entity["pos"] + $entity["len"]) {
        if ($entity["pos"] + $entity["len"] <= $max) {
            $pre = iconv_substr($text, 0, $entity["pos"], "UTF-8");
            $post = iconv_substr($text, $entity["pos"] + $entity["len"], 1000000, "UTF-8");
            $text = $pre . "[" . $entity["text"] . "](" . $entity["url"] . ")" . $post;
        }
    }
    return $text;
}
Exemplo n.º 5
0
function tumblr_send(&$a, &$b)
{
    if ($b['deleted'] || $b['private'] || $b['created'] !== $b['edited']) {
        return;
    }
    if (!strstr($b['postopts'], 'tumblr')) {
        return;
    }
    if ($b['parent'] != $b['id']) {
        return;
    }
    $oauth_token = get_pconfig($b['uid'], "tumblr", "oauth_token");
    $oauth_token_secret = get_pconfig($b['uid'], "tumblr", "oauth_token_secret");
    $page = get_pconfig($b['uid'], "tumblr", "page");
    $tmbl_blog = 'blog/' . $page . '/post';
    if ($oauth_token && $oauth_token_secret && $tmbl_blog) {
        require_once 'include/bbcode.php';
        $tag_arr = array();
        $tags = '';
        $x = preg_match_all('/\\#\\[(.*?)\\](.*?)\\[/', $b['tag'], $matches, PREG_SET_ORDER);
        if ($x) {
            foreach ($matches as $mtch) {
                $tag_arr[] = $mtch[2];
            }
        }
        if (count($tag_arr)) {
            $tags = implode(',', $tag_arr);
        }
        $title = trim($b['title']);
        require_once 'include/plaintext.php';
        $siteinfo = get_attached_data($b["body"]);
        $params = array('state' => 'published', 'tags' => $tags, 'tweet' => 'off', 'format' => 'html');
        if (!isset($siteinfo["type"])) {
            $siteinfo["type"] = "";
        }
        if ($title == "" and isset($siteinfo["title"])) {
            $title = $siteinfo["title"];
        }
        if (isset($siteinfo["text"])) {
            $body = $siteinfo["text"];
        } else {
            $body = bb_remove_share_information($b["body"]);
        }
        switch ($siteinfo["type"]) {
            case "photo":
                $params['type'] = "photo";
                $params['caption'] = bbcode($body, false, false, 4);
                if (isset($siteinfo["url"])) {
                    $params['link'] = $siteinfo["url"];
                }
                $params['source'] = $siteinfo["image"];
                break;
            case "link":
                $params['type'] = "link";
                $params['title'] = $title;
                $params['url'] = $siteinfo["url"];
                $params['description'] = bbcode($body, false, false, 4);
                break;
            case "audio":
                $params['type'] = "audio";
                $params['external_url'] = $siteinfo["url"];
                $params['caption'] = bbcode($body, false, false, 4);
                break;
            case "video":
                $params['type'] = "video";
                $params['embed'] = $siteinfo["url"];
                $params['caption'] = bbcode($body, false, false, 4);
                break;
            default:
                $params['type'] = "text";
                $params['title'] = $title;
                $params['body'] = bbcode($b['body'], false, false, 4);
                break;
        }
        if (isset($params['caption']) and trim($title) != "") {
            $params['caption'] = '<h1>' . $title . "</h1>" . "<p>" . $params['caption'] . "</p>";
        }
        if (trim($params['caption']) == "") {
            $params['caption'] = bbcode("[quote]" . $siteinfo["description"] . "[/quote]", false, false, 4);
        }
        $consumer_key = get_config('tumblr', 'consumer_key');
        $consumer_secret = get_config('tumblr', 'consumer_secret');
        $tum_oauth = new TumblrOAuth($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret);
        // Make an API call with the TumblrOAuth instance.
        $x = $tum_oauth->post($tmbl_blog, $params);
        $ret_code = $tum_oauth->http_code;
        //print_r($params);
        if ($ret_code == 201) {
            logger('tumblr_send: success');
        } elseif ($ret_code == 403) {
            logger('tumblr_send: authentication failure');
        } else {
            logger('tumblr_send: general error: ' . print_r($x, true));
        }
    }
}
Exemplo n.º 6
0
function atom_entry($item, $type, $author, $owner, $comment = false, $cid = 0)
{
    $a = get_app();
    if (!$item['parent']) {
        return;
    }
    if ($item['deleted']) {
        return '<at:deleted-entry ref="' . xmlify($item['uri']) . '" when="' . xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00', ATOM_TIME)) . '" />' . "\r\n";
    }
    if ($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid']) {
        $body = fix_private_photos($item['body'], $owner['uid'], $item, $cid);
    } else {
        $body = $item['body'];
    }
    $o = "\r\n\r\n<entry>\r\n";
    if (is_array($author)) {
        $o .= atom_author('author', $author['name'], $author['url'], 80, 80, $author['thumb']);
    } else {
        $o .= atom_author('author', $item['author-name'] ? $item['author-name'] : $item['name'], $item['author-link'] ? $item['author-link'] : $item['url'], 80, 80, $item['author-avatar'] ? $item['author-avatar'] : $item['thumb']);
    }
    if (strlen($item['owner-name'])) {
        $o .= atom_author('dfrn:owner', $item['owner-name'], $item['owner-link'], 80, 80, $item['owner-avatar']);
    }
    if ($item['parent'] != $item['id'] || $item['parent-uri'] !== $item['uri'] || $item['thr-parent'] !== '' && $item['thr-parent'] !== $item['uri']) {
        $parent_item = $item['thr-parent'] ? $item['thr-parent'] : $item['parent-uri'];
        $o .= '<thr:in-reply-to ref="' . xmlify($parent_item) . '" type="text/html" href="' . xmlify($a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['parent']) . '" />' . "\r\n";
    }
    $htmlbody = $body;
    if ($item['title'] != "") {
        $htmlbody = "[b]" . $item['title'] . "[/b]\n\n" . $htmlbody;
    }
    $htmlbody = bbcode(bb_remove_share_information($htmlbody), false, false, 7);
    $o .= '<id>' . xmlify($item['uri']) . '</id>' . "\r\n";
    $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";
    $o .= '<dfrn:env>' . base64url_encode($body, true) . '</dfrn:env>' . "\r\n";
    $o .= '<content type="' . $type . '" >' . xmlify($type === 'html' ? $htmlbody : $body) . '</content>' . "\r\n";
    $o .= '<link rel="alternate" type="text/html" href="' . xmlify($a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id']) . '" />' . "\r\n";
    if ($comment) {
        $o .= '<dfrn:comment-allow>' . intval($item['last-child']) . '</dfrn:comment-allow>' . "\r\n";
    }
    if ($item['location']) {
        $o .= '<dfrn:location>' . xmlify($item['location']) . '</dfrn:location>' . "\r\n";
        $o .= '<poco:address><poco:formatted>' . xmlify($item['location']) . '</poco:formatted></poco:address>' . "\r\n";
    }
    if ($item['coord']) {
        $o .= '<georss:point>' . xmlify($item['coord']) . '</georss:point>' . "\r\n";
    }
    if ($item['private'] || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) {
        $o .= '<dfrn:private>' . ($item['private'] ? $item['private'] : 1) . '</dfrn:private>' . "\r\n";
    }
    if ($item['extid']) {
        $o .= '<dfrn:extid>' . xmlify($item['extid']) . '</dfrn:extid>' . "\r\n";
    }
    if ($item['bookmark']) {
        $o .= '<dfrn:bookmark>true</dfrn:bookmark>' . "\r\n";
    }
    if ($item['app']) {
        $o .= '<statusnet:notice_info local_id="' . $item['id'] . '" source="' . xmlify($item['app']) . '" ></statusnet:notice_info>' . "\r\n";
    }
    if ($item['guid']) {
        $o .= '<dfrn:diaspora_guid>' . $item['guid'] . '</dfrn:diaspora_guid>' . "\r\n";
    }
    if ($item['signed_text']) {
        $sign = base64_encode(json_encode(array('signed_text' => $item['signed_text'], 'signature' => $item['signature'], 'signer' => $item['signer'])));
        $o .= '<dfrn:diaspora_signature>' . xmlify($sign) . '</dfrn:diaspora_signature>' . "\r\n";
    }
    $verb = construct_verb($item);
    $o .= '<as:verb>' . xmlify($verb) . '</as:verb>' . "\r\n";
    $actobj = construct_activity_object($item);
    if (strlen($actobj)) {
        $o .= $actobj;
    }
    $actarg = construct_activity_target($item);
    if (strlen($actarg)) {
        $o .= $actarg;
    }
    $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";
        }
    }
    $o .= item_getfeedattach($item);
    $mentioned = get_mentions($item);
    if ($mentioned) {
        $o .= $mentioned;
    }
    call_hooks('atom_entry', $o);
    $o .= '</entry>' . "\r\n";
    return $o;
}