diff --git a/src/Model/Photo.php b/src/Model/Photo.php index 68665126f..7df96fccd 100644 --- a/src/Model/Photo.php +++ b/src/Model/Photo.php @@ -16,6 +16,7 @@ use Friendica\Database\DBA; use Friendica\Database\DBStructure; use Friendica\Model\Storage\IStorage; use Friendica\Object\Image; +use Friendica\Protocol\DFRN; use Friendica\Util\DateTimeFormat; use Friendica\Util\Network; use Friendica\Util\Security; @@ -133,8 +134,16 @@ class Photo extends BaseObject if ($r === false) { return false; } + $uid = $r["uid"]; - $sql_acl = Security::getPermissionsSQLByUserId($r["uid"]); + // This is the first place, when retrieving just a photo, that we know who owns the photo. + // Make sure that the requester's session is appropriately authenticated to that user + // otherwise permissions checks done by getPermissionsSQLByUserId() won't work correctly + $r = DBA::selectFirst("user", ["nickname"], ["uid" => $uid], []); + // this will either just return (if auth all ok) or will redirect and exit (starting over) + DFRN::autoRedir(self::getApp(), $r["nickname"]); + + $sql_acl = Security::getPermissionsSQLByUserId($uid); $conditions = [ "`resource-id` = ? AND `scale` <= ? " . $sql_acl, diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index ec4557e82..91ca2545d 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -2899,7 +2899,12 @@ class DFRN { // prevent looping if (!empty($_REQUEST['redir'])) { - return; + Logger::log('autoRedir might be looping because redirect has been redirected', Logger::DEBUG); + // looping prevention also appears to sometimes prevent authentication for images + // because browser may have multiple connections open and load an image on a connection + // whose session wasn't updated when a previous redirect authenticated + // Leaving commented in case looping reappears + //return; } if ((! $contact_nick) || ($contact_nick === $a->user['nickname'])) { @@ -2923,6 +2928,9 @@ class DFRN $baseurl = substr($baseurl, $domain_st + 3); $nurl = Strings::normaliseLink($baseurl); + $r = User::getByNickname($contact_nick, ["uid"]); + $contact_uid = $r["uid"]; + /// @todo Why is there a query for "url" *and* "nurl"? Especially this normalising is strange. $r = q("SELECT `id` FROM `contact` WHERE `uid` = (SELECT `uid` FROM `user` WHERE `nickname` = '%s' LIMIT 1) AND `nick` = '%s' AND NOT `self` AND (`url` LIKE '%%%s%%' OR `nurl` LIKE '%%%s%%') AND NOT `blocked` AND NOT `pending` LIMIT 1", @@ -2931,9 +2939,19 @@ class DFRN DBA::escape($baseurl), DBA::escape($nurl) ); - if ((! DBA::isResult($r)) || $r[0]['id'] == remote_user()) { + if ((! DBA::isResult($r))) { return; } + // test if redirect authentication already succeeded + // Note that "contact" in the sense used in the $contact_nick argument to this function + // and the sense in the $remote[]["cid"] in the session are opposite. + // In the session variable the user currently fetching is the contact + // while $contact_nick is the nick of tho user who owns the stuff being fetched. + foreach (\Friendica\Core\Session::get('remote', []) as $visitor) { + if ($visitor['uid'] == $contact_uid && $visitor['cid'] == $r[0]['id']) { + return; + } + } $r = q("SELECT * FROM contact WHERE nick = '%s' AND network = '%s' AND uid = %d AND url LIKE '%%%s%%' LIMIT 1",