Example #1
0
function get_atom_elements($item)
{
    $res = array();
    $author = $item->get_author();
    $res['author-name'] = unxmlify($author->get_name());
    $res['author-link'] = unxmlify($author->get_link());
    $res['author-avatar'] = unxmlify($author->get_avatar());
    $res['uri'] = unxmlify($item->get_id());
    $res['title'] = unxmlify($item->get_title());
    $res['body'] = unxmlify($item->get_content());
    $maxlen = get_max_import_size();
    if ($maxlen && strlen($res['body']) > $maxlen) {
        $res['body'] = substr($res['body'], 0, $maxlen);
    }
    $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']);
    }
    $rawedited = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated');
    if ($rawedited) {
        $res['edited'] = unxmlify($rawcreated[0]['data']);
    }
    $rawowner = $item->get_item_tags(NAMESPACE_DFRN, 'owner');
    if ($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data']) {
        $res['owner-name'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data']);
    }
    if ($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data']) {
        $res['owner-link'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data']);
    }
    if ($rawowner[0]['child'][NAMESPACE_DFRN]['avatar'][0]['data']) {
        $res['owner-avatar'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['avatar'][0]['data']);
    }
    return $res;
}
Example #2
0
function get_item_elements($x)
{
    $arr = array();
    $arr['body'] = $x['body'] ? htmlspecialchars($x['body'], ENT_COMPAT, 'UTF-8', false) : '';
    $key = get_config('system', 'pubkey');
    $maxlen = get_max_import_size();
    if ($maxlen && mb_strlen($arr['body']) > $maxlen) {
        $arr['body'] = mb_substr($arr['body'], 0, $maxlen, 'UTF-8');
        logger('get_item_elements: message length exceeds max_import_size: truncated');
    }
    $arr['created'] = datetime_convert('UTC', 'UTC', $x['created']);
    $arr['edited'] = datetime_convert('UTC', 'UTC', $x['edited']);
    if ($arr['created'] > datetime_convert()) {
        $arr['created'] = datetime_convert();
    }
    if ($arr['edited'] > datetime_convert()) {
        $arr['edited'] = datetime_convert();
    }
    $arr['expires'] = x($x, 'expires') && $x['expires'] ? datetime_convert('UTC', 'UTC', $x['expires']) : NULL_DATE;
    $arr['commented'] = x($x, 'commented') && $x['commented'] ? datetime_convert('UTC', 'UTC', $x['commented']) : $arr['created'];
    $arr['comments_closed'] = x($x, 'comments_closed') && $x['comments_closed'] ? datetime_convert('UTC', 'UTC', $x['comments_closed']) : NULL_DATE;
    $arr['title'] = $x['title'] ? htmlspecialchars($x['title'], ENT_COMPAT, 'UTF-8', false) : '';
    if (mb_strlen($arr['title']) > 255) {
        $arr['title'] = mb_substr($arr['title'], 0, 255);
    }
    $arr['app'] = $x['app'] ? htmlspecialchars($x['app'], ENT_COMPAT, 'UTF-8', false) : '';
    $arr['route'] = $x['route'] ? htmlspecialchars($x['route'], 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) : '';
    $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['public_policy'] = $x['public_scope'] ? htmlspecialchars($x['public_scope'], ENT_COMPAT, 'UTF-8', false) : '';
    if ($arr['public_policy'] === 'public') {
        $arr['public_policy'] = '';
    }
    $arr['comment_policy'] = $x['comment_scope'] ? htmlspecialchars($x['comment_scope'], ENT_COMPAT, 'UTF-8', false) : 'contacts';
    $arr['sig'] = $x['signature'] ? htmlspecialchars($x['signature'], ENT_COMPAT, 'UTF-8', false) : '';
    $arr['diaspora_meta'] = $x['diaspora_signature'] ? json_encode(crypto_encapsulate($x['diaspora_signature'], $key)) : '';
    $arr['object'] = activity_sanitise($x['object']);
    $arr['target'] = activity_sanitise($x['target']);
    $arr['attach'] = activity_sanitise($x['attach']);
    $arr['term'] = decode_tags($x['tags']);
    $arr['item_private'] = array_key_exists('flags', $x) && is_array($x['flags']) && in_array('private', $x['flags']) ? 1 : 0;
    $arr['item_flags'] = 0;
    if (array_key_exists('flags', $x) && in_array('consensus', $x['flags'])) {
        $arr['item_flags'] |= ITEM_CONSENSUS;
    }
    if (array_key_exists('flags', $x) && in_array('deleted', $x['flags'])) {
        $arr['item_restrict'] |= ITEM_DELETED;
    }
    if (array_key_exists('flags', $x) && in_array('hidden', $x['flags'])) {
        $arr['item_restrict'] |= ITEM_HIDDEN;
    }
    // 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.
    if (($xchan_hash = import_author_xchan($x['author'])) !== false) {
        $arr['author_xchan'] = $xchan_hash;
    } else {
        return array();
    }
    // save a potentially expensive lookup if author == owner
    if ($arr['author_xchan'] === make_xchan_hash($x['owner']['guid'], $x['owner']['guid_sig'])) {
        $arr['owner_xchan'] = $arr['author_xchan'];
    } else {
        if (($xchan_hash = import_author_xchan($x['owner'])) !== false) {
            $arr['owner_xchan'] = $xchan_hash;
        } else {
            return array();
        }
    }
    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;
        if ($arr['title']) {
            $arr['title'] = json_encode(crypto_encapsulate($arr['title'], $key));
        }
        if ($arr['body']) {
            $arr['body'] = json_encode(crypto_encapsulate($arr['body'], $key));
        }
    }
    if (array_key_exists('revision', $x)) {
        // extended export encoding
        $arr['revision'] = $x['revision'];
        $arr['allow_cid'] = $x['allow_cid'];
        $arr['allow_gid'] = $x['allow_gid'];
        $arr['deny_cid'] = $x['deny_cid'];
        $arr['deny_gid'] = $x['deny_gid'];
        $arr['layout_mid'] = $x['layout_mid'];
        $arr['postopts'] = $x['postopts'];
        $arr['resource_id'] = $x['resource_id'];
        $arr['resource_type'] = $x['resource_type'];
        $arr['item_restrict'] = $x['item_restrict'];
        $arr['item_flags'] = $x['item_flags'];
        $arr['attach'] = $x['attach'];
    }
    return $arr;
}
Example #3
0
function get_atom_elements($item)
{
    require_once 'library/HTMLPurifier.auto.php';
    require_once 'include/html2bbcode.php';
    $res = array();
    $raw_author = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author');
    if ($raw_author) {
        if ($raw_author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['rel'] == 'photo') {
            $res['author-avatar'] = unxmlify($raw_author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['href']);
        }
    }
    $author = $item->get_author();
    $res['author-name'] = unxmlify($author->get_name());
    $res['author-link'] = unxmlify($author->get_link());
    if (!$res['author-avatar']) {
        $res['author-avatar'] = unxmlify($author->get_avatar());
    }
    $res['uri'] = unxmlify($item->get_id());
    $res['title'] = unxmlify($item->get_title());
    $res['body'] = unxmlify($item->get_content());
    $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
    // 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.
    if (strpos($res['body'], '<')) {
        $res['body'] = preg_replace('#<object[^>]+>.+?' . 'http://www.youtube.com/((?:v|cp)/[A-Za-z0-9\\-_=]+).+?</object>#s', '[youtube]$1[/youtube]', $res['body']);
        $config = HTMLPurifier_Config::createDefault();
        $config->set('Core.DefinitionCache', null);
        // we shouldn't need a whitelist, because the bbcode converter
        // will strip out any unsupported tags.
        // $config->set('HTML.Allowed', 'p,b,a[href],i');
        $purifier = new HTMLPurifier($config);
        $res['body'] = $purifier->purify($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']);
    }
    $rawlocation = $item->get_item_tags(NAMESPACE_DFRN, 'location');
    if ($rawlocation) {
        $res['location'] = unxmlify($rawlocation[0]['data']);
    }
    $rawedited = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated');
    if ($rawedited) {
        $res['edited'] = unxmlify($rawcreated[0]['data']);
    }
    $rawowner = $item->get_item_tags(NAMESPACE_DFRN, 'owner');
    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']) {
        $res['owner-name'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data']);
    }
    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']) {
        $res['owner-link'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data']);
    }
    if ($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['rel'] == 'photo') {
        $res['owner-avatar'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['href']);
    } elseif ($rawowner[0]['child'][NAMESPACE_DFRN]['avatar'][0]['data']) {
        $res['owner-avatar'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['avatar'][0]['data']);
    }
    $rawverb = $item->get_item_tags(NAMESPACE_ACTIVITY, 'verb');
    // select between supported verbs
    if ($rawverb) {
        $res['verb'] = unxmlify($rawverb[0]['data']);
    }
    $rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'object');
    if ($rawobj) {
        $res['object-type'] = $rawobj[0]['object-type'][0]['data'];
        $res['object'] = $rawobj[0];
    }
    return $res;
}
Example #4
0
function get_item_elements($x, $allow_code = false)
{
    $arr = array();
    if ($allow_code) {
        $arr['body'] = $x['body'];
    } else {
        $arr['body'] = $x['body'] ? htmlspecialchars($x['body'], ENT_COMPAT, 'UTF-8', false) : '';
    }
    $key = get_config('system', 'pubkey');
    $maxlen = get_max_import_size();
    if ($maxlen && mb_strlen($arr['body']) > $maxlen) {
        $arr['body'] = mb_substr($arr['body'], 0, $maxlen, 'UTF-8');
        logger('get_item_elements: message length exceeds max_import_size: truncated');
    }
    $arr['created'] = datetime_convert('UTC', 'UTC', $x['created']);
    $arr['edited'] = datetime_convert('UTC', 'UTC', $x['edited']);
    if ($arr['created'] > datetime_convert()) {
        $arr['created'] = datetime_convert();
    }
    if ($arr['edited'] > datetime_convert()) {
        $arr['edited'] = datetime_convert();
    }
    $arr['expires'] = x($x, 'expires') && $x['expires'] ? datetime_convert('UTC', 'UTC', $x['expires']) : NULL_DATE;
    $arr['commented'] = x($x, 'commented') && $x['commented'] ? datetime_convert('UTC', 'UTC', $x['commented']) : $arr['created'];
    $arr['comments_closed'] = x($x, 'comments_closed') && $x['comments_closed'] ? datetime_convert('UTC', 'UTC', $x['comments_closed']) : NULL_DATE;
    $arr['title'] = $x['title'] ? htmlspecialchars($x['title'], ENT_COMPAT, 'UTF-8', false) : '';
    if (mb_strlen($arr['title']) > 255) {
        $arr['title'] = mb_substr($arr['title'], 0, 255);
    }
    $arr['app'] = $x['app'] ? htmlspecialchars($x['app'], ENT_COMPAT, 'UTF-8', false) : '';
    $arr['route'] = $x['route'] ? htmlspecialchars($x['route'], 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) : '';
    $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['public_policy'] = $x['public_scope'] ? htmlspecialchars($x['public_scope'], ENT_COMPAT, 'UTF-8', false) : '';
    if ($arr['public_policy'] === 'public') {
        $arr['public_policy'] = '';
    }
    $arr['comment_policy'] = $x['comment_scope'] ? htmlspecialchars($x['comment_scope'], ENT_COMPAT, 'UTF-8', false) : 'contacts';
    $arr['sig'] = $x['signature'] ? htmlspecialchars($x['signature'], ENT_COMPAT, 'UTF-8', false) : '';
    if (array_key_exists('diaspora_signature', $x) && is_array($x['diaspora_signature'])) {
        $x['diaspora_signature'] = json_encode($x['diaspora_signature']);
    }
    $arr['diaspora_meta'] = $x['diaspora_signature'] ? $x['diaspora_signature'] : '';
    $arr['object'] = activity_sanitise($x['object']);
    $arr['target'] = activity_sanitise($x['target']);
    $arr['attach'] = activity_sanitise($x['attach']);
    $arr['term'] = decode_tags($x['tags']);
    $arr['item_private'] = array_key_exists('flags', $x) && is_array($x['flags']) && in_array('private', $x['flags']) ? 1 : 0;
    $arr['item_flags'] = 0;
    if (array_key_exists('flags', $x) && in_array('consensus', $x['flags'])) {
        $arr['item_consensus'] = 1;
    }
    if (array_key_exists('flags', $x) && in_array('deleted', $x['flags'])) {
        $arr['item_deleted'] = 1;
    }
    if (array_key_exists('flags', $x) && in_array('hidden', $x['flags'])) {
        $arr['item_hidden'] = 1;
    }
    // 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.
    if (($xchan_hash = import_author_xchan($x['author'])) !== false) {
        $arr['author_xchan'] = $xchan_hash;
    } else {
        return array();
    }
    // save a potentially expensive lookup if author == owner
    if ($arr['author_xchan'] === make_xchan_hash($x['owner']['guid'], $x['owner']['guid_sig'])) {
        $arr['owner_xchan'] = $arr['author_xchan'];
    } else {
        if (($xchan_hash = import_author_xchan($x['owner'])) !== false) {
            $arr['owner_xchan'] = $xchan_hash;
        } else {
            return array();
        }
    }
    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_verified'] = 1;
        } else {
            logger('get_item_elements: message verification failed.');
        }
    }
    if (array_key_exists('revision', $x)) {
        // extended export encoding
        $arr['revision'] = $x['revision'];
        $arr['allow_cid'] = $x['allow_cid'];
        $arr['allow_gid'] = $x['allow_gid'];
        $arr['deny_cid'] = $x['deny_cid'];
        $arr['deny_gid'] = $x['deny_gid'];
        $arr['layout_mid'] = $x['layout_mid'];
        $arr['postopts'] = $x['postopts'];
        $arr['resource_id'] = $x['resource_id'];
        $arr['resource_type'] = $x['resource_type'];
        $arr['attach'] = $x['attach'];
        $arr['item_origin'] = $x['item_origin'];
        $arr['item_unseen'] = $x['item_unseen'];
        $arr['item_starred'] = $x['item_starred'];
        $arr['item_uplink'] = $x['item_uplink'];
        $arr['item_consensus'] = $x['item_consensus'];
        $arr['item_wall'] = $x['item_wall'];
        $arr['item_thread_top'] = $x['item_thread_top'];
        $arr['item_notshown'] = $x['item_notshown'];
        $arr['item_nsfw'] = $x['item_nsfw'];
        // local only		$arr['item_relay'] = $x['item_relay'];
        $arr['item_mentionsme'] = $x['item_mentionsme'];
        $arr['item_nocomment'] = $x['item_nocomment'];
        // local only $arr['item_obscured'] = $x['item_obscured'];
        // local only $arr['item_verified'] = $x['item_verified'];
        $arr['item_retained'] = $x['item_retained'];
        $arr['item_rss'] = $x['item_rss'];
        $arr['item_deleted'] = $x['item_deleted'];
        $arr['item_type'] = $x['item_type'];
        $arr['item_hidden'] = $x['item_hidden'];
        $arr['item_unpublished'] = $x['item_unpublished'];
        $arr['item_delayed'] = $x['item_delayed'];
        $arr['item_pending_remove'] = $x['item_pending_remove'];
        $arr['item_blocked'] = $x['item_blocked'];
        if (array_key_exists('item_flags', $x)) {
            if ($x['item_flags'] & 0x4) {
                $arr['item_starred'] = 1;
            }
            if ($x['item_flags'] & 0x8) {
                $arr['item_uplink'] = 1;
            }
            if ($x['item_flags'] & 0x10) {
                $arr['item_consensus'] = 1;
            }
            if ($x['item_flags'] & 0x20) {
                $arr['item_wall'] = 1;
            }
            if ($x['item_flags'] & 0x40) {
                $arr['item_thread_top'] = 1;
            }
            if ($x['item_flags'] & 0x80) {
                $arr['item_notshown'] = 1;
            }
            if ($x['item_flags'] & 0x100) {
                $arr['item_nsfw'] = 1;
            }
            if ($x['item_flags'] & 0x400) {
                $arr['item_mentionsme'] = 1;
            }
            if ($x['item_flags'] & 0x800) {
                $arr['item_nocomment'] = 1;
            }
            if ($x['item_flags'] & 0x4000) {
                $arr['item_retained'] = 1;
            }
            if ($x['item_flags'] & 0x8000) {
                $arr['item_rss'] = 1;
            }
        }
        if (array_key_exists('item_restrict', $x)) {
            if ($x['item_restrict'] & 0x1) {
                $arr['item_hidden'] = 1;
            }
            if ($x['item_restrict'] & 0x2) {
                $arr['item_blocked'] = 1;
            }
            if ($x['item_restrict'] & 0x10) {
                $arr['item_deleted'] = 1;
            }
            if ($x['item_restrict'] & 0x20) {
                $arr['item_unpublished'] = 1;
            }
            if ($x['item_restrict'] & 0x40) {
                $arr['item_type'] = ITEM_TYPE_WEBPAGE;
            }
            if ($x['item_restrict'] & 0x80) {
                $arr['item_delayed'] = 1;
            }
            if ($x['item_restrict'] & 0x100) {
                $arr['item_type'] = ITEM_TYPE_BLOCK;
            }
            if ($x['item_restrict'] & 0x200) {
                $arr['item_type'] = ITEM_TYPE_PDL;
            }
            if ($x['item_restrict'] & 0x400) {
                $arr['item_type'] = ITEM_TYPE_BUG;
            }
            if ($x['item_restrict'] & 0x800) {
                $arr['item_pending_remove'] = 1;
            }
            if ($x['item_restrict'] & 0x1000) {
                $arr['item_type'] = ITEM_TYPE_DOC;
            }
        }
    }
    return $arr;
}
Example #5
0
 function limit_body_size($body)
 {
     //	logger('limit_body_size: start', LOGGER_DEBUG);
     $maxlen = get_max_import_size();
     // If the length of the body, including the embedded images, is smaller
     // than the maximum, then don't waste time looking for the images
     if ($maxlen && strlen($body) > $maxlen) {
         logger('limit_body_size: the total body length exceeds the limit', LOGGER_DEBUG);
         $orig_body = $body;
         $new_body = '';
         $textlen = 0;
         $max_found = false;
         $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) {
             $img_st_close++;
             // make it point to AFTER the closing bracket
             $img_end += $img_start;
             $img_end += strlen('[/img]');
             if (!strcmp(substr($orig_body, $img_start + $img_st_close, 5), 'data:')) {
                 // This is an embedded image
                 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;
                     }
                 } else {
                     $new_body = $new_body . substr($orig_body, 0, $img_start);
                     $textlen += $img_start;
                 }
                 $new_body = $new_body . substr($orig_body, $img_start, $img_end - $img_start);
             } else {
                 if ($textlen + $img_end > $maxlen) {
                     if ($textlen < $maxlen) {
                         logger('limit_body_size: the limit happens before the end of a non-embedded image', LOGGER_DEBUG);
                         $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;
                 }
             }
             $orig_body = substr($orig_body, $img_end);
             if ($orig_body === false) {
                 // in case the body ends on a closing image tag
                 $orig_body = '';
             }
             $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;
         }
         if ($textlen + strlen($orig_body) > $maxlen) {
             if ($textlen < $maxlen) {
                 logger('limit_body_size: the limit happens after the end of the last image', LOGGER_DEBUG);
                 $new_body = $new_body . substr($orig_body, 0, $maxlen - $textlen);
                 $textlen = $maxlen;
             }
         } else {
             logger('limit_body_size: the text size with embedded images extracted did not violate the limit', LOGGER_DEBUG);
             $new_body = $new_body . $orig_body;
             $textlen += strlen($orig_body);
         }
         return $new_body;
     } else {
         return $body;
     }
 }
