Merge pull request #323 from fermionic/add-relayable-retraction-support-for-diaspora
Add relayable retraction support for diaspora
This commit is contained in:
commit
a66baf2918
12 changed files with 371 additions and 77 deletions
2
boot.php
2
boot.php
|
@ -11,7 +11,7 @@ require_once('include/cache.php');
|
||||||
define ( 'FRIENDICA_PLATFORM', 'Friendica');
|
define ( 'FRIENDICA_PLATFORM', 'Friendica');
|
||||||
define ( 'FRIENDICA_VERSION', '3.0.1362' );
|
define ( 'FRIENDICA_VERSION', '3.0.1362' );
|
||||||
define ( 'DFRN_PROTOCOL_VERSION', '2.23' );
|
define ( 'DFRN_PROTOCOL_VERSION', '2.23' );
|
||||||
define ( 'DB_UPDATE_VERSION', 1147 );
|
define ( 'DB_UPDATE_VERSION', 1148 );
|
||||||
|
|
||||||
define ( 'EOL', "<br />\r\n" );
|
define ( 'EOL', "<br />\r\n" );
|
||||||
define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' );
|
define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' );
|
||||||
|
|
|
@ -944,12 +944,14 @@ CREATE TABLE IF NOT EXISTS `session` (
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `sign` (
|
CREATE TABLE IF NOT EXISTS `sign` (
|
||||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
`iid` int(10) unsigned NOT NULL,
|
`iid` int(10) unsigned NOT NULL DEFAULT '0',
|
||||||
|
`retract_iid` int(10) unsigned NOT NULL DEFAULT '0',
|
||||||
`signed_text` mediumtext NOT NULL,
|
`signed_text` mediumtext NOT NULL,
|
||||||
`signature` text NOT NULL,
|
`signature` text NOT NULL,
|
||||||
`signer` char(255) NOT NULL,
|
`signer` char(255) NOT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `iid` (`iid`)
|
KEY `iid` (`iid`),
|
||||||
|
KEY `retract_iid` (`retract_iid`)
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
|
@ -113,6 +113,7 @@ function delivery_run($argv, $argc){
|
||||||
$uid = $r[0]['uid'];
|
$uid = $r[0]['uid'];
|
||||||
$updated = $r[0]['edited'];
|
$updated = $r[0]['edited'];
|
||||||
|
|
||||||
|
// The following seems superfluous. We've already checked for "if (! intval($r[0]['parent']))" a few lines up
|
||||||
if(! $parent_id)
|
if(! $parent_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -508,17 +509,17 @@ function delivery_run($argv, $argc){
|
||||||
// unsupported
|
// unsupported
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
elseif(($target_item['deleted']) && ($target_item['verb'] !== ACTIVITY_LIKE)) {
|
elseif(($target_item['deleted']) && ($target_item['uri'] === $target_item['parent-uri'])) {
|
||||||
|
// top-level retraction
|
||||||
logger('delivery: diaspora retract: ' . $loc);
|
logger('delivery: diaspora retract: ' . $loc);
|
||||||
// diaspora delete,
|
|
||||||
diaspora_send_retraction($target_item,$owner,$contact,$public_message);
|
diaspora_send_retraction($target_item,$owner,$contact,$public_message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
elseif($target_item['parent'] != $target_item['id']) {
|
elseif($target_item['uri'] !== $target_item['parent-uri']) {
|
||||||
|
// we are the relay - send comments, likes and relayable_retractions to our conversants
|
||||||
logger('delivery: diaspora relay: ' . $loc);
|
logger('delivery: diaspora relay: ' . $loc);
|
||||||
|
|
||||||
// we are the relay - send comments, likes and unlikes to our conversants
|
|
||||||
diaspora_send_relay($target_item,$owner,$contact,$public_message);
|
diaspora_send_relay($target_item,$owner,$contact,$public_message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
181
include/diaspora.php
Normal file → Executable file
181
include/diaspora.php
Normal file → Executable file
|
@ -83,6 +83,9 @@ function diaspora_dispatch($importer,$msg) {
|
||||||
elseif($xmlbase->signed_retraction) {
|
elseif($xmlbase->signed_retraction) {
|
||||||
$ret = diaspora_signed_retraction($importer,$xmlbase->signed_retraction,$msg);
|
$ret = diaspora_signed_retraction($importer,$xmlbase->signed_retraction,$msg);
|
||||||
}
|
}
|
||||||
|
elseif($xmlbase->relayable_retraction) {
|
||||||
|
$ret = diaspora_signed_retraction($importer,$xmlbase->relayable_retraction,$msg);
|
||||||
|
}
|
||||||
elseif($xmlbase->photo) {
|
elseif($xmlbase->photo) {
|
||||||
$ret = diaspora_photo($importer,$xmlbase->photo,$msg);
|
$ret = diaspora_photo($importer,$xmlbase->photo,$msg);
|
||||||
}
|
}
|
||||||
|
@ -1602,22 +1605,28 @@ function diaspora_like($importer,$xml,$msg) {
|
||||||
logger('diaspora_like: duplicate like: ' . $guid);
|
logger('diaspora_like: duplicate like: ' . $guid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Note: I don't think "Like" objects with positive = "false" are ever actually used
|
||||||
|
// It looks like "RelayableRetractions" are used for "unlike" instead
|
||||||
if($positive === 'false') {
|
if($positive === 'false') {
|
||||||
q("UPDATE `item` SET `deleted` = 1 WHERE `id` = %d AND `uid` = %d LIMIT 1",
|
logger('diaspora_like: received a like with positive set to "false"...ignoring');
|
||||||
|
/* q("UPDATE `item` SET `deleted` = 1 WHERE `id` = %d AND `uid` = %d LIMIT 1",
|
||||||
intval($r[0]['id']),
|
intval($r[0]['id']),
|
||||||
intval($importer['uid'])
|
intval($importer['uid'])
|
||||||
);
|
);*/
|
||||||
// FIXME
|
// FIXME
|
||||||
// send notification via proc_run()
|
// send notification via proc_run()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Note: I don't think "Like" objects with positive = "false" are ever actually used
|
||||||
|
// It looks like "RelayableRetractions" are used for "unlike" instead
|
||||||
if($positive === 'false') {
|
if($positive === 'false') {
|
||||||
logger('diaspora_like: unlike received with no corresponding like');
|
logger('diaspora_like: received a like with positive set to "false"');
|
||||||
|
logger('diaspora_like: unlike received with no corresponding like...ignoring');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$author_signed_data = $guid . ';' . $target_type . ';' . $parent_guid . ';' . $positive . ';' . $diaspora_handle;
|
$signed_data = $guid . ';' . $target_type . ';' . $parent_guid . ';' . $positive . ';' . $diaspora_handle;
|
||||||
|
|
||||||
$author_signature = base64_decode($author_signature);
|
$author_signature = base64_decode($author_signature);
|
||||||
|
|
||||||
|
@ -1635,20 +1644,20 @@ function diaspora_like($importer,$xml,$msg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(! rsa_verify($author_signed_data,$author_signature,$key,'sha256')) {
|
if(! rsa_verify($signed_data,$author_signature,$key,'sha256')) {
|
||||||
logger('diaspora_like: verification failed.');
|
logger('diaspora_like: verification failed.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($parent_author_signature) {
|
if($parent_author_signature) {
|
||||||
|
|
||||||
$owner_signed_data = $guid . ';' . $target_type . ';' . $parent_guid . ';' . $positive . ';' . $diaspora_handle;
|
//$owner_signed_data = $guid . ';' . $target_type . ';' . $parent_guid . ';' . $positive . ';' . $diaspora_handle;
|
||||||
|
|
||||||
$parent_author_signature = base64_decode($parent_author_signature);
|
$parent_author_signature = base64_decode($parent_author_signature);
|
||||||
|
|
||||||
$key = $msg['key'];
|
$key = $msg['key'];
|
||||||
|
|
||||||
if(! rsa_verify($owner_signed_data,$parent_author_signature,$key,'sha256')) {
|
if(! rsa_verify($signed_data,$parent_author_signature,$key,'sha256')) {
|
||||||
logger('diaspora_like: owner verification failed.');
|
logger('diaspora_like: owner verification failed.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1783,38 +1792,89 @@ function diaspora_signed_retraction($importer,$xml,$msg) {
|
||||||
$type = notags(unxmlify($xml->target_type));
|
$type = notags(unxmlify($xml->target_type));
|
||||||
$sig = notags(unxmlify($xml->target_author_signature));
|
$sig = notags(unxmlify($xml->target_author_signature));
|
||||||
|
|
||||||
|
$parent_author_signature = (($xml->parent_author_signature) ? notags(unxmlify($xml->parent_author_signature)) : '');
|
||||||
|
|
||||||
$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
|
$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
|
||||||
if(! $contact) {
|
if(! $contact) {
|
||||||
logger('diaspora_signed_retraction: no contact');
|
logger('diaspora_signed_retraction: no contact');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this may not yet work for comments. Need to see how the relaying works
|
|
||||||
// and figure out who signs it.
|
|
||||||
|
|
||||||
|
|
||||||
$signed_data = $guid . ';' . $type ;
|
$signed_data = $guid . ';' . $type ;
|
||||||
|
|
||||||
$sig = base64_decode($sig);
|
$sig_decode = base64_decode($sig);
|
||||||
|
|
||||||
|
if(strcasecmp($diaspora_handle,$msg['author']) == 0) {
|
||||||
|
$person = $contact;
|
||||||
$key = $msg['key'];
|
$key = $msg['key'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$person = find_diaspora_person_by_handle($diaspora_handle);
|
||||||
|
|
||||||
if(! rsa_verify($signed_data,$sig,$key,'sha256')) {
|
if(is_array($person) && x($person,'pubkey'))
|
||||||
logger('diaspora_signed_retraction: owner verification failed.' . print_r($msg,true));
|
$key = $person['pubkey'];
|
||||||
|
else {
|
||||||
|
logger('diaspora_signed_retraction: unable to find author details');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(! rsa_verify($signed_data,$sig_decode,$key,'sha256')) {
|
||||||
|
logger('diaspora_signed_retraction: retraction-owner verification failed.' . print_r($msg,true));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($type === 'StatusMessage') {
|
if($parent_author_signature) {
|
||||||
|
$parent_author_signature = base64_decode($parent_author_signature);
|
||||||
|
|
||||||
|
$key = $msg['key'];
|
||||||
|
|
||||||
|
if(! rsa_verify($signed_data,$parent_author_signature,$key,'sha256')) {
|
||||||
|
logger('diaspora_signed_retraction: failed to verify person relaying the retraction (e.g. owner of a post relaying a retracted comment');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if($type === 'StatusMessage' || $type === 'Comment' || $type === 'Like') {
|
||||||
$r = q("select * from item where guid = '%s' and uid = %d and not file like '%%[%%' limit 1",
|
$r = q("select * from item where guid = '%s' and uid = %d and not file like '%%[%%' limit 1",
|
||||||
dbesc($guid),
|
dbesc($guid),
|
||||||
intval($importer['uid'])
|
intval($importer['uid'])
|
||||||
);
|
);
|
||||||
if(count($r)) {
|
if(count($r)) {
|
||||||
if(link_compare($r[0]['author-link'],$contact['url'])) {
|
if(link_compare($r[0]['author-link'],$contact['url'])) {
|
||||||
q("update item set `deleted` = 1, `changed` = '%s' where `id` = %d limit 1",
|
q("update item set `deleted` = 1, `edited` = '%s', `changed` = '%s', `body` = '' , `title` = '' where `id` = %d limit 1",
|
||||||
|
dbesc(datetime_convert()),
|
||||||
dbesc(datetime_convert()),
|
dbesc(datetime_convert()),
|
||||||
intval($r[0]['id'])
|
intval($r[0]['id'])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Now check if the retraction needs to be relayed by us
|
||||||
|
//
|
||||||
|
// 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 origin from item where parent = %d and id = %d limit 1",
|
||||||
|
$r[0]['parent'],
|
||||||
|
$r[0]['parent']
|
||||||
|
);
|
||||||
|
if(count($p)) {
|
||||||
|
if(($p[0]['origin']) && (! $parent_author_signature)) {
|
||||||
|
q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
|
||||||
|
$r[0]['id'],
|
||||||
|
dbesc($signed_data),
|
||||||
|
dbesc($sig),
|
||||||
|
dbesc($diaspora_handle)
|
||||||
|
);
|
||||||
|
|
||||||
|
// the existence of parent_author_signature would have meant the parent_author or owner
|
||||||
|
// is already relaying.
|
||||||
|
logger('diaspora_signed_retraction: relaying relayable_retraction');
|
||||||
|
|
||||||
|
proc_run('php','include/notifier.php','relayable_retraction',$r[0]['id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2071,7 +2131,11 @@ function diaspora_send_followup($item,$owner,$contact,$public_batch = false) {
|
||||||
$tpl = get_markup_template('diaspora_like.tpl');
|
$tpl = get_markup_template('diaspora_like.tpl');
|
||||||
$like = true;
|
$like = true;
|
||||||
$target_type = 'Post';
|
$target_type = 'Post';
|
||||||
$positive = (($item['deleted']) ? 'false' : 'true');
|
// $positive = (($item['deleted']) ? 'false' : 'true');
|
||||||
|
$positive = 'true';
|
||||||
|
|
||||||
|
if(($item['deleted']))
|
||||||
|
logger('diaspora_send_followup: received deleted "like". Those should go to diaspora_send_retraction');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$tpl = get_markup_template('diaspora_comment.tpl');
|
$tpl = get_markup_template('diaspora_comment.tpl');
|
||||||
|
@ -2127,29 +2191,35 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) {
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if($item['verb'] === ACTIVITY_LIKE) {
|
$like = false;
|
||||||
|
$relay_retract = false;
|
||||||
|
$sql_sign_id = 'iid';
|
||||||
|
if( $item['deleted']) {
|
||||||
|
$tpl = get_markup_template('diaspora_relayable_retraction.tpl');
|
||||||
|
$relay_retract = true;
|
||||||
|
$sql_sign_id = 'retract_iid';
|
||||||
|
$target_type = ( ($item['verb'] === ACTIVITY_LIKE) ? 'Like' : 'Comment');
|
||||||
|
}
|
||||||
|
elseif($item['verb'] === ACTIVITY_LIKE) {
|
||||||
$tpl = get_markup_template('diaspora_like_relay.tpl');
|
$tpl = get_markup_template('diaspora_like_relay.tpl');
|
||||||
$like = true;
|
$like = true;
|
||||||
$target_type = 'Post';
|
$target_type = 'Post';
|
||||||
$positive = (($item['deleted']) ? 'false' : 'true');
|
// $positive = (($item['deleted']) ? 'false' : 'true');
|
||||||
|
$positive = 'true';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$tpl = get_markup_template('diaspora_comment_relay.tpl');
|
$tpl = get_markup_template('diaspora_comment_relay.tpl');
|
||||||
$like = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$body = $item['body'];
|
$body = $item['body'];
|
||||||
|
|
||||||
$text = html_entity_decode(bb2diaspora($body));
|
$text = html_entity_decode(bb2diaspora($body));
|
||||||
|
|
||||||
// fetch the original signature if somebody sent the post to us to relay
|
|
||||||
// If we are relaying for a reply originating on our own account, there wasn't a 'send to relay'
|
|
||||||
// action. It wasn't needed. In that case create the original signature and the
|
|
||||||
// owner (parent author) signature
|
|
||||||
// comments from other networks will be relayed under our name, with a brief
|
|
||||||
// preamble to describe what's happening and noting the real author
|
|
||||||
|
|
||||||
$r = q("select * from sign where iid = %d limit 1",
|
// 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'])
|
intval($item['id'])
|
||||||
);
|
);
|
||||||
if(count($r)) {
|
if(count($r)) {
|
||||||
|
@ -2160,6 +2230,12 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) {
|
||||||
}
|
}
|
||||||
else {
|
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;
|
||||||
|
/*
|
||||||
$itemcontact = q("select * from contact where `id` = %d limit 1",
|
$itemcontact = q("select * from contact where `id` = %d limit 1",
|
||||||
intval($item['contact-id'])
|
intval($item['contact-id'])
|
||||||
);
|
);
|
||||||
|
@ -2168,29 +2244,40 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) {
|
||||||
$prefix = sprintf( t('[Relayed] Comment authored by %s from network %s'),
|
$prefix = sprintf( t('[Relayed] Comment authored by %s from network %s'),
|
||||||
'['. $item['author-name'] . ']' . '(' . $item['author-link'] . ')',
|
'['. $item['author-name'] . ']' . '(' . $item['author-link'] . ')',
|
||||||
network_to_name($itemcontact['network'])) . "\n";
|
network_to_name($itemcontact['network'])) . "\n";
|
||||||
|
// "$body" was assigned to "$text" above. It isn't used after that, so I don't think
|
||||||
|
// the following change will do anything
|
||||||
$body = $prefix . $body;
|
$body = $prefix . $body;
|
||||||
|
|
||||||
|
// I think this comment will fail upon reaching Diaspora, because "$signed_text" is not defined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// I'm confused about this "else." Since it sets "$handle = $myaddr," it seems like it should be for the case
|
||||||
|
// where the top-level post owner commented on his own post, i.e. "$itemcontact[0]['self']" is true. But it's
|
||||||
|
// positioned to be for the case where "count($itemcontact)" is 0.
|
||||||
|
|
||||||
|
$handle = $myaddr;
|
||||||
|
|
||||||
if($like)
|
if($like)
|
||||||
$signed_text = $item['guid'] . ';' . $target_type . ';' . $parent_guid . ';' . $positive . ';' . $myaddr;
|
$signed_text = $item['guid'] . ';' . $target_type . ';' . $parent_guid . ';' . $positive . ';' . $handle;
|
||||||
|
elseif($relay_retract)
|
||||||
|
$signed_text = $item['guid'] . ';' . $target_type;
|
||||||
else
|
else
|
||||||
$signed_text = $item['guid'] . ';' . $parent_guid . ';' . $text . ';' . $myaddr;
|
$signed_text = $item['guid'] . ';' . $parent_guid . ';' . $text . ';' . $handle;
|
||||||
|
|
||||||
$authorsig = base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256'));
|
$authorsig = base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256'));
|
||||||
|
|
||||||
q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
|
q("insert into sign (`" . $sql_sign_id . "`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
|
||||||
intval($item['id']),
|
intval($item['id']),
|
||||||
dbesc($signed_text),
|
dbesc($signed_text),
|
||||||
dbesc(base64_encode($authorsig)),
|
dbesc($authorsig),
|
||||||
dbesc($myaddr)
|
dbesc($handle)
|
||||||
);
|
);
|
||||||
$handle = $myaddr;
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// sign it
|
// sign it with the top-level owner's signature
|
||||||
|
|
||||||
$parentauthorsig = base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256'));
|
$parentauthorsig = base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256'));
|
||||||
|
|
||||||
|
@ -2198,14 +2285,15 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) {
|
||||||
'$guid' => xmlify($item['guid']),
|
'$guid' => xmlify($item['guid']),
|
||||||
'$parent_guid' => xmlify($parent_guid),
|
'$parent_guid' => xmlify($parent_guid),
|
||||||
'$target_type' =>xmlify($target_type),
|
'$target_type' =>xmlify($target_type),
|
||||||
'$authorsig' => xmlify($orig_sign['signature']),
|
'$authorsig' => xmlify($authorsig),
|
||||||
'$parentsig' => xmlify($parentauthorsig),
|
'$parentsig' => xmlify($parentauthorsig),
|
||||||
'$body' => xmlify($text),
|
'$body' => xmlify($text),
|
||||||
'$positive' => xmlify($positive),
|
'$positive' => xmlify($positive),
|
||||||
'$handle' => xmlify($handle)
|
'$handle' => xmlify($handle)
|
||||||
));
|
));
|
||||||
|
|
||||||
logger('diaspora_relay_comment: base message: ' . $msg, LOGGER_DATA);
|
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(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['uprvkey'],$contact['pubkey'],$public_batch)));
|
||||||
|
|
||||||
|
@ -2220,14 +2308,25 @@ function diaspora_send_retraction($item,$owner,$contact,$public_batch = false) {
|
||||||
$a = get_app();
|
$a = get_app();
|
||||||
$myaddr = $owner['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
|
$myaddr = $owner['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
|
||||||
|
|
||||||
$signed_text = $item['guid'] . ';' . 'StatusMessage';
|
// Check whether the retraction is for a top-level post or whether it's a relayable
|
||||||
|
if( $item['uri'] !== $item['parent-uri'] ) {
|
||||||
|
|
||||||
|
$tpl = get_markup_template('diaspora_relay_retraction.tpl');
|
||||||
|
$target_type = (($item['verb'] === ACTIVITY_LIKE) ? 'Like' : 'Comment');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
$tpl = get_markup_template('diaspora_signed_retract.tpl');
|
$tpl = get_markup_template('diaspora_signed_retract.tpl');
|
||||||
|
$target_type = 'StatusMessage';
|
||||||
|
}
|
||||||
|
|
||||||
|
$signed_text = $item['guid'] . ';' . $target_type;
|
||||||
|
|
||||||
$msg = replace_macros($tpl, array(
|
$msg = replace_macros($tpl, array(
|
||||||
'$guid' => $item['guid'],
|
'$guid' => xmlify($item['guid']),
|
||||||
'$type' => 'StatusMessage',
|
'$type' => xmlify($target_type),
|
||||||
'$handle' => $myaddr,
|
'$handle' => xmlify($myaddr),
|
||||||
'$signature' => base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256'))
|
'$signature' => xmlify(base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256')))
|
||||||
));
|
));
|
||||||
|
|
||||||
$slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['uprvkey'],$contact['pubkey'],$public_batch)));
|
$slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['uprvkey'],$contact['pubkey'],$public_batch)));
|
||||||
|
@ -2351,3 +2450,5 @@ function diaspora_transmit($owner,$contact,$slap,$public_batch) {
|
||||||
|
|
||||||
return(($return_code) ? $return_code : (-1));
|
return(($return_code) ? $return_code : (-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
35
include/items.php
Normal file → Executable file
35
include/items.php
Normal file → Executable file
|
@ -3279,6 +3279,41 @@ function drop_item($id,$interactive = true) {
|
||||||
intval($r[0]['id'])
|
intval($r[0]['id'])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a relayable_retraction signature for Diaspora. Note that we can't add a target_author_signature
|
||||||
|
// if the comment was deleted by a remote user. That should be ok, because if a remote user is deleting
|
||||||
|
// the comment, that means we're the home of the post, and Diaspora will only
|
||||||
|
// check the parent_author_signature of retractions that it doesn't have to relay further
|
||||||
|
//
|
||||||
|
// I don't think this function gets called for an "unlike," but I'll check anyway
|
||||||
|
$signed_text = $item['guid'] . ';' . ( ($item['verb'] === ACTIVITY_LIKE) ? 'Like' : 'Comment');
|
||||||
|
|
||||||
|
if(local_user() == $item['uid']) {
|
||||||
|
|
||||||
|
$handle = $a->user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
|
||||||
|
$authorsig = base64_encode(rsa_sign($signed_text,$a->user['prvkey'],'sha256'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$r = q("SELECT `nick`, `url` FROM `contact` WHERE `id` = '%d' LIMIT 1",
|
||||||
|
$item['contact-id']
|
||||||
|
);
|
||||||
|
if(count($r)) {
|
||||||
|
// The below handle only works for NETWORK_DFRN. I think that's ok, because this function
|
||||||
|
// only handles DFRN deletes
|
||||||
|
$handle_baseurl_start = strpos($r['url'],'://') + 3;
|
||||||
|
$handle_baseurl_length = strpos($r['url'],'/profile') - $handle_baseurl_start;
|
||||||
|
$handle = $r['nick'] . '@' . substr($r['url'], $handle_baseurl_start, $handle_baseurl_length);
|
||||||
|
$authorsig = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($handle))
|
||||||
|
q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
|
||||||
|
intval($item['id']),
|
||||||
|
dbesc($signed_text),
|
||||||
|
dbesc($authorsig),
|
||||||
|
dbesc($handle)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
$drop_id = intval($item['id']);
|
$drop_id = intval($item['id']);
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,7 @@ function notifier_run($argv, $argc){
|
||||||
$uid = $r[0]['uid'];
|
$uid = $r[0]['uid'];
|
||||||
$updated = $r[0]['edited'];
|
$updated = $r[0]['edited'];
|
||||||
|
|
||||||
|
// The following seems superfluous. We've already checked for "if (! intval($r[0]['parent']))" a few lines up
|
||||||
if(! $parent_id)
|
if(! $parent_id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -596,7 +597,7 @@ function notifier_run($argv, $argc){
|
||||||
break;
|
break;
|
||||||
case NETWORK_OSTATUS:
|
case NETWORK_OSTATUS:
|
||||||
|
|
||||||
// Do not send to otatus if we are not configured to send to public networks
|
// Do not send to ostatus if we are not configured to send to public networks
|
||||||
if($owner['prvnets'])
|
if($owner['prvnets'])
|
||||||
break;
|
break;
|
||||||
if(get_config('system','ostatus_disabled') || get_config('system','dfrn_only'))
|
if(get_config('system','ostatus_disabled') || get_config('system','dfrn_only'))
|
||||||
|
@ -737,18 +738,19 @@ function notifier_run($argv, $argc){
|
||||||
// unsupported
|
// unsupported
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
elseif(($target_item['deleted']) && ($target_item['verb'] !== ACTIVITY_LIKE)) {
|
elseif(($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
|
||||||
// diaspora delete,
|
// send both top-level retractions and relayable retractions for owner to relay
|
||||||
diaspora_send_retraction($target_item,$owner,$contact);
|
diaspora_send_retraction($target_item,$owner,$contact);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
elseif($followup) {
|
elseif($followup) {
|
||||||
// send comments, likes and retractions of likes to owner to relay
|
// send comments and likes to owner to relay
|
||||||
diaspora_send_followup($target_item,$owner,$contact);
|
diaspora_send_followup($target_item,$owner,$contact);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
elseif($target_item['parent'] != $target_item['id']) {
|
elseif($target_item['uri'] !== $target_item['parent-uri']) {
|
||||||
// we are the relay - send comments, likes and unlikes to our conversants
|
// we are the relay - send comments, likes and relayable_retractions
|
||||||
|
// (of comments and likes) to our conversants
|
||||||
diaspora_send_relay($target_item,$owner,$contact);
|
diaspora_send_relay($target_item,$owner,$contact);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -858,6 +860,13 @@ function notifier_run($argv, $argc){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the item was deleted, clean up the `sign` table
|
||||||
|
if($target_item['deleted']) {
|
||||||
|
$r = q("DELETE FROM sign where `retract_iid` = %d",
|
||||||
|
intval($target_item['id'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
logger('notifier: calling hooks', LOGGER_DEBUG);
|
logger('notifier: calling hooks', LOGGER_DEBUG);
|
||||||
|
|
||||||
if($normal_mode)
|
if($normal_mode)
|
||||||
|
|
123
mod/like.php
Normal file → Executable file
123
mod/like.php
Normal file → Executable file
|
@ -104,7 +104,8 @@ function like_content(&$a) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$r = q("SELECT `id` FROM `item` WHERE `verb` = '%s' AND `deleted` = 0
|
|
||||||
|
$r = q("SELECT * FROM `item` WHERE `verb` = '%s' AND `deleted` = 0
|
||||||
AND `contact-id` = %d AND ( `parent` = '%s' OR `parent-uri` = '%s') LIMIT 1",
|
AND `contact-id` = %d AND ( `parent` = '%s' OR `parent-uri` = '%s') LIMIT 1",
|
||||||
dbesc($activity),
|
dbesc($activity),
|
||||||
intval($contact['id']),
|
intval($contact['id']),
|
||||||
|
@ -112,13 +113,70 @@ function like_content(&$a) {
|
||||||
dbesc($item_id)
|
dbesc($item_id)
|
||||||
);
|
);
|
||||||
if(count($r)) {
|
if(count($r)) {
|
||||||
|
$like_item = $r[0];
|
||||||
|
|
||||||
// Already voted, undo it
|
// Already voted, undo it
|
||||||
$r = q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `id` = %d LIMIT 1",
|
$r = q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `id` = %d LIMIT 1",
|
||||||
dbesc(datetime_convert()),
|
dbesc(datetime_convert()),
|
||||||
intval($r[0]['id'])
|
intval($like_item['id'])
|
||||||
);
|
);
|
||||||
|
|
||||||
proc_run('php',"include/notifier.php","like","$post_id");
|
// Clean up the `sign` table
|
||||||
|
$r = q("DELETE FROM `sign` WHERE `iid` = %d",
|
||||||
|
intval($like_item['id'])
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save the author information for the unlike in case we need to relay to Diaspora
|
||||||
|
// Note that we can only create a signature for a user of the local server. We don't have
|
||||||
|
// a key for remote users. That is ok, because if a remote user is "unlike"ing a post, it
|
||||||
|
// means we are the relay, and for relayable_retractions, Diaspora
|
||||||
|
// only checks the parent_author_signature if it doesn't have to relay further
|
||||||
|
//
|
||||||
|
// If $item['resource-id'] exists, it means the item is a photo. Diaspora doesn't support
|
||||||
|
// likes on photos, so don't bother.
|
||||||
|
|
||||||
|
if(($activity === ACTIVITY_LIKE) && (! $item['resource-id'])) {
|
||||||
|
$signed_text = $like_item['guid'] . ';' . 'Like';
|
||||||
|
|
||||||
|
if( $contact['network'] === NETWORK_DIASPORA)
|
||||||
|
$diaspora_handle = $contact['addr'];
|
||||||
|
else { // Only works for NETWORK_DFRN
|
||||||
|
$contact_baseurl_start = strpos($contact['url'],'://') + 3;
|
||||||
|
$contact_baseurl_length = strpos($contact['url'],'/profile') - $contact_baseurl_start;
|
||||||
|
$contact_baseurl = substr($contact['url'], $contact_baseurl_start, $contact_baseurl_length);
|
||||||
|
$diaspora_handle = $contact['nick'] . '@' . $contact_baseurl;
|
||||||
|
|
||||||
|
// Get contact's private key if he's a user of the local Friendica server
|
||||||
|
$r = q("SELECT `contact`.`uid` FROM `contact` WHERE `url` = '%s' AND `self` = 1 LIMIT 1",
|
||||||
|
dbesc($contact['url'])
|
||||||
|
);
|
||||||
|
|
||||||
|
if( $r) {
|
||||||
|
$contact_uid = $r['uid'];
|
||||||
|
$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
|
||||||
|
intval($contact_uid)
|
||||||
|
);
|
||||||
|
|
||||||
|
if( $r)
|
||||||
|
$authorsig = base64_encode(rsa_sign($signed_text,$r['prvkey'],'sha256'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(! isset($authorsig))
|
||||||
|
$authorsig = '';
|
||||||
|
|
||||||
|
q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
|
||||||
|
intval($like_item['id']),
|
||||||
|
dbesc($signed_text),
|
||||||
|
dbesc($authorsig),
|
||||||
|
dbesc($diaspora_handle)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// proc_run('php',"include/notifier.php","like","$post_id"); // $post_id isn't defined here!
|
||||||
|
$like_item_id = $like_item['id'];
|
||||||
|
proc_run('php',"include/notifier.php","like","$like_item_id");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,6 +249,65 @@ EOT;
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Save the author information for the like in case we need to relay to Diaspora
|
||||||
|
// Note that we can only create a signature for a user of the local server. We don't have
|
||||||
|
// a key for remote users. That is ok, because if a remote user is "unlike"ing a post, it
|
||||||
|
// means we are the relay, and for relayable_retractions, Diaspora
|
||||||
|
// only checks the parent_author_signature if it doesn't have to relay further
|
||||||
|
|
||||||
|
if(($activity === ACTIVITY_LIKE) && ($post_type === t('status'))) {
|
||||||
|
if( $contact['network'] === NETWORK_DIASPORA)
|
||||||
|
$diaspora_handle = $contact['addr'];
|
||||||
|
else { // Only works for NETWORK_DFRN
|
||||||
|
$contact_baseurl_start = strpos($contact['url'],'://') + 3;
|
||||||
|
$contact_baseurl_length = strpos($contact['url'],'/profile') - $contact_baseurl_start;
|
||||||
|
$contact_baseurl = substr($contact['url'], $contact_baseurl_start, $contact_baseurl_length);
|
||||||
|
$diaspora_handle = $contact['nick'] . '@' . $contact_baseurl;
|
||||||
|
|
||||||
|
// Get contact's private key if he's a user of the local Friendica server
|
||||||
|
$r = q("SELECT `contact`.`uid` FROM `contact` WHERE `url` = '%s' AND `self` = 1 LIMIT 1",
|
||||||
|
dbesc($contact['url'])
|
||||||
|
);
|
||||||
|
|
||||||
|
if( $r) {
|
||||||
|
$contact_uid = $r['uid'];
|
||||||
|
$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
|
||||||
|
intval($contact_uid)
|
||||||
|
);
|
||||||
|
|
||||||
|
if( $r)
|
||||||
|
$contact_uprvkey = $r['prvkey'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = q("SELECT guid, parent FROM `item` WHERE id = %d LIMIT 1",
|
||||||
|
intval($post_id)
|
||||||
|
);
|
||||||
|
if( $r) {
|
||||||
|
$p = q("SELECT guid FROM `item` WHERE id = %d AND parent = %d LIMIT 1",
|
||||||
|
intval($r[0]['parent']),
|
||||||
|
intval($r[0]['parent'])
|
||||||
|
);
|
||||||
|
if( $p) {
|
||||||
|
$signed_text = $r[0]['guid'] . ';Post;' . $p[0]['guid'] . ';true;' . $diaspora_handle;
|
||||||
|
|
||||||
|
if(isset($contact_uprvkey))
|
||||||
|
$authorsig = base64_encode(rsa_sign($signed_text,$contact_uprvkey,'sha256'));
|
||||||
|
else
|
||||||
|
$authorsig = '';
|
||||||
|
|
||||||
|
q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
|
||||||
|
intval($post_id),
|
||||||
|
dbesc($signed_text),
|
||||||
|
dbesc($authorsig),
|
||||||
|
dbesc($diaspora_handle)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$arr['id'] = $post_id;
|
$arr['id'] = $post_id;
|
||||||
|
|
||||||
call_hooks('post_local_end', $arr);
|
call_hooks('post_local_end', $arr);
|
||||||
|
|
10
update.php
10
update.php
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
define( 'UPDATE_VERSION' , 1147 );
|
define( 'UPDATE_VERSION' , 1148 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -1274,4 +1274,12 @@ function update_1146() {
|
||||||
return UPDATE_SUCCESS ;
|
return UPDATE_SUCCESS ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function update_1147() {
|
||||||
|
$r1 = q("ALTER TABLE `sign` ALTER `iid` SET DEFAULT '0'");
|
||||||
|
$r2 = q("ALTER TABLE `sign` ADD `retract_iid` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `iid`");
|
||||||
|
$r3 = q("ALTER TABLE `sign` ADD INDEX ( `retract_iid` )");
|
||||||
|
if((! $r1) || (! $r2) || (! $r3))
|
||||||
|
return UPDATE_FAILED ;
|
||||||
|
return UPDATE_SUCCESS ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
2
view/diaspora_like_relay.tpl
Normal file → Executable file
2
view/diaspora_like_relay.tpl
Normal file → Executable file
|
@ -5,7 +5,7 @@
|
||||||
<target_type>$target_type</target_type>
|
<target_type>$target_type</target_type>
|
||||||
<parent_guid>$parent_guid</parent_guid>
|
<parent_guid>$parent_guid</parent_guid>
|
||||||
<parent_author_signature>$parentsig</parent_author_signature>
|
<parent_author_signature>$parentsig</parent_author_signature>
|
||||||
<author_signature>$authrosig</author_signature>
|
<author_signature>$authorsig</author_signature>
|
||||||
<positive>$positive</positive>
|
<positive>$positive</positive>
|
||||||
<diaspora_handle>$handle</diaspora_handle>
|
<diaspora_handle>$handle</diaspora_handle>
|
||||||
</like>
|
</like>
|
||||||
|
|
10
view/diaspora_relay_retraction.tpl
Normal file
10
view/diaspora_relay_retraction.tpl
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<XML>
|
||||||
|
<post>
|
||||||
|
<relayable_retraction>
|
||||||
|
<target_type>$type</target_type>
|
||||||
|
<target_guid>$guid</target_guid>
|
||||||
|
<target_author_signature>$signature</target_author_signature>
|
||||||
|
<sender_handle>$handle</sender_handle>
|
||||||
|
</relayable_retraction>
|
||||||
|
</post>
|
||||||
|
</XML>
|
11
view/diaspora_relayable_retraction.tpl
Executable file
11
view/diaspora_relayable_retraction.tpl
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
<XML>
|
||||||
|
<post>
|
||||||
|
<relayable_retraction>
|
||||||
|
<target_type>$target_type</target_type>
|
||||||
|
<target_guid>$guid</target_guid>
|
||||||
|
<parent_author_signature>$parentsig</parent_author_signature>
|
||||||
|
<target_author_signature>$authorsig</target_author_signature>
|
||||||
|
<sender_handle>$handle</sender_handle>
|
||||||
|
</relayable_retraction>
|
||||||
|
</post>
|
||||||
|
</XML>
|
Loading…
Reference in a new issue