Merge pull request #7282 from annando/issue-6477
Issue 6477: Automatically repair self contact avatar
This commit is contained in:
		
				commit
				
					
						2ba4116118
					
				
			
		
					 6 changed files with 84 additions and 90 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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['poll'],
 | 
			
		||||
				],
 | 
			
		||||
				[
 | 
			
		||||
					'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['poll'],
 | 
			
		||||
			'$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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue