I have a IP Camera and I would like to show liveview at my webpage.
IP Camera don't allow for anonymous log in so I need to put username and password while connecting.
I have javascript:
<img src="http://user:password#camera_ip_address/cgi-bin/jpg/image.cgi?" width="640" height="480" name="refresh">
<script language="JavaScript" type="text/javascript">
image = "http://camera_ip_address/cgi-bin/jpg/image.cgi?"
function Start() {
tmp = new Date();
tmp = "?"+tmp.getTime()
document.images["refresh"].src = image+tmp
setTimeout("Start()", 100)
}
Start();
</SCRIPT>
And it works ok in firefox but:
http://user:password#camera_ip_number
don't work in other browsers (it popup a form to enter username and password).
But in PHP you can use user:password I've check it by using:
<?php
header('Content-type: image/jpeg');
print( file_get_contents( 'http://user:password#camera_ip_address/cgi-bin/jpg/image.cgi?' ));
?>
of course it shows only one frame but you don't have to enter username and password.
How can I log in into IP Camera using PHP ? If I could log in one time while enetering webpage, my javascript will work ok because browser will remember username and password until I close the browser.
I don't know how to send username and password to log in.
Sorry for my English.
Ok, so I've made it work using PHP and JavaScript. Maybe it will be helpful for someone else:
Save the PHP file as, for example, snapshot.php:
<?php
$img="http://user:password#camera_ip/cgi-bin/jpg/image.cgi?";
header ('content-type: image/jpeg');
readfile($img);
?>
In the HTML file, add this script:
<img src="http://domain.com/snapshot.php" width="640" height="380" name="refresh">
<script language="JavaScript" type="text/javascript">
image = "http://domain.com/snapshot.php"
function Start() {
tmp = new Date();
tmp = "?"+tmp.getTime()
document.images["refresh"].src = image+tmp
setTimeout("Start()", 300)
}
Start();
</script>
It works ok under every browser. If I set timeout to less then 300, there is some lag. I don't know why that would be caused by; maybe internet connection or website speed.
You may be able to use Apache mod_rewrite instead - Less overhead from the PHP stack, and probably generally faster. See this page for more information.
Choose one of these.
Apache .htaccess - Your page requests http://yoursite/livecam/image.jpg, which is run through Apache's proxy to your camera.
RewriteEngine on
RewriteBase /livecam/
RewriteRule ^image.jpg$ http://user:password#camera_ip_address/cgi-bin/jpg/image.cgi [P]
ProxyPassReverse /livecam/image.jpg http://user:password#camera_ip_address/cgi-bin/jpg/image.cgi
In PHP, create a file called image.php - Your page requests http://yoursite/image.php, which streams the image to whatever requests it.
<?php
$file = 'http://user:password#camera_ip_address/cgi-bin/jpg/image.cgi';
if (file_exists($file)) {
header('Content-Type: image/jpeg');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
?>
Both will proxy the image through your server. It's generally bad practice to give the username and password on any public page, even if an attacker can't damage anything of concern.
See readfile() on PHP.net
Your code would look like (replace image.php with livecam/image.jpg if using the Apache version). I also shortened your code a bit.
<img src="http://yourserver/image.php" width="640" height="480" name="refresh">
<script language="JavaScript" type="text/javascript">setTimeout(function() {document.images["refresh"].src = "http://yourserver/image.php?"+math.random();}, 100);</SCRIPT>
IP:port/cgi-bin/jpg/image.cgi?&user=XXX&pwd=XXX
IP:port/cgi-bin/jpg/image.cgi?&usr=XXX&pwd=XXX
IP:port/snapshot.cgi?&user=XXX&pwd=XXX';
IP:port/cgi-bin/CGIProxy.fcgi?cmd=snapPicture2&usr=XXX&pwd=XXX';
Related
I would like to refresh my static web page running on apache when the index changes. I've already tried to use server-side events, where I had a PHP file checking if the index changed and if yes, it sent the event to the webpage. This works exactly how I want, but there is a problem. Because the page is used by a lot of people sometimes (tens or up to a hundred opened tabs), it quickly starts to spam many apache processes. Then, it reaches the limit, and the apache freezes.
The question is how to handle this. If a user closes the tab, the process is killed, however, if not, the apache freezes.
The PHP script looks like this (it is checking two things, first, if the file chenged, or second if the status is something. As I said, this works fine, the problem is its lagging the server):
<?php
session_start();
session_write_close();
ignore_user_abort(false);
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$filename = "index.html";
while(True){
if ( connection_aborted() ){
exit();
}else{
try{
$string = file_get_contents("current_status.json");
$json = json_decode($string, true);
$pom1 = $json["state"];
$t1 = shell_exec("date -r index.html");
sleep(3);
$pom2 = $json["state"];
if($t1 != shell_exec("date -r index.html")) {
sleep(2);
echo "data: file changed \n\n";
} else if($pom2=="ready") {
sleep(2);
echo "data: new shot available \n\n";
} else {
echo "heartbeat";
}
ob_flush();
flush();
}
catch (\Error $e){
echo "data: error, json not available \n\n";
}
}
}
ob_end_flush()
?>
Then, there is a classical javascript function in the index file with event source on the PHP file.
My question is, how can I do this to not make apache crashing? Can I somehow set up SSE to handle it? I know I can allow more processes on apache, but my resources are limited.
Is there any other way how to do this? For example, live.js works as well, but the problem is the sam, a lot of processes when opened multiple times.
Yes, I can see how this would put far more strain on your server than necessary.
What you should do is poll for changes from javascript. You send an asynchronous request for the last time the index file changed from your javascript. You do it once when the page loads and store the time. Then you check again on an interval and compare the result with the first one. If it changed you refresh the page.
The PHP script should get the last change date, output it and exit - no continuously running PHP scripts.
Here is what the PHP file should look like:
<?php
header('Content-type: text/plain');
echo filemtime('index.html');
?>
Keep this minimal. The built in filemtime function is more efficient than running shell_exec commands.
Here is an example javascript:
chk_index_change_time(false);
function chk_index_change_time(last){
fetch('http://yourdomain.com/yourpath/get_index_change_time.php')
.then(res => res.text())
.then((index_change_time) => {
if ((false !== last) && (last != index_change_time)){
location.reload();
} else {
setTimeout(chk_index_change_time, 3000, index_change_time);
}
});
}
Feel free to error handling or whatever, but this will work. I used a timeout here instead of interval so that if the server is slow the server response time doesn't come out of the 3 second delay.
I know there are many different posts concerning this, but none of the posts seemed to help.
I have tried inputting
include_path=".:/path/to/dir"
along with
safe_mode_exec_dir=".:/path/to/dir"
into php.ini. I have tried turning safe_mode on, turning allow_url_fopen to On and then putting ftp:// in front of the path, and without the ftp://. I have tried using multiple different ways of opening it including...
$folder = $_GET['dir'];
$path = $folder;
$file = fopen($path, 'r');
$lines = array();
while(!feof($file)){
$lines[] = fgets($file);
}
fclose($file);
and
$lines = explode("\n", file_get_contents('doc.txt'));
I have tried setting permissions to 777 under /var/www/html and permissions on the other directory which is under /home/pi/
Nothing seems to be working.
So. I am completely out of ideas. Please help before my head banging becomes dangerous.
Here is my code for what I am trying to do...
<?php
header('Content-Type: text/xml');
echo '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
echo '<response>';
$folder = $_GET['dir'];
$path = $folder."/myfile.txt";
$file = fopen($path, 'r');
$lines = array();
while(!feof($file)){
$lines[] = fgets($file);
}
fclose($file);
for($x = 0; $x < sizeof($lines); $x++){
echo $lines[$x];
}
echo '</response>';
?>
xmlHttp = createXmlHttpObject();
xmlHttp.open("GET", "getClientData.php?folder="+dir, false);
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && (xmlHttp.status == 200 || xmlHttp.status == 206)) {
xmlResponse = xmlHttp.responseXML;
xmlDocumentElement = xmlResponse.documentElement;
var message = xmlDocumentElement.firstChild.textContent;
}
};
xmlHttp.send();
I am running this on a Raspberry Pi 3 Model B, Rasbian Jessie, if that has anything to do with it. And Apache2.
It's interesting to note that when I change the php file a little bit to have an if/else statement like "if(file_exists($path)){}else{echo "null"}", if I call alert() in javascript from the input, I DO get "null". That's why my first assumption was a file permission thing or php.ini setting.
So I have solved it. And I will give a detailed description as to how I solved it.
First of all, do make sure that allow_url_fopen to be On and to have safe_mode off. Look through both the Apache2 php.ini and the regular php.ini as there is two of them and I believe both have to be set in order for it to work. If you installed php with apache2 on your platform, both php.ini files should be under "/etc/php5". There will be a folder called "apache2" and "cli". Each one has a file.
Secondly, Chrome Web Development Tools are amazing. Press F12 with Chrome open and go to the "Networks" tab. There will be a checkbox that says "Disable Cache" at the top of the tab. This makes sure that Chrome won't cache the results of your changes to your website. KEEP THIS WINDOW OPEN BECAUSE IF YOU CLOSE IT, IT WON'T DISABLE THE CACHE ANYMORE!!! You can also download a Chrome extention like "cache killer" which will disable cached results just the same. Also, with CWDT, the Console Tab is a debugging miracle. I have been programming the site on Aptana, which is not very good at all at noticing small semi colon or bracket errors. Utilize this tool! It will save your life as it did mine!!
Please ask questions or comments if I didn't explain something in detail.
This question already has answers here:
How do I execute some javascript after a file is downloaded?
(3 answers)
Closed 6 years ago.
Say I have the following pages:
index.php
<html>
<form action="/make_file" method="get">
<select name="client" style="width: 80%;">
<?php foreach($clients as $client): ?>
<option value="<?=$client;?>"><?=$client;?></option>
<?php endforeach; ?>
</select>
<input type="submit" value="Download Client Info">
</form>
</html>
make_file.php
<?php
$client = $_GET['client'];
//check that client is valid and grab client information from the database
$tmpfname = tempnam(sys_get_temp_dir(), $clientName);
$handle = fopen($tmpfname, "w");
//create a txt file containing information about the client
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($tmpfname).'.txt"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($tmpfname));
readfile($tmpfname);
unlink($tmpfname);
!!! //now here is where I'd like to create a custom message
?>
So in simple terms, I would like a user to be able to choose a client on index.php, then the make_file.php page will create and serve a text file with information about the client. But ideally, after that I would like to send a crafted alert message (via jquery/ajax..) to the user on index.php. The alert message will depend on the client and their information so it cannot be static.
I have tried several methods, but I'm having a problem with the fact that once you set the content-disposition header the whole output is put into the file (which is the expected behaviour) so I don't really know how to send this alert?
Adapting the suggesion in this answer, we can set a cookie using setrawcookie() and rawurlencode() 1 right before calling readfile().
$message = 'hey there you picked client: '.$client.' tmpfilename: '.$tmpfname;
setrawcookie('message', rawurlencode($message), 2147483647, "/");
Then in the client-side page (i.e. index.php) we can add JavaScript (could utilize jQuery functions if you really wanted to but the code below is vanilla JS). It uses Event Delegation to add an event listener (with document.forms[0].addEventListener()) to the submission event on the form, setInterval() to create a function that runs periodically.
In that interval function, it checks for a cookie being set utilizing document.cookie. If a message is found in the cookies, then it decodes the message with decodeURIComponent(), sends that message to the alert() and clears the interval using clearInterval().
<!-- form HTML-->
</form>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded',function(DOMReadyEvent) {
document.forms[0].addEventListener('submit',startMessageCheck);
});
var messageCheck;
function startMessageCheck(formSubmitEvent) {
messageCheck = window.setInterval(function() {
var message = getCookie('message');
if (message) {
var decodedMessage = decodeURIComponent(message);
alert('message: '+decodedMessage);
deleteCookie('message');
window.clearInterval(messageCheck);
}
},1000);
}
function getCookie( name ) {
var parts = document.cookie.split(name + "=");
if (parts.length == 2) {
return parts.pop().split(";").shift();
}
}
function deleteCookie( cName ) {
document.cookie = cName + "=; Path=/; Expires=" + new Date( 0 ).toUTCString();
}
</script>
A demonstration of this can be seen on this page.
1 Initially I used setcookie() but was having issues with the default string encoding in the client-side.
I tried to output a simple ping command on a web page in a similar way( and same time) as it is displaying in terminal, using shell_exec; But it is displaying only after the complete execution, while I needed it to display whenever it is displaying on terminal, My code is
<?php
$i= shell_exec("ping -c 4 google.com");
echo "<pre> $i <pre>";
?>
It is waiting for a while and the dumping the whole thing on a single shot.. can PHP recognize the outputting of each line and display it on the web page
EDIT I tried this also
<?php
$proc = popen("ping -c 4 google.com", 'r');
echo '<pre>';
while (!feof($proc)) {
echo fread($proc, 4096);
}
echo '</pre>';
?>
But still I gets the same result..
EDIT When I tried to execute this PHP code in terminal , ( php test.php) it is working properly in the same way it gives when we directly do ping on server. but in web page it is still the same.
Uhm, strange behavior from the web browser. I'm using this code:
<?php
ob_end_flush();
ini_set("output_buffering", "0");
ob_implicit_flush(true);
function pingtest()
{
$proc = popen("ping -c 5 google.com", 'r');
while (!feof($proc))
{
echo "[".date("i:s")."] ".fread($proc, 4096);
}
}
?>
<!DOCTYPE html>
<html>
<body>
<pre>
Immediate output:
<?php
pingtest();
?>
</pre>
</body>
</html>
In the browser the content appears after all bytes has been received.
But, the content is actually delivered on time, do this test:
wget -O - -q "http://localhost/ping.php"
You will see that the response is delivered by php & apache2 on time.
I'm using this kind of execution on long task for a while, but using a more complex solution:
an html file for interface
a php file that run the long task
Connect html interface with php long execution using EventSource object (available on html5)
interface (test.html)
<!DOCTYPE html>
<html>
<head>
<title>Simple EventSource example</title>
</head>
<body>
<script type="text/javascript">
function eventsourcetest() {
var ta = document.getElementById('output');
var source = new EventSource('test.php');
source.addEventListener('message', function(e) {
if (e.data !== '') {
ta.value += e.data + '\n';
}
}, false);
source.addEventListener('error', function(e) {
source.close();
}, false);
}
</script>
<p>Output:<br/><textarea id="output" style="width: 80%; height: 25em;"></textarea></p>
<p><button type="button" onclick="eventsourcetest();">ping google.com</button>
</html>
Server Side Component (test.php)
<?php
ob_end_flush();
ini_set("output_buffering", "0");
ob_implicit_flush(true);
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
function echoEvent($datatext) {
echo "data: ".implode("\ndata: ", explode("\n", $datatext))."\n\n";
}
echoEvent("Start!");
$proc = popen("ping -c 5 google.com", 'r');
while (!feof($proc)) {
echoEvent(fread($proc, 4096));
}
echoEvent("Finish!");
Put both files in one place on a webserver and enter test.html, I think this is what you are looking for from the beginning.
Use output buffering and flush. You might also want to look into the Symfony 2 process component.
Its not a PHP matter, or rather its a shared matter between php and the browser.
In PHP: Make sure output buffering is off, you can do this by running ob_end_clean() before outputting anything.
As this SO post suggests you have to either pad the very first string outputted to 512 bytes OR specify a charset encoding via http header. The padding solution may very well be the easiest way around this, its basically this: echo(str_pad("Live Ping Test!",512)); and then start echoing the result of your fread.
You might want to try using flush() to flush the output as and when its ready, and use passthru() to execute the command.
Carlos C Soto is right, you have to use javascript. EventSource is the way to go. Basically, it's javascript code that will constantly call a url
You can write the output of ping in a file, and write a php script that will read the last line, then call this script with eventsource.
Search "Server Sent Events" on the web to find more examples
if can resolve using apache execution user. if your root user is diffrent and server user different then it will not allow to execute command line command.
I tested Carlos's answer on my side...
and I HAD to add flush();ob_flush(); for it to work properly (both needed flush AND ob_flush)
like this
<?php
$proc = popen("ping -c 5 google.com", 'r');
while (!feof($proc))
{
echo "[".date("i:s")."] ".fread($proc, 4096).'<br>';flush();ob_flush();
}
?>
I have two urls - biothoughtblog.co and playfight.co. The first is forwarding to the second and masking is used. I am using this
<?php
function curPageURL() {
$pageURL = 'http';
if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
$pageURL .= "://";
if ($_SERVER["SERVER_PORT"] != "80") {
$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
} else {
$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
return $pageURL;
}
?>
<?php
echo curPageURL();
?>
on the page http://www.biothoughtblog.co/test.php - however, it echoes the real URL which is http://www.playfight.co/test.php. I need it to echo the URL that is in the address bar. I know very very little Javascript - is it what I need to be using here?
Thanks a lot.
P.S Oh, and the purpose is to run the same website under two different domains and different branding (logo, etc).
That's because http://www.biothoughtblog.co/test.php is framing http://www.playfight.co/test.php.
<frame src="http://www.playfight.co/test.php" frameborder="0" />
PHP has no way of knowing that it is loaded inside a frameset, and how to get the URL of the parent frame.
You want to avoid using the "masking" feature of your registrar or DNS provider. Point the biothoughtblog.co domain to the same hosting server, ensure that your hosting account is setup for both domains. Then biothoughtblog.co wil be hitting your website directly, and PHP will know what it is.
You don't need to do anything in PHP to run the same website under two different domains.
If you are using apache, open your conf file, locate your virtual host config and add a serverAlias.
Example:
<VirtualHost *:80>
DocumentRoot "/var/www/html"
ServerName biothoughtblog.co
ServerAlias playfight.co
<Directory "/var/www/html">
AllowOverride All
</Directory>
</VirtualHost>