From 4ab772ed673d38ff7458e2e0155fdf9b9155551f Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 19 Jun 2019 17:05:29 +0000 Subject: [PATCH] Issue 6477: Automatically repair self contact avatar --- src/Model/Contact.php | 29 +++++----- src/Model/User.php | 34 ++++++++++-- src/Module/Xrd.php | 71 +++++++++++++----------- src/Protocol/ActivityPub/Transmitter.php | 7 +-- view/templates/tag_slap.tpl | 31 ----------- view/templates/xrd_person.tpl | 2 +- 6 files changed, 84 insertions(+), 90 deletions(-) delete mode 100644 view/templates/tag_slap.tpl diff --git a/src/Model/Contact.php b/src/Model/Contact.php index a7914a190..9e3f2a15d 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -593,11 +593,13 @@ class Contact extends BaseObject return; } + $file_suffix = 'jpg'; + $fields = ['name' => $profile['name'], 'nick' => $user['nickname'], 'avatar-date' => $self['avatar-date'], 'location' => Profile::formatLocation($profile), 'about' => $profile['about'], 'keywords' => $profile['pub_keywords'], - 'gender' => $profile['gender'], 'avatar' => $profile['photo'], - 'contact-type' => $user['account-type'], 'xmpp' => $profile['xmpp']]; + 'gender' => $profile['gender'], 'contact-type' => $user['account-type'], + 'xmpp' => $profile['xmpp']]; $avatar = Photo::selectFirst(['resource-id', 'type'], ['uid' => $uid, 'profile' => true]); if (DBA::isResult($avatar)) { @@ -609,8 +611,6 @@ class Contact extends BaseObject $types = Image::supportedTypes(); if (isset($types[$avatar['type']])) { $file_suffix = $types[$avatar['type']]; - } else { - $file_suffix = 'jpg'; } // We are adding a timestamp value so that other systems won't use cached content @@ -629,6 +629,7 @@ class Contact extends BaseObject $fields['micro'] = System::baseUrl() . '/images/person-48.jpg'; } + $fields['avatar'] = System::baseUrl() . '/photo/profile/' .$uid . '.' . $file_suffix; $fields['forum'] = $user['page-flags'] == User::PAGE_FLAGS_COMMUNITY; $fields['prv'] = $user['page-flags'] == User::PAGE_FLAGS_PRVGROUP; @@ -661,8 +662,8 @@ class Contact extends BaseObject DBA::update('contact', $fields, ['uid' => 0, 'nurl' => $self['nurl']]); // Update the profile - $fields = ['photo' => System::baseUrl() . '/photo/profile/' .$uid . '.jpg', - 'thumb' => System::baseUrl() . '/photo/avatar/' . $uid .'.jpg']; + $fields = ['photo' => System::baseUrl() . '/photo/profile/' .$uid . '.' . $file_suffix, + 'thumb' => System::baseUrl() . '/photo/avatar/' . $uid .'.' . $file_suffix]; DBA::update('profile', $fields, ['uid' => $uid, 'is-default' => true]); } } @@ -1725,7 +1726,7 @@ class Contact extends BaseObject */ public static function updateAvatar($avatar, $uid, $cid, $force = false) { - $contact = DBA::selectFirst('contact', ['avatar', 'photo', 'thumb', 'micro', 'nurl'], ['id' => $cid]); + $contact = DBA::selectFirst('contact', ['avatar', 'photo', 'thumb', 'micro', 'nurl'], ['id' => $cid, 'self' => false]); if (!DBA::isResult($contact)) { return false; } else { @@ -2153,7 +2154,7 @@ class Contact extends BaseObject return false; } - $fields = ['url', 'name', 'nick', 'photo', 'network', 'blocked']; + $fields = ['url', 'name', 'nick', 'avatar', 'photo', 'network', 'blocked']; $pub_contact = DBA::selectFirst('contact', $fields, ['id' => $datarray['author-id']]); if (!DBA::isResult($pub_contact)) { // Should never happen @@ -2167,16 +2168,16 @@ class Contact extends BaseObject $url = defaults($datarray, 'author-link', $pub_contact['url']); $name = $pub_contact['name']; - $photo = $pub_contact['photo']; + $photo = defaults($pub_contact, 'avatar', $pub_contact["photo"]); $nick = $pub_contact['nick']; $network = $pub_contact['network']; if (!empty($contact)) { - // Contact is blocked at user-level - if (!empty($contact['id']) && !empty($importer['id']) && - self::isBlockedByUser($contact['id'], $importer['id'])) { - return false; - } + // Contact is blocked at user-level + if (!empty($contact['id']) && !empty($importer['id']) && + self::isBlockedByUser($contact['id'], $importer['id'])) { + return false; + } // Make sure that the existing contact isn't archived self::unmarkForArchival($contact); diff --git a/src/Model/User.php b/src/Model/User.php index b73356306..de6931052 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -16,6 +16,7 @@ use Friendica\Core\Protocol; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBA; +use Friendica\Model\Photo; use Friendica\Object\Image; use Friendica\Util\Crypto; use Friendica\Util\DateTimeFormat; @@ -149,10 +150,11 @@ class User * @brief Get owner data by user id * * @param int $uid + * @param boolean $check_valid Test if data is invalid and correct it * @return boolean|array * @throws Exception */ - public static function getOwnerDataById($uid) { + public static function getOwnerDataById($uid, $check_valid = true) { $r = DBA::fetchFirst("SELECT `contact`.*, `user`.`prvkey` AS `uprvkey`, @@ -180,12 +182,34 @@ class User return false; } - // Check if the returned data is valid, otherwise fix it. See issue #6122 - $url = System::baseUrl() . '/profile/' . $r['nickname']; - $addr = $r['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3); + if (!$check_valid) { + return $r; + } - if (($addr != $r['addr']) || ($r['url'] != $url) || ($r['nurl'] != Strings::normaliseLink($r['url']))) { + // Check if the returned data is valid, otherwise fix it. See issue #6122 + + // Check for correct url and normalised nurl + $url = System::baseUrl() . '/profile/' . $r['nickname']; + $repair = ($r['url'] != $url) || ($r['nurl'] != Strings::normaliseLink($r['url'])); + + if (!$repair) { + // Check if "addr" is present and correct + $addr = $r['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3); + $repair = ($addr != $r['addr']); + } + + if (!$repair) { + // Check if the avatar field is filled and the photo directs to the correct path + $avatar = Photo::selectFirst(['resource-id'], ['uid' => $uid, 'profile' => true]); + if (DBA::isResult($avatar)) { + $repair = empty($r['avatar']) || !strpos($r['photo'], $avatar['resource-id']); + } + } + + if ($repair) { Contact::updateSelfFromUserID($uid); + // Return the corrected data and avoid a loop + $r = self::getOwnerDataById($uid, false); } return $r; diff --git a/src/Module/Xrd.php b/src/Module/Xrd.php index b6bd87594..0618a5de6 100644 --- a/src/Module/Xrd.php +++ b/src/Module/Xrd.php @@ -4,9 +4,11 @@ namespace Friendica\Module; use Friendica\BaseModule; use Friendica\Core\Hook; +use Friendica\Database\DBA; use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\Model\User; +use Friendica\Model\Photo; use Friendica\Protocol\Salmon; use Friendica\Util\Strings; @@ -61,67 +63,69 @@ class Xrd extends BaseModule throw new \Friendica\Network\HTTPException\NotFoundException(); } - $profileURL = $app->getBaseURL() . '/profile/' . $user['nickname']; - $alias = str_replace('/profile/', '/~', $profileURL); + $owner = User::getOwnerDataById($user['uid']); - $addr = 'acct:' . $user['nickname'] . '@' . $app->getHostName(); - if ($app->getURLPath()) { - $addr .= '/' . $app->getURLPath(); + $alias = str_replace('/profile/', '/~', $owner['url']); + + $avatar = Photo::selectFirst(['type'], ['uid' => $owner['uid'], 'profile' => true]); + + if (!DBA::isResult($avatar)) { + $avatar = ['type' => 'image/jpeg']; } if ($mode == 'xml') { - self::printXML($addr, $alias, $profileURL, $app->getBaseURL(), $user); + self::printXML($alias, $app->getBaseURL(), $user, $owner, $avatar); } else { - self::printJSON($addr, $alias, $profileURL, $app->getBaseURL(), $user); + self::printJSON($alias, $app->getBaseURL(), $owner, $avatar); } } - private static function printJSON($uri, $alias, $orofileURL, $baseURL, $user) + private static function printJSON($alias, $baseURL, $owner, $avatar) { - $salmon_key = Salmon::salmonKey($user['spubkey']); + $salmon_key = Salmon::salmonKey($owner['spubkey']); header('Access-Control-Allow-Origin: *'); header('Content-type: application/json; charset=utf-8'); $json = [ - 'subject' => $uri, + 'subject' => 'acct:' . $owner['addr'], 'aliases' => [ $alias, - $orofileURL, + $owner['url'], ], 'links' => [ [ 'rel' => NAMESPACE_DFRN, - 'href' => $orofileURL, + 'href' => $owner['url'], ], [ 'rel' => NAMESPACE_FEED, 'type' => 'application/atom+xml', - 'href' => $baseURL . '/dfrn_poll/' . $user['nickname'], + 'href' => $owner['notify'], ], [ 'rel' => 'http://webfinger.net/rel/profile-page', 'type' => 'text/html', - 'href' => $orofileURL, + 'href' => $owner['url'], ], [ 'rel' => 'self', 'type' => 'application/activity+json', - 'href' => $orofileURL, + 'href' => $owner['url'], ], [ 'rel' => 'http://microformats.org/profile/hcard', 'type' => 'text/html', - 'href' => $baseURL . '/hcard/' . $user['nickname'], + 'href' => $baseURL . '/hcard/' . $owner['nickname'], ], [ 'rel' => NAMESPACE_POCO, - 'href' => $baseURL . '/poco/' . $user['nickname'], + 'href' => $owner['poco'], ], [ 'rel' => 'http://webfinger.net/rel/avatar', - 'type' => 'image/jpeg', - 'href' => $baseURL . '/photo/profile/' . $user['uid'] . '.jpg', + 'type' => $avatar['type'], + 'href' => $owner['photo'], ], [ 'rel' => 'http://joindiaspora.com/seed_location', @@ -130,15 +134,15 @@ class Xrd extends BaseModule ], [ 'rel' => 'salmon', - 'href' => $baseURL . '/salmon/' . $user['nickname'], + 'href' => $baseURL . '/salmon/' . $owner['nickname'], ], [ 'rel' => 'http://salmon-protocol.org/ns/salmon-replies', - 'href' => $baseURL . '/salmon/' . $user['nickname'], + 'href' => $baseURL . '/salmon/' . $owner['nickname'], ], [ 'rel' => 'http://salmon-protocol.org/ns/salmon-mention', - 'href' => $baseURL . '/salmon/' . $user['nickname'] . '/mention', + 'href' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention', ], [ 'rel' => 'http://ostatus.org/schema/1.0/subscribe', @@ -160,9 +164,9 @@ class Xrd extends BaseModule exit(); } - private static function printXML($uri, $alias, $profileURL, $baseURL, $user) + private static function printXML($alias, $baseURL, $user, $owner, $avatar) { - $salmon_key = Salmon::salmonKey($user['spubkey']); + $salmon_key = Salmon::salmonKey($owner['spubkey']); header('Access-Control-Allow-Origin: *'); header('Content-type: text/xml'); @@ -170,16 +174,17 @@ class Xrd extends BaseModule $tpl = Renderer::getMarkupTemplate('xrd_person.tpl'); $o = Renderer::replaceMacros($tpl, [ - '$nick' => $user['nickname'], - '$accturi' => $uri, + '$nick' => $owner['nickname'], + '$accturi' => 'acct:' . $owner['addr'], '$alias' => $alias, - '$profile_url' => $profileURL, - '$hcard_url' => $baseURL . '/hcard/' . $user['nickname'], - '$atom' => $baseURL . '/dfrn_poll/' . $user['nickname'], - '$poco_url' => $baseURL . '/poco/' . $user['nickname'], - '$photo' => $baseURL . '/photo/profile/' . $user['uid'] . '.jpg', - '$salmon' => $baseURL . '/salmon/' . $user['nickname'], - '$salmen' => $baseURL . '/salmon/' . $user['nickname'] . '/mention', + '$profile_url' => $owner['url'], + '$hcard_url' => $baseURL . '/hcard/' . $owner['nickname'], + '$atom' => $owner['notify'], + '$poco_url' => $owner['poco'], + '$photo' => $owner['photo'], + '$type' => $avatar['type'], + '$salmon' => $baseURL . '/salmon/' . $owner['nickname'], + '$salmen' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention', '$subscribe' => $baseURL . '/follow?url={uri}', '$openwebauth' => $baseURL . '/owa', '$modexp' => 'data:application/magic-public-key,' . $salmon_key diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 81b8bc1de..cafdfc772 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -229,11 +229,6 @@ class Transmitter return []; } - // On old installations and never changed contacts this might not be filled - if (empty($contact['avatar'])) { - $contact['avatar'] = $contact['photo']; - } - $data = ['@context' => ActivityPub::CONTEXT]; $data['id'] = $contact['url']; $data['diaspora:guid'] = $user['guid']; @@ -254,7 +249,7 @@ class Transmitter 'publicKeyPem' => $user['pubkey']]; $data['endpoints'] = ['sharedInbox' => System::baseUrl() . '/inbox']; $data['icon'] = ['type' => 'Image', - 'url' => $contact['avatar']]; + 'url' => $contact['photo']]; $data['generator'] = self::getService(); diff --git a/view/templates/tag_slap.tpl b/view/templates/tag_slap.tpl deleted file mode 100644 index ac492b6dd..000000000 --- a/view/templates/tag_slap.tpl +++ /dev/null @@ -1,31 +0,0 @@ - - - - {{$name}} - {{$profile_page}} - - - - - {{$item_id}} - {{$title}} - {{$published}} - {{$content nofilter}} - - - http://activitystrea.ms/schema/1.0/person - {{$profile_page}} - - - - {{$nick}} - {{$name}} - - {{$verb}} - - - - - - - diff --git a/view/templates/xrd_person.tpl b/view/templates/xrd_person.tpl index 578698b46..0fb81b09c 100644 --- a/view/templates/xrd_person.tpl +++ b/view/templates/xrd_person.tpl @@ -18,7 +18,7 @@