X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FProtocol%2FDiaspora.php;h=20d1d74fea12ad99133019a3b72f537815e24181;hb=e3ee9ee501f6a02ba64b95cd593f7f2cbffa1631;hp=e81c53499fa92337b41858148be96022b049eaca;hpb=37e5272f921bfe4cac111dc69867bce90def32cf;p=friendica.git diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index e81c53499f..20d1d74fea 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -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 * @@ -590,59 +599,15 @@ class Diaspora return false; } - if (!($postdata = self::validPosting($msg))) { + if (!($fields = self::validPosting($msg))) { logger("Invalid posting"); return false; } - $fields = $postdata['fields']; - - // Is it a an action (comment, like, ...) for our own post? - if (isset($fields->parent_guid) && !$postdata["relayed"]) { - $guid = notags(unxmlify($fields->parent_guid)); - $importer = self::importerForGuid($guid); - if (is_array($importer)) { - logger("delivering to origin: ".$importer["name"]); - $message_id = self::dispatch($importer, $msg, $fields); - return $message_id; - } - } + $importer = ["uid" => 0, "page-flags" => PAGE_FREELOVE]; + $success = self::dispatch($importer, $msg, $fields); - // Process item retractions. This has to be done separated from the other stuff, - // since retractions for comments could come even from non followers. - if (!empty($fields) && in_array($fields->getName(), ['retraction'])) { - $target = notags(unxmlify($fields->target_type)); - if (in_array($target, ["Comment", "Like", "Post", "Reshare", "StatusMessage"])) { - logger('processing retraction for '.$target, LOGGER_DEBUG); - $importer = ["uid" => 0, "page-flags" => PAGE_FREELOVE]; - $message_id = self::dispatch($importer, $msg, $fields); - return $message_id; - } - } - - // Now distribute it to the followers - $r = q( - "SELECT `user`.* FROM `user` WHERE `user`.`uid` IN - (SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s') - AND NOT `account_expired` AND NOT `account_removed`", - dbesc(NETWORK_DIASPORA), - dbesc($msg["author"]) - ); - - if (DBM::is_result($r)) { - foreach ($r as $rr) { - logger("delivering to: ".$rr["username"]); - self::dispatch($rr, $msg, $fields); - } - } elseif (!Config::get('system', 'relay_subscribe', false)) { - logger("Unwanted message from ".$msg["author"]." send by ".$_SERVER["REMOTE_ADDR"]." with ".$_SERVER["HTTP_USER_AGENT"].": ".print_r($msg, true), LOGGER_DEBUG); - } else { - // Use a dummy importer to import the data for the public copy - $importer = ["uid" => 0, "page-flags" => PAGE_FREELOVE]; - $message_id = self::dispatch($importer, $msg, $fields); - } - - return $message_id; + return $success; } /** @@ -662,11 +627,13 @@ class Diaspora // This is only needed for private postings since this is already done for public ones before if (is_null($fields)) { - if (!($postdata = self::validPosting($msg))) { + $private = true; + if (!($fields = self::validPosting($msg))) { logger("Invalid posting"); return false; } - $fields = $postdata['fields']; + } else { + $private = false; } $type = $fields->getName(); @@ -675,27 +642,47 @@ class Diaspora switch ($type) { case "account_migration": + if (!$private) { + logger('Message with type ' . $type . ' is not private, quitting.'); + return false; + } return self::receiveAccountMigration($importer, $fields); case "account_deletion": - return self::receiveAccountDeletion($importer, $fields); + return self::receiveAccountDeletion($fields); case "comment": return self::receiveComment($importer, $sender, $fields, $msg["message"]); case "contact": + if (!$private) { + logger('Message with type ' . $type . ' is not private, quitting.'); + return false; + } return self::receiveContactRequest($importer, $fields); case "conversation": + if (!$private) { + logger('Message with type ' . $type . ' is not private, quitting.'); + return false; + } return self::receiveConversation($importer, $msg, $fields); case "like": return self::receiveLike($importer, $sender, $fields); case "message": + if (!$private) { + logger('Message with type ' . $type . ' is not private, quitting.'); + return false; + } return self::receiveMessage($importer, $fields); case "participation": + if (!$private) { + logger('Message with type ' . $type . ' is not private, quitting.'); + return false; + } return self::receiveParticipation($importer, $fields); case "photo": // Not implemented @@ -705,6 +692,10 @@ class Diaspora return self::receivePollParticipation($importer, $fields); case "profile": + if (!$private) { + logger('Message with type ' . $type . ' is not private, quitting.'); + return false; + } return self::receiveProfile($importer, $fields); case "reshare": @@ -840,7 +831,7 @@ class Diaspora // Only some message types have signatures. So we quit here for the other types. if (!in_array($type, ["comment", "like"])) { - return ["fields" => $fields, "relayed" => false]; + return $fields; } // No author_signature? This is a must, so we quit. if (!isset($author_signature)) { @@ -849,25 +840,29 @@ class Diaspora } if (isset($parent_author_signature)) { - $relayed = true; - $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); return false; } - } else { - $relayed = false; } $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); return false; } else { - return ["fields" => $fields, "relayed" => $relayed]; + return $fields; } } @@ -925,7 +920,7 @@ class Diaspora // Note that Friendica contacts will return a "Diaspora person" // if Diaspora connectivity is enabled on their server if ($r && ($r["network"] === NETWORK_DIASPORA)) { - self::addFContact($r, $update); + self::updateFContact($r); // Fetch the updated or added contact $person = dba::selectFirst('fcontact', [], ['network' => NETWORK_DIASPORA, 'addr' => $handle]); @@ -941,70 +936,21 @@ class Diaspora /** * @brief Updates the fcontact table * - * @param array $arr The fcontact data - * @param bool $update Update or insert? - * - * @return string The id of the fcontact entry + * @param array $arr The fcontact data */ - private static function addFContact($arr, $update = false) + private static function updateFContact($arr) { - if ($update) { - $r = q( - "UPDATE `fcontact` SET - `name` = '%s', - `photo` = '%s', - `request` = '%s', - `nick` = '%s', - `addr` = '%s', - `guid` = '%s', - `batch` = '%s', - `notify` = '%s', - `poll` = '%s', - `confirm` = '%s', - `alias` = '%s', - `pubkey` = '%s', - `updated` = '%s' - WHERE `url` = '%s' AND `network` = '%s'", - dbesc($arr["name"]), - dbesc($arr["photo"]), - dbesc($arr["request"]), - dbesc($arr["nick"]), - dbesc(strtolower($arr["addr"])), - dbesc($arr["guid"]), - dbesc($arr["batch"]), - dbesc($arr["notify"]), - dbesc($arr["poll"]), - dbesc($arr["confirm"]), - dbesc($arr["alias"]), - dbesc($arr["pubkey"]), - dbesc(DateTimeFormat::utcNow()), - dbesc($arr["url"]), - dbesc($arr["network"]) - ); - } else { - $r = q( - "INSERT INTO `fcontact` (`url`,`name`,`photo`,`request`,`nick`,`addr`, `guid`, - `batch`, `notify`,`poll`,`confirm`,`network`,`alias`,`pubkey`,`updated`) - VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')", - dbesc($arr["url"]), - dbesc($arr["name"]), - dbesc($arr["photo"]), - dbesc($arr["request"]), - dbesc($arr["nick"]), - dbesc($arr["addr"]), - dbesc($arr["guid"]), - dbesc($arr["batch"]), - dbesc($arr["notify"]), - dbesc($arr["poll"]), - dbesc($arr["confirm"]), - dbesc($arr["network"]), - dbesc($arr["alias"]), - dbesc($arr["pubkey"]), - dbesc(DateTimeFormat::utcNow()) - ); - } + $fields = ['name' => $arr["name"], 'photo' => $arr["photo"], + 'request' => $arr["request"], 'nick' => $arr["nick"], + 'addr' => strtolower($arr["addr"]), 'guid' => $arr["guid"], + 'batch' => $arr["batch"], 'notify' => $arr["notify"], + 'poll' => $arr["poll"], 'confirm' => $arr["confirm"], + 'alias' => $arr["alias"], 'pubkey' => $arr["pubkey"], + 'updated' => DateTimeFormat::utcNow()]; - return $r; + $condition = ['url' => $arr["url"], 'network' => $arr["network"]]; + + dba::update('fcontact', $fields, $condition, true); } /** @@ -1165,7 +1111,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? @@ -1613,34 +1559,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.'); @@ -1650,25 +1571,23 @@ class Diaspora /** * @brief Processes an account deletion * - * @param array $importer Array of the importer user * @param object $data The message object * * @return bool Success */ - private static function receiveAccountDeletion($importer, $data) + private static function receiveAccountDeletion($data) { - /// @todo Account deletion should remove the contact from the global contacts as well - $author = notags(unxmlify($data->author)); - $contact = self::contactByHandle($importer["uid"], $author); - if (!$contact) { - logger("cannot find contact for author: ".$author); - return false; + $contacts = dba::select('contact', ['id'], ['addr' => $author]); + while ($contact = dba::fetch($contacts)) { + Contact::remove($contact["id"]); } - // We now remove the contact - Contact::remove($contact["id"]); + dba::delete('gcontact', ['addr' => $author]); + + logger('Removed contacts for ' . $author); + return true; } @@ -1683,11 +1602,21 @@ class Diaspora */ private static function getUriFromGuid($author, $guid, $onlyfound = false) { - $r = q("SELECT `uri` FROM `item` WHERE `guid` = '%s' LIMIT 1", dbesc($guid)); - if (DBM::is_result($r)) { - return $r[0]["uri"]; + $item = dba::selectFirst('item', ['uri'], ['guid' => $guid]); + if (DBM::is_result($item)) { + return $item["uri"]; } elseif (!$onlyfound) { - return $author.":".$guid; + $contact = Contact::getDetailsByAddr($author, 0); + if (!empty($contact['network'])) { + $prefix = 'urn:X-' . $contact['network'] . ':'; + } else { + // This fallback should happen most unlikely + $prefix = 'urn:X-dspr:'; + } + + $author_parts = explode('@', $author); + + return $prefix . $author_parts[1] . ':' . $author_parts[0] . ':'. $guid; } return ""; @@ -1828,6 +1757,12 @@ class Diaspora self::fetchGuid($datarray); + // If we are the origin of the parent we store the original data. + // We notify our followers during the item storage. + if ($parent_item["origin"]) { + $datarray['diaspora_signed_text'] = json_encode($data); + } + $message_id = Item::insert($datarray); if ($message_id <= 0) { @@ -1836,16 +1771,9 @@ class Diaspora if ($message_id) { logger("Stored comment ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG); - } - - // If we are the origin of the parent we store the original data and notify our followers - if ($message_id && $parent_item["origin"]) { - // Formerly we stored the signed text, the signature and the author in different fields. - // We now store the raw data so that we are more flexible. - dba::insert('sign', ['iid' => $message_id, 'signed_text' => json_encode($data)]); - - // notify others - Worker::add(PRIORITY_HIGH, "Notifier", "comment-import", $message_id); + if ($datarray['uid'] == 0) { + Item::distribute($message_id, json_encode($data)); + } } return true; @@ -2149,16 +2077,6 @@ class Diaspora $datarray["body"] = self::constructLikeBody($contact, $parent_item, $guid); - $message_id = Item::insert($datarray); - - if ($message_id <= 0) { - return false; - } - - if ($message_id) { - logger("Stored like ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG); - } - // like on comments have the comment as parent. So we need to fetch the toplevel parent if ($parent_item["id"] != $parent_item["parent"]) { $toplevel = dba::selectFirst('item', ['origin'], ['id' => $parent_item["parent"]]); @@ -2167,14 +2085,23 @@ class Diaspora $origin = $parent_item["origin"]; } - // If we are the origin of the parent we store the original data and notify our followers - if ($message_id && $origin) { - // Formerly we stored the signed text, the signature and the author in different fields. - // We now store the raw data so that we are more flexible. - dba::insert('sign', ['iid' => $message_id, 'signed_text' => json_encode($data)]); + // If we are the origin of the parent we store the original data. + // We notify our followers during the item storage. + if ($origin) { + $datarray['diaspora_signed_text'] = json_encode($data); + } + + $message_id = Item::insert($datarray); + + if ($message_id <= 0) { + return false; + } - // notify others - Worker::add(PRIORITY_HIGH, "Notifier", "comment-import", $message_id); + if ($message_id) { + logger("Stored like ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG); + if ($datarray['uid'] == 0) { + Item::distribute($message_id, json_encode($data)); + } } return true; @@ -2424,21 +2351,17 @@ class Diaspora $birthday = $contact["bd"]; } - $r = q( - "UPDATE `contact` SET `name` = '%s', `nick` = '%s', `addr` = '%s', `name-date` = '%s', `bd` = '%s', - `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `id` = %d AND `uid` = %d", - dbesc($name), - dbesc($nick), - dbesc($author), - dbesc(DateTimeFormat::utcNow()), - dbesc($birthday), - dbesc($location), - dbesc($about), - dbesc($keywords), - dbesc($gender), - intval($contact["id"]), - intval($importer["uid"]) - ); + $fields = ['name' => $name, 'location' => $location, + 'name-date' => DateTimeFormat::utcNow(), + 'about' => $about, 'gender' => $gender, + 'addr' => $author, 'nick' => $nick, + 'keywords' => $keywords]; + + if (!empty($birthday)) { + $fields['bd'] = $birthday; + } + + dba::update('contact', $fields, ['id' => $contact['id']]); $gcontact = ["url" => $contact["url"], "network" => NETWORK_DIASPORA, "generation" => 2, "photo" => $image_url, "name" => $name, "location" => $location, @@ -2473,78 +2396,6 @@ class Diaspora ['id' => $contact["id"], 'uid' => $importer["uid"]] ); } - // send notification - - $r = q( - "SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1", - intval($importer["uid"]) - ); - - if ($r && !$r[0]["hide-friends"] && !$contact["hidden"] && intval(PConfig::get($importer["uid"], "system", "post_newfriend"))) { - $self = q( - "SELECT * FROM `contact` WHERE `self` AND `uid` = %d LIMIT 1", - intval($importer["uid"]) - ); - - // they are not CONTACT_IS_FOLLOWER anymore but that's what we have in the array - - if ($self && $contact["rel"] == CONTACT_IS_FOLLOWER) { - $arr = []; - $arr["protocol"] = PROTOCOL_DIASPORA; - $arr["uri"] = $arr["parent-uri"] = item_new_uri($a->get_hostname(), $importer["uid"]); - $arr["uid"] = $importer["uid"]; - $arr["contact-id"] = $self[0]["id"]; - $arr["wall"] = 1; - $arr["type"] = 'wall'; - $arr["gravity"] = 0; - $arr["origin"] = 1; - $arr["author-name"] = $arr["owner-name"] = $self[0]["name"]; - $arr["author-link"] = $arr["owner-link"] = $self[0]["url"]; - $arr["author-avatar"] = $arr["owner-avatar"] = $self[0]["thumb"]; - $arr["verb"] = ACTIVITY_FRIEND; - $arr["object-type"] = ACTIVITY_OBJ_PERSON; - - $A = "[url=".$self[0]["url"]."]".$self[0]["name"]."[/url]"; - $B = "[url=".$contact["url"]."]".$contact["name"]."[/url]"; - $BPhoto = "[url=".$contact["url"]."][img]".$contact["thumb"]."[/img][/url]"; - $arr["body"] = L10n::t('%1$s is now friends with %2$s', $A, $B)."\n\n\n".$BPhoto; - - $arr["object"] = self::constructNewFriendObject($contact); - - $user = dba::selectFirst('user', ['allow_cid', 'allow_gid', 'deny_cid', 'deny_gid'], ['uid' => $importer["uid"]]); - - $arr["allow_cid"] = $user["allow_cid"]; - $arr["allow_gid"] = $user["allow_gid"]; - $arr["deny_cid"] = $user["deny_cid"]; - $arr["deny_gid"] = $user["deny_gid"]; - - $i = Item::insert($arr); - if ($i) { - Worker::add(PRIORITY_HIGH, "Notifier", "activity", $i); - } - } - } - } - - /** - * @brief Creates a XML object for a "new friend" message - * - * @param array $contact Array of the contact - * - * @return string The XML - */ - private static function constructNewFriendObject($contact) - { - $objtype = ACTIVITY_OBJ_PERSON; - $link = ''."\n". - ''."\n"; - - $xmldata = ["object" => ["type" => $objtype, - "title" => $contact["name"], - "id" => $contact["url"]."/".$contact["name"], - "link" => $link]]; - - return XML::fromArray($xmldata, $xml, true); } /** @@ -2739,10 +2590,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)) { @@ -2752,7 +2608,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"])); @@ -2767,21 +2623,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)) { @@ -2883,6 +2744,9 @@ class Diaspora if ($message_id) { logger("Stored reshare ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG); + if ($datarray['uid'] == 0) { + Item::distribute($message_id); + } return true; } else { return false; @@ -2931,7 +2795,7 @@ class Diaspora while ($item = dba::fetch($r)) { // Fetch the parent item - $parent = dba::selectFirst('item', ['author-link', 'origin'], ['id' => $item["parent"]]); + $parent = dba::selectFirst('item', ['author-link'], ['id' => $item["parent"]]); // Only delete it if the parent author really fits if (!link_compare($parent["author-link"], $contact["url"]) && !link_compare($item["author-link"], $contact["url"])) { @@ -2939,15 +2803,9 @@ class Diaspora continue; } - Item::deleteById($item["id"]); + Item::delete(['id' => $item['id']]); logger("Deleted target ".$target_guid." (".$item["id"].") from user ".$item["uid"]." parent: ".$item["parent"], LOGGER_DEBUG); - - // Now check if the retraction needs to be relayed by us - if ($parent["origin"]) { - // notify others - Worker::add(PRIORITY_HIGH, "Notifier", "drop", $item["id"]); - } } return true; @@ -2982,12 +2840,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); @@ -3107,6 +2963,9 @@ class Diaspora if ($message_id) { logger("Stored item ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG); + if ($datarray['uid'] == 0) { + Item::distribute($message_id); + } return true; } else { return false; @@ -3580,9 +3439,17 @@ class Diaspora $ret["root_handle"] = self::handleFromContact($item["contact-id"]); $ret["root_guid"] = $guid; return $ret; + } elseif ($complete) { + // We are resharing something that isn't a DFRN or Diaspora post. + // So we have to return "false" on "$complete" to not trigger a reshare. + return false; } + } elseif (($guid == "") && $complete) { + return false; } + $ret["root_guid"] = $guid; + $profile = ""; preg_match("/profile='(.*?)'/ism", $attributes, $matches); if ($matches[1] != "") { @@ -3603,10 +3470,6 @@ class Diaspora } } - if (!empty($guid)) { - $ret["root_guid"] = $guid; - } - if (empty($ret) && !$complete) { return true; }