/**
* @brief Return a list of relay servers
*
- * This is an experimental Diaspora feature.
+ * The list contains not only the official relays but also servers that we serve directly
+ *
+ * @param integer $item_id The id of the item that is sent
+ * @param array $contacts The previously fetched contacts
*
* @return array of relay servers
*/
- public static function relayList()
+ public static function relayList($item_id, $contacts = [])
{
+ $serverlist = [];
+
+ // Fetching relay servers
$serverdata = Config::get("system", "relay_server");
- if ($serverdata == "") {
- return [];
+ if ($serverdata != "") {
+ $servers = explode(",", $serverdata);
+ foreach ($servers as $server) {
+ $serverlist[$server] = trim($server);
+ }
}
- $relay = [];
+ 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 = explode(",", $serverdata);
+ // Servers that want to get all content
+ $servers = dba::select('gserver', ['url'], ['relay-subscribe' => true, 'relay-scope' => 'all']);
+ while ($server = dba::fetch($servers)) {
+ $serverlist[$server['url']] = $server['url'];
+ }
- foreach ($servers as $server) {
- $server = trim($server);
- $addr = "relay@".str_replace("http://", "", normalise_link($server));
- $batch = $server."/receive/public";
+ // All tags of the current post
+ $condition = ['otype' => TERM_OBJ_POST, 'type' => TERM_HASHTAG, 'oid' => $parent['parent']];
+ $tags = dba::select('term', ['term'], $condition);
+ $taglist = [];
+ while ($tag = dba::fetch($tags)) {
+ $taglist[] = $tag['term'];
+ }
- $relais = q(
- "SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' AND `addr` = '%s' AND `nurl` = '%s' LIMIT 1",
- dbesc($batch),
- dbesc($addr),
- dbesc(normalise_link($server))
- );
+ // All servers who wants content with this tag
+ $tagserverlist = [];
+ if (!empty($taglist)) {
+ $tagserver = dba::select('gserver-tag', ['gserver-id'], ['tag' => $taglist]);
+ while ($server = dba::fetch($tagserver)) {
+ $tagserverlist[] = $server['gserver-id'];
+ }
+ }
- if (!$relais) {
- $r = q(
- "INSERT INTO `contact` (`uid`, `created`, `name`, `nick`, `addr`, `url`, `nurl`, `batch`, `network`, `rel`, `blocked`, `pending`, `writable`, `name-date`, `uri-date`, `avatar-date`)
- VALUES (0, '%s', '%s', 'relay', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, '%s', '%s', '%s')",
- DateTimeFormat::utcNow(),
- dbesc($addr),
- dbesc($addr),
- dbesc($server),
- dbesc(normalise_link($server)),
- dbesc($batch),
- dbesc(NETWORK_DIASPORA),
- intval(CONTACT_IS_FOLLOWER),
- dbesc(DateTimeFormat::utcNow()),
- dbesc(DateTimeFormat::utcNow()),
- dbesc(DateTimeFormat::utcNow())
- );
+ // All adresses with the given id
+ if (!empty($tagserverlist)) {
+ $servers = dba::select('gserver', ['url'], ['relay-subscribe' => true, 'relay-scope' => 'tags', 'id' => $tagserverlist]);
+ while ($server = dba::fetch($servers)) {
+ $serverlist[$server['url']] = $server['url'];
+ }
+ }
+ }
+
+ // Now we are collecting all relay contacts
+ foreach ($serverlist as $server_url) {
+ // We don't send messages to ourselves
+ if (link_compare($server_url, System::baseUrl())) {
+ continue;
+ }
+ $contact = self::getRelayContact($server_url);
+ if (is_bool($contact)) {
+ continue;
+ }
- $relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch));
- if ($relais) {
- $relay[] = $relais[0];
+ $exists = false;
+ foreach ($contacts as $entry) {
+ if ($entry['batch'] == $contact['batch']) {
+ $exists = true;
}
- } else {
- $relay[] = $relais[0];
+ }
+
+ if (!$exists) {
+ $contacts[] = $contact;
+ }
+ }
+
+ return $contacts;
+ }
+
+ /**
+ * @brief Return a contact for a given server address or creates a dummy entry
+ *
+ * @param string $server_url The url of the server
+ * @return array with the contact
+ */
+ private static function getRelayContact($server_url)
+ {
+ $fields = ['batch', 'id', 'name', 'network', 'archive', 'blocked'];
+
+ // Fetch the relay contact
+ $condition = ['uid' => 0, 'nurl' => normalise_link($server_url),
+ 'contact-type' => ACCOUNT_TYPE_RELAY];
+ $contact = dba::selectFirst('contact', $fields, $condition);
+
+ if (DBM::is_result($contact)) {
+ if ($contact['archive'] || $contact['blocked']) {
+ return false;
+ }
+ return $contact;
+ } else {
+ self::setRelayContact($server_url);
+
+ $contact = dba::selectFirst('contact', $fields, $condition);
+ if (DBM::is_result($contact)) {
+ return $contact;
}
}
- return $relay;
+ // 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);
}
/**
return false;
}
- if (!($postdata = self::validPosting($msg))) {
+ if (!($fields = self::validPosting($msg))) {
logger("Invalid posting");
return false;
}
- $fields = $postdata['fields'];
+ $importer = ["uid" => 0, "page-flags" => PAGE_FREELOVE];
+ $success = self::dispatch($importer, $msg, $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;
- }
- }
-
- // 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;
}
/**
// 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();
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
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":
// 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)) {
}
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;
}
}
//}
// 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?
// Yes, then it is fine.
return true;
// Is it a post to a community?
- } elseif (($contact["rel"] == CONTACT_IS_FOLLOWER) && ($importer["page-flags"] == PAGE_COMMUNITY)) {
+ } elseif (($contact["rel"] == CONTACT_IS_FOLLOWER) && in_array($importer["page-flags"], [PAGE_COMMUNITY, PAGE_PRVGROUP])) {
// That's good
return true;
// Is the message a global user or a comment?
*/
private static function plink($addr, $guid, $parent_guid = '')
{
- $r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr));
+ $contact = Contact::getDetailsByAddr($addr);
// Fallback
- if (!DBM::is_result($r)) {
+ if (!$contact) {
if ($parent_guid != '') {
- return "https://".substr($addr, strpos($addr, "@") + 1) . "/posts/" . $parent_guid . "#" . $guid;
+ return "https://" . substr($addr, strpos($addr, "@") + 1) . "/posts/" . $parent_guid . "#" . $guid;
} else {
- return "https://".substr($addr, strpos($addr, "@") + 1) . "/posts/" . $guid;
+ return "https://" . substr($addr, strpos($addr, "@") + 1) . "/posts/" . $guid;
}
}
- // Friendica contacts are often detected as Diaspora contacts in the "fcontact" table
- // So we try another way as well.
- $s = q("SELECT `network` FROM `gcontact` WHERE `nurl`='%s' LIMIT 1", dbesc(normalise_link($r[0]["url"])));
- if (DBM::is_result($s)) {
- $r[0]["network"] = $s[0]["network"];
- }
-
- if ($r[0]["network"] == NETWORK_DFRN) {
- return str_replace("/profile/".$r[0]["nick"]."/", "/display/".$guid, $r[0]["url"]."/");
+ if ($contact["network"] == NETWORK_DFRN) {
+ return str_replace("/profile/" . $contact["nick"] . "/", "/display/" . $guid, $contact["url"] . "/");
}
- if (self::isRedmatrix($r[0]["url"])) {
- return $r[0]["url"]."/?f=&mid=".$guid;
+ if (self::isRedmatrix($contact["url"])) {
+ return $contact["url"] . "/?f=&mid=" . $guid;
}
if ($parent_guid != '') {
- return "https://".substr($addr, strpos($addr, "@") + 1) . "/posts/" . $parent_guid . "#" . $guid;
+ return "https://" . substr($addr, strpos($addr, "@") + 1) . "/posts/" . $parent_guid . "#" . $guid;
} else {
- return "https://".substr($addr, strpos($addr, "@") + 1) . "/posts/" . $guid;
+ return "https://" . substr($addr, strpos($addr, "@") + 1) . "/posts/" . $guid;
}
}
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.');
/**
* @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;
}
if ($message_id) {
logger("Stored comment ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
+ if ($datarray['uid'] == 0) {
+ Item::distribute($message_id);
+ }
}
// If we are the origin of the parent we store the original data and notify our followers
if ($message_id) {
logger("Stored like ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
+ if ($datarray['uid'] == 0) {
+ Item::distribute($message_id);
+ }
}
// like on comments have the comment as parent. So we need to fetch the toplevel parent
Contact::updateAvatar($ret["photo"], $importer['uid'], $contact_record["id"], true);
- if ($importer["page-flags"] == PAGE_NORMAL) {
+ if (in_array($importer["page-flags"], [PAGE_NORMAL, PAGE_PRVGROUP])) {
logger("Sending intra message for author ".$author.".", LOGGER_DEBUG);
$hash = random_string().(string)time(); // Generate a confirm_key
*
* @return array The fetched item
*/
- private static function originalItem($guid, $orig_author, $author)
+ public static function originalItem($guid, $orig_author)
{
+ if (empty($guid)) {
+ logger('Empty guid. Quitting.');
+ return false;
+ }
+
// Do we already have this item?
- $r = q(
- "SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`,
- `author-name`, `author-link`, `author-avatar`
- FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
- dbesc($guid)
- );
+ $fields = ['body', 'tag', 'app', 'created', 'object-type', 'uri', 'guid',
+ 'author-name', 'author-link', 'author-avatar'];
+ $condition = ['guid' => $guid, 'visible' => true, 'deleted' => false, 'private' => false];
+ $item = dba::selectfirst('item', $fields, $condition);
- if (DBM::is_result($r)) {
+ if (DBM::is_result($item)) {
logger("reshared message ".$guid." already exists on system.");
// Maybe it is already a reshared item?
// 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($r[0]["body"], true)) {
- $r = [];
- } elseif (self::isReshare($r[0]["body"], false) || strstr($r[0]["body"], "[share")) {
- $r[0]["body"] = Markdown::toBBCode(BBCode::toMarkdown($r[0]["body"]));
+ if (self::isReshare($item["body"], true)) {
+ $item = [];
+ } elseif (self::isReshare($item["body"], false) || strstr($item["body"], "[share")) {
+ $item["body"] = Markdown::toBBCode(BBCode::toMarkdown($item["body"]));
- $r[0]["body"] = self::replacePeopleGuid($r[0]["body"], $r[0]["author-link"]);
+ $item["body"] = self::replacePeopleGuid($item["body"], $item["author-link"]);
// Add OEmbed and other information to the body
- $r[0]["body"] = add_page_info_to_body($r[0]["body"], false, true);
+ $item["body"] = add_page_info_to_body($item["body"], false, true);
- return $r[0];
+ return $item;
} else {
- return $r[0];
+ return $item;
}
}
- 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) {
- $r = q(
- "SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`,
- `author-name`, `author-link`, `author-avatar`
- FROM `item` WHERE `id` = %d AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
- intval($item_id)
- );
+ if ($stored) {
+ $fields = ['body', 'tag', 'app', 'created', 'object-type', 'uri', 'guid',
+ 'author-name', 'author-link', 'author-avatar'];
+ $condition = ['guid' => $guid, 'visible' => true, 'deleted' => false, 'private' => false];
+ $item = dba::selectfirst('item', $fields, $condition);
- if (DBM::is_result($r)) {
+ if (DBM::is_result($item)) {
// If it is a reshared post from another network then reformat to avoid display problems with two share elements
- if (self::isReshare($r[0]["body"], false)) {
- $r[0]["body"] = Markdown::toBBCode(BBCode::toMarkdown($r[0]["body"]));
- $r[0]["body"] = self::replacePeopleGuid($r[0]["body"], $r[0]["author-link"]);
+ if (self::isReshare($item["body"], false)) {
+ $item["body"] = Markdown::toBBCode(BBCode::toMarkdown($item["body"]));
+ $item["body"] = self::replacePeopleGuid($item["body"], $item["author-link"]);
}
- return $r[0];
+ return $item;
}
}
}
return true;
}
- $original_item = self::originalItem($root_guid, $root_author, $author);
+ $original_item = self::originalItem($root_guid, $root_author);
if (!$original_item) {
return false;
}
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;
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);
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;
*
* @return string The message that will be transmitted to other servers
*/
- private static function buildMessage($msg, $user, $contact, $prvkey, $pubkey, $public = false)
+ public static function buildMessage($msg, $user, $contact, $prvkey, $pubkey, $public = false)
{
// The message is put into an envelope with the sender's signature
$envelope = self::buildMagicEnvelope($msg, $user);
$logid = random_string(4);
+ $dest_url = ($public_batch ? $contact["batch"] : $contact["notify"]);
+
// We always try to use the data from the fcontact table.
// This is important for transmitting data to Friendica servers.
- if (!empty($contact['addr']) && ($contact['network'] != NETWORK_DIASPORA)) {
+ if (!empty($contact['addr'])) {
$fcontact = self::personByHandle($contact['addr']);
- $dest_url = ($public_batch ? $fcontact["batch"] : $fcontact["notify"]);
- } else {
- $dest_url = ($public_batch ? $contact["batch"] : $contact["notify"]);
+ if (!empty($fcontact)) {
+ $dest_url = ($public_batch ? $fcontact["batch"] : $fcontact["notify"]);
+ }
}
if (!$dest_url) {
}
}
- logger("transmit: ".$logid."-".$guid." returns: ".$return_code);
+ logger("transmit: ".$logid."-".$guid." to ".$dest_url." returns: ".$return_code);
if (!$return_code || (($return_code == 503) && (stristr($a->get_curl_headers(), "retry-after")))) {
- if (!$no_queue) {
+ if (!$no_queue && ($contact['contact-type'] != ACCOUNT_TYPE_RELAY)) {
logger("queue message");
// queue message for redelivery
Queue::add($contact["id"], NETWORK_DIASPORA, $envelope, $public_batch, $guid);
// Skip if it isn't a pure repeated messages
// Does it start with a share?
if ((strpos($body, "[share") > 0) && $complete) {
- return(false);
+ return false;
}
// Does it end with a share?
if (strlen($body) > (strrpos($body, "[/share]") + 8)) {
- return(false);
+ return false;
}
$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", "$1", $body);
// Skip if there is no shared message in there
if ($body == $attributes) {
- return(false);
+ return false;
}
// If we don't do the complete check we quit here
- if (!$complete) {
- return true;
- }
$guid = "";
preg_match("/guid='(.*?)'/ism", $attributes, $matches);
$guid = $matches[1];
}
- if ($guid != "") {
- $r = q(
- "SELECT `contact-id` FROM `item` WHERE `guid` = '%s' AND `network` IN ('%s', '%s') LIMIT 1",
- dbesc($guid),
- NETWORK_DFRN,
- NETWORK_DIASPORA
- );
- if ($r) {
+ if (($guid != "") && $complete) {
+ $condition = ['guid' => $guid, 'network' => [NETWORK_DFRN, NETWORK_DIASPORA]];
+ $item = dba::selectFirst('item', ['contact-id'], $condition);
+ if (DBM::is_result($item)) {
$ret= [];
- $ret["root_handle"] = self::handleFromContact($r[0]["contact-id"]);
+ $ret["root_handle"] = self::handleFromContact($item["contact-id"]);
$ret["root_guid"] = $guid;
- return($ret);
+ return $ret;
}
+ } elseif (($guid == "") && $complete) {
+ return false;
}
+ $ret["root_guid"] = $guid;
+
$profile = "";
preg_match("/profile='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "") {
$ret= [];
- $ret["root_handle"] = preg_replace("=https?://(.*)/u/(.*)=ism", "$2@$1", $profile);
- if (($ret["root_handle"] == $profile) || ($ret["root_handle"] == "")) {
- return(false);
- }
-
- $link = "";
- preg_match("/link='(.*?)'/ism", $attributes, $matches);
- if ($matches[1] != "") {
- $link = $matches[1];
- }
-
- preg_match('/link="(.*?)"/ism', $attributes, $matches);
- if ($matches[1] != "") {
- $link = $matches[1];
+ if ($profile != "") {
+ if (Contact::getIdForURL($profile)) {
+ $author = Contact::getDetailsByURL($profile);
+ $ret["root_handle"] = $author['addr'];
+ }
}
- $ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link);
- if (($ret["root_guid"] == $link) || (trim($ret["root_guid"]) == "")) {
- return(false);
+ if (empty($ret) && !$complete) {
+ return true;
}
- return($ret);
+ return $ret;
}
/**
$title = $item["title"];
$body = $item["body"];
+ if ($item['author-link'] != $item['owner-link']) {
+ require_once 'mod/share.php';
+ $body = share_header($item['author-name'], $item['author-link'], $item['author-avatar'],
+ "", $item['created'], $item['plink']) . $body . '[/share]';
+ }
+
// convert to markdown
$body = html_entity_decode(BBCode::toMarkdown($body));