suppress error using fread() - php

I wrote a script for screen pops from our soft phone that locates a directory listing for the caller but occasionally they get "Can't read input stream" and the rest of the script quits.
Does anyone have any suggestions on how to suppress error the error message and allow the rest of the script to run? Thanks!
$i=0;
$open = fopen("http://www.411.ca/whitepages/?n=".$_GET['phone'], "r");
$read = fread($open, 9024);
fclose($open);
eregi("'/(.*)';",$read,$got);
$tv = ereg_replace('[[:blank:]]',' ',$got[1]);
$url = "http://www.411.ca/".$tv;
while ($name=="unknown" && $i < 15) { ## try 15 times before giving up
$file = # fopen($fn=$url,"r") or die ("Can't read input stream");
$text = fread($file,16384);
if (preg_match('/"name">(.*?)<\/div>/is',$text,$found)) {
$name = $found[1];
}
if (preg_match('/"phone">(.*?)<\/div>/is',$text,$found)) {
$phone = $found[1];
}
if (preg_match('/"address">(.*?)<\/div>/is',$text,$found)) {
$address = $found[1];
}
fclose($file);
$i++;
}

You need to check your return values, specifically for fopen.
Something like this:
$file = fopen($fn=$url,"r");
if ($file === false) {
// Unable to open stream, handle error
}
Then you need to decide how to handle the error that occurs when fopen can't read from the URL you're giving it. I doubt you actually want to simply suppress the error and allow the script to continue without the data it needs to do something meaningful. You could pause briefly and attempt to re-open the file, or direct the user to a more friendly error page instead of dying with a bare "Cannot open file" message.

Related

DOMDocument::Load(); error read read of 8192 bytes failed with errno=13 Permission denied

I am at an internship right now and got this old 2012 code, I have tried my best to debug it but I can only get this error. I have already tried to increase my PHP limit in php.ini and that did nothing. it also isn't the XML file because I can print the entire thing to the website with no problem. it might be a problem with the file locking since this is the first time I have used it.
this is the PHP
<?PHP
// First Clear any status messages from CMS
// Find filepath
$dir = getcwd();
$pieces = explode("/", $dir);
$processname = $pieces[count($pieces) - 1];
$recmsgfilepath = "savedmsg.default.xml";
//saved for later use in $recmsgfilepath
//tmp/webpage/".$processname."/msgfromcms.xml
// Lock file
$newmsgfile = fopen($recmsgfilepath, "r+");
while(!flock($newmsgfile, LOCK_EX))
{
// Continue to try to lock file, webserver will eventually terminate PHP script
}
$newmsgdoc = new domDocument();
if((filesize($recmsgfilepath) > 0) && $newmsgdoc->load($recmsgfilepath))
{
// Clear rec message file
ftruncate($newmsgfile, 0);
}
flock($newmsgfile, LOCK_UN); // release the lock
fclose($newmsgfile);
// Check if any buttons pressed
if(isset($_POST['clearmessages']))
{
// Send message to delete all messages in web app
SendMessage("", "WEBVIEW", "4", "", "", "", "", "");
}
the xml
<SAVEDMESSAGES last_changed="16449122918046">
<TEXTMESSAGE TIMESTAMP="16449122918046" TIMESTAMP_MSG="1644912290" PRIO="0" ALARMID="-">
<TIME>09:04:50</TIME>
<DATE>2022-02-15</DATE>
<ADDRESS></ADDRESS>
<PRIO>0</PRIO>
<TIMEOUT>60</TIMEOUT>
<TEXT>TESTMESSAGE</TEXT>
<ALERTTYPE>0</ALERTTYPE>
<CALLBACK></CALLBACK>
<SENDERID></SENDERID>
<ALARMINITIATOR>0</ALARMINITIATOR>
<ACKDATA></ACKDATA>
<POSINFO1>0</POSINFO1>
<POSINFO2>0</POSINFO2>
<RFP0>0</RFP0>
<STATUS>ORIGINAL</STATUS>
<ORIGIN>CONFIG</ORIGIN>
<MESSAGEID>338599</MESSAGEID>
</TEXTMESSAGE>
</SAVEDMESSAGES>

PHP: Missing records when writing to file

My telecom vendor is sending me a report each time a message goes out. I have written a very simple PHP script that receive values via HTTP GET. Using fwrite I write the query parameter to a CSV file.The filename is report.csv with the current date as a prefix.
Here is the code :
<?php
error_reporting(E_ALL ^ E_NOTICE);
date_default_timezone_set('America/New_York');
//setting a the CSV File
$fileDate = date("m-d-Y") ;
$filename = $fileDate."_Report.csv";
$directory = "./csv_archive/";
//Creating handle
$handle = fopen($filename, "a");
//These are the main data field
$item1 = $_GET['item1'];
$item2 = $_GET['item2'];
$item3 = $_GET['item3'];
$mydate = date("Y-m-d H:i:s") ;
$pass = $_GET['pass'];
//testing the pass
if (isset($_GET['pass']) AND $_GET['pass'] == "password")
{
echo 'Login successful';
// just making sure the function could write to it
if (!$handle = fopen($directory.$filename, 'a')){
echo "Cannot open file ($filename)";
exit;
}
//writing the data I receive through query string
if (fwrite($handle, "$item1,$item2,$item3,$mydate \n") === FALSE) {
echo "Cannot write to file ($filename)";
exit;
}
fclose($handle);
}
else{
echo 'Login Failure please add the right pass to URL';
}
?>
The script does what I want, but the only problem is inconsistency, meaning that a good portion of the records are missing (about half the report). When I log to my account I can get the complete report.
I have no clue of what I need to do to fix this, please advice.
I have a couple of suggestions for this script.
To address Andrew Rhyne's suggestion, change your code that reads from each $GET variable to:
$item1 = (isset($_GET['item1']) && $_GET['item1']) ? $_GET['item1'] : 'empty';
This will tell you if all your fields are being populated.
I suspect you problem is something else. It sounds like you are getting a seperate request for each record that you want to save. Perhaps some of these requests are happening to close together and are messing up each other's ability to open and write to the file. To check if this is happening, you might try using the following code check if you opened the file correctly. (Note that your first use of 'fopen' in your script does nothing, because you are overwriting $handle with your second use of 'fopen', it is also opening the wrong file...)
if (!$handle = fopen($directory.$filename, 'a')){
$handle = fopen($directory.date("Y-m-d H:i:s:u").'_Record_Error.txt', 'a');
exit;
}
This will make sure that you don't ever lose data because of concurrent write attempts. If you find that this is indeed you issue, you can delay subsequent write attempts until the file is not busy.
$tries = 0;
while ($tries < 50 && !$handle = fopen($directory.$filename, 'a')){
sleep(.5);//wait half a second
$tries++;
}
if($handle){
flock($handle);//lock the file to prevent other requests from opening the file until you are done.
} else {
$handle = fopen($directory.date("Y-m-d H:i:s:u").'_Record_Error.txt', 'a');//the 'u' is for milliseconds
exit;
}
This will spend 25 seconds, trying to open the file once every half second and will still output your record to a unique file every time you are still unable to open the file to write to. You can then safely fwrite() and fclose() $handle as you were.

PHP not writing to file from one source

I have an issue I can't seem to find the solution for. I am trying to write to a flat text file. I have echoed all variables out on the screen, verified permissions for the user (www-data) and just for grins set everything in the whole folder to 777 - all to no avail. Worst part is I can call on the same function from another file and it writes. I can't see to find the common thread here.....
function ReplaceAreaInFile($AreaStart, $AreaEnd, $File, $ReplaceWith){
$FileContents = GetFileAsString($File);
$Section = GetAreaFromFile($AreaStart, $AreaEnd, $FileContents, TRUE);
if(isset($Section)){
$SectionTop = $AreaStart."\n";
$SectionTop .= $ReplaceWith;
$NewContents = str_replace($Section, $SectionTop, $FileContents);
if (!$Handle = fopen($File, 'w')) {
return "Cannot open file ($File)";
exit;
}/*
if(!flock($Handle, LOCK_EX | LOCK_NB)) {
echo 'Unable to obtain file lock';
exit(-1);
}*/
if (fwrite($Handle, $NewContents) === FALSE) {
return "Cannot write to file ($File)";
exit;
}else{
return $NewContents;
}
}else{
return "<p align=\"center\">There was an issue saving your settings. Please try again. If the issue persists contact your provider.</p>";
}
}
Try with...
$Handle = fopen($File, 'w');
if ($Handle === false) {
die("Cannot open file ($File)");
}
$written = fwrite($Handle, $NewContents);
if ($written === false) {
die("Invalid arguments - could not write to file ($File)");
}
if ((strlen($NewContents) > 0) && ($written < strlen($NewContents))) {
die("There was a problem writing to $File - $written chars written");
}
fclose($Handle);
echo "Wrote $written bytes to $File\n"; // or log to a file
return $NewContents;
and also check for any problems in the error log. There should be something, assuming you've enabled error logging.
You need to check for number of characters written since in PHP fwrite behaves like this:
After having problems with fwrite() returning 0 in cases where one
would fully expect a return value of false, I took a look at the
source code for php's fwrite() itself. The function will only return
false if you pass in invalid arguments. Any other error, just as a
broken pipe or closed connection, will result in a return value of
less than strlen($string), in most cases 0.
Also, note that you might be writing to a file, but to a different file that you're expecting to write. Absolute paths might help with tracking this.
The final solution I ended up using for this:
function ReplaceAreaInFile($AreaStart, $AreaEnd, $File, $ReplaceWith){
$FileContents = GetFileAsString($File);
$Section = GetAreaFromFile($AreaStart, $AreaEnd, $FileContents, TRUE);
if(isset($Section)){
$SectionTop = $AreaStart."\n";
$SectionTop .= $ReplaceWith;
$NewContents = str_replace($Section, $SectionTop, $FileContents);
return $NewContents;
}else{
return "<p align=\"center\">There was an issue saving your settings.</p>";
}
}
function WriteNewConfigToFile($File2WriteName, $ContentsForFile){
file_put_contents($File2WriteName, $ContentsForFile, LOCK_EX);
}
I did end up using absolute file paths and had to check the permissions on the files. I had to make sure the www-data user in Apache was able to write to the files and was also the user running the script.

PHP Readfile() number of bytes when user aborted

I'm using a PHP script to stream a live video (i.e. a file which never ends) from a remote source. The output is viewed in VLC, not a web browser. I need to keep a count of the number of bytes transferred. Here is my code:
<?php
ignore_user_abort(true);
$stream = $_GET['stream'];
if($stream == "vid1")
{
$count = readfile('http://127.0.0.1:8080/');
logThis($count);
}
function logThis($c)
{
$myFile = "bytecount.txt";
$handle = fopen($myFile,'a');
fwrite($handle,"Count: " . $c . "\n");
fclose($handle);
}
?>
However it appears that when the user presses the stop button, logThis() is never called, even though I've put in ignore_user_abort(true);
Any ideas on what I'm doing wrong?
Thanks
Update2: I've changed my code as I shoudn't be using ignore_user_abort(true) as that would continue to download the file forever even after the client has gone. I've changed my code to this:
<?php
$count = 0;
function bye()
{
//Create Dummy File with the filename of equal to count
}
register_shutdown_function('bye');
set_time_limit(0);
ignore_user_abort(false);
$stream = $_GET['stream'];
if($stream == "vid1")
{
$GLOBALS['count'] = readfile('http://127.0.0.1:8080/');
exit();
}
?>
My problem now is that when the script is aborted (i.e. user presses stop), readfile won't return a value (i.e. count remains at 0). Any ideas on how I can fix this?
Thanks
When a PHP script is running normally the NORMAL state, is active. If the remote client disconnects the ABORTED state flag is turned on. A remote client disconnect is usually caused by the user hitting his STOP button. If the PHP-imposed time limit (see set_time_limit()) is hit, the TIMEOUT state flag is turned on.
so setting the set_time_limit to 0 should help.
Ok folks I managed to fix this. The trick was to not use readfile() but read the video stream byte by byte. Ok it may not be 100% accurate, however a few bytes inaccuracy here or there is ok.
<?php
$count = 0;
function logCount()
{
//Write out dummy file with a filename equal to count
}
register_shutdown_function('logCount');
set_time_limit(0);
ignore_user_abort(false);
$stream = $_GET['stream'];
if($stream == "vid1")
{
$filename = 'http://127.0.0.1:8080/';
$f = fopen($filename, "rb");
while($chunk = fread($f, 1024)) {
echo $chunk;
flush();
if(!connection_aborted()) {
$GLOBALS['count'] += strlen($chunk);
}
else {
exit();
}
}
}
?>

PHP - failed write

I am stuck and in need of a hand. Hope someone can help?
Anyone have any idea why I am getting "failed write" in this code?
$write_file = "/usr/home/public_html/php/users_v2.sql";
$write_handle = fopen($write_file, "w") || die("Couln't open users_v2!");
if (is_writeable($write_file)) {
if ($write_handle === FALSE) echo 'Failed handle?!';
if (fwrite($write_handle, "Hi\n") === FALSE) echo "Failed write!\n";
}
fclose($write_handle);
Thanks in advance.
By using the OR operator when creating your file handle, you are returning a boolean value depending on the operation. So $write_handle will contain true or false, instead of the file resource. A better way to open a file for writing and test that it was successful would be this:
$write_handle = fopen($write_file, 'w');
if ($write_handle === false)
{
die('Could not open file ' . $write_file);
}
Additionally, you could use the file_put_contents() function which handles the fopen(), fwrite() and fclose() for you. I only recommend this if you are executing only one write to the same file, as it will be a lot of overhead, and unless you pass the FILE_APPEND flag, it will empty the file for every write.
I have seen it used everywhere but the problem is the || die("Couln't open users_v2!");
First I added:
error_reporting(E_ALL);
to see what php is reporting for errors.
$write_handle = fopen($write_file, "w") || die("Couln't open users_v2!");
fclose($write_handle);
Returns an invalid stream handle error and file handle of 1. Without it the returned file handle is "Resource id #x".
Changing the line to:
$write_handle = fopen($write_file, "w"); // || die("Couln't open users_v2!");
and your code works fine. Gonna go post this on php.net now.

Categories