]> git.mxchange.org Git - friendica.git/blobdiff - src/Protocol/Diaspora.php
Some corrections
[friendica.git] / src / Protocol / Diaspora.php
index 6f03c0df87ad559cd0137034cb2d9d6f0f8d5a93..981abb0831defaec2816419afe5ec16b307cbc7b 100644 (file)
@@ -68,6 +68,12 @@ class Diaspora
                }
 
                if (Config::get("system", "relay_directly", false)) {
+                       // We distribute our stuff based on the parent to ensure that the thread will be complete
+                       $parent = dba::selectFirst('item', ['parent'], ['id' => $item_id]);
+                       if (!DBM::is_result($parent)) {
+                               return;
+                       }
+
                        // Servers that want to get all content
                        $servers = dba::select('gserver', ['url'], ['relay-subscribe' => true, 'relay-scope' => 'all']);
                        while ($server = dba::fetch($servers)) {
@@ -75,7 +81,7 @@ class Diaspora
                        }
 
                        // All tags of the current post
-                       $condition = ['otype' => TERM_OBJ_POST, 'type' => TERM_HASHTAG, 'oid' => $item_id];
+                       $condition = ['otype' => TERM_OBJ_POST, 'type' => TERM_HASHTAG, 'oid' => $parent['parent']];
                        $tags = dba::select('term', ['term'], $condition);
                        $taglist = [];
                        while ($tag = dba::fetch($tags)) {
@@ -134,55 +140,58 @@ class Diaspora
         */
        private static function getRelayContact($server_url)
        {
-               $batch = $server_url . '/receive/public';
-
                $fields = ['batch', 'id', 'name', 'network', 'archive', 'blocked'];
 
                // Fetch the relay contact
-               $condition = ['uid' => 0, 'network' => NETWORK_DIASPORA, 'batch' => $batch,
+               $condition = ['uid' => 0, 'nurl' => normalise_link($server_url),
                        'contact-type' => ACCOUNT_TYPE_RELAY];
                $contact = dba::selectFirst('contact', $fields, $condition);
 
-               // If there is nothing found, we check if there is some unmarked relay
-               // This code segment can be removed before the release 2018-05
-               if (!DBM::is_result($contact)) {
-                       $condition = ['uid' => 0, 'network' => NETWORK_DIASPORA, 'batch' => $batch,
-                               'name' => 'relay', 'nick' => 'relay', 'url' => $server_url];
-                       $contact = dba::selectFirst('contact', $fields, $condition);
-
-                       if (DBM::is_result($contact)) {
-                               // Mark the relay account as a relay account
-                               $fields = ['contact-type' => ACCOUNT_TYPE_RELAY];
-                               dba::update('contact', $fields, ['id' => $contact['id']]);
-                       }
-               }
                if (DBM::is_result($contact)) {
                        if ($contact['archive'] || $contact['blocked']) {
                                return false;
                        }
                        return $contact;
                } else {
-                       $fields = ['uid' => 0, 'created' => DateTimeFormat::utcNow(),
-                               'name' => 'relay', 'nick' => 'relay',
-                               'url' => $server_url, 'nurl' => normalise_link($server_url),
-                               'batch' => $batch, 'network' => NETWORK_DIASPORA,
-                               'rel' => CONTACT_IS_FOLLOWER, 'blocked' => false,
-                               'contact-type' => ACCOUNT_TYPE_RELAY,
-                               'pending' => false, 'writable' => true];
-                       dba::insert('contact', $fields);
-
-                       $fields = ['batch', 'id', 'name', 'network'];
+                       self::setRelayContact($server_url);
+
                        $contact = dba::selectFirst('contact', $fields, $condition);
                        if (DBM::is_result($contact)) {
                                return $contact;
                        }
-
                }
 
                // It should never happen that we arrive here
                return [];
        }
 
+       /**
+        * @brief Update or insert a relay contact
+        *
+        * @param string $server_url The url of the server
+        * @param array $network_fields Optional network specific fields
+        */
+       public static function setRelayContact($server_url, $network_fields = [])
+       {
+               $fields = ['created' => DateTimeFormat::utcNow(),
+                       'name' => 'relay', 'nick' => 'relay',
+                       'url' => $server_url, 'network' => NETWORK_DIASPORA,
+                       'batch' => $server_url . '/receive/public',
+                       'rel' => CONTACT_IS_FOLLOWER, 'blocked' => false,
+                       'pending' => false, 'writable' => true];
+
+               $fields = array_merge($fields, $network_fields);
+
+               $condition = ['uid' => 0, 'nurl' => normalise_link($server_url),
+                       'contact-type' => ACCOUNT_TYPE_RELAY];
+
+               if (dba::exists('contact', $condition)) {
+                       unset($fields['created']);
+               }
+
+               dba::update('contact', $fields, $condition, true);
+       }
+
        /**
         * @brief Return a list of participating contacts for a thread
         *
@@ -596,9 +605,9 @@ class Diaspora
                }
 
                $importer = ["uid" => 0, "page-flags" => PAGE_FREELOVE];
-               $message_id = self::dispatch($importer, $msg, $fields);
+               $success = self::dispatch($importer, $msg, $fields);
 
-               return $message_id;
+               return $success;
        }
 
        /**
@@ -832,6 +841,10 @@ class Diaspora
 
                if (isset($parent_author_signature)) {
                        $key = self::key($msg["author"]);
+                       if (empty($key)) {
+                               logger("No key found for parent author ".$msg["author"], LOGGER_DEBUG);
+                               return false;
+                       }
 
                        if (!Crypto::rsaVerify($signed_data, $parent_author_signature, $key, "sha256")) {
                                logger("No valid parent author signature for parent author ".$msg["author"]. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$parent_author_signature, LOGGER_DEBUG);
@@ -840,6 +853,10 @@ class Diaspora
                }
 
                $key = self::key($fields->author);
+               if (empty($key)) {
+                       logger("No key found for author ".$fields->author, LOGGER_DEBUG);
+                       return false;
+               }
 
                if (!Crypto::rsaVerify($signed_data, $author_signature, $key, "sha256")) {
                        logger("No valid author signature for author ".$fields->author. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$author_signature, LOGGER_DEBUG);
@@ -1143,7 +1160,7 @@ class Diaspora
                //}
 
                // We don't seem to like that person
-               if ($contact["blocked"] || $contact["readonly"]) {
+               if ($contact["blocked"]) {
                        // Maybe blocked, don't accept.
                        return false;
                        // We are following this person?
@@ -1591,34 +1608,9 @@ class Diaspora
                logger('Contacts are updated.');
 
                // update items
-               /// @todo This is an extreme performance killer
-               $fields = [
-                       'owner-link' => [$contact["url"], $data["url"]],
-                       'author-link' => [$contact["url"], $data["url"]],
-               ];
-               foreach ($fields as $n => $f) {
-                       $r = q(
-                               "SELECT `id` FROM `item` WHERE `%s` = '%s' AND `uid` = %d LIMIT 1",
-                               $n,
-                               dbesc($f[0]),
-                               intval($importer["uid"])
-                       );
-
-                       if (DBM::is_result($r)) {
-                               $x = q(
-                                       "UPDATE `item` SET `%s` = '%s' WHERE `%s` = '%s' AND `uid` = %d",
-                                       $n,
-                                       dbesc($f[1]),
-                                       $n,
-                                       dbesc($f[0]),
-                                       intval($importer["uid"])
-                               );
-
-                               if ($x === false) {
-                                       return false;
-                               }
-                       }
-               }
+               // This is an extreme performance killer
+               Item::update(['owner-link' => $data["url"]], ['owner-link' => $contact["url"], 'uid' => $importer["uid"]]);
+               Item::update(['author-link' => $data["url"]], ['author-link' => $contact["url"], 'uid' => $importer["uid"]]);
 
                logger('Items are updated.');
 
@@ -2721,10 +2713,15 @@ class Diaspora
         */
        public static function originalItem($guid, $orig_author)
        {
+               if (empty($guid)) {
+                       logger('Empty guid. Quitting.');
+                       return false;
+               }
+
                // Do we already have this item?
                $fields = ['body', 'tag', 'app', 'created', 'object-type', 'uri', 'guid',
                        'author-name', 'author-link', 'author-avatar'];
-               $condition = ['guid' => $guid, 'visible' => true, 'deleted' => false];
+               $condition = ['guid' => $guid, 'visible' => true, 'deleted' => false, 'private' => false];
                $item = dba::selectfirst('item', $fields, $condition);
 
                if (DBM::is_result($item)) {
@@ -2734,7 +2731,7 @@ class Diaspora
                        // Then refetch the content, if it is a reshare from a reshare.
                        // If it is a reshared post from another network then reformat to avoid display problems with two share elements
                        if (self::isReshare($item["body"], true)) {
-                               $r = [];
+                               $item = [];
                        } elseif (self::isReshare($item["body"], false) || strstr($item["body"], "[share")) {
                                $item["body"] = Markdown::toBBCode(BBCode::toMarkdown($item["body"]));
 
@@ -2749,21 +2746,26 @@ class Diaspora
                        }
                }
 
-               if (!DBM::is_result($r)) {
+               if (!DBM::is_result($item)) {
+                       if (empty($orig_author)) {
+                               logger('Empty author for guid ' . $guid . '. Quitting.');
+                               return false;
+                       }
+
                        $server = "https://".substr($orig_author, strpos($orig_author, "@") + 1);
                        logger("1st try: reshared message ".$guid." will be fetched via SSL from the server ".$server);
-                       $item_id = self::storeByGuid($guid, $server);
+                       $stored = self::storeByGuid($guid, $server);
 
-                       if (!$item_id) {
+                       if (!$stored) {
                                $server = "http://".substr($orig_author, strpos($orig_author, "@") + 1);
-                               logger("2nd try: reshared message ".$guid." will be fetched without SLL from the server ".$server);
-                               $item_id = self::storeByGuid($guid, $server);
+                               logger("2nd try: reshared message ".$guid." will be fetched without SSL from the server ".$server);
+                               $stored = self::storeByGuid($guid, $server);
                        }
 
-                       if ($item_id) {
+                       if ($stored) {
                                $fields = ['body', 'tag', 'app', 'created', 'object-type', 'uri', 'guid',
                                        'author-name', 'author-link', 'author-avatar'];
-                               $condition = ['id' => $item_id, 'visible' => true, 'deleted' => false];
+                               $condition = ['guid' => $guid, 'visible' => true, 'deleted' => false, 'private' => false];
                                $item = dba::selectfirst('item', $fields, $condition);
 
                                if (DBM::is_result($item)) {
@@ -2967,12 +2969,10 @@ class Diaspora
                        case "StatusMessage":
                                return self::itemRetraction($importer, $contact, $data);
 
-                       case "Contact":
-                       case "Person":
-                               /// @todo What should we do with an "unshare"?
-                               // Removing the contact isn't correct since we still can read the public items
-                               Contact::remove($contact["id"]);
-                               return true;
+                       case "PollParticipation":
+                       case "Photo":
+                               // Currently unsupported
+                               break;
 
                        default:
                                logger("Unknown target type ".$target_type);
@@ -3569,8 +3569,12 @@ class Diaspora
                                $ret["root_guid"] = $guid;
                                return $ret;
                        }
+               } elseif (($guid == "") && $complete) {
+                       return false;
                }
 
+               $ret["root_guid"] = $guid;
+
                $profile = "";
                preg_match("/profile='(.*?)'/ism", $attributes, $matches);
                if ($matches[1] != "") {
@@ -3591,10 +3595,6 @@ class Diaspora
                        }
                }
 
-               if (!empty($guid)) {
-                       $ret["root_guid"] = $guid;
-               }
-
                if (empty($ret) && !$complete) {
                        return true;
                }