I'm have a PHP file that contains HTML markup for a video. Instead of using a full URL in the src part of the source tags, I use a PHP file that contains code that renders the video file.
The PHP file name is appended by a random string of characters that serve as a key to the actual video file name. I store these values in $_SESSION so that the PHP file that is rendering the video file will know which file to look for. I also have it use cookies so that nobody can reuse the tokens.
This works great in Firefox and Chrome, but it fails for Safari and for all mobile browsers I have tried on both Android and iOS.
For the sake of simplicity, I stripped down the whole process to simply have the video rendering PHP file while the PHP file containing the HTML markup calls the that file directly without using unique tokens.
When I do that, sometimes Safari loads it (very slowly) and mobile is still a complete fail.
The pertinent part of the first file looks something like this:
<video>
<source src=\"/videofile.php\" type=\"video/mp4\">
</video>
The other file simply has this just to see if that alone works:
readfile('filename.mp4');
So, non-mobile Safari sometimes loads it (very slowly) like that. However, it always fails whenever I add anything else including storing the file name in a variable and calling the variable as a parameter in readfile(), whenever I use sessions, when I use cookies, and basically anything else.
I tried many other ways to break the file down into chunks since I figured that's why it won't play on mobile, but loading the video file directly into the source tags has no problem. The problem seems to lay with how I'm calling the video file.
I have no idea why it works with Firefox and Chrome, but it won't work for the others stated above. I am not sure what to do at this point. I am not even sure if I'm phrasing the problem correctly since all of my Google queries have failed to yield anything like what I'm talking about.
EDIT: I've added the full file code I'm using
First One
<?php
ini_set('session.use_cookies',1);
session_start();
$mp4=uniqid();
$_SESSION[$mp4]='video.mp4';
$ogv=uniqid();
$_SESSION[$ogv]='video.ogv';
echo "
<div style=\"position: relative;padding-bottom: 56.25%;padding-top:35px;height: 0;overflow: hidden;\" oncontextmenu=\"return false\">
<video style=\"position: absolute;top:0;left: 0;width: 100%;height: 100%;\" height=\"540\" width=\"864\" controls>
<source src=\"/videorender.php?video=" . $mp4 . "\" type=\"video/mp4\">
<source src=\"/videorender.php?video=" . $ogv . "\" type=\"video/ogv\">
</video>
</div>
";
?>
Now for VideoRenderer.php
<?php
ini_set('session.use_cookies',1);
session_start();
$file = $_SESSION[$_GET['video']];
$_SESSION=array();
$params = session_get_cookie_params();
setcookie(session_name(),'', time()-42000,$params["path"],$params["domain"],
$params["secure"], $params["httponly"]);
if(!file_exists($file) || $file === '' || !is_readable($file)){
header('HTTP/1.1 404 File not found',true);
exit;
}
readfile($file);
exit;
?>
Did you compared the http headers between your php script and a direct embedding of the video file?
You have to sent Content-Type:video/mp4 for example:
header("Content-Type:video/mp4");
The Content-Length header is also a good idea:
header('Content-Length: '.filesize($videoFile));
There are several other circumstances like some browsers send more then one requests. See a similar question here: https://stackoverflow.com/a/3125869/2797243
On the other side: Piping a video file through php is a realy bad idea (server performance) like you described. With this approach you will get no solution that will satisfy you.
If you want to implement something like authorization for ex., best approach is using a streaming server. Regardless the video is being streamed or will be provided as a progressive download.
The only solution I can think of, is to make http redirect to the video file. But I guess this could also fails, specially on the native players like the mobile ones.
Related
Background
I am working on setting up an intranet webpage where the user can select an item from a list, and it will display information about that item and a PDF as a block element.
The PDFs will need to be updated and replaced by specific people, so they are stored on a separate file server on the internal network.
HTML Solution Attempt
I've tried using
<embed src="file:///myFileServer/PDFs/filename.pdf" width="1000" height="600" type="application/pdf">
but I get local resource errors:
Firefox: "Security Error: Content at myWebServer/file_read.php may not load or link to file:///myFileServer/PDFs/filename.pdf."
Edge/Chrome: "Not allowed to load local resource: file:///myFileServer/PDFs/filename.pdf"
I understand the error is because the PDF path is loaded by the browser, not the web server. This likely would be a problem even if it was allowed, because not all of the users would have access to the file server. Naturally, my next thought was to try using PHP to display the element so that the browser never needs to see a file path and the web server loads the PDF.
PHP Solution Attempt
I then tried using
<?php
$filename = "file:///myFileServer/PDFs/filename.pdf";
header("Content-type: application/pdf");
header("Content-Length: " . filesize($filename));
readfile($filename);
?>
This gave me the following warning, which had to do with the PHP that is used to load the page's navigation bar.
"Cannot modify header information - headers already sent by (output started at C:\Apache24\htdocs\nav.php:66) in C:\Apache24\htdocs\file_read.php on line 81"
Removing <?php include 'nav.php' ?> in the file_read.php caused the PHP code mentioned above to work, but not as I wanted. It basically loads a full-page PDF view as if you selected a PDF to open it in the browser, instead of displaying it as a page element.
PHP PDF to Base64 Solution
Since the above did not work, I kept digging for a solution. It's a little hacky, but I did find one solution that seems to works.
<?php
$fileLocation = "//myFileServer/PDFs/filename.pdf";
$pdf = chunk_split(base64_encode(file_get_contents($fileLocation))); //Convert to Base64
echo '<embed src="data:application/pdf;base64,' . $pdf . '" style="height:500px;width:80%;" title="test"></embed>';
?>
While this does work and the code is rather clean, it's a bit slow and I feel like there has to be a more efficient way to do this.
My Question
Is there a better way to deal with the limitations of loading a local resource from another internal server than converting the PDF to Base64?
I came up with some weird stuff that I haven't seen before.
I used <source type="video/webm" src="test.php">
instead of <source type="video/webm" src="example.webm">
...Test.php file containing only this line of code:
header("Location: https://www.example.com/example.webm");
and it works..
Is this normal or maybe has some downside for the video/loading/flash(or browser support), is there actually any difference using test.php or example.webm directly? I am so confused because what I know... this is too good to be true, and too simple. Would appreciate any comment/pointer...
It is ok to use. The browser just looks for "https://www.example.com/example.webm" when accessing test.php, so the difference in load is very small. (as small as it takes your browser to be redirected).
How can I create a php code that will process an ID for example and return corresponding image without providing client with actual image hotlink.
As implemented on link below the image is displayed in html page, but the hot link is hidden from client. Even opening the image in new window same link is shown not the original link to image.
This is definitely not implemented in .htaccess file as for each image URL with id corresponding image is rendered and is not a redirect to a single page.
http://www.imagesup.net/?di=15140291437113
a basic way could be something like this
<?php
// query to database mabye?
$myPath = getImagePath($_GET['id']);
// what kind of image file is that?
$contentType = getContentType($myPath);
// read file content
$img = file_get_contents($myPath);
// here you tell the browser what kind of image is that e.g. jpeg,png,gif...
header("Content-Type: $contentType");
echo $img;
?>
you need to define getImagePath and getContentType functions according to your needs.
Whenever a surfer enters one of my websites, I always assign a session to him. The session holds a couple infos, for example: agent, IP, language, date, … etc., and gets passed along via cookie or via GET (as parameter to each one of my pages).
Since I deal with a lot of image content, I started databasing my collection. Which basically means that for administration and clustering purposes, I am saving all my images to a SQL database which is multi-homed and spread accross several servers. One could argue if that is a smart thing to do, but we can argue that on another day and in another article.
I wrote a little script which is used throughout my site:
<img src="http://example.com/display.php?id=34" border="0" alt="" />
With an ever changing ID of course. That’s the part referencing my images in the database.
The following is the code from the script which I use to retrieve the image from the database:
<?php
$connection=#mysql_connect(...);
#mysql_select_db(...);
$query="SELECT mime, file FROM images
WHERE id=".$_GET["id"];
$rawdb=#mysql_query ($query,$connection);
if($rawdb AND #mysql_num_rows($rawd-->0){
$array=# mysql_fetch_array($result);
if (!empty($array["fileContents"])){
// Output the MIME header
header("Content-Type: ".$array["mime"]}");
// Output the image
echo $array["file"];
}else{
// something else...
}
#mysql_free_result($rawdb);
}else{
// something else...
}
#mysql_close($connection);
?>
Since I already have a session for each user that comes to my website, I just added the following:
<img src="http://example.com/display.php?id=34&sid=383829" border="0" alt="" />
And implement a small session checkup in the script itself:
<!--
session_start();
if($_SESSION["is_known"]){
// do database calls
}else{
header("Location:http://mydomain.tld/dontsteal.html");
}
-->
The main advantage to my method is, that the session is entirely server side. A user can not rid himself off it, or fake information. Since I have a timeout and save all the necessary info (IP!) to validate against, it looks pretty perfect to me and fit my needs.
One of the setbacks here are resources and performance. But since I am not forcing you, you may test and evaluate. Hope that helps!
Create a php script which you use as src in the img tag.
In that script get the data from the image with file_get_contents. Then send the header with the right mime type. For example header('Content-type: image/jpeg'); Then output the data.
I have one problem. I would like to order from (zip) files play video in such a way to get out connection so you can include it in HTML5 badge. As I gave an example. But this not working.
<?php $video = fopen('zip://video.zip#video.mp4', 'r'); ?>
<video>
<source src='<? echo $video; ?>' type='video/mp4' />
</video>
$video in the above code is just a server-side file handle you could use to read the file from the zip. It's not directly usable for the browser.
You'll need to handle reading the file and returning it in a separate HTTP request. Usually you'd use a second script for this. (Or if your video is relatively small, you might be able to use data urls, but it's not something I'd try to do.) Additionally, if you want to allow for byte range requests, you'd have to handle that yourself in your video serving logic.
Here's a fairly simple scenario:
My videos.zip file contains a couple of different videos, and I want to retrieve a specific one and show it on a page called video.php
First I have my viewer, say video.php, [edit: containing the video tag and with a URL to my second script as the source. Since I might want to serve the other file at some point, I set it up to accept a filename in the v query parameter.]
..some html/php..
<video>
<source src='zipserve.php?v=itsrainintoast.mp4' type='video/mp4' />
</video>
..more html/php..
Then, in zipserve.php I have something like this:
$filename = $_GET['v']; //You probably want to check that this exists first, btw.
$fp = fopen('zip://videos.zip#'.$filename, 'r');
if($fp)
{
header('content-type: video/mp4');
//Note: you should probably also output an appropriate content-length header.
while(!feof($fp))
{
echo fread($fp, 8196);
}
fclose($fp);
}
else
{
echo 'Some error message here.';
}
--Addendum--
It should also be noted that this'll require the zip php extension to be enabled.
A more complete example of a video fetching script with range handling and the like can be found in the question at mp4 from PHP - Not playing in HTML5 Video tag but you'd need to tweak it to allow reading from the zip file.
So this is simple to understand what i want to achieve. So i get links like theese:
http://rockdizfile.com/atfmzkm7236t
http://rockdizfile.com/xuj5oincoqmy
http://rockdizfile.com/pg8wg9ej3pou
So theese links are from one cloud storage site I want to make a php script that automates their downloading.
So I can't find which is the script or the thing these links download button starts and how can I start that so i can download it with php on my server?
Basically my idea is to download a lot of files but don't wanna do it manually so need automatic way of doing it. As far as I know I make a request which is the following 2 urls:
http://rockdizfile.com/pg8wg9ej3pou
http://wi32.rockdizfile.com/d/wsli6rbhfp4r2ge4t7cqeeztijrprelfiw4afvqg5iwspmvqabpkmgiz/Desislava%20feat.%20Mandi%20&%20Ustata%20-%20Pusni%20go%20pak%20(CDRIP).mp3
So the first url is executing the next one but here comes the tricky part as far as I tested that last string Desislava%20feat.%20Mandi%20&%20Ustata%20-%20Pusni%20go%20pak%20(CDRIP).mp3 is the file name we get when downloading so if you change it with for example somefile.mp3 it will download somefile.mp3 but with the same file content as http://wi32.rockdizfile.com/d/wsli6rbhfp4r2ge4t7cqeeztijrprelfiw4afvqg5iwspmvqabpkmgiz/Desislava%20feat.%20Mandi%20&%20Ustata%20-%20Pusni%20go%20pak%20(CDRIP).mp3 so the data is hidden in this hash wsli6rbhfp4r2ge4t7cqeeztijrprelfiw4afvqg5iwspmvqabpkmgiz or i think so. And now is the tricky part how to get this hash? we have almost everything we have the code for the url atfmzkm7236t the hash wsli6rbhfp4r2ge4t7cqeeztijrprelfiw4afvqg5iwspmvqabpkmgiz and the filename Desislava%20feat.%20Mandi%20&%20Ustata%20-%20Pusni%20go%20pak%20(CDRIP).mp3 There must be a way to download from this site without clicking so please help me kinda a hack this :)
you can use PHP's header function to force a file to download
header('Content-disposition: attachment; filename=index.php');
readfile('Link');
You should know that this will not give you the ability to download PHP files from external websites.
You can only use this if you got the direct link to a file
It's impossibly to tell you without the source code
e.g. sha1("Test Message") gives you 35ee8386410d41d14b3f779fc95f4695f4851682 but sha256("Vote this up") gives you 65e03c456bcc3d71dde6b28d441f5a933f6f0eaf6222e578612f2982759378ed
totally different... unless you're hidden function add's "65e03c456bcc3d71dde6b28dxxxxxxxxxxxxxxxxxxxxxxxxxx" (where xxxxxxxxxxxxxxxxxxxxxxxxxx is a bunch of numbers I can't be arsed to work out) to each hash...
then sha1("Test Message") gives you 65e03c456bcc3d71dde6b28d441f5a933f6f0eaf6222e578612f2982759378ed
The file is embedded into the swf player.
alert(jwplayer('mp3player').config.file);
Something like:
<?PHP echo file_get_contents($_GET["url"]); ?>
<script>
document.location=jwplayer('mp3player').config.file;
</script>
Though I've actually just noticed they change 5 digits of the URL on each page request, and the script above uses 2 page requests. One to get the URL and HTML source and another to try and download the file, meaning the URL has changed before the second request has started.