I have a slightly unusual problem here. I have a php server that is reachable from the internet. This server hosts a small control panel that allows me to do a few things, but I mostly use it to turn on my PC remotely. This system is password-protected, and I have it this way because wake-on-lan commands do not have any form of authentication.
I have an IP camera that is not accessible from the internet, but it is reachable from the local network via HTTP. It serves a webpage, and several ways to view the camera stream. One of them is a "video.mp4" file that shows the camera stream. I want to make this accessible from my server, by embedding the video.mp4 file in a php page. There are two problems with this, however:
I've tried include()-ing the remote file, but this gave an error message:
PHP Warning: include(http://...@192.168.2.7/video.mp4): failed to open stream: no suitable wrapper could be found in /var/www/html/camera.php
PHP Warning: include(): Failed opening 'http://...@192.168.2.7/video.mp4' for inclusion (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/html/camera.php
This probably means that I can't just copy an mp4 stream into a php file. I didn't really expect it to work to be honest, it was more to see if the error message would give me a hint on how to do this properly.
I thought about opening a port to the camera, but since its web interface does not support SSL I consider that too insecure.
To allow inclusion of remote files, the directive allow_url_include
must be set to On in php.ini
But it is bad, in a security-oriented point of view ; and, so, it is generally disabled (I've never seen it enabled, actually)
It is not the same as allow_url_fopen
, which deals with opening (and not including) remote files -- and this one is generally enabled, because it makes fetching of data through HTTP much easier (easier than using curl)
Basic example of reading a mp4 file
<?php
// replace 'file.mp4' to your file in the line bellow
$path = 'file.mp4';
$size=filesize($path);
$fm=@fopen($path,'rb');
if(!$fm) {
// You can also redirect here
header ("HTTP/1.0 404 Not Found");
die();
}
$begin=0;
$end=$size;
if(isset($_SERVER['HTTP_RANGE'])) {
if(preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches)) {
$begin=intval($matches[0]);
if(!empty($matches[1])) {
$end=intval($matches[1]);
}
}
}
if($begin>0||$end<$size)
header('HTTP/1.0 206 Partial Content');
else
header('HTTP/1.0 200 OK');
header("Content-Type: video/mp4");
header('Accept-Ranges: bytes');
header('Content-Length:'.($end-$begin));
header("Content-Disposition: inline;");
header("Content-Range: bytes $begin-$end/$size");
header("Content-Transfer-Encoding: binary
");
header('Connection: close');
$cur=$begin;
fseek($fm,$begin,0);
while(!feof($fm)&&$cur<$end&&(connection_status()==0))
{ print fread($fm,min(1024*16,$end-$cur));
$cur+=1024*16;
usleep(1000);
}
die();
You can also use
readfile('http://example.com/file.mp4');
readfile() reads a file (even remotely over http) and immediately outputs it's contents.