Exemple #1
0
function p_init($a)
{
    if ($a->argc != 2) {
        header($_SERVER["SERVER_PROTOCOL"] . ' 510 ' . t('Not Extended'));
        killme();
    }
    $guid = $a->argv[1];
    if (strtolower(substr($guid, -4)) != ".xml") {
        header($_SERVER["SERVER_PROTOCOL"] . ' 404 ' . t('Not Found'));
        killme();
    }
    $guid = strtolower(substr($guid, 0, -4));
    $item = q("SELECT `body`, `guid`, `contact-id`, `private`, `created`, `app` FROM `item` WHERE `uid` = 0 AND `guid` = '%s' AND `network` IN ('%s', '%s') LIMIT 1", dbesc($guid), NETWORK_DFRN, NETWORK_DIASPORA);
    if (!$item) {
        header($_SERVER["SERVER_PROTOCOL"] . ' 404 ' . t('Not Found'));
        killme();
    }
    $post = array();
    $reshared = diaspora_is_reshare($item[0]["body"]);
    if ($reshared) {
        $nodename = "reshare";
        $post["root_diaspora_id"] = $reshared["root_handle"];
        $post["root_guid"] = $reshared["root_guid"];
        $post["guid"] = $item[0]["guid"];
        $post["diaspora_handle"] = diaspora_handle_from_contact($item[0]["contact-id"]);
        $post["public"] = !$item[0]["private"] ? 'true' : 'false';
        $post["created_at"] = datetime_convert('UTC', 'UTC', $item[0]["created"]);
    } else {
        $nodename = "status_message";
        $post["raw_message"] = str_replace("&", "&", bb2diaspora($item[0]["body"]));
        $post["guid"] = $item[0]["guid"];
        $post["diaspora_handle"] = diaspora_handle_from_contact($item[0]["contact-id"]);
        $post["public"] = !$item[0]["private"] ? 'true' : 'false';
        $post["created_at"] = datetime_convert('UTC', 'UTC', $item[0]["created"]);
        $post["provider_display_name"] = $item[0]["app"];
    }
    $dom = new DOMDocument("1.0");
    $root = $dom->createElement("XML");
    $dom->appendChild($root);
    $postelement = $dom->createElement("post");
    $root->appendChild($postelement);
    $statuselement = $dom->createElement($nodename);
    $postelement->appendChild($statuselement);
    foreach ($post as $index => $value) {
        $postnode = $dom->createElement($index, $value);
        $statuselement->appendChild($postnode);
    }
    header("Content-Type: application/xml; charset=utf-8");
    $xml = $dom->saveXML();
    // Diaspora doesn't send the XML header, so we remove them as well.
    // So we avoid possible compatibility problems.
    if (substr($xml, 0, 21) == '<?xml version="1.0"?>') {
        $xml = trim(substr($xml, 21));
    }
    echo $xml;
    killme();
}
Exemple #2
0
function diaspora_send_relay($item, $owner, $contact, $public_batch = false)
{
    $a = get_app();
    $myaddr = $owner['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(), '://') + 3);
    //	$theiraddr = $contact['addr'];
    $body = $item['body'];
    $text = html_entity_decode(bb2diaspora($body));
    // Diaspora doesn't support threaded comments, but some
    // versions of Diaspora (i.e. Diaspora-pistos) support
    // likes on comments
    if ($item['verb'] === ACTIVITY_LIKE && $item['thr-parent']) {
        $p = q("select guid, type, uri, `parent-uri` from item where uri = '%s' limit 1", dbesc($item['thr-parent']));
    } else {
        // The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always
        // return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent.
        // The only item with `parent` and `id` as the parent id is the parent item.
        $p = q("select guid, type, uri, `parent-uri` from item where parent = %d and id = %d limit 1", intval($item['parent']), intval($item['parent']));
    }
    if (count($p)) {
        $parent = $p[0];
    } else {
        return;
    }
    $like = false;
    $relay_retract = false;
    $sql_sign_id = 'iid';
    if ($item['deleted']) {
        $relay_retract = true;
        $target_type = $item['verb'] === ACTIVITY_LIKE ? 'Like' : 'Comment';
        $sql_sign_id = 'retract_iid';
        $tpl = get_markup_template('diaspora_relayable_retraction.tpl');
    } elseif ($item['verb'] === ACTIVITY_LIKE) {
        $like = true;
        $target_type = $parent['uri'] === $parent['parent-uri'] ? 'Post' : 'Comment';
        //		$positive = (($item['deleted']) ? 'false' : 'true');
        $positive = 'true';
        $tpl = get_markup_template('diaspora_like_relay.tpl');
    } else {
        // item is a comment
        $tpl = get_markup_template('diaspora_comment_relay.tpl');
    }
    // fetch the original signature	if the relayable was created by a Diaspora
    // or DFRN user. Relayables for other networks are not supported.
    /*	$r = q("select * from sign where " . $sql_sign_id . " = %d limit 1",
    		intval($item['id'])
    	);
    	if(count($r)) { 
    		$orig_sign = $r[0];
    		$signed_text = $orig_sign['signed_text'];
    		$authorsig = $orig_sign['signature'];
    		$handle = $orig_sign['signer'];
    	}
    	else {
    
    		// Author signature information (for likes, comments, and retractions of likes or comments,
    		// whether from Diaspora or Friendica) must be placed in the `sign` table before this 
    		// function is called
    		logger('diaspora_send_relay: original author signature not found, cannot send relayable');
    		return;
    	}*/
    /* Since the author signature is only checked by the parent, not by the relay recipients,
     * I think it may not be necessary for us to do so much work to preserve all the original
     * signatures. The important thing that Diaspora DOES need is the original creator's handle.
     * Let's just generate that and forget about all the original author signature stuff.
     *
     * Note: this might be more of an problem if we want to support likes on comments for older
     * versions of Diaspora (diaspora-pistos), but since there are a number of problems with
     * doing that, let's ignore it for now.
     *
     * Currently, only DFRN contacts are supported. StatusNet shouldn't be hard, but it hasn't
     * been done yet
     */
    $handle = diaspora_handle_from_contact($item['contact-id']);
    if (!$handle) {
        return;
    }
    if ($relay_retract) {
        $sender_signed_text = $item['guid'] . ';' . $target_type;
    } elseif ($like) {
        $sender_signed_text = $item['guid'] . ';' . $target_type . ';' . $parent['guid'] . ';' . $positive . ';' . $handle;
    } else {
        $sender_signed_text = $item['guid'] . ';' . $parent['guid'] . ';' . $text . ';' . $handle;
    }
    // Sign the relayable with the top-level owner's signature
    //
    // We'll use the $sender_signed_text that we just created, instead of the $signed_text
    // stored in the database, because that provides the best chance that Diaspora will
    // be able to reconstruct the signed text the same way we did. This is particularly a
    // concern for the comment, whose signed text includes the text of the comment. The
    // smallest change in the text of the comment, including removing whitespace, will
    // make the signature verification fail. Since we translate from BB code to Diaspora's
    // markup at the top of this function, which is AFTER we placed the original $signed_text
    // in the database, it's hazardous to trust the original $signed_text.
    $parentauthorsig = base64_encode(rsa_sign($sender_signed_text, $owner['uprvkey'], 'sha256'));
    $msg = replace_macros($tpl, array('$guid' => xmlify($item['guid']), '$parent_guid' => xmlify($parent['guid']), '$target_type' => xmlify($target_type), '$authorsig' => xmlify($authorsig), '$parentsig' => xmlify($parentauthorsig), '$body' => xmlify($text), '$positive' => xmlify($positive), '$handle' => xmlify($handle)));
    logger('diaspora_send_relay: base message: ' . $msg, LOGGER_DATA);
    $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg, $owner, $contact, $owner['uprvkey'], $contact['pubkey'], $public_batch)));
    //$slap = 'xml=' . urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['uprvkey'],$contact['pubkey'],$public_batch));
    return diaspora_transmit($owner, $contact, $slap, $public_batch);
}
Exemple #3
0
function diaspora_send_relay($item, $owner, $contact, $public_batch = false)
{
    $a = get_app();
    $myaddr = $owner['channel_address'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(), '://') + 3);
    $text = bb2diaspora_itembody($item);
    $body = $text;
    // Diaspora doesn't support threaded comments, but some
    // versions of Diaspora (i.e. Diaspora-pistos) support
    // likes on comments
    if ($item['verb'] === ACTIVITY_LIKE && $item['thr_parent']) {
        $p = q("select * from item where mid = '%s' limit 1", dbesc($item['thr_parent']));
    } else {
        // The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always
        // return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent.
        // The only item with `parent` and `id` as the parent id is the parent item.
        $p = q("select * from item where parent = %d and id = %d limit 1", intval($item['parent']), intval($item['parent']));
    }
    if ($p) {
        $parent = $p[0];
    } else {
        logger('diaspora_send_relay: no parent');
        return;
    }
    $like = false;
    $relay_retract = false;
    $sql_sign_id = 'iid';
    if ($item['item_restrict'] & ITEM_DELETED) {
        $relay_retract = true;
        $target_type = $item['verb'] === ACTIVITY_LIKE ? 'Like' : 'Comment';
        $sql_sign_id = 'retract_iid';
        $tpl = get_markup_template('diaspora_relayable_retraction.tpl');
    } elseif ($item['verb'] === ACTIVITY_LIKE) {
        $like = true;
        $target_type = $parent['mid'] === $parent['parent_mid'] ? 'Post' : 'Comment';
        //		$positive = (($item['item_restrict'] & ITEM_DELETED) ? 'false' : 'true');
        $positive = 'true';
        $tpl = get_markup_template('diaspora_like_relay.tpl');
    } else {
        // item is a comment
        $tpl = get_markup_template('diaspora_comment_relay.tpl');
    }
    $diaspora_meta = $item['diaspora_meta'] ? json_decode($item['diaspora_meta'], true) : '';
    if ($diaspora_meta) {
        $sender_signed_text = $diaspora_meta['signed_text'];
        $authorsig = $diaspora_meta['signature'];
        $handle = $diaspora_meta['signer'];
        $text = $diaspora_meta['body'];
    } else {
        logger('diaspora_send_relay: original author signature not found');
    }
    /* Since the author signature is only checked by the parent, not by the relay recipients,
     * I think it may not be necessary for us to do so much work to preserve all the original
     * signatures. The important thing that Diaspora DOES need is the original creator's handle.
     * Let's just generate that and forget about all the original author signature stuff.
     *
     * Note: this might be more of an problem if we want to support likes on comments for older
     * versions of Diaspora (diaspora-pistos), but since there are a number of problems with
     * doing that, let's ignore it for now.
     *
     *
     */
    // bug - nomadic identity may/will affect diaspora_handle_from_contact
    if (!$handle) {
        if ($item['author_xchan'] === $owner['channel_hash']) {
            $handle = $owner['channel_address'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(), '://') + 3);
        } else {
            $handle = diaspora_handle_from_contact($item['author_xchan']);
        }
    }
    if (!$handle) {
        logger('diaspora_send_relay: no handle');
        return;
    }
    if (!$sender_signed_text) {
        if ($relay_retract) {
            $sender_signed_text = $item['mid'] . ';' . $target_type;
        } elseif ($like) {
            $sender_signed_text = $positive . ';' . $item['mid'] . ';' . $target_type . ';' . $parent['mid'] . ';' . $handle;
        } else {
            $sender_signed_text = $item['mid'] . ';' . $parent['mid'] . ';' . $text . ';' . $handle;
        }
    }
    // Sign the relayable with the top-level owner's signature
    //
    // We'll use the $sender_signed_text that we just created, instead of the $signed_text
    // stored in the database, because that provides the best chance that Diaspora will
    // be able to reconstruct the signed text the same way we did. This is particularly a
    // concern for the comment, whose signed text includes the text of the comment. The
    // smallest change in the text of the comment, including removing whitespace, will
    // make the signature verification fail. Since we translate from BB code to Diaspora's
    // markup at the top of this function, which is AFTER we placed the original $signed_text
    // in the database, it's hazardous to trust the original $signed_text.
    $parentauthorsig = base64_encode(rsa_sign($sender_signed_text, $owner['channel_prvkey'], 'sha256'));
    $msg = replace_macros($tpl, array('$guid' => xmlify($item['mid']), '$parent_guid' => xmlify($parent['mid']), '$target_type' => xmlify($target_type), '$authorsig' => xmlify($authorsig), '$parentsig' => xmlify($parentauthorsig), '$body' => xmlify($text), '$positive' => xmlify($positive), '$handle' => xmlify($handle)));
    logger('diaspora_send_relay: base message: ' . $msg, LOGGER_DATA);
    $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg, $owner, $contact, $owner['channel_prvkey'], $contact['xchan_pubkey'], $public_batch)));
    return diaspora_transmit($owner, $contact, $slap, $public_batch);
}
Exemple #4
0
function diaspora_send_relay($item, $owner, $contact, $public_batch = false)
{
    $a = get_app();
    $myaddr = $owner['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(), '://') + 3);
    //	$theiraddr = $contact['addr'];
    // Diaspora doesn't support threaded comments, but some
    // versions of Diaspora (i.e. Diaspora-pistos) support
    // likes on comments
    if ($item['verb'] === ACTIVITY_LIKE && $item['thr-parent']) {
        $p = q("select guid, type, uri, `parent-uri` from item where uri = '%s' limit 1", dbesc($item['thr-parent']));
    } else {
        // The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always
        // return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent.
        // The only item with `parent` and `id` as the parent id is the parent item.
        $p = q("select guid, type, uri, `parent-uri` from item where parent = %d and id = %d limit 1", intval($item['parent']), intval($item['parent']));
    }
    if (count($p)) {
        $parent = $p[0];
    } else {
        return;
    }
    $like = false;
    $relay_retract = false;
    $sql_sign_id = 'iid';
    if ($item['deleted']) {
        $relay_retract = true;
        $target_type = $item['verb'] === ACTIVITY_LIKE ? 'Like' : 'Comment';
        $sql_sign_id = 'retract_iid';
        $tpl = get_markup_template('diaspora_relayable_retraction.tpl');
    } elseif ($item['verb'] === ACTIVITY_LIKE) {
        $like = true;
        $target_type = $parent['uri'] === $parent['parent-uri'] ? 'Post' : 'Comment';
        //		$positive = (($item['deleted']) ? 'false' : 'true');
        $positive = 'true';
        $tpl = get_markup_template('diaspora_like_relay.tpl');
    } else {
        // item is a comment
        $tpl = get_markup_template('diaspora_comment_relay.tpl');
    }
    // fetch the original signature	if the relayable was created by a Diaspora
    // or DFRN user. Relayables for other networks are not supported.
    $r = q("SELECT `signed_text`, `signature`, `signer` FROM `sign` WHERE " . $sql_sign_id . " = %d LIMIT 1", intval($item['id']));
    if (count($r)) {
        $orig_sign = $r[0];
        $signed_text = $orig_sign['signed_text'];
        $authorsig = $orig_sign['signature'];
        $handle = $orig_sign['signer'];
        // Friendica servers lower than 3.5 had double encoded the signature ...
        if (substr($authorsig, -1, 1) != "=") {
            $authorsig = base64_decode($authorsig);
        }
        // Split the signed text
        $signed_parts = explode(";", $signed_text);
        // Remove the parent guid
        array_shift($signed_parts);
        // Remove the comment guid
        array_shift($signed_parts);
        // Remove the handle
        array_pop($signed_parts);
        // Glue the parts together
        $text = implode(";", $signed_parts);
    } else {
        // This part is meant for cases where we don't have the signatur. (Which shouldn't happen with posts from Diaspora and Friendica)
        // This means that the comment won't be accepted by newer Diaspora servers
        $body = $item['body'];
        $text = html_entity_decode(bb2diaspora($body));
        $handle = diaspora_handle_from_contact($item['contact-id']);
        if (!$handle) {
            return;
        }
        if ($relay_retract) {
            $signed_text = $item['guid'] . ';' . $target_type;
        } elseif ($like) {
            $signed_text = $item['guid'] . ';' . $target_type . ';' . $parent['guid'] . ';' . $positive . ';' . $handle;
        } else {
            $signed_text = $item['guid'] . ';' . $parent['guid'] . ';' . $text . ';' . $handle;
        }
        $authorsig = base64_encode(rsa_sign($signed_text, $owner['uprvkey'], 'sha256'));
    }
    // Sign the relayable with the top-level owner's signature
    $parentauthorsig = base64_encode(rsa_sign($signed_text, $owner['uprvkey'], 'sha256'));
    $msg = replace_macros($tpl, array('$guid' => xmlify($item['guid']), '$parent_guid' => xmlify($parent['guid']), '$target_type' => xmlify($target_type), '$authorsig' => xmlify($authorsig), '$parentsig' => xmlify($parentauthorsig), '$body' => xmlify($text), '$positive' => xmlify($positive), '$handle' => xmlify($handle)));
    logger('diaspora_send_relay: base message: ' . $msg, LOGGER_DATA);
    $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg, $owner, $contact, $owner['uprvkey'], $contact['pubkey'], $public_batch)));
    //$slap = 'xml=' . urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['uprvkey'],$contact['pubkey'],$public_batch));
    return diaspora_transmit($owner, $contact, $slap, $public_batch);
}