Example #1
0
function item_store_update($arr, $allow_exec = false)
{
    $d = array('item' => $arr, 'allow_exec' => $allow_exec);
    call_hooks('item_store_update', $d);
    $arr = $d['item'];
    $allow_exec = $d['allow_exec'];
    $ret = array('success' => false, 'item_id' => 0);
    if (!intval($arr['uid'])) {
        logger('item_store_update: no uid');
        $ret['message'] = 'no uid.';
        return $ret;
    }
    if (!intval($arr['id'])) {
        logger('item_store_update: no id');
        $ret['message'] = 'no id.';
        return $ret;
    }
    $orig_post_id = $arr['id'];
    $uid = $arr['uid'];
    $orig = q("select * from item where id = %d and uid = %d limit 1", intval($orig_post_id), intval($uid));
    if (!$orig) {
        logger('item_store_update: original post not found: ' . $orig_post_id);
        $ret['message'] = 'no original';
        return $ret;
    }
    // override the unseen flag with the original
    if (intval($arr['item_flags'])) {
        $arr['item_unseen'] = 0;
    }
    if ($orig[0]['item_flags'] & ITEM_VERIFIED) {
        $orig[0]['item_flags'] = $orig[0]['item_flags'] ^ ITEM_VERIFIED;
    }
    if ($orig[0]['item_flags'] & ITEM_OBSCURED) {
        $orig[0]['item_flags'] = $orig[0]['item_flags'] ^ ITEM_OBSCURED;
    }
    $arr['item_flags'] = intval($arr['item_flags']) | $orig[0]['item_flags'];
    $arr['item_restrict'] = intval($arr['item_restrict']) | $orig[0]['item_restrict'];
    if (array_key_exists('edit', $arr)) {
        unset($arr['edit']);
    }
    $arr['mimetype'] = x($arr, 'mimetype') ? notags(trim($arr['mimetype'])) : 'text/bbcode';
    if ($arr['mimetype'] == 'application/x-php' && !$allow_exec) {
        logger('item_store: php mimetype but allow_exec is denied.');
        $ret['message'] = 'exec denied.';
        return $ret;
    }
    if (!($arr['item_flags'] & ITEM_OBSCURED)) {
        $arr['lang'] = detect_language($arr['body']);
        // apply the input filter here - if it is obscured it has been filtered already
        $arr['body'] = trim(z_input_filter($arr['uid'], $arr['body'], $arr['mimetype']));
        if (local_channel() && !$arr['sig']) {
            $channel = get_app()->get_channel();
            if ($channel['channel_hash'] === $arr['author_xchan']) {
                $arr['sig'] = base64url_encode(rsa_sign($arr['body'], $channel['channel_prvkey']));
                $arr['item_flags'] |= ITEM_VERIFIED;
            }
        }
        $allowed_languages = get_pconfig($arr['uid'], 'system', 'allowed_languages');
        if (is_array($allowed_languages) && $arr['lang'] && !array_key_exists($arr['lang'], $allowed_languages)) {
            $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false);
            call_hooks('item_translate', $translate);
            if (!$translate['translated'] && intval(get_pconfig($arr['uid'], 'system', 'reject_disallowed_languages'))) {
                logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']);
                $ret['message'] = 'language not accepted';
                return $ret;
            }
            $arr = $translate['item'];
        }
        if ($arr['item_private']) {
            $key = get_config('system', 'pubkey');
            $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 (x($arr, 'object') && is_array($arr['object'])) {
        activity_sanitise($arr['object']);
        $arr['object'] = json_encode($arr['object']);
    }
    if (x($arr, 'target') && is_array($arr['target'])) {
        activity_sanitise($arr['target']);
        $arr['target'] = json_encode($arr['target']);
    }
    if (x($arr, 'attach') && is_array($arr['attach'])) {
        activity_sanitise($arr['attach']);
        $arr['attach'] = json_encode($arr['attach']);
    }
    unset($arr['id']);
    unset($arr['uid']);
    unset($arr['aid']);
    unset($arr['mid']);
    unset($arr['parent']);
    unset($arr['parent_mid']);
    unset($arr['created']);
    unset($arr['author_xchan']);
    unset($arr['owner_xchan']);
    unset($arr['thr_parent']);
    unset($arr['llink']);
    $arr['edited'] = x($arr, 'edited') !== false ? datetime_convert('UTC', 'UTC', $arr['edited']) : datetime_convert();
    $arr['expires'] = x($arr, 'expires') !== false ? datetime_convert('UTC', 'UTC', $arr['expires']) : $orig[0]['expires'];
    if (array_key_exists('comments_closed', $arr) && $arr['comments_closed'] != NULL_DATE) {
        $arr['comments_closed'] = datetime_convert('UTC', 'UTC', $arr['comments_closed']);
    } else {
        $arr['comments_closed'] = $orig[0]['comments_closed'];
    }
    $arr['commented'] = $orig[0]['commented'];
    $arr['received'] = datetime_convert();
    $arr['changed'] = datetime_convert();
    $arr['route'] = array_key_exists('route', $arr) ? trim($arr['route']) : $orig[0]['route'];
    $arr['diaspora_meta'] = x($arr, 'diaspora_meta') ? $arr['diaspora_meta'] : $orig[0]['diaspora_meta'];
    $arr['location'] = x($arr, 'location') ? notags(trim($arr['location'])) : $orig[0]['location'];
    $arr['coord'] = x($arr, 'coord') ? notags(trim($arr['coord'])) : $orig[0]['coord'];
    $arr['verb'] = x($arr, 'verb') ? notags(trim($arr['verb'])) : $orig[0]['verb'];
    $arr['obj_type'] = x($arr, 'obj_type') ? notags(trim($arr['obj_type'])) : $orig[0]['obj_type'];
    $arr['object'] = x($arr, 'object') ? trim($arr['object']) : $orig[0]['object'];
    $arr['tgt_type'] = x($arr, 'tgt_type') ? notags(trim($arr['tgt_type'])) : $orig[0]['tgt_type'];
    $arr['target'] = x($arr, 'target') ? trim($arr['target']) : $orig[0]['target'];
    $arr['plink'] = x($arr, 'plink') ? notags(trim($arr['plink'])) : $orig[0]['plink'];
    $arr['allow_cid'] = array_key_exists('allow_cid', $arr) ? trim($arr['allow_cid']) : $orig[0]['allow_cid'];
    $arr['allow_gid'] = array_key_exists('allow_gid', $arr) ? trim($arr['allow_gid']) : $orig[0]['allow_gid'];
    $arr['deny_cid'] = array_key_exists('deny_cid', $arr) ? trim($arr['deny_cid']) : $orig[0]['deny_cid'];
    $arr['deny_gid'] = array_key_exists('deny_gid', $arr) ? trim($arr['deny_gid']) : $orig[0]['deny_gid'];
    $arr['item_private'] = array_key_exists('item_private', $arr) ? intval($arr['item_private']) : $orig[0]['item_private'];
    $arr['title'] = array_key_exists('title', $arr) ? trim($arr['title']) : $orig[0]['title'];
    $arr['body'] = array_key_exists('body', $arr) ? trim($arr['body']) : $orig[0]['body'];
    $arr['attach'] = x($arr, 'attach') ? notags(trim($arr['attach'])) : $orig[0]['attach'];
    $arr['app'] = x($arr, 'app') ? notags(trim($arr['app'])) : $orig[0]['app'];
    //	$arr['item_restrict'] = ((x($arr,'item_restrict')) ? intval($arr['item_restrict'])       : $orig[0]['item_restrict'] );
    //	$arr['item_flags']    = ((x($arr,'item_flags'))    ? intval($arr['item_flags'])          : $orig[0]['item_flags'] );
    $arr['sig'] = x($arr, 'sig') ? $arr['sig'] : '';
    $arr['layout_mid'] = array_key_exists('layout_mid', $arr) ? dbesc($arr['layout_mid']) : $orig[0]['layout_mid'];
    $arr['public_policy'] = x($arr, 'public_policy') ? notags(trim($arr['public_policy'])) : $orig[0]['public_policy'];
    $arr['comment_policy'] = x($arr, 'comment_policy') ? notags(trim($arr['comment_policy'])) : $orig[0]['comment_policy'];
    call_hooks('post_remote_update', $arr);
    if (x($arr, 'cancel')) {
        logger('item_store_update: post cancelled by plugin.');
        $ret['message'] = 'cancelled.';
        return $ret;
    }
    // pull out all the taxonomy stuff for separate storage
    $terms = null;
    if (array_key_exists('term', $arr)) {
        $terms = $arr['term'];
        unset($arr['term']);
    }
    dbesc_array($arr);
    logger('item_store_update: ' . print_r($arr, true), LOGGER_DATA);
    $str = '';
    foreach ($arr as $k => $v) {
        if ($str) {
            $str .= ",";
        }
        $str .= " `" . $k . "` = '" . $v . "' ";
    }
    $r = dbq("update `item` set " . $str . " where id = " . $orig_post_id);
    if ($r) {
        logger('item_store_update: updated item ' . $orig_post_id, LOGGER_DEBUG);
    } else {
        logger('item_store_update: could not update item');
        $ret['message'] = 'DB update failed.';
        return $ret;
    }
    $r = q("delete from term where oid = %d and otype = %d", intval($orig_post_id), intval(TERM_OBJ_POST));
    if (is_array($terms)) {
        foreach ($terms as $t) {
            q("insert into term (uid,oid,otype,type,term,url)\n\t\t\t\tvalues(%d,%d,%d,%d,'%s','%s') ", intval($uid), intval($orig_post_id), intval(TERM_OBJ_POST), intval($t['type']), dbesc($t['term']), dbesc($t['url']));
        }
        $arr['term'] = $terms;
    }
    call_hooks('post_remote_update_end', $arr);
    send_status_notifications($orig_post_id, $arr);
    tag_deliver($uid, $orig_post_id);
    $ret['success'] = true;
    $ret['item_id'] = $orig_post_id;
    return $ret;
}
Example #2
0
function diaspora_comment($importer, $xml, $msg)
{
    $a = get_app();
    $guid = notags(unxmlify($xml->guid));
    $parent_guid = notags(unxmlify($xml->parent_guid));
    $diaspora_handle = notags(unxmlify($xml->diaspora_handle));
    $target_type = notags(unxmlify($xml->target_type));
    $text = unxmlify($xml->text);
    $author_signature = notags(unxmlify($xml->author_signature));
    $parent_author_signature = $xml->parent_author_signature ? notags(unxmlify($xml->parent_author_signature)) : '';
    $contact = diaspora_get_contact_by_handle($importer['channel_id'], $msg['author']);
    if (!$contact) {
        logger('diaspora_comment: cannot find contact: ' . $msg['author']);
        return;
    }
    if (!perm_is_allowed($importer['channel_id'], $contact['xchan_hash'], 'post_comments')) {
        logger('diaspora_comment: Ignoring this author.');
        return 202;
    }
    // Friendica is currently truncating guids at 64 chars
    $search_guid = $guid;
    if (strlen($guid) == 64) {
        $search_guid = $guid . '%';
    }
    $r = q("SELECT * FROM item WHERE uid = %d AND mid like '%s' LIMIT 1", intval($importer['channel_id']), dbesc($search_guid));
    if ($r) {
        logger('diaspora_comment: our comment just got relayed back to us (or there was a guid collision) : ' . $guid);
        return;
    }
    $search_guid = $parent_guid;
    if (strlen($parent_guid) == 64) {
        $search_guid = $parent_guid . '%';
    }
    $r = q("SELECT * FROM item WHERE uid = %d AND mid LIKE '%s' LIMIT 1", intval($importer['channel_id']), dbesc($search_guid));
    if (!$r) {
        logger('diaspora_comment: parent item not found: parent: ' . $parent_guid . ' item: ' . $guid);
        return;
    }
    $parent_item = $r[0];
    /* How Diaspora performs comment signature checking:
    
    	   - If an item has been sent by the comment author to the top-level post owner to relay on
    	     to the rest of the contacts on the top-level post, the top-level post owner should check
    	     the author_signature, then create a parent_author_signature before relaying the comment on
    	   - If an item has been relayed on by the top-level post owner, the contacts who receive it
    	     check only the parent_author_signature. Basically, they trust that the top-level post
    	     owner has already verified the authenticity of anything he/she sends out
    	   - In either case, the signature that get checked is the signature created by the person
    	     who sent the psuedo-salmon
    	*/
    $signed_data = $guid . ';' . $parent_guid . ';' . $text . ';' . $diaspora_handle;
    $key = $msg['key'];
    if ($parent_author_signature) {
        // If a parent_author_signature exists, then we've received the comment
        // relayed from the top-level post owner. There's no need to check the
        // author_signature if the parent_author_signature is valid
        $parent_author_signature = base64_decode($parent_author_signature);
        if (!rsa_verify($signed_data, $parent_author_signature, $key, 'sha256')) {
            logger('diaspora_comment: top-level owner verification failed.');
            return;
        }
    } else {
        // If there's no parent_author_signature, then we've received the comment
        // from the comment creator. In that case, the person is commenting on
        // our post, so he/she must be a contact of ours and his/her public key
        // should be in $msg['key']
        $author_signature = base64_decode($author_signature);
        if (!rsa_verify($signed_data, $author_signature, $key, 'sha256')) {
            logger('diaspora_comment: comment author verification failed.');
            return;
        }
    }
    // Phew! Everything checks out. Now create an item.
    // Find the original comment author information.
    // We need this to make sure we display the comment author
    // information (name and avatar) correctly.
    if (strcasecmp($diaspora_handle, $msg['author']) == 0) {
        $person = $contact;
    } else {
        $person = find_diaspora_person_by_handle($diaspora_handle);
        if (!is_array($person)) {
            logger('diaspora_comment: unable to find author details');
            return;
        }
    }
    $body = diaspora2bb($text);
    $datarray = array();
    $tags = get_tags($body);
    if (count($tags)) {
        $datarray['term'] = array();
        foreach ($tags as $tag) {
            if (strpos($tag, '#') === 0) {
                if (strpos($tag, '[url=')) {
                    continue;
                }
                // don't link tags that are already embedded in links
                if (preg_match('/\\[(.*?)' . preg_quote($tag, '/') . '(.*?)\\]/', $body)) {
                    continue;
                }
                if (preg_match('/\\[(.*?)\\]\\((.*?)' . preg_quote($tag, '/') . '(.*?)\\)/', $body)) {
                    continue;
                }
                $basetag = str_replace('_', ' ', substr($tag, 1));
                $body = str_replace($tag, '#[url=' . $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag) . ']' . $basetag . '[/url]', $body);
                $datarray['term'][] = array('uid' => $importer['channel_id'], 'type' => TERM_HASHTAG, 'otype' => TERM_OBJ_POST, 'term' => $basetag, 'url' => z_root() . '/search?tag=' . rawurlencode($basetag));
            }
        }
    }
    $cnt = preg_match_all('/@\\[url=(.*?)\\](.*?)\\[\\/url\\]/ism', $body, $matches, PREG_SET_ORDER);
    if ($cnt) {
        foreach ($matches as $mtch) {
            $datarray['term'][] = array('uid' => $importer['channel_id'], 'type' => TERM_MENTION, 'otype' => TERM_OBJ_POST, 'term' => $mtch[2], 'url' => $mtch[1]);
        }
    }
    $datarray['uid'] = $importer['channel_id'];
    $datarray['verb'] = ACTIVITY_POST;
    $datarray['mid'] = $guid;
    $datarray['parent_mid'] = $parent_item['mid'];
    // No timestamps for comments? OK, we'll the use current time.
    $datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert();
    $datarray['item_private'] = $parent_item['item_private'];
    $datarray['owner_xchan'] = $parent_item['owner_xchan'];
    $datarray['author_xchan'] = $person['xchan_hash'];
    $datarray['body'] = $body;
    $datarray['app'] = 'Diaspora';
    if (!$parent_author_signature) {
        $datarray['diaspora_meta'] = array('signer' => $diaspora_handle, 'body' => $text, 'signed_text' => $signed_data, 'signature' => base64_encode($author_signature));
    }
    $result = item_store($datarray);
    if ($result && $result['success']) {
        $message_id = $result['item_id'];
    }
    if ($parent_item['item_flags'] & ITEM_ORIGIN && !$parent_author_signature) {
        q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", intval($message_id), dbesc($signed_data), dbesc(base64_encode($author_signature)), dbesc($diaspora_handle));
        // if the message isn't already being relayed, notify others
        // the existence of parent_author_signature means the parent_author or owner
        // is already relaying.
        proc_run('php', 'include/notifier.php', 'comment-import', $message_id);
    }
    if ($result['item_id']) {
        $r = q("select * from item where id = %d limit 1", intval($result['item_id']));
        if ($r) {
            send_status_notifications($result['item_id'], $r[0]);
        }
    }
    return;
}
Example #3
0
function diaspora_comment($importer, $xml, $msg)
{
    $a = get_app();
    $guid = notags(unxmlify($xml->guid));
    $parent_guid = notags(unxmlify($xml->parent_guid));
    $diaspora_handle = notags(unxmlify($xml->diaspora_handle));
    $target_type = notags(unxmlify($xml->target_type));
    $text = unxmlify($xml->text);
    $author_signature = notags(unxmlify($xml->author_signature));
    $parent_author_signature = $xml->parent_author_signature ? notags(unxmlify($xml->parent_author_signature)) : '';
    $contact = diaspora_get_contact_by_handle($importer['channel_id'], $msg['author']);
    if (!$contact) {
        logger('diaspora_comment: cannot find contact: ' . $msg['author']);
        return;
    }
    $pubcomment = get_pconfig($importer['channel_id'], 'system', 'diaspora_public_comments');
    // by default comments on public posts are allowed from anybody on Diaspora. That is their policy.
    // Once this setting is set to something we'll track your preference and it will over-ride the default.
    if ($pubcomment === false) {
        $pubcomment = 1;
    }
    // Friendica is currently truncating guids at 64 chars
    $search_guid = $parent_guid;
    if (strlen($parent_guid) == 64) {
        $search_guid = $parent_guid . '%';
    }
    $r = q("SELECT * FROM item WHERE uid = %d AND mid LIKE '%s' LIMIT 1", intval($importer['channel_id']), dbesc($search_guid));
    if (!$r) {
        logger('diaspora_comment: parent item not found: parent: ' . $parent_guid . ' item: ' . $guid);
        return;
    }
    $parent_item = $r[0];
    if (intval($parent_item['item_private'])) {
        $pubcomment = 0;
    }
    $search_guid = $guid;
    if (strlen($guid) == 64) {
        $search_guid = $guid . '%';
    }
    $r = q("SELECT * FROM item WHERE uid = %d AND mid like '%s' LIMIT 1", intval($importer['channel_id']), dbesc($search_guid));
    if ($r) {
        logger('diaspora_comment: our comment just got relayed back to us (or there was a guid collision) : ' . $guid);
        return;
    }
    /* How Diaspora performs comment signature checking:
    
    	   - If an item has been sent by the comment author to the top-level post owner to relay on
    	     to the rest of the contacts on the top-level post, the top-level post owner should check
    	     the author_signature, then create a parent_author_signature before relaying the comment on
    	   - If an item has been relayed on by the top-level post owner, the contacts who receive it
    	     check only the parent_author_signature. Basically, they trust that the top-level post
    	     owner has already verified the authenticity of anything he/she sends out
    	   - In either case, the signature that get checked is the signature created by the person
    	     who sent the psuedo-salmon
    	*/
    $signed_data = $guid . ';' . $parent_guid . ';' . $text . ';' . $diaspora_handle;
    $key = $msg['key'];
    if ($parent_author_signature) {
        // If a parent_author_signature exists, then we've received the comment
        // relayed from the top-level post owner. There's no need to check the
        // author_signature if the parent_author_signature is valid
        $parent_author_signature = base64_decode($parent_author_signature);
        if (!rsa_verify($signed_data, $parent_author_signature, $key, 'sha256')) {
            logger('diaspora_comment: top-level owner verification failed.');
            return;
        }
    } else {
        // If there's no parent_author_signature, then we've received the comment
        // from the comment creator. In that case, the person is commenting on
        // our post, so he/she must be a contact of ours and his/her public key
        // should be in $msg['key']
        if ($importer['system']) {
            // don't relay to the sys channel
            logger('diaspora_comment: relay to sys channel blocked.');
            return;
        }
        $author_signature = base64_decode($author_signature);
        if (!rsa_verify($signed_data, $author_signature, $key, 'sha256')) {
            logger('diaspora_comment: comment author verification failed.');
            return;
        }
    }
    // Phew! Everything checks out. Now create an item.
    // Find the original comment author information.
    // We need this to make sure we display the comment author
    // information (name and avatar) correctly.
    if (strcasecmp($diaspora_handle, $msg['author']) == 0) {
        $person = $contact;
    } else {
        $person = find_diaspora_person_by_handle($diaspora_handle);
        if (!is_array($person)) {
            logger('diaspora_comment: unable to find author details');
            return;
        }
    }
    $body = diaspora2bb($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');
    }
    $datarray = array();
    // Look for tags and linkify them
    $results = linkify_tags(get_app(), $body, $importer['channel_id'], true);
    $datarray['term'] = array();
    if ($results) {
        foreach ($results as $result) {
            $success = $result['success'];
            if ($success['replaced']) {
                $datarray['term'][] = array('uid' => $importer['channel_id'], 'type' => $success['termtype'], 'otype' => TERM_OBJ_POST, 'term' => $success['term'], 'url' => $success['url']);
            }
        }
    }
    $cnt = preg_match_all('/@\\[url=(.*?)\\](.*?)\\[\\/url\\]/ism', $body, $matches, PREG_SET_ORDER);
    if ($cnt) {
        foreach ($matches as $mtch) {
            $datarray['term'][] = array('uid' => $importer['channel_id'], 'type' => TERM_MENTION, 'otype' => TERM_OBJ_POST, 'term' => $mtch[2], 'url' => $mtch[1]);
        }
    }
    $cnt = preg_match_all('/@\\[zrl=(.*?)\\](.*?)\\[\\/zrl\\]/ism', $body, $matches, PREG_SET_ORDER);
    if ($cnt) {
        foreach ($matches as $mtch) {
            // don't include plustags in the term
            $term = substr($mtch[2], -1, 1) === '+' ? substr($mtch[2], 0, -1) : $mtch[2];
            $datarray['term'][] = array('uid' => $importer['channel_id'], 'type' => TERM_MENTION, 'otype' => TERM_OBJ_POST, 'term' => $term, 'url' => $mtch[1]);
        }
    }
    $datarray['uid'] = $importer['channel_id'];
    $datarray['verb'] = ACTIVITY_POST;
    $datarray['mid'] = $guid;
    $datarray['parent_mid'] = $parent_item['mid'];
    // set the route to that of the parent so downstream hubs won't reject it.
    $datarray['route'] = $parent_item['route'];
    // No timestamps for comments? OK, we'll the use current time.
    $datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert();
    $datarray['item_private'] = $parent_item['item_private'];
    $datarray['owner_xchan'] = $parent_item['owner_xchan'];
    $datarray['author_xchan'] = $person['xchan_hash'];
    $datarray['body'] = $body;
    if (strstr($person['xchan_network'], 'friendica')) {
        $app = 'Friendica';
    } else {
        $app = 'Diaspora';
    }
    $datarray['app'] = $app;
    if (!$parent_author_signature) {
        $key = get_config('system', 'pubkey');
        $x = array('signer' => $diaspora_handle, 'body' => $text, 'signed_text' => $signed_data, 'signature' => base64_encode($author_signature));
        $datarray['diaspora_meta'] = json_encode(crypto_encapsulate(json_encode($x), $key));
    }
    // So basically if something arrives at the sys channel it's by definition public and we allow it.
    // If $pubcomment and the parent was public, we allow it.
    // In all other cases, honour the permissions for this Diaspora connection
    $tgroup = tgroup_check($importer['channel_id'], $datarray);
    if (!$importer['system'] && !$pubcomment && !perm_is_allowed($importer['channel_id'], $contact['xchan_hash'], 'post_comments') && !$tgroup) {
        logger('diaspora_comment: Ignoring this author.');
        return 202;
    }
    $result = item_store($datarray);
    if ($result && $result['success']) {
        $message_id = $result['item_id'];
    }
    if ($parent_item['item_flags'] & ITEM_ORIGIN && !$parent_author_signature) {
        // if the message isn't already being relayed, notify others
        // the existence of parent_author_signature means the parent_author or owner
        // is already relaying.
        proc_run('php', 'include/notifier.php', 'comment-import', $message_id);
    }
    if ($result['item_id']) {
        $r = q("select * from item where id = %d limit 1", intval($result['item_id']));
        if ($r) {
            send_status_notifications($result['item_id'], $r[0]);
        }
    }
    return;
}
Example #4
0
function item_store_update($arr, $allow_exec = false, $deliver = true)
{
    $d = array('item' => $arr, 'allow_exec' => $allow_exec);
    call_hooks('item_store_update', $d);
    $arr = $d['item'];
    $allow_exec = $d['allow_exec'];
    $ret = array('success' => false, 'item_id' => 0);
    if (!intval($arr['uid'])) {
        logger('item_store_update: no uid');
        $ret['message'] = 'no uid.';
        return $ret;
    }
    if (!intval($arr['id'])) {
        logger('item_store_update: no id');
        $ret['message'] = 'no id.';
        return $ret;
    }
    $orig_post_id = $arr['id'];
    $uid = $arr['uid'];
    $orig = q("select * from item where id = %d and uid = %d limit 1", intval($orig_post_id), intval($uid));
    if (!$orig) {
        logger('item_store_update: original post not found: ' . $orig_post_id);
        $ret['message'] = 'no original';
        return $ret;
    }
    // override the unseen flag with the original
    $arr['item_unseen'] = $orig[0]['item_unseen'];
    if (array_key_exists('edit', $arr)) {
        unset($arr['edit']);
    }
    $arr['mimetype'] = x($arr, 'mimetype') ? notags(trim($arr['mimetype'])) : 'text/bbcode';
    if ($arr['mimetype'] == 'application/x-php' && !$allow_exec) {
        logger('item_store: php mimetype but allow_exec is denied.');
        $ret['message'] = 'exec denied.';
        return $ret;
    }
    if (!array_key_exists('item_obscured', $arr) || $arr['item_obscured'] == 0) {
        $arr['lang'] = detect_language($arr['body']);
        // apply the input filter here - if it is obscured it has been filtered already
        $arr['body'] = trim(z_input_filter($arr['uid'], $arr['body'], $arr['mimetype']));
        if (local_channel() && !$arr['sig']) {
            $channel = App::get_channel();
            if ($channel['channel_hash'] === $arr['author_xchan']) {
                $arr['sig'] = base64url_encode(rsa_sign($arr['body'], $channel['channel_prvkey']));
                $arr['item_verified'] = 1;
            }
        }
        $allowed_languages = get_pconfig($arr['uid'], 'system', 'allowed_languages');
        if (is_array($allowed_languages) && $arr['lang'] && !array_key_exists($arr['lang'], $allowed_languages)) {
            $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false);
            call_hooks('item_translate', $translate);
            if (!$translate['translated'] && intval(get_pconfig($arr['uid'], 'system', 'reject_disallowed_languages'))) {
                logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']);
                $ret['message'] = 'language not accepted';
                return $ret;
            }
            $arr = $translate['item'];
        }
    }
    if (x($arr, 'obj') && is_array($arr['obj'])) {
        activity_sanitise($arr['obj']);
        $arr['obj'] = json_encode($arr['obj']);
    }
    if (x($arr, 'target') && is_array($arr['target'])) {
        activity_sanitise($arr['target']);
        $arr['target'] = json_encode($arr['target']);
    }
    if (x($arr, 'attach') && is_array($arr['attach'])) {
        activity_sanitise($arr['attach']);
        $arr['attach'] = json_encode($arr['attach']);
    }
    unset($arr['id']);
    unset($arr['uid']);
    unset($arr['aid']);
    unset($arr['mid']);
    unset($arr['parent']);
    unset($arr['parent_mid']);
    unset($arr['created']);
    unset($arr['author_xchan']);
    unset($arr['owner_xchan']);
    unset($arr['thr_parent']);
    unset($arr['llink']);
    $arr['edited'] = x($arr, 'edited') !== false ? datetime_convert('UTC', 'UTC', $arr['edited']) : datetime_convert();
    $arr['expires'] = x($arr, 'expires') !== false ? datetime_convert('UTC', 'UTC', $arr['expires']) : $orig[0]['expires'];
    if (array_key_exists('comments_closed', $arr) && $arr['comments_closed'] > NULL_DATE) {
        $arr['comments_closed'] = datetime_convert('UTC', 'UTC', $arr['comments_closed']);
    } else {
        $arr['comments_closed'] = $orig[0]['comments_closed'];
    }
    $arr['commented'] = $orig[0]['commented'];
    if ($deliver) {
        $arr['received'] = datetime_convert();
        $arr['changed'] = datetime_convert();
    } else {
        // When deliver flag is false, we are *probably* performing an import or bulk migration.
        // If one updates the changed timestamp it will be made available to zotfeed and delivery
        // will still take place through backdoor methods. Since these fields are rarely used
        // otherwise, just preserve the original timestamp.
        $arr['received'] = $orig[0]['received'];
        $arr['changed'] = $orig[0]['changed'];
    }
    $arr['route'] = array_key_exists('route', $arr) ? trim($arr['route']) : $orig[0]['route'];
    $arr['diaspora_meta'] = x($arr, 'diaspora_meta') ? $arr['diaspora_meta'] : $orig[0]['diaspora_meta'];
    $arr['location'] = x($arr, 'location') ? notags(trim($arr['location'])) : $orig[0]['location'];
    $arr['coord'] = x($arr, 'coord') ? notags(trim($arr['coord'])) : $orig[0]['coord'];
    $arr['verb'] = x($arr, 'verb') ? notags(trim($arr['verb'])) : $orig[0]['verb'];
    $arr['obj_type'] = x($arr, 'obj_type') ? notags(trim($arr['obj_type'])) : $orig[0]['obj_type'];
    $arr['obj'] = x($arr, 'obj') ? trim($arr['obj']) : $orig[0]['obj'];
    $arr['tgt_type'] = x($arr, 'tgt_type') ? notags(trim($arr['tgt_type'])) : $orig[0]['tgt_type'];
    $arr['target'] = x($arr, 'target') ? trim($arr['target']) : $orig[0]['target'];
    $arr['plink'] = x($arr, 'plink') ? notags(trim($arr['plink'])) : $orig[0]['plink'];
    $arr['allow_cid'] = array_key_exists('allow_cid', $arr) ? trim($arr['allow_cid']) : $orig[0]['allow_cid'];
    $arr['allow_gid'] = array_key_exists('allow_gid', $arr) ? trim($arr['allow_gid']) : $orig[0]['allow_gid'];
    $arr['deny_cid'] = array_key_exists('deny_cid', $arr) ? trim($arr['deny_cid']) : $orig[0]['deny_cid'];
    $arr['deny_gid'] = array_key_exists('deny_gid', $arr) ? trim($arr['deny_gid']) : $orig[0]['deny_gid'];
    $arr['item_private'] = array_key_exists('item_private', $arr) ? intval($arr['item_private']) : $orig[0]['item_private'];
    $arr['title'] = array_key_exists('title', $arr) && strlen($arr['title']) ? trim($arr['title']) : '';
    $arr['body'] = array_key_exists('body', $arr) && strlen($arr['body']) ? trim($arr['body']) : '';
    $arr['html'] = array_key_exists('html', $arr) && strlen($arr['html']) ? trim($arr['html']) : '';
    $arr['attach'] = array_key_exists('attach', $arr) ? notags(trim($arr['attach'])) : $orig[0]['attach'];
    $arr['app'] = array_key_exists('app', $arr) ? notags(trim($arr['app'])) : $orig[0]['app'];
    $arr['item_origin'] = array_key_exists('item_origin', $arr) ? intval($arr['item_origin']) : $orig[0]['item_origin'];
    $arr['item_unseen'] = array_key_exists('item_unseen', $arr) ? intval($arr['item_unseen']) : $orig[0]['item_unseen'];
    $arr['item_starred'] = array_key_exists('item_starred', $arr) ? intval($arr['item_starred']) : $orig[0]['item_starred'];
    $arr['item_uplink'] = array_key_exists('item_uplink', $arr) ? intval($arr['item_uplink']) : $orig[0]['item_uplink'];
    $arr['item_consensus'] = array_key_exists('item_consensus', $arr) ? intval($arr['item_consensus']) : $orig[0]['item_consensus'];
    $arr['item_wall'] = array_key_exists('item_wall', $arr) ? intval($arr['item_wall']) : $orig[0]['item_wall'];
    $arr['item_thread_top'] = array_key_exists('item_thread_top', $arr) ? intval($arr['item_thread_top']) : $orig[0]['item_thread_top'];
    $arr['item_notshown'] = array_key_exists('item_notshown', $arr) ? intval($arr['item_notshown']) : $orig[0]['item_notshown'];
    $arr['item_nsfw'] = array_key_exists('item_nsfw', $arr) ? intval($arr['item_nsfw']) : $orig[0]['item_nsfw'];
    $arr['item_relay'] = array_key_exists('item_relay', $arr) ? intval($arr['item_relay']) : $orig[0]['item_relay'];
    $arr['item_mentionsme'] = array_key_exists('item_mentionsme', $arr) ? intval($arr['item_mentionsme']) : $orig[0]['item_mentionsme'];
    $arr['item_nocomment'] = array_key_exists('item_nocomment', $arr) ? intval($arr['item_nocomment']) : $orig[0]['item_nocomment'];
    $arr['item_obscured'] = array_key_exists('item_obscured', $arr) ? intval($arr['item_obscured']) : $orig[0]['item_obscured'];
    $arr['item_verified'] = array_key_exists('item_verified', $arr) ? intval($arr['item_verified']) : $orig[0]['item_verified'];
    $arr['item_retained'] = array_key_exists('item_retained', $arr) ? intval($arr['item_retained']) : $orig[0]['item_retained'];
    $arr['item_rss'] = array_key_exists('item_rss', $arr) ? intval($arr['item_rss']) : $orig[0]['item_rss'];
    $arr['item_deleted'] = array_key_exists('item_deleted', $arr) ? intval($arr['item_deleted']) : $orig[0]['item_deleted'];
    $arr['item_type'] = array_key_exists('item_type', $arr) ? intval($arr['item_type']) : $orig[0]['item_type'];
    $arr['item_hidden'] = array_key_exists('item_hidden', $arr) ? intval($arr['item_hidden']) : $orig[0]['item_hidden'];
    $arr['item_unpublished'] = array_key_exists('item_unpublished', $arr) ? intval($arr['item_unpublished']) : $orig[0]['item_unpublished'];
    $arr['item_delayed'] = array_key_exists('item_delayed', $arr) ? intval($arr['item_delayed']) : $orig[0]['item_delayed'];
    $arr['item_pending_remove'] = array_key_exists('item_pending_remove', $arr) ? intval($arr['item_pending_remove']) : $orig[0]['item_pending_remove'];
    $arr['item_blocked'] = array_key_exists('item_blocked', $arr) ? intval($arr['item_blocked']) : $orig[0]['item_blocked'];
    $arr['sig'] = x($arr, 'sig') ? $arr['sig'] : '';
    $arr['layout_mid'] = array_key_exists('layout_mid', $arr) ? dbesc($arr['layout_mid']) : $orig[0]['layout_mid'];
    $arr['public_policy'] = x($arr, 'public_policy') ? notags(trim($arr['public_policy'])) : $orig[0]['public_policy'];
    $arr['comment_policy'] = x($arr, 'comment_policy') ? notags(trim($arr['comment_policy'])) : $orig[0]['comment_policy'];
    call_hooks('post_remote_update', $arr);
    if (x($arr, 'cancel')) {
        logger('item_store_update: post cancelled by plugin.');
        $ret['message'] = 'cancelled.';
        return $ret;
    }
    // pull out all the taxonomy stuff for separate storage
    $terms = null;
    if (array_key_exists('term', $arr)) {
        $terms = $arr['term'];
        unset($arr['term']);
    }
    $meta = null;
    if (array_key_exists('iconfig', $arr)) {
        $meta = $arr['iconfig'];
        unset($arr['iconfig']);
    }
    dbesc_array($arr);
    logger('item_store_update: ' . print_r($arr, true), LOGGER_DATA);
    $str = '';
    foreach ($arr as $k => $v) {
        if ($str) {
            $str .= ",";
        }
        $str .= " `" . $k . "` = '" . $v . "' ";
    }
    $r = dbq("update `item` set " . $str . " where id = " . $orig_post_id);
    if ($r) {
        logger('item_store_update: updated item ' . $orig_post_id, LOGGER_DEBUG);
    } else {
        logger('item_store_update: could not update item');
        $ret['message'] = 'DB update failed.';
        return $ret;
    }
    // fetch an unescaped complete copy of the stored item
    $r = q("select * from item where id = %d", intval($orig_post_id));
    if ($r) {
        $arr = $r[0];
    }
    $r = q("delete from term where oid = %d and otype = %d", intval($orig_post_id), intval(TERM_OBJ_POST));
    if (is_array($terms)) {
        foreach ($terms as $t) {
            q("insert into term (uid,oid,otype,ttype,term,url)\n\t\t\t\tvalues(%d,%d,%d,%d,'%s','%s') ", intval($uid), intval($orig_post_id), intval(TERM_OBJ_POST), intval($t['ttype']), dbesc($t['term']), dbesc($t['url']));
        }
        $arr['term'] = $terms;
    }
    $r = q("delete from iconfig where iid = %d", intval($orig_post_id));
    if ($meta) {
        foreach ($meta as $m) {
            set_iconfig($orig_post_id, $m['cat'], $m['k'], $m['v'], $m['sharing']);
        }
        $arr['iconfig'] = $meta;
    }
    $ret['item'] = $arr;
    call_hooks('post_remote_update_end', $arr);
    if ($deliver) {
        send_status_notifications($orig_post_id, $arr);
        tag_deliver($uid, $orig_post_id);
    }
    $ret['success'] = true;
    $ret['item_id'] = $orig_post_id;
    return $ret;
}
                        $data['RECPR_PAGERANK'] = get_page_rank($data['RECPR_URL']);
                    }
                }
                $data['ID'] = $id;
                if (!isset($data['RECPR_REQUIRED'])) {
                    $data['RECPR_REQUIRED'] = 0;
                }
                if (db_replace('link', $data, 'ID') > 0) {
                    $tpl->assign('posted', true);
                    if ($action == 'N') {
                        $cid = $data['CATEGORY_ID'];
                        $data = array();
                        $data['STATUS'] = 2;
                        $data['CATEGORY_ID'] = $cid;
                    } else {
                        send_status_notifications($id);
                        if (isset($_SESSION['return'])) {
                            @header('Location: ' . $_SESSION['return']);
                            @exit;
                        }
                    }
                } else {
                    $tpl->assign('sql_error', $db->ErrorMsg());
                }
            }
        }
        $tpl->assign($data);
        $content = $tpl->fetch('dir_links_edit.tpl');
        break;
}
$tpl->assign('content', $content);