I have a PHP file who's sole job is to check if a user is logged in + if a session variable is set, then delivers a file via nginx X-Sendfile. It works perfectly on any desktop browser, and previously on any mobile browser - but fails on any ios 10 browser with mp4s only. What makes little sense to me is that if I comment the die()
line, it works as expected, but the php code should never even get into that line.
<?php
require_once('authConfig.php');
$userInfo = $auth0->getUser();
session_start();
include('cururl.php');
$murl = curPageURL();
parse_str($murl, $result);
$filename=$result['file'];
$folder=$result['folder'];
if (!$userInfo || !isset($_SESSION[$folder])) {
header('Location:login.php');
die();
}
$file="/var/www/uploads/" . $folder . "/" . $filename;
$aliasedFile = '/protected/' . $folder .'/' . $filename;
$realFile = $file;
header('Cache-Control: public, must-revalidate');
header('Pragma: no-cache');
header('Content-Type: ' . mime_content_type($file));
header('Content-Length: ' .(string)(filesize($realFile)) );
header('X-Accel-Redirect: ' . $aliasedFile);
exit;
?>
I can confirm that $_SESSION[$folder]
is actually set by changing the code to:
if(isset($_SESSION[$folder])){
echo "OK";
die();
}
UPDATE: Here's the access log from the iPhone. It should have access to the file.
10.0.0.1 forwarded for ..., 10.0.0.1 - - [16/Sep/2016:10:07:20 -0400] "GET /xfiles.php?&file=001.mp4&folder=NNx6659rvB HTTP/1.0" 200 1944706 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A403 Safari/602.1"
10.0.0.1 forwarded for ..., 10.0.0.1 - - [16/Sep/2016:10:07:21 -0400] "GET /xfiles.php?&file=001.mp4&folder=NNx6659rvB HTTP/1.0" 302 0 "https://www.sonoclipshare.com/xfiles.php?&file=001.mp4&folder=NNx6659rvB" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A403 Safari/602.1"
10.0.0.1 forwarded for ..., 10.0.0.1 - - [16/Sep/2016:10:07:21 -0400] "GET /login.php HTTP/1.0" 200 4166 "https://www.sonoclipshare.com/xfiles.php?&file=001.mp4&folder=NNx6659rvB" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A403 Safari/602.1"
UPDATE2: If I change the php file to examine the variables more closely:
<?php
require_once('authConfig.php');
$userInfo = $auth0->getUser();
session_start();
include('cururl.php');
$murl = curPageURL();
parse_str($murl, $result);
$filename=$result['file'];
$folder=$result['folder'];
print("info: $userInfo <br>SESSION: $_SESSION[$folder] <br>");
if(!$userInfo || !isset($_SESSION[$folder])) {
print("exiting");
}else {
print("sending file");
}
I'm getting a result of:
info: Array
SESSION: NNc6659rvB
sending file
when logged in, and:
info:
SESSION:
exiting
when not logged in. It should be working as expected.
UPDATE3:
Adding var_dump:
if(!$userInfo || !isset($_SESSION[$folder])) {
var_dump($userInfo);
var_dump($_SESSION[$folder]);
//header('Location:login.php');
exit();
}
echo "sending file";
I get NULL NULL when not logged in and sending file
when logged in. No echo from the loop. iOS acts like it's loading the mp4, shows the play button but no video unless I remove the exit()
line.
UPDATE4: If I replace die() with exit(), same effect. Replacing it with a nonsense function to kill the script also have the same effect. For some reason it gets into the if statement when I request an mp4 only.
SOLUTION: I had to pass the session ID to the page as a query string and then set it manually. This works well for my use case, as this php page shouldn't ever link out to other pages, exposing the session ID as a referral link. Not 100% ideal, but it'll bridge me until Apple pushes an iOS fix. Oh, and I removed the authConfig code check as this was redundant. The session variable can't be set if the user isn't already logged in.
include('cururl.php');
$murl = curPageURL();
parse_str($murl, $result);
$filename=$result['file'];
$folder=$result['folder'];
$session_id=$result['session_id'];
session_id($session_id);
session_start();
if(empty($_SESSION[$folder])) {
echo "redirecting";
exit(header("Location: login.php"));
}
$file="/var/www/uploads/" . $folder . "/" . $filename;
$aliasedFile = '/protected/' . $folder .'/' . $filename; //this is the nginx alias of the file path
$realFile = $file; //this is the physical file path
header('Cache-Control: public, must-revalidate');
header('Pragma: no-cache');
header('Content-Type: ' . mime_content_type($file));
header('Content-Length: ' .(string)(filesize($realFile)) );
header('X-Accel-Redirect: ' . $aliasedFile);
exit;
if (!$userInfo || !isset($_SESSION[$folder])) { header('Location:login.php'); exit();}
– Chrysarobindie()/exit()
, the redirect doesn't work but the file is delivered just fine. – Chrysarobinif(!isset($_SESSION[$folder]))
block is having an effect, then you must be receiving a request with$_SESSION[$folder]
unset. Perhaps iOS is sending two requests for the file for some reason? Have you actually looked into your request logs? (You do have request logging enabled, right?) – Arianaarianedie();
statement. Without that, you'll have a hard time figuring out what's going on – Rarotonga$userInfo=$_SESSION[$folder]=1;
– Chrysarobin