Example #6
0
function diaspora_message($importer, $xml, $msg)
{
    $a = get_app();
    $msg_guid = notags(unxmlify($xml->guid));
    $msg_parent_guid = notags(unxmlify($xml->parent_guid));
    $msg_parent_author_signature = notags(unxmlify($xml->parent_author_signature));
    $msg_author_signature = notags(unxmlify($xml->author_signature));
    $msg_text = unxmlify($xml->text);
    $msg_created_at = datetime_convert('UTC', 'UTC', notags(unxmlify($xml->created_at)));
    $msg_diaspora_handle = notags(unxmlify($xml->diaspora_handle));
    $msg_conversation_guid = notags(unxmlify($xml->conversation_guid));
    $parent_uri = $msg_parent_guid;
    $contact = diaspora_get_contact_by_handle($importer['channel_id'], $msg_diaspora_handle);
    if (!$contact) {
        logger('diaspora_message: cannot find contact: ' . $msg_diaspora_handle);
        return;
    }
    if ($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['blocked'] || $contact['readonly']) {
        logger('diaspora_message: Ignoring this author.');
        return 202;
    }
    $conversation = null;
    $c = q("select * from conv where uid = %d and guid = '%s' limit 1", intval($importer['channel_id']), dbesc($msg_conversation_guid));
    if ($c) {
        $conversation = $c[0];
    } else {
        logger('diaspora_message: conversation not available.');
        return;
    }
    $reply = 0;
    $subject = $conversation['subject'];
    $body = diaspora2bb($msg_text);
    $maxlen = get_max_import_size();
    if ($maxlen && mb_strlen($body) > $maxlen) {
        $body = mb_substr($body, 0, $maxlen, 'UTF-8');
        logger('message length exceeds max_import_size: truncated');
    }
    $message_id = $msg_diaspora_handle . ':' . $msg_guid;
    $author_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($xml->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
    $author_signature = base64_decode($msg_author_signature);
    $person = find_diaspora_person_by_handle($msg_diaspora_handle);
    if (is_array($person) && x($person, 'xchan_pubkey')) {
        $key = $person['xchan_pubkey'];
    } else {
        logger('diaspora_message: unable to find author details');
        return;
    }
    if (!rsa_verify($author_signed_data, $author_signature, $key, 'sha256')) {
        logger('diaspora_message: verification failed.');
        return;
    }
    $r = q("select id from mail where mid = '%s' and channel_id = %d limit 1", dbesc($message_id), intval($importer['channel_id']));
    if ($r) {
        logger('diaspora_message: duplicate message already delivered.', LOGGER_DEBUG);
        return;
    }
    $key = get_config('system', 'pubkey');
    if ($subject) {
        $subject = json_encode(crypto_encapsulate($subject, $key));
    }
    if ($body) {
        $body = json_encode(crypto_encapsulate($body, $key));
    }
    q("insert into mail ( `channel_id`, `convid`, `from_xchan`,`to_xchan`,`title`,`body`,`mail_flags`,`mid`,`parent_mid`,`created`) values ( %d, %d, '%s', '%s', '%s', '%s', '%d','%s','%s','%s')", intval($importer['channel_id']), intval($conversation['id']), dbesc($person['xchan_hash']), dbesc($importer['xchan_hash']), dbesc($subject), dbesc($body), intval(MAIL_OBSCURED), dbesc($msg_guid), dbesc($parent_uri), dbesc($msg_created_at));
    q("update conv set updated = '%s' where id = %d", dbesc(datetime_convert()), intval($conversation['id']));
    return;
}
Example #7
0
function diaspora_message($importer, $xml, $msg)
{
    $a = get_app();
    $msg_guid = notags(unxmlify($xml['guid']));
    $msg_parent_guid = notags(unxmlify($xml['parent_guid']));
    $msg_parent_author_signature = notags(unxmlify($xml['parent_author_signature']));
    $msg_author_signature = notags(unxmlify($xml['author_signature']));
    $msg_text = unxmlify($xml['text']);
    $msg_created_at = datetime_convert('UTC', 'UTC', notags(unxmlify($xml['created_at'])));
    $msg_diaspora_handle = notags(diaspora_get_author($xml));
    $msg_conversation_guid = notags(unxmlify($xml['conversation_guid']));
    $parent_uri = $msg_parent_guid;
    $contact = diaspora_get_contact_by_handle($importer['channel_id'], $msg_diaspora_handle);
    if (!$contact) {
        logger('diaspora_message: cannot find contact: ' . $msg_diaspora_handle);
        return;
    }
    if (!perm_is_allowed($importer['channel_id'], $contact['xchan_hash'], 'post_mail')) {
        logger('Ignoring this author.');
        return 202;
    }
    $conversation = null;
    $c = q("select * from conv where uid = %d and guid = '%s' limit 1", intval($importer['channel_id']), dbesc($msg_conversation_guid));
    if ($c) {
        $conversation = $c[0];
    } else {
        logger('diaspora_message: conversation not available.');
        return;
    }
    $reply = 0;
    $subject = $conversation['subject'];
    //this is already encoded
    $body = diaspora2bb($msg_text);
    $maxlen = get_max_import_size();
    if ($maxlen && mb_strlen($body) > $maxlen) {
        $body = mb_substr($body, 0, $maxlen, 'UTF-8');
        logger('message length exceeds max_import_size: truncated');
    }
    $parent_ptr = $msg_parent_guid;
    if ($parent_ptr === $conversation['guid']) {
        // this should always be the case
        $x = q("select mid from mail where conv_guid = '%s' and channel_id = %d order by id asc limit 1", dbesc($conversation['guid']), intval($importer['channel_id']));
        if ($x) {
            $parent_ptr = $x[0]['mid'];
        }
    }
    $author_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($xml['created_at']) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
    $author_signature = base64_decode($msg_author_signature);
    $person = find_diaspora_person_by_handle($msg_diaspora_handle);
    if (is_array($person) && x($person, 'xchan_pubkey')) {
        $key = $person['xchan_pubkey'];
    } else {
        logger('diaspora_message: unable to find author details');
        return;
    }
    if (!rsa_verify($author_signed_data, $author_signature, $key, 'sha256')) {
        logger('diaspora_message: verification failed.');
        return;
    }
    $r = q("select id from mail where mid = '%s' and channel_id = %d limit 1", dbesc($msg_guid), intval($importer['channel_id']));
    if ($r) {
        logger('diaspora_message: duplicate message already delivered.', LOGGER_DEBUG);
        return;
    }
    $key = get_config('system', 'pubkey');
    // $subject is a copy of the already obscured subject from the conversation structure
    if ($body) {
        $body = str_rot47(base64url_encode($body));
    }
    q("insert into mail ( `account_id`, `channel_id`, `convid`, `conv_guid`, `from_xchan`,`to_xchan`,`title`,`body`,`mail_obscured`,`mid`,`parent_mid`,`created`, mail_isreply) values ( %d, %d, %d, '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', %d)", intval($importer['channel_account_id']), intval($importer['channel_id']), intval($conversation['id']), dbesc($conversation['guid']), dbesc($person['xchan_hash']), dbesc($importer['xchan_hash']), dbesc($subject), dbesc($body), intval(1), dbesc($msg_guid), dbesc($parent_ptr), dbesc($msg_created_at), intval(1));
    q("update conv set updated = '%s' where id = %d", dbesc(datetime_convert()), intval($conversation['id']));
    $z = q("select * from mail where mid = '%s' and channel_id = %d limit 1", dbesc($msg_guid), intval($importer['channel_id']));
    \Zotlabs\Lib\Enotify::submit(array('from_xchan' => $person['xchan_hash'], 'to_xchan' => $importer['channel_hash'], 'type' => NOTIFY_MAIL, 'item' => $z[0], 'verb' => ACTIVITY_POST, 'otype' => 'mail'));
    return;
}
Example #8
0
function get_atom_elements($feed, $item)
{
    require_once 'library/HTMLPurifier.auto.php';
    require_once 'include/html2bbcode.php';
    $best_photo = array();
    $res = array();
    $author = $item->get_author();
    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());
    }
    $res['uri'] = unxmlify($item->get_id());
    $res['title'] = unxmlify($item->get_title());
    $res['body'] = unxmlify($item->get_content());
    $res['plink'] = unxmlify($item->get_link(0));
    if ($res['plink']) {
        $base_url = implode('/', array_slice(explode('/', $res['plink']), 0, 3));
    } else {
        $base_url = '';
    }
    // 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) {
            if (!x($res, 'author-avatar') || !$res['author-avatar']) {
                if ($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar') {
                    $res['author-avatar'] = unxmlify($link['attribs']['']['href']);
                }
            }
        }
    }
    $rawactor = $item->get_item_tags(NAMESPACE_ACTIVITY, 'actor');
    if ($rawactor && activity_match($rawactor[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'], ACTIVITY_OBJ_PERSON)) {
        $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']);
                }
                if (!x($res, 'author-avatar') || !$res['author-avatar']) {
                    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
    if (!x($res, 'author-link') || !x($res, 'author-avatar')) {
        $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']);
                    }
                }
            }
        }
        $rawactor = $feed->get_feed_tags(NAMESPACE_ACTIVITY, 'subject');
        if ($rawactor && activity_match($rawactor[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'], ACTIVITY_OBJ_PERSON)) {
            $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']);
                    }
                    if (!x($res, 'author-avatar')) {
                        if ($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo') {
                            $res['author-avatar'] = unxmlify($link['attribs']['']['href']);
                        }
                    }
                }
            }
        }
    }
    $apps = $item->get_item_tags(NAMESPACE_STATUSNET, 'notice_info');
    if ($apps && $apps[0]['attribs']['']['source']) {
        $res['app'] = strip_tags(unxmlify($apps[0]['attribs']['']['source']));
        if ($res['app'] === 'web') {
            $res['app'] = 'OStatus';
        }
    }
    // base64 encoded json structure representing Diaspora signature
    $dsig = $item->get_item_tags(NAMESPACE_DFRN, 'diaspora_signature');
    if ($dsig) {
        $res['dsprsig'] = unxmlify($dsig[0]['data']);
    }
    $dguid = $item->get_item_tags(NAMESPACE_DFRN, 'diaspora_guid');
    if ($dguid) {
        $res['guid'] = unxmlify($dguid[0]['data']);
    }
    $bm = $item->get_item_tags(NAMESPACE_DFRN, 'bookmark');
    if ($bm) {
        $res['bookmark'] = unxmlify($bm[0]['data']) === 'true' ? 1 : 0;
    }
    /**
     * 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 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
    // 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.
    if (strpos($res['body'], '<') !== false && strpos($res['body'], '>') !== false) {
        $res['body'] = reltoabs($res['body'], $base_url);
        $res['body'] = html2bb_video($res['body']);
        $res['body'] = oembed_html2bbcode($res['body']);
        $config = HTMLPurifier_Config::createDefault();
        $config->set('Cache.DefinitionImpl', null);
        // we shouldn't need a whitelist, because the bbcode converter
        // will strip out any unsupported tags.
        $purifier = new HTMLPurifier($config);
        $res['body'] = $purifier->purify($res['body']);
        $res['body'] = @html2bbcode($res['body']);
    } 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']);
    }
    // this tag is obsolete but we keep it for really old sites
    $allow = $item->get_item_tags(NAMESPACE_DFRN, 'comment-allow');
    if ($allow && $allow[0]['data'] == 1) {
        $res['last-child'] = 1;
    } else {
        $res['last-child'] = 0;
    }
    $private = $item->get_item_tags(NAMESPACE_DFRN, 'private');
    if ($private && $private[0]['data'] == 1) {
        $res['private'] = 1;
    } else {
        $res['private'] = 0;
    }
    $extid = $item->get_item_tags(NAMESPACE_DFRN, 'extid');
    if ($extid && $extid[0]['data']) {
        $res['extid'] = $extid[0]['data'];
    }
    $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($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');
    }
    // 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();
    }
    $rawowner = $item->get_item_tags(NAMESPACE_DFRN, 'owner');
    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']) {
        $res['owner-name'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data']);
    }
    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']) {
        $res['owner-link'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data']);
    }
    if ($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
        $base = $rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
        foreach ($base as $link) {
            if (!x($res, 'owner-avatar') || !$res['owner-avatar']) {
                if ($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar') {
                    $res['owner-avatar'] = unxmlify($link['attribs']['']['href']);
                }
            }
        }
    }
    $rawgeo = $item->get_item_tags(NAMESPACE_GEORSS, 'point');
    if ($rawgeo) {
        $res['coord'] = unxmlify($rawgeo[0]['data']);
    }
    $rawverb = $item->get_item_tags(NAMESPACE_ACTIVITY, 'verb');
    // select between supported verbs
    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;
    }
    $cats = $item->get_categories();
    if ($cats) {
        $tag_arr = array();
        foreach ($cats as $cat) {
            $term = $cat->get_term();
            if (!$term) {
                $term = $cat->get_label();
            }
            $scheme = $cat->get_scheme();
            if ($scheme && $term && stristr($scheme, 'X-DFRN:')) {
                $tag_arr[] = substr($scheme, 7, 1) . '[url=' . unxmlify(substr($scheme, 9)) . ']' . unxmlify($term) . '[/url]';
            } elseif ($term) {
                $tag_arr[] = notags(trim($term));
            }
        }
        $res['tag'] = implode(',', $tag_arr);
    }
    $attach = $item->get_enclosures();
    if ($attach) {
        $att_arr = array();
        foreach ($attach as $att) {
            $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, ';'));
            }
            if (!$link || strpos($link, 'http') !== 0) {
                continue;
            }
            if (!$title) {
                $title = ' ';
            }
            if (!$type) {
                $type = 'application/octet-stream';
            }
            $att_arr[] = '[attach]href="' . $link . '" length="' . $len . '" type="' . $type . '" title="' . $title . '"[/attach]';
        }
        $res['attach'] = implode(',', $att_arr);
    }
    $rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'object');
    if ($rawobj) {
        $res['object'] = '<object>' . "\n";
        $child = $rawobj[0]['child'];
        if ($child[NAMESPACE_ACTIVITY]['object-type'][0]['data']) {
            $res['object-type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
            $res['object'] .= '<type>' . $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'] . '</type>' . "\n";
        }
        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'];
            if (!$body) {
                $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data'];
            }
            // 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";
            if (strpos($body, '<') !== false || strpos($body, '>') !== false) {
                $body = html2bb_video($body);
                $config = HTMLPurifier_Config::createDefault();
                $config->set('Cache.DefinitionImpl', null);
                $purifier = new HTMLPurifier($config);
                $body = $purifier->purify($body);
                $body = html2bbcode($body);
            }
            $res['object'] .= '<content>' . $body . '</content>' . "\n";
        }
        $res['object'] .= '</object>' . "\n";
    }
    $rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'target');
    if ($rawobj) {
        $res['target'] = '<target>' . "\n";
        $child = $rawobj[0]['child'];
        if ($child[NAMESPACE_ACTIVITY]['object-type'][0]['data']) {
            $res['target'] .= '<type>' . $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'] . '</type>' . "\n";
        }
        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'];
            if (!$body) {
                $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data'];
            }
            // preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events
            $res['target'] .= '<orig>' . xmlify($body) . '</orig>' . "\n";
            if (strpos($body, '<') !== false || strpos($body, '>') !== false) {
                $body = html2bb_video($body);
                $config = HTMLPurifier_Config::createDefault();
                $config->set('Cache.DefinitionImpl', null);
                $purifier = new HTMLPurifier($config);
                $body = $purifier->purify($body);
                $body = html2bbcode($body);
            }
            $res['target'] .= '<content>' . $body . '</content>' . "\n";
        }
        $res['target'] .= '</target>' . "\n";
    }
    $arr = array('feed' => $feed, 'item' => $item, 'result' => $res);
    call_hooks('parse_atom', $arr);
    return $res;
}