]> git.mxchange.org Git - friendica.git/commitdiff
Implement relaying of relayable_retractions
authorZach Prezkuta <fermion@gmx.com>
Fri, 1 Jun 2012 01:40:12 +0000 (19:40 -0600)
committerZach Prezkuta <fermion@gmx.com>
Sun, 3 Jun 2012 20:53:29 +0000 (14:53 -0600)
Also: some whitespace cleanup, fix Diaspora parent DB query

include/delivery.php
include/diaspora.php
include/items.php
include/notifier.php
mod/item.php
update.php
view/diaspora_relay_retraction.tpl [new file with mode: 0644]
view/diaspora_relayable_retraction.tpl [new file with mode: 0644]

index 0e40e3db7237883905d0f3e5297f3a6f615817ec..62c9f92020f231965182e7f78f733085e8770e4c 100644 (file)
@@ -509,7 +509,7 @@ function delivery_run($argv, $argc){
                                        // unsupported
                                        break;
                                }
-                               elseif(($target_item['deleted']) && ($target_item['verb'] !== ACTIVITY_LIKE)) {
+                               elseif(($target_item['deleted']) && ($top_level) && ($target_item['verb'] !== ACTIVITY_LIKE)) {
                                logger('delivery: diaspora retract: ' . $loc);
                                        // diaspora delete, 
                                        diaspora_send_retraction($target_item,$owner,$contact,$public_message);
@@ -519,7 +519,7 @@ function delivery_run($argv, $argc){
 
                                logger('delivery: diaspora relay: ' . $loc);
 
-                                       // we are the relay - send comments, likes and unlikes to our conversants
+                                       // we are the relay - send comments, likes, unlikes and relayable_retractions to our conversants
                                        diaspora_send_relay($target_item,$owner,$contact,$public_message);
                                        break;
                                }               
index 8b8050a61483b1c23430fe54e6e942899f9da6d4..584be5ef266d3db7879fe9afcd20e61720994128 100644 (file)
@@ -680,7 +680,7 @@ function diaspora_post($importer,$xml) {
                return;
        }
 
-        // allocate a guid on our system - we aren't fixing any collisions.
+       // allocate a guid on our system - we aren't fixing any collisions.
        // we're ignoring them
 
        $g = q("select * from guid where guid = '%s' limit 1",
@@ -847,7 +847,7 @@ function diaspora_reshare($importer,$xml) {
        $prefix = '&#x2672; ' . $details . "\n"; 
 
 
-        // allocate a guid on our system - we aren't fixing any collisions.
+       // allocate a guid on our system - we aren't fixing any collisions.
        // we're ignoring them
 
        $g = q("select * from guid where guid = '%s' limit 1",
@@ -951,7 +951,7 @@ function diaspora_asphoto($importer,$xml) {
                return;
        }
 
-        // allocate a guid on our system - we aren't fixing any collisions.
+       // allocate a guid on our system - we aren't fixing any collisions.
        // we're ignoring them
 
        $g = q("select * from guid where guid = '%s' limit 1",
@@ -1168,7 +1168,22 @@ function diaspora_comment($importer,$xml,$msg) {
                );
        }
 
-       if(($parent_item['origin']) && (! $parent_author_signature)) {
+       if(($parent_item['origin']) && (! $parent_author_signature)) {  if(($parent_item['origin']) && (! $parent_author_signature)) {
+               q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
+                       intval($message_id),
+                       dbesc($author_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',$message_id);
+       }
+
+
                q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
                        intval($message_id),
                        dbesc($author_signed_data),
@@ -1797,7 +1812,7 @@ function diaspora_signed_retraction($importer,$xml,$msg) {
 
        $signed_data = $guid . ';' . $type ;
 
-       $sig = base64_decode($sig);
+       $sig_decode = base64_decode($sig);
 
        if(strcasecmp($diaspora_handle,$msg['author']) == 0) {
                $person = $contact;
@@ -1814,22 +1829,21 @@ function diaspora_signed_retraction($importer,$xml,$msg) {
                }
        }
 
-       if(! rsa_verify($signed_data,$sig,$key,'sha256')) {
+       if(! rsa_verify($signed_data,$sig_decode,$key,'sha256')) {
                logger('diaspora_signed_retraction: retraction-owner verification failed.' . print_r($msg,true));
                return;
        }
 
        if($parent_author_signature) {
-               $owner_signed_data = $guid . ';' . $type ;
-
                $parent_author_signature = base64_decode($parent_author_signature);
 
                $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_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') {
@@ -1839,10 +1853,36 @@ function diaspora_signed_retraction($importer,$xml,$msg) {
                );
                if(count($r)) {
                        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()),                      
                                        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']);
+                                       }
+                               }
                        }
                }
        }
@@ -2136,10 +2176,28 @@ function diaspora_send_followup($item,$owner,$contact,$public_batch = false) {
 
 
 function diaspora_send_relay($item,$owner,$contact,$public_batch = false) {
+// I think the first comment or like on a post whose home is our Friendica server is saved as an item
+// as the top-level post owner's contact for writer of the comment or post. Thus, the "uid"
+// on the item is `user`.`id` of the top-level post owner. That user is passed to this function
+// as "$owner."
+//
+// I'm assuming for now that "$owner" will be the user of the top-level post for retractions too. Be
+// aware that another reasonable possibility is that it's the "$owner" of the deleted comment.
+
+// TODO
+// CHECK       1. If we receive a retraction from Diaspora to be relayed by us, we need to insert the signature
+//                into the DB and call notifier.php
+// CHECK       2. diaspora_send_retraction() needs to be modified to send
+//                Diaspora a retraction for it to relay when appropriate
+// CHECK       3. notifier.php (and delivery.php?) need to be modified to call the right functions for the right
+//                retraction situation
+// 4. If possible, modify notifier.php (and delivery.php?) to remove the relayable retraction's signature
+//    from the DB after finishing with relaying retractions
+
 
 
        $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);
        $theiraddr = $contact['addr'];
 
 
@@ -2155,29 +2213,42 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) {
        else
                return;
 
+       $like = false;
+       $relay_retract = false;
+       $sql_sign_id = 'iid';
        if($item['verb'] === ACTIVITY_LIKE) {
                $tpl = get_markup_template('diaspora_like_relay.tpl');
                $like = true;
                $target_type = 'Post';
                $positive = (($item['deleted']) ? 'false' : 'true');
        }
-       else {
+       elseif(! $item['deleted']) {
                $tpl = get_markup_template('diaspora_comment_relay.tpl');
-               $like = false;
+       }
+       else {
+               $tpl = get_markup_template('diaspora_relayable_retraction.tpl');
+               $relay_retract = true;
+               $sql_sign_id = 'retract_iid';
+               $target_type = 'Comment';
        }
 
        $body = $item['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
+       // Note that mod/item.php seems to take care of creating a signature for Diaspora for replies
+       // created on our own account
+       //
        // 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",
+       $r = q("select * from sign where " . $sql_sign_id . " = %d limit 1",
                intval($item['id'])
        );
        if(count($r)) { 
@@ -2196,29 +2267,39 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) {
                                $prefix = sprintf( t('[Relayed] Comment authored by %s from network %s'),
                                        '['. $item['author-name'] . ']' . '(' . $item['author-link'] . ')',  
                                        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;
+
+                               // I think this comment will fail upon reaching Diaspora, because "$signed_text" is not defined
                        }
                }
                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)
-                               $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
-                               $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'));
 
-                       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']),
                                dbesc($signed_text),
-                               dbesc(base64_encode($authorsig)),
-                               dbesc($myaddr)
+                               dbesc($authorsig),
+                               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'));
 
@@ -2226,14 +2307,15 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) {
                '$guid' => xmlify($item['guid']),
                '$parent_guid' => xmlify($parent_guid),
                '$target_type' =>xmlify($target_type),
-               '$authorsig' => xmlify($orig_sign['signature']),
+               '$authorsig' => xmlify($authorsig),
                '$parentsig' => xmlify($parentauthorsig),
                '$body' => xmlify($text),
                '$positive' => xmlify($positive),
                '$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)));
 
@@ -2248,14 +2330,25 @@ function diaspora_send_retraction($item,$owner,$contact,$public_batch = false) {
        $a = get_app();
        $myaddr = $owner['nickname'] . '@' .  substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
 
-       $signed_text = $item['guid'] . ';' . 'StatusMessage';
+       // Check if the retraction is for a top-level post, or whether it's for a comment
+       if( $item['id'] !== $item['parent'] ) {
+
+               $tpl = get_markup_template('diaspora_relay_retraction.tpl');
+               $target_type = 'Comment';
+       }
+       else {
+               
+               $tpl = get_markup_template('diaspora_signed_retract.tpl');
+               $target_type = 'StatusMessage';
+       }
+
+       $signed_text = $item['guid'] . ';' . $target_type;
 
-       $tpl = get_markup_template('diaspora_signed_retract.tpl');
        $msg = replace_macros($tpl, array(
-               '$guid'   => $item['guid'],
-               '$type'   => 'StatusMessage',
-               '$handle' => $myaddr,
-               '$signature' => base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256'))
+               '$guid'   => xmlify($item['guid']),
+               '$type'   => xmlify($target_type),
+               '$handle' => xmlify($myaddr),
+               '$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)));
index 0ed16217fae917634a0cad8db85ee62c728266b2..8858ca64fab9a7c8946dbf59e8b03d21fc75b15d 100644 (file)
@@ -3278,7 +3278,36 @@ function drop_item($id,$interactive = true) {
                                q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d LIMIT 1",
                                        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
+                       if( strcmp($item['type'], 'activity') != 0) {
+                               $signed_text = $item['guid'] . ';' . '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))
+                                               $handle = $r['nick'] . '@' . substr($r['url'], strpos($r['url'],'://') + 3, strpos($r['url'],'/profile') - 1);
+                               }
+
+                               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']);
 
index 47ad29310f58256cf49eff9fa993502ba897c077..68f230a05f8fc6c0640e1f5f905c3997d4cbc541 100644 (file)
@@ -597,7 +597,7 @@ function notifier_run($argv, $argc){
                                        break;
                                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'])
                                                break;
                                        if(get_config('system','ostatus_disabled') || get_config('system','dfrn_only'))
@@ -738,8 +738,8 @@ function notifier_run($argv, $argc){
                                                // unsupported
                                                break;
                                        }
-                                       elseif(($target_item['deleted']) && ($target_item['verb'] !== ACTIVITY_LIKE)) {
-                                               // diaspora delete, 
+                                       elseif(($target_item['deleted']) && ($top_level || $followup) && ($target_item['verb'] !== ACTIVITY_LIKE)) {
+                                               // diaspora delete, including relayable_retractions that need to be relayed
                                                diaspora_send_retraction($target_item,$owner,$contact);
                                                break;
                                        }
@@ -749,7 +749,7 @@ function notifier_run($argv, $argc){
                                                break;
                                        }
                                        elseif($target_item['parent'] != $target_item['id']) {
-                                               // we are the relay - send comments, likes and unlikes to our conversants
+                                               // we are the relay - send comments, likes, unlikes and relayable_retractions to our conversants
                                                diaspora_send_relay($target_item,$owner,$contact);
                                                break;
                                        }
@@ -859,6 +859,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);
 
        if($normal_mode)
index 497cf5daa2d3e97c4cd694a5dbae89f356c18e91..c1c0b14ec6cd507acb1f51f43857e0755f949c8c 100644 (file)
@@ -737,16 +737,16 @@ function item_post(&$a) {
                                if($datarray['verb'] === ACTIVITY_LIKE) 
                                        $signed_text = $datarray['guid'] . ';' . 'Post' . ';' . $parent_item['guid'] . ';' . 'true' . ';' . $myaddr;
                                else
-                               $signed_text = $datarray['guid'] . ';' . $parent_item['guid'] . ';' . $signed_body . ';' . $myaddr;
+                                       $signed_text = $datarray['guid'] . ';' . $parent_item['guid'] . ';' . $signed_body . ';' . $myaddr;
 
                                $authorsig = base64_encode(rsa_sign($signed_text,$a->user['prvkey'],'sha256'));
 
                                q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
                                        intval($post_id),
-                       dbesc($signed_text),
-                       dbesc(base64_encode($authorsig)),
-                       dbesc($myaddr)
-                       );
+                                       dbesc($signed_text),
+                                       dbesc(base64_encode($authorsig)),
+                                       dbesc($myaddr)
+                               );
                        }
                }
                else {
index 1b2098e6eb2bc5cf30a9bd2827d64a94f8ce1e9d..e1a554533ca4fab3d2314b922c4e181d644f7d55 100644 (file)
@@ -1137,8 +1137,8 @@ INDEX ( `username` )
 }
 
 function update_1133() {
-q("ALTER TABLE `user` ADD `unkmail` TINYINT( 1 ) NOT NULL DEFAULT '0' AFTER `blocktags` , ADD INDEX ( `unkmail` ) ");\r
-q("ALTER TABLE `user` ADD `cntunkmail` INT NOT NULL DEFAULT '10' AFTER `unkmail` , ADD INDEX ( `cntunkmail` ) ");\r
+q("ALTER TABLE `user` ADD `unkmail` TINYINT( 1 ) NOT NULL DEFAULT '0' AFTER `blocktags` , ADD INDEX ( `unkmail` ) ");
+q("ALTER TABLE `user` ADD `cntunkmail` INT NOT NULL DEFAULT '10' AFTER `unkmail` , ADD INDEX ( `cntunkmail` ) ");
 q("ALTER TABLE `mail` ADD `unknown` TINYINT( 1 ) NOT NULL DEFAULT '0' AFTER `replied` , ADD INDEX ( `unknown` ) ");
 }
 
@@ -1274,4 +1274,5 @@ function update_1146() {
        return UPDATE_SUCCESS ;
 }
 
+//ALTER TABLE `sign` MODIFY column int Default '10';
 
diff --git a/view/diaspora_relay_retraction.tpl b/view/diaspora_relay_retraction.tpl
new file mode 100644 (file)
index 0000000..e76c7c6
--- /dev/null
@@ -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>
diff --git a/view/diaspora_relayable_retraction.tpl b/view/diaspora_relayable_retraction.tpl
new file mode 100644 (file)
index 0000000..27936f7
--- /dev/null
@@ -0,0 +1,11 @@
+<XML>
+  <post>
+    <relayable_retraction>
+      <target_type>$target_type</target_type>
+      <target_guid>$guid</target_guid>
+      <parent_author_signature>$parentauthorsig</parent_author_signature>
+      <target_author_signature>$authorsig</target_author_signature>
+      <sender_handle>$handle</sender_handle>
+    </relayable_retraction>
+  </post>
+</XML>