From 8974c147e03df876a7225af4412f4f79e4582b9c Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sun, 9 Aug 2015 08:31:42 +0200 Subject: [PATCH 1/3] First steps for a public relay for posts. --- mod/_well_known.php | 50 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/mod/_well_known.php b/mod/_well_known.php index 6792d36fe0..5c8a3380fd 100644 --- a/mod/_well_known.php +++ b/mod/_well_known.php @@ -2,13 +2,45 @@ require_once("mod/hostxrd.php"); function _well_known_init(&$a){ - if ($a->argc > 1) { - switch($a->argv[1]) { - case "host-meta": - hostxrd_init($a); - break; - } - } - http_status_exit(404); - killme(); + if ($a->argc > 1) { + switch($a->argv[1]) { + case "host-meta": + hostxrd_init($a); + break; + case "x-social-relay": + wk_social_relay($a); + break; + } + } + http_status_exit(404); + killme(); +} + +function wk_social_relay(&$a) { + + define('SR_SCOPE_ALL', 'all'); + define('SR_SCOPE_TAGS', 'tags'); + + $subscribe = (bool)true; + $scope = SR_SCOPE_ALL; + //$scope = SR_SCOPE_TAGS; + + $tags = array(); + + if ($scope == SR_SCOPE_TAGS) { + $terms = q("SELECT DISTINCT(`term`) FROM `search`"); + + foreach($terms AS $term) { + $tag = trim($term["term"], "#"); + $tags[] = $tag; + } + } + + $relay = array("subscribe" => $subscribe, + "scope" => $scope, + "tags" => array_unique($tags)); + + header('Content-type: application/json; charset=utf-8'); + echo json_encode($relay, true); + exit; } From 65921bf2e70c10641672464d151a24f1c015f8d9 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sun, 9 Aug 2015 14:28:59 +0200 Subject: [PATCH 2/3] Posts from Diaspora are always accepted for the global contact --- include/diaspora.php | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/include/diaspora.php b/include/diaspora.php index 534e2541cb..fd9dd8fb75 100755 --- a/include/diaspora.php +++ b/include/diaspora.php @@ -34,8 +34,13 @@ function diaspora_dispatch_public($msg) { diaspora_dispatch($rr,$msg); } } - else - logger('diaspora_public: no subscribers'); + else { + logger('diaspora_public: no subscribers '.print_r($msg, true)); + + // Use a dummy importer + $importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE); + diaspora_dispatch($importer,$msg); + } } @@ -782,6 +787,11 @@ function diaspora_post_allow($importer,$contact) { if($contact['rel'] == CONTACT_IS_FOLLOWER) if($importer['page-flags'] == PAGE_COMMUNITY) return true; + + // Messages for the global users are always accepted + if ($importer['uid'] == 0) + return true; + return false; } @@ -1605,7 +1615,7 @@ function diaspora_conversation($importer,$xml,$msg) { $created_at = datetime_convert('UTC','UTC',notags(unxmlify($xml->created_at))); $parent_uri = $diaspora_handle . ':' . $guid; - + $messages = $xml->message; if(! count($messages)) { @@ -1619,7 +1629,7 @@ function diaspora_conversation($importer,$xml,$msg) { return; } - if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) { + if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) { logger('diaspora_conversation: Ignoring this author.'); return 202; } @@ -1776,14 +1786,14 @@ function diaspora_message($importer,$xml,$msg) { $msg_conversation_guid = notags(unxmlify($xml->conversation_guid)); $parent_uri = $diaspora_handle . ':' . $msg_parent_guid; - + $contact = diaspora_get_contact_by_handle($importer['uid'],$msg_diaspora_handle); if(! $contact) { logger('diaspora_message: cannot find contact: ' . $msg_diaspora_handle); return; } - if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) { + if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) { logger('diaspora_message: Ignoring this author.'); return 202; } From b24453f8da5c587a13ff0bbe6c71ee1fef84bff5 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sun, 9 Aug 2015 20:39:11 +0200 Subject: [PATCH 3/3] Messages are now sent to the relay server - and the options are configurable --- include/diaspora.php | 172 ++++++++++++++++++++++++++++--------------- include/notifier.php | 10 ++- mod/_well_known.php | 32 ++++++-- 3 files changed, 142 insertions(+), 72 deletions(-) mode change 100755 => 100644 include/diaspora.php diff --git a/include/diaspora.php b/include/diaspora.php old mode 100755 new mode 100644 index fd9dd8fb75..3640c74959 --- a/include/diaspora.php +++ b/include/diaspora.php @@ -23,8 +23,8 @@ function diaspora_dispatch_public($msg) { } $r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN - ( SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s' ) - AND `account_expired` = 0 AND `account_removed` = 0 ", + ( SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s' ) + AND `account_expired` = 0 AND `account_removed` = 0 ", dbesc(NETWORK_DIASPORA), dbesc($msg['author']) ); @@ -35,11 +35,13 @@ function diaspora_dispatch_public($msg) { } } else { - logger('diaspora_public: no subscribers '.print_r($msg, true)); + logger('diaspora_public: no subscribers for '.$msg["author"].' '.print_r($msg, true)); // Use a dummy importer $importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE); - diaspora_dispatch($importer,$msg); + $result = diaspora_dispatch($importer,$msg); + + logger("Dispatcher reported ".$result, LOGGER_DEBUG); } } @@ -550,7 +552,7 @@ function diaspora_decode($importer,$xml) { // This will also convert diaspora public key from pkcs#1 to pkcs#8 logger('mod-diaspora: Fetching key for ' . $author_link ); - $key = get_diaspora_key($author_link); + $key = get_diaspora_key($author_link); if(! $key) { logger('mod-diaspora: Could not retrieve author key.'); @@ -645,7 +647,7 @@ function diaspora_request($importer,$xml) { $i = item_store($arr); if($i) - proc_run('php',"include/notifier.php","activity","$i"); + proc_run('php',"include/notifier.php","activity","$i"); } @@ -833,8 +835,10 @@ function diaspora_post($importer,$xml,$msg) { } $contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle); - if(! $contact) - return; + if(! $contact) { + logger('diaspora_post: A Contact for handle '.$diaspora_handle.' and user '.$importer['uid'].' was not found'); + return 203; + } if(! diaspora_post_allow($importer,$contact)) { logger('diaspora_post: Ignoring this author.'); @@ -849,7 +853,7 @@ function diaspora_post($importer,$xml,$msg) { ); if(count($r)) { logger('diaspora_post: message exists: ' . $guid); - return; + return 208; } $created = unxmlify($xml->created_at); @@ -904,7 +908,7 @@ function diaspora_post($importer,$xml,$msg) { $datarray['body'] = $body; $datarray['tag'] = $str_tags; if ($xml->provider_display_name) - $datarray["app"] = unxmlify($xml->provider_display_name); + $datarray["app"] = unxmlify($xml->provider_display_name); else $datarray['app'] = 'Diaspora'; @@ -915,7 +919,9 @@ function diaspora_post($importer,$xml,$msg) { DiasporaFetchGuid($datarray); $message_id = item_store($datarray); - return; + logger("Stored item with message id ".$message_id, LOGGER_DEBUG); + + return 201; } @@ -936,8 +942,8 @@ function DiasporaFetchGuidSub($match, $item) { function diaspora_store_by_guid($guid, $server, $uid = 0) { require_once("include/Contact.php"); - $serverparts = parse_url($server); - $server = $serverparts["scheme"]."://".$serverparts["host"]; + $serverparts = parse_url($server); + $server = $serverparts["scheme"]."://".$serverparts["host"]; logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG); @@ -969,7 +975,7 @@ function diaspora_store_by_guid($guid, $server, $uid = 0) { $person = find_diaspora_person_by_handle($author); - $datarray = array(); + $datarray = array(); $datarray['uid'] = $uid; $datarray['contact-id'] = get_contact($person['url'], $uid); $datarray['wall'] = 0; @@ -1654,11 +1660,11 @@ function diaspora_conversation($importer,$xml,$msg) { ); if($r) $c = q("select * from conv where uid = %d and guid = '%s' limit 1", - intval($importer['uid']), - dbesc($guid) - ); + intval($importer['uid']), + dbesc($guid) + ); if(count($c)) - $conversation = $c[0]; + $conversation = $c[0]; } if(! $conversation) { logger('diaspora_conversation: unable to create conversation.'); @@ -1944,7 +1950,7 @@ function diaspora_photo($importer,$xml,$msg,$attempt=1) { $link_text = '[img]' . $remote_photo_path . $remote_photo_name . '[/img]' . "\n"; $link_text = scale_external_images($link_text, true, - array($remote_photo_name, 'scaled_full_' . $remote_photo_name)); + array($remote_photo_name, 'scaled_full_' . $remote_photo_name)); if(strpos($parent_item['body'],$link_text) === false) { $r = q("UPDATE `item` SET `body` = '%s', `visible` = 1 WHERE `id` = %d AND `uid` = %d", @@ -2608,28 +2614,28 @@ function diaspora_send_status($item,$owner,$contact,$public_batch = false) { function diaspora_is_reshare($body) { $body = trim($body); - // Skip if it isn't a pure repeated messages - // Does it start with a share? - if (strpos($body, "[share") > 0) - return(false); + // Skip if it isn't a pure repeated messages + // Does it start with a share? + if (strpos($body, "[share") > 0) + return(false); - // Does it end with a share? - if (strlen($body) > (strrpos($body, "[/share]") + 8)) - return(false); + // Does it end with a share? + if (strlen($body) > (strrpos($body, "[/share]") + 8)) + 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); + $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); - $guid = ""; - preg_match("/guid='(.*?)'/ism", $attributes, $matches); - if ($matches[1] != "") - $guid = $matches[1]; + $guid = ""; + preg_match("/guid='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $guid = $matches[1]; - preg_match('/guid="(.*?)"/ism', $attributes, $matches); - if ($matches[1] != "") - $guid = $matches[1]; + preg_match('/guid="(.*?)"/ism', $attributes, $matches); + if ($matches[1] != "") + $guid = $matches[1]; if ($guid != "") { $r = q("SELECT `contact-id` FROM `item` WHERE `guid` = '%s' AND `network` IN ('%s', '%s') LIMIT 1", @@ -2642,35 +2648,35 @@ function diaspora_is_reshare($body) { } } - $profile = ""; - preg_match("/profile='(.*?)'/ism", $attributes, $matches); - if ($matches[1] != "") - $profile = $matches[1]; + $profile = ""; + preg_match("/profile='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $profile = $matches[1]; - preg_match('/profile="(.*?)"/ism', $attributes, $matches); - if ($matches[1] != "") - $profile = $matches[1]; + preg_match('/profile="(.*?)"/ism', $attributes, $matches); + if ($matches[1] != "") + $profile = $matches[1]; - $ret= array(); + $ret= array(); - $ret["root_handle"] = preg_replace("=https?://(.*)/u/(.*)=ism", "$2@$1", $profile); - if (($ret["root_handle"] == $profile) OR ($ret["root_handle"] == "")) - return(false); + $ret["root_handle"] = preg_replace("=https?://(.*)/u/(.*)=ism", "$2@$1", $profile); + if (($ret["root_handle"] == $profile) OR ($ret["root_handle"] == "")) + return(false); - $link = ""; - preg_match("/link='(.*?)'/ism", $attributes, $matches); - if ($matches[1] != "") - $link = $matches[1]; + $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]; + preg_match('/link="(.*?)"/ism', $attributes, $matches); + if ($matches[1] != "") + $link = $matches[1]; - $ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link); - if (($ret["root_guid"] == $link) OR ($ret["root_guid"] == "")) - return(false); + $ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link); + if (($ret["root_guid"] == $link) OR ($ret["root_guid"] == "")) + return(false); - return($ret); + return($ret); } function diaspora_send_images($item,$owner,$contact,$images,$public_batch = false) { @@ -2724,7 +2730,7 @@ function diaspora_send_followup($item,$owner,$contact,$public_batch = false) { // likes on comments if($item['verb'] === ACTIVITY_LIKE && $item['thr-parent']) { $p = q("select guid, type, uri, `parent-uri` from item where uri = '%s' limit 1", - dbesc($item['thr-parent']) + dbesc($item['thr-parent']) ); } else { @@ -2802,7 +2808,7 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) { // likes on comments if($item['verb'] === ACTIVITY_LIKE && $item['thr-parent']) { $p = q("select guid, type, uri, `parent-uri` from item where uri = '%s' limit 1", - dbesc($item['thr-parent']) + dbesc($item['thr-parent']) ); } else { @@ -3074,3 +3080,47 @@ function diaspora_transmit($owner,$contact,$slap,$public_batch,$queue_run=false) return(($return_code) ? $return_code : (-1)); } + +function diaspora_fetch_relay() { + + $serverdata = get_config("system", "relay_server"); + if ($serverdata == "") + return array(); + + $relay = array(); + + $servers = explode(",", $serverdata); + + foreach($servers AS $server) { + $server = trim($server); + $batch = $server."/receive/public"; + + $relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch)); + + if (!$relais) { + $addr = "relay@".str_replace("http://", "", normalise_link($server)); + + $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')", + datetime_convert(), + dbesc($addr), + dbesc($addr), + dbesc($server), + dbesc(normalise_link($server)), + dbesc($batch), + dbesc(NETWORK_DIASPORA), + intval(CONTACT_IS_FOLLOWER), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc(datetime_convert()) + ); + + $relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch)); + if ($relais) + $relay[] = $relais[0]; + } else + $relay[] = $relais[0]; + } + + return $relay; +} diff --git a/include/notifier.php b/include/notifier.php index 67d5cdbbd8..84ed9884aa 100644 --- a/include/notifier.php +++ b/include/notifier.php @@ -3,6 +3,7 @@ require_once("boot.php"); require_once('include/queue_fn.php'); require_once('include/html2plain.php'); require_once("include/Scrape.php"); +require_once('include/diaspora.php'); /* * This file was at one time responsible for doing all deliveries, but this caused @@ -874,8 +875,6 @@ function notifier_run(&$argv, &$argc){ } break; case NETWORK_DIASPORA: - require_once('include/diaspora.php'); - if(get_config('system','dfrn_only') || (! get_config('system','diaspora_enabled'))) break; @@ -958,6 +957,11 @@ function notifier_run(&$argv, &$argc){ if($public_message) { + if (!$followup) + $r0 = diaspora_fetch_relay(); + else + $r0 = array(); + $r1 = q("SELECT DISTINCT(`batch`), `id`, `name`,`network` FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `rel` != %d group by `batch` ORDER BY rand() ", dbesc(NETWORK_DIASPORA), @@ -974,7 +978,7 @@ function notifier_run(&$argv, &$argc){ intval(CONTACT_IS_SHARING) ); - $r = array_merge($r2,$r1); + $r = array_merge($r2,$r1,$r0); if(count($r)) { logger('pubdeliver: ' . print_r($r,true), LOGGER_DEBUG); diff --git a/mod/_well_known.php b/mod/_well_known.php index 5c8a3380fd..3d722f7224 100644 --- a/mod/_well_known.php +++ b/mod/_well_known.php @@ -21,24 +21,40 @@ function wk_social_relay(&$a) { define('SR_SCOPE_ALL', 'all'); define('SR_SCOPE_TAGS', 'tags'); - $subscribe = (bool)true; - $scope = SR_SCOPE_ALL; - //$scope = SR_SCOPE_TAGS; + $subscribe = (bool)get_config('system', 'relay_subscribe'); + + if ($subscribe) + $scope = get_config('system', 'relay_scope'); + else + $scope = ""; $tags = array(); if ($scope == SR_SCOPE_TAGS) { - $terms = q("SELECT DISTINCT(`term`) FROM `search`"); - foreach($terms AS $term) { - $tag = trim($term["term"], "#"); - $tags[] = $tag; + $server_tags = get_config('system', 'relay_server_tags'); + $tagitems = explode(",", $server_tags); + + foreach($tagitems AS $tag) + $tags[trim($tag, "# ")] = trim($tag, "# "); + + if (get_config('system', 'relay_user_tags')) { + $terms = q("SELECT DISTINCT(`term`) FROM `search`"); + + foreach($terms AS $term) { + $tag = trim($term["term"], "#"); + $tags[$tag] = $tag; + } } } + $taglist = array(); + foreach($tags AS $tag) + $taglist[] = $tag; + $relay = array("subscribe" => $subscribe, "scope" => $scope, - "tags" => array_unique($tags)); + "tags" => $taglist); header('Content-type: application/json; charset=utf-8'); echo json_encode($relay, true);