diff --git a/src/Model/APContact.php b/src/Model/APContact.php index 0a9d45f35..d0a0d0d3f 100644 --- a/src/Model/APContact.php +++ b/src/Model/APContact.php @@ -28,6 +28,7 @@ use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Database\DBStructure; use Friendica\DI; +use Friendica\Network\HTTPException; use Friendica\Network\Probe; use Friendica\Protocol\ActivityNamespace; use Friendica\Protocol\ActivityPub; @@ -178,8 +179,12 @@ class APContact } if (Network::isLocalLink($url) && ($local_uid = User::getIdForURL($url))) { - $data = Transmitter::getProfile($local_uid); - $local_owner = User::getOwnerDataById($local_uid); + try { + $data = Transmitter::getProfile($local_uid); + $local_owner = User::getOwnerDataById($local_uid); + } catch(HTTPException\NotFoundException $e) { + $data = null; + } } if (empty($data)) { diff --git a/src/Module/Friendica.php b/src/Module/Friendica.php index 5e77eb00f..95a319a41 100644 --- a/src/Module/Friendica.php +++ b/src/Module/Friendica.php @@ -29,6 +29,7 @@ use Friendica\Core\System; use Friendica\Database\PostUpdate; use Friendica\DI; use Friendica\Model\User; +use Friendica\Network\HTTPException; use Friendica\Protocol\ActivityPub; /** @@ -112,11 +113,13 @@ class Friendica extends BaseModule public static function rawContent(array $parameters = []) { if (ActivityPub::isRequest()) { - $data = ActivityPub\Transmitter::getProfile(0); - if (!empty($data)) { + try { + $data = ActivityPub\Transmitter::getProfile(0); header('Access-Control-Allow-Origin: *'); header('Cache-Control: max-age=23200, stale-while-revalidate=23200'); System::jsonExit($data, 'application/activity+json'); + } catch (HTTPException\NotFoundException $e) { + System::jsonError(404, ['error' => 'Record not found']); } } diff --git a/src/Module/Profile/Profile.php b/src/Module/Profile/Profile.php index 4f083db26..a4fc69685 100644 --- a/src/Module/Profile/Profile.php +++ b/src/Module/Profile/Profile.php @@ -52,12 +52,13 @@ class Profile extends BaseProfile if (ActivityPub::isRequest()) { $user = DBA::selectFirst('user', ['uid'], ['nickname' => $parameters['nickname']]); if (DBA::isResult($user)) { - // The function returns an empty array when the account is removed, expired or blocked - $data = ActivityPub\Transmitter::getProfile($user['uid']); - if (!empty($data)) { + try { + $data = ActivityPub\Transmitter::getProfile($user['uid']); header('Access-Control-Allow-Origin: *'); header('Cache-Control: max-age=23200, stale-while-revalidate=23200'); System::jsonExit($data, 'application/activity+json'); + } catch (HTTPException\NotFoundException $e) { + System::jsonError(404, ['error' => 'Record not found']); } } diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 9ee338e8f..d0aaaa7a0 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -23,6 +23,7 @@ namespace Friendica\Network; use DOMDocument; use DomXPath; +use Exception; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Protocol; @@ -2198,10 +2199,17 @@ class Probe * * @param string $url * @return array probed data + * @throws HTTPException\InternalServerErrorException + * @throws HTTPException\NotFoundException */ - private static function localProbe(string $url) + private static function localProbe(string $url): array { - if ($uid = User::getIdForURL($url)) { + try { + $uid = User::getIdForURL($url); + if (!$uid) { + throw new HTTPException\NotFoundException('User not found.'); + } + $profile = User::getOwnerDataById($uid); $approfile = ActivityPub\Transmitter::getProfile($uid); @@ -2209,25 +2217,30 @@ class Probe $profile['gsid'] = GServer::getID($approfile['generator']['url']); } - $data = ['name' => $profile['name'], 'nick' => $profile['nick'], 'guid' => $approfile['diaspora:guid'] ?? '', + $data = [ + 'name' => $profile['name'], 'nick' => $profile['nick'], 'guid' => $approfile['diaspora:guid'] ?? '', 'url' => $profile['url'], 'addr' => $profile['addr'], 'alias' => $profile['alias'], 'photo' => Contact::getAvatarUrlForId($profile['id'], $profile['updated']), 'header' => $profile['header'] ? Contact::getHeaderUrlForId($profile['id'], $profile['updated']) : '', 'account-type' => $profile['contact-type'], 'community' => ($profile['contact-type'] == User::ACCOUNT_TYPE_COMMUNITY), - 'keywords' => $profile['keywords'], 'location' => $profile['location'], 'about' => $profile['about'], + 'keywords' => $profile['keywords'], 'location' => $profile['location'], 'about' => $profile['about'], 'hide' => !$profile['net-publish'], 'batch' => '', 'notify' => $profile['notify'], 'poll' => $profile['poll'], 'request' => $profile['request'], 'confirm' => $profile['confirm'], - 'subscribe' => $approfile['generator']['url'] . '/follow?url={uri}', 'poco' => $profile['poco'], + 'subscribe' => $approfile['generator']['url'] . '/follow?url={uri}', 'poco' => $profile['poco'], 'following' => $approfile['following'], 'followers' => $approfile['followers'], 'inbox' => $approfile['inbox'], 'outbox' => $approfile['outbox'], - 'sharedinbox' => $approfile['endpoints']['sharedInbox'], 'network' => Protocol::DFRN, + 'sharedinbox' => $approfile['endpoints']['sharedInbox'], 'network' => Protocol::DFRN, 'pubkey' => $profile['upubkey'], 'baseurl' => $approfile['generator']['url'], 'gsid' => $profile['gsid'], - 'manually-approve' => in_array($profile['page-flags'], [User::PAGE_FLAGS_NORMAL, User::PAGE_FLAGS_PRVGROUP])]; - } else { + 'manually-approve' => in_array($profile['page-flags'], [User::PAGE_FLAGS_NORMAL, User::PAGE_FLAGS_PRVGROUP]) + ]; + } catch (Exception $e) { // Default values for non existing targets - $data = ['name' => $url, 'nick' => $url, 'url' => $url, 'network' => Protocol::PHANTOM, - 'photo' => DI::baseUrl() . Contact::DEFAULT_AVATAR_PHOTO]; + $data = [ + 'name' => $url, 'nick' => $url, 'url' => $url, 'network' => Protocol::PHANTOM, + 'photo' => DI::baseUrl() . Contact::DEFAULT_AVATAR_PHOTO + ]; } - return self::rearrangeData($data); + + return self::rearrangeData($data); } } diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 20b8f2a26..6c78db302 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -23,7 +23,6 @@ namespace Friendica\Protocol\ActivityPub; use Friendica\Content\Feature; use Friendica\Content\Text\BBCode; -use Friendica\Content\Text\Plaintext; use Friendica\Core\Cache\Duration; use Friendica\Core\Logger; use Friendica\Core\Protocol; @@ -35,12 +34,12 @@ use Friendica\Model\Contact; use Friendica\Model\Conversation; use Friendica\Model\GServer; use Friendica\Model\Item; -use Friendica\Model\ItemURI; -use Friendica\Model\Profile; use Friendica\Model\Photo; use Friendica\Model\Post; +use Friendica\Model\Profile; use Friendica\Model\Tag; use Friendica\Model\User; +use Friendica\Network\HTTPException; use Friendica\Protocol\Activity; use Friendica\Protocol\ActivityPub; use Friendica\Protocol\Relay; @@ -310,13 +309,18 @@ class Transmitter /** * Return the ActivityPub profile of the given user * - * @param integer $uid User ID + * @param int $uid User ID * @return array with profile data - * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws HTTPException\NotFoundException + * @throws HTTPException\InternalServerErrorException */ - public static function getProfile($uid) + public static function getProfile(int $uid): array { $owner = User::getOwnerDataById($uid); + if (!isset($owner['id'])) { + DI::logger()->error('Unable to find owner data for uid', ['uid' => $uid, 'callstack' => System::callstack(20)]); + throw new HTTPException\NotFoundException('User not found.'); + } $data = ['@context' => ActivityPub::CONTEXT]; $data['id'] = $owner['url']; @@ -1855,10 +1859,11 @@ class Transmitter * @param string $inbox Target inbox * * @return boolean was the transmission successful? - * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws HTTPException\InternalServerErrorException + * @throws HTTPException\NotFoundException * @throws \ImagickException */ - public static function sendProfileUpdate($uid, $inbox) + public static function sendProfileUpdate(int $uid, string $inbox): bool { $owner = User::getOwnerDataById($uid); $profile = APContact::getByURL($owner['url']);