| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  | <?php | 
					
						
							|  |  |  | // This file is part of GNU social - https://www.gnu.org/software/social
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // GNU social is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // GNU social is distributed in the hope that it will be useful,
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with GNU social.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * ActivityPub implementation for GNU social | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @package   GNUsocial | 
					
						
							|  |  |  |  * @author    Diogo Cordeiro <diogo@fc.up.pt> | 
					
						
							|  |  |  |  * @copyright 2018-2019 Free Software Foundation, Inc http://www.fsf.org | 
					
						
							|  |  |  |  * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later | 
					
						
							|  |  |  |  * @link      http://www.gnu.org/software/social/ | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | defined('GNUSOCIAL') || die(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * ActivityPub's own Postman | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Standard workflow expects that we send an Explorer to find out destinataries' | 
					
						
							|  |  |  |  * inbox address. Then we send our postman to deliver whatever we want to send them. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @category  Plugin | 
					
						
							|  |  |  |  * @package   GNUsocial | 
					
						
							|  |  |  |  * @author    Diogo Cordeiro <diogo@fc.up.pt> | 
					
						
							|  |  |  |  * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class Activitypub_postman | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     private $actor; | 
					
						
							|  |  |  |     private $actor_uri; | 
					
						
							|  |  |  |     private $to = []; | 
					
						
							|  |  |  |     private $client; | 
					
						
							|  |  |  |     private $headers; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Create a postman to deliver something to someone | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2019-08-19 23:33:18 +01:00
										 |  |  |      * @param Profile $from sender Profile | 
					
						
							|  |  |  |      * @param array $to receiver Profiles | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |      * @throws Exception | 
					
						
							|  |  |  |      * @author Diogo Cordeiro <diogo@fc.up.pt> | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-08-27 15:37:01 +01:00
										 |  |  |     public function __construct(Profile $from, array $to = []) | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         $this->actor = $from; | 
					
						
							|  |  |  |         $this->to = $to; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-10 22:27:32 +00:00
										 |  |  |         $this->actor_uri = $this->actor->getUri(); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $this->client = new HTTPClient(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Send something to remote instance | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $data request body | 
					
						
							|  |  |  |      * @param string $inbox url of remote inbox | 
					
						
							|  |  |  |      * @param string $method request method | 
					
						
							|  |  |  |      * @return GNUsocial_HTTPResponse | 
					
						
							|  |  |  |      * @throws HTTP_Request2_Exception | 
					
						
							|  |  |  |      * @throws Exception | 
					
						
							|  |  |  |      * @author Diogo Cordeiro <diogo@fc.up.pt> | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function send($data, $inbox, $method = 'POST') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         common_debug('ActivityPub Postman: Delivering '.$data.' to '.$inbox); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $headers = HttpSignature::sign($this->actor, $inbox, $data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         common_debug('ActivityPub Postman: Delivery headers were: '.print_r($headers, true)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->client->setBody($data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch ($method) { | 
					
						
							|  |  |  |             case 'POST': | 
					
						
							|  |  |  |                 $response = $this->client->post($inbox, $headers); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case 'GET': | 
					
						
							|  |  |  |                 $response = $this->client->get($inbox, $headers); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 throw new Exception("Unsupported request method for postman."); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         common_debug('ActivityPub Postman: Delivery result with status code '.$response->getStatus().': '.$response->getBody()); | 
					
						
							|  |  |  |         return $response; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Send a follow notification to remote instance | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return bool | 
					
						
							|  |  |  |      * @throws HTTP_Request2_Exception | 
					
						
							|  |  |  |      * @throws Exception | 
					
						
							|  |  |  |      * @author Diogo Cordeiro <diogo@fc.up.pt> | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function follow() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-08-05 23:22:32 +01:00
										 |  |  |         $data = Activitypub_follow::follow_to_array($this->actor_uri, $this->to[0]->getUrl()); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |         $res = $this->send(json_encode($data, JSON_UNESCAPED_SLASHES), $this->to[0]->get_inbox()); | 
					
						
							| 
									
										
										
										
											2019-11-01 00:12:45 +00:00
										 |  |  |         $res_body = json_decode($res->getBody(), true); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ($res->getStatus() == 200 || $res->getStatus() == 202 || $res->getStatus() == 409) { | 
					
						
							|  |  |  |             $pending_list = new Activitypub_pending_follow_requests($this->actor->getID(), $this->to[0]->getID()); | 
					
						
							|  |  |  |             $pending_list->add(); | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2019-11-01 00:12:45 +00:00
										 |  |  |         } elseif (isset($res_body['error'])) { | 
					
						
							|  |  |  |             throw new Exception($res_body['error']); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         throw new Exception("An unknown error occurred."); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Send a Undo Follow notification to remote instance | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return bool | 
					
						
							|  |  |  |      * @throws HTTP_Request2_Exception | 
					
						
							|  |  |  |      * @throws Exception | 
					
						
							|  |  |  |      * @throws Exception | 
					
						
							|  |  |  |      * @throws Exception | 
					
						
							|  |  |  |      * @throws Exception | 
					
						
							|  |  |  |      * @author Diogo Cordeiro <diogo@fc.up.pt> | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function undo_follow() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $data = Activitypub_undo::undo_to_array( | 
					
						
							|  |  |  |             Activitypub_follow::follow_to_array( | 
					
						
							| 
									
										
										
										
											2019-08-05 23:22:32 +01:00
										 |  |  |                 $this->actor_uri, | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |                 $this->to[0]->getUrl() | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |         $res = $this->send(json_encode($data, JSON_UNESCAPED_SLASHES), $this->to[0]->get_inbox()); | 
					
						
							| 
									
										
										
										
											2019-11-01 00:12:45 +00:00
										 |  |  |         $res_body = json_decode($res->getBody(), true); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ($res->getStatus() == 200 || $res->getStatus() == 202 || $res->getStatus() == 409) { | 
					
						
							| 
									
										
										
										
											2019-07-08 19:23:48 +01:00
										 |  |  |             Activitypub_profile::unsubscribeCacheUpdate($this->actor, $this->to[0]->local_profile()); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |             $pending_list = new Activitypub_pending_follow_requests($this->actor->getID(), $this->to[0]->getID()); | 
					
						
							|  |  |  |             $pending_list->remove(); | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-11-01 00:12:45 +00:00
										 |  |  |         if (isset($res_body['error'])) { | 
					
						
							|  |  |  |             throw new Exception($res_body['error']); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         throw new Exception("An unknown error occurred."); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Send a Accept Follow notification to remote instance | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2019-08-05 23:22:32 +01:00
										 |  |  |      * @param string $id Follow activity id | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |      * @return bool | 
					
						
							|  |  |  |      * @throws HTTP_Request2_Exception | 
					
						
							| 
									
										
										
										
											2019-08-05 23:22:32 +01:00
										 |  |  |      * @throws Exception Description of HTTP Response error or generic error message. | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |      * @author Diogo Cordeiro <diogo@fc.up.pt> | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-08-05 23:22:32 +01:00
										 |  |  |     public function accept_follow(string $id): bool | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         $data = Activitypub_accept::accept_to_array( | 
					
						
							|  |  |  |             Activitypub_follow::follow_to_array( | 
					
						
							|  |  |  |                 $this->to[0]->getUrl(), | 
					
						
							| 
									
										
										
										
											2019-08-05 23:22:32 +01:00
										 |  |  |                 $this->actor_uri, | 
					
						
							|  |  |  |                 $id | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             ); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |         $res = $this->send(json_encode($data, JSON_UNESCAPED_SLASHES), $this->to[0]->get_inbox()); | 
					
						
							| 
									
										
										
										
											2019-11-01 00:12:45 +00:00
										 |  |  |         $res_body = json_decode($res->getBody(), true); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ($res->getStatus() == 200 || $res->getStatus() == 202 || $res->getStatus() == 409) { | 
					
						
							| 
									
										
										
										
											2019-07-08 19:23:48 +01:00
										 |  |  |             $pending_list = new Activitypub_pending_follow_requests($this->to[0]->getID(), $this->actor->getID()); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |             $pending_list->remove(); | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-11-01 00:12:45 +00:00
										 |  |  |         if (isset($res_body['error'])) { | 
					
						
							|  |  |  |             throw new Exception($res_body['error']); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         throw new Exception("An unknown error occurred."); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Send a Like notification to remote instances holding the notice | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Notice $notice | 
					
						
							|  |  |  |      * @throws HTTP_Request2_Exception | 
					
						
							|  |  |  |      * @throws InvalidUrlException | 
					
						
							|  |  |  |      * @throws Exception | 
					
						
							|  |  |  |      * @author Diogo Cordeiro <diogo@fc.up.pt> | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function like($notice) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $data = Activitypub_like::like_to_array( | 
					
						
							| 
									
										
										
										
											2019-08-05 23:22:32 +01:00
										 |  |  |             $this->actor_uri, | 
					
						
							| 
									
										
										
										
											2019-07-18 19:18:23 +01:00
										 |  |  |             Activitypub_notice::getUrl($notice) | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |                 ); | 
					
						
							|  |  |  |         $data = json_encode($data, JSON_UNESCAPED_SLASHES); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($this->to_inbox() as $inbox) { | 
					
						
							| 
									
										
										
										
											2019-07-18 19:18:23 +01:00
										 |  |  |             $res = $this->send($data, $inbox); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // accummulate errors for later use, if needed
 | 
					
						
							|  |  |  |             if (!($res->getStatus() == 200 || $res->getStatus() == 202 || $res->getStatus() == 409)) { | 
					
						
							|  |  |  |                 $res_body = json_decode($res->getBody(), true); | 
					
						
							| 
									
										
										
										
											2019-11-01 00:12:45 +00:00
										 |  |  |                 $errors[] = isset($res_body['error']) ? | 
					
						
							|  |  |  |                           $res_body['error'] : "An unknown error occurred."; | 
					
						
							| 
									
										
										
										
											2019-07-18 19:18:23 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($errors)) { | 
					
						
							|  |  |  |             common_log(LOG_ERR, sizeof($errors) . " instance/s failed to handle the like activity!"); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Send a Undo Like notification to remote instances holding the notice | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Notice $notice | 
					
						
							|  |  |  |      * @throws HTTP_Request2_Exception | 
					
						
							|  |  |  |      * @throws InvalidUrlException | 
					
						
							|  |  |  |      * @throws Exception | 
					
						
							|  |  |  |      * @author Diogo Cordeiro <diogo@fc.up.pt> | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function undo_like($notice) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $data = Activitypub_undo::undo_to_array( | 
					
						
							|  |  |  |             Activitypub_like::like_to_array( | 
					
						
							| 
									
										
										
										
											2019-08-05 23:22:32 +01:00
										 |  |  |                 $this->actor_uri, | 
					
						
							| 
									
										
										
										
											2019-07-18 19:18:23 +01:00
										 |  |  |                 Activitypub_notice::getUrl($notice) | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |                          ) | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |         $data = json_encode($data, JSON_UNESCAPED_SLASHES); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($this->to_inbox() as $inbox) { | 
					
						
							| 
									
										
										
										
											2019-07-18 19:18:23 +01:00
										 |  |  |             $res = $this->send($data, $inbox); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // accummulate errors for later use, if needed
 | 
					
						
							|  |  |  |             if (!($res->getStatus() == 200 || $res->getStatus() == 202 || $res->getStatus() == 409)) { | 
					
						
							|  |  |  |                 $res_body = json_decode($res->getBody(), true); | 
					
						
							| 
									
										
										
										
											2019-11-01 00:12:45 +00:00
										 |  |  |                 $errors[] = isset($res_body['error']) ? | 
					
						
							|  |  |  |                           $res_body['error'] : "An unknown error occurred."; | 
					
						
							| 
									
										
										
										
											2019-07-18 19:18:23 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($errors)) { | 
					
						
							|  |  |  |             common_log(LOG_ERR, sizeof($errors) . " instance/s failed to handle the undo-like activity!"); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Send a Create notification to remote instances | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Notice $notice | 
					
						
							|  |  |  |      * @throws EmptyPkeyValueException | 
					
						
							|  |  |  |      * @throws HTTP_Request2_Exception | 
					
						
							|  |  |  |      * @throws InvalidUrlException | 
					
						
							|  |  |  |      * @throws ServerException | 
					
						
							|  |  |  |      * @author Diogo Cordeiro <diogo@fc.up.pt> | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function create_note($notice) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $data = Activitypub_create::create_to_array( | 
					
						
							|  |  |  |             $this->actor_uri, | 
					
						
							|  |  |  |             Activitypub_notice::notice_to_array($notice) | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |         $data = json_encode($data, JSON_UNESCAPED_SLASHES); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($this->to_inbox() as $inbox) { | 
					
						
							| 
									
										
										
										
											2019-07-18 19:18:23 +01:00
										 |  |  |             $res = $this->send($data, $inbox); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // accummulate errors for later use, if needed
 | 
					
						
							|  |  |  |             if (!($res->getStatus() == 200 || $res->getStatus() == 202 || $res->getStatus() == 409)) { | 
					
						
							|  |  |  |                 $res_body = json_decode($res->getBody(), true); | 
					
						
							| 
									
										
										
										
											2019-11-01 00:12:45 +00:00
										 |  |  |                 $errors[] = isset($res_body['error']) ? | 
					
						
							|  |  |  |                           $res_body['error'] : "An unknown error occurred."; | 
					
						
							| 
									
										
										
										
											2019-07-18 19:18:23 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($errors)) { | 
					
						
							|  |  |  |             common_log(LOG_ERR, sizeof($errors) . " instance/s failed to handle the create-note activity!"); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-19 23:33:18 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Send a Create direct-notification to remote instances | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Notice $message | 
					
						
							|  |  |  |      * @author Bruno Casteleiro <brunoccast@fc.up.pt> | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function create_direct_note(Notice $message) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $data = Activitypub_create::create_to_array( | 
					
						
							|  |  |  |             $this->actor_uri, | 
					
						
							|  |  |  |             Activitypub_message::message_to_array($message), | 
					
						
							|  |  |  |             true | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |         $data = json_encode($data, JSON_UNESCAPED_SLASHES); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-20 01:08:02 +01:00
										 |  |  |         foreach ($this->to_inbox(false) as $inbox) { | 
					
						
							| 
									
										
										
										
											2019-08-19 23:33:18 +01:00
										 |  |  |             $res = $this->send($data, $inbox); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // accummulate errors for later use, if needed
 | 
					
						
							|  |  |  |             if (!($res->getStatus() == 200 || $res->getStatus() == 202 || $res->getStatus() == 409)) { | 
					
						
							|  |  |  |                 $res_body = json_decode($res->getBody(), true); | 
					
						
							| 
									
										
										
										
											2019-11-01 00:12:45 +00:00
										 |  |  |                 $errors[] = isset($res_body['error']) ? | 
					
						
							|  |  |  |                           $res_body['error'] : "An unknown error occurred."; | 
					
						
							| 
									
										
										
										
											2019-08-19 23:33:18 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($errors)) { | 
					
						
							|  |  |  |             common_log(LOG_ERR, sizeof($errors) . " instance/s failed to handle the create-note activity!"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Send a Announce notification to remote instances | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Notice $notice | 
					
						
							|  |  |  |      * @throws HTTP_Request2_Exception | 
					
						
							|  |  |  |      * @throws Exception | 
					
						
							|  |  |  |      * @author Diogo Cordeiro <diogo@fc.up.pt> | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function announce($notice) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-08-05 23:22:32 +01:00
										 |  |  |         $data = json_encode(Activitypub_announce::announce_to_array($this->actor, $notice), | 
					
						
							|  |  |  |                             JSON_UNESCAPED_SLASHES); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         foreach ($this->to_inbox() as $inbox) { | 
					
						
							| 
									
										
										
										
											2019-07-18 19:18:23 +01:00
										 |  |  |             $res = $this->send($data, $inbox); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // accummulate errors for later use, if needed
 | 
					
						
							|  |  |  |             if (!($res->getStatus() == 200 || $res->getStatus() == 202 || $res->getStatus() == 409)) { | 
					
						
							|  |  |  |                 $res_body = json_decode($res->getBody(), true); | 
					
						
							| 
									
										
										
										
											2019-11-01 00:12:45 +00:00
										 |  |  |                 $errors[] = isset($res_body['error']) ? | 
					
						
							|  |  |  |                           $res_body['error'] : "An unknown error occurred."; | 
					
						
							| 
									
										
										
										
											2019-07-18 19:18:23 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($errors)) { | 
					
						
							|  |  |  |             common_log(LOG_ERR, sizeof($errors) . " instance/s failed to handle the announce activity!"); | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Send a Delete notification to remote instances holding the notice | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Notice $notice | 
					
						
							|  |  |  |      * @throws HTTP_Request2_Exception | 
					
						
							|  |  |  |      * @throws InvalidUrlException | 
					
						
							|  |  |  |      * @throws Exception | 
					
						
							|  |  |  |      * @author Diogo Cordeiro <diogo@fc.up.pt> | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-08-27 15:37:01 +01:00
										 |  |  |     public function delete_note($notice) | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         $data = Activitypub_delete::delete_to_array( | 
					
						
							| 
									
										
										
										
											2019-12-10 22:27:32 +00:00
										 |  |  |             $notice->getProfile()->getUri(), | 
					
						
							| 
									
										
										
										
											2019-07-25 03:29:11 +01:00
										 |  |  |             Activitypub_notice::getUrl($notice) | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |                 ); | 
					
						
							|  |  |  |         $errors = []; | 
					
						
							|  |  |  |         $data = json_encode($data, JSON_UNESCAPED_SLASHES); | 
					
						
							|  |  |  |         foreach ($this->to_inbox() as $inbox) { | 
					
						
							|  |  |  |             $res = $this->send($data, $inbox); | 
					
						
							| 
									
										
										
										
											2019-07-18 19:18:23 +01:00
										 |  |  |             if (!($res->getStatus() == 200 || $res->getStatus() == 202 || $res->getStatus() == 409)) { | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |                 $res_body = json_decode($res->getBody(), true); | 
					
						
							| 
									
										
										
										
											2019-11-01 00:12:45 +00:00
										 |  |  |                 $errors[] = isset($res_body['error']) ? | 
					
						
							|  |  |  |                           $res_body['error'] : "An unknown error occurred."; | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!empty($errors)) { | 
					
						
							|  |  |  |             throw new Exception(json_encode($errors)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-27 15:37:01 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Send a Delete notification to remote followers of some deleted profile | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Notice $notice | 
					
						
							|  |  |  |      * @throws HTTP_Request2_Exception | 
					
						
							|  |  |  |      * @throws InvalidUrlException | 
					
						
							|  |  |  |      * @throws Exception | 
					
						
							|  |  |  |      * @author Bruno Casteleiro <brunoccast@fc.up.pt> | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function delete_profile() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $data = Activitypub_delete::delete_to_array($this->actor_uri, $this->actor_uri); | 
					
						
							|  |  |  |         $data = json_encode($data, JSON_UNESCAPED_SLASHES); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $errors = []; | 
					
						
							|  |  |  |         foreach ($this->to_inbox() as $inbox) { | 
					
						
							|  |  |  |             $res = $this->send($data, $inbox); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // accummulate errors for later use, if needed
 | 
					
						
							|  |  |  |             if (!($res->getStatus() == 200 || $res->getStatus() == 202 || $res->getStatus() == 409)) { | 
					
						
							|  |  |  |                 $res_body = json_decode($res->getBody(), true); | 
					
						
							| 
									
										
										
										
											2019-11-01 00:12:45 +00:00
										 |  |  |                 $errors[] = isset($res_body['error']) ? | 
					
						
							|  |  |  |                           $res_body['error'] : "An unknown error occurred."; | 
					
						
							| 
									
										
										
										
											2019-08-27 15:37:01 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($errors)) { | 
					
						
							|  |  |  |             common_log(LOG_ERR, sizeof($errors) . " instance/s failed to handle the delete_profile activity!"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Clean list of inboxes to deliver messages | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2019-08-20 01:08:02 +01:00
										 |  |  |      * @param bool $actorFollowers whether to include the actor's follower collection | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |      * @return array To Inbox URLs | 
					
						
							| 
									
										
										
										
											2019-12-11 00:15:27 +00:00
										 |  |  |      * @throws Exception | 
					
						
							|  |  |  |      * @author Diogo Cordeiro <diogo@fc.up.pt> | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-08-20 01:08:02 +01:00
										 |  |  |     private function to_inbox(bool $actorFollowers = true): array | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-08-20 01:08:02 +01:00
										 |  |  |         if ($actorFollowers) { | 
					
						
							|  |  |  |             $discovery = new Activitypub_explorer(); | 
					
						
							|  |  |  |             $followers = apActorFollowersAction::generate_followers($this->actor, 0, null); | 
					
						
							|  |  |  |             foreach ($followers as $sub) { | 
					
						
							|  |  |  |                 try { | 
					
						
							|  |  |  |                     $this->to[]= Activitypub_profile::from_profile($discovery->lookup($sub)[0]); | 
					
						
							|  |  |  |                 } catch (Exception $e) { | 
					
						
							|  |  |  |                     // Not an ActivityPub Remote Follower, let it go
 | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             unset($discovery); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |         $to_inboxes = []; | 
					
						
							|  |  |  |         foreach ($this->to as $to_profile) { | 
					
						
							|  |  |  |             $i = $to_profile->get_inbox(); | 
					
						
							|  |  |  |             // Prevent delivering to self
 | 
					
						
							| 
									
										
										
										
											2019-12-11 00:15:27 +00:00
										 |  |  |             if ($i == common_local_url('apInbox')) { | 
					
						
							| 
									
										
										
										
											2019-05-11 12:27:21 +01:00
										 |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $to_inboxes[] = $i; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return array_unique($to_inboxes); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |