I have the following code in a PHP page. Some times when I delete the cache2.html file, I expect the php to recreate it and the next person will get the cache2.html instead of executing the php code. I get the following warning some times on the page and no content. Is it because of multiple users accessing the php concurrently? If so, How do I fix it? Thank you.
Warning: include(dir1/cache2.html) [function.include]: failed to
open stream: No such file or directory in
/home/content/54/site/index.php on line 8
<?php
if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler"); else ob_start();
$cachefile = "dir1/cache2.html";
if (file_exists($cachefile)) {
include($cachefile); // output the contents of the cache file
} else {
/* HTML (BUILT USING PHP/MYSQL) */
$cachefile = "dir1/cache2.html";
$fp = fopen($cachefile, 'w');
fwrite($fp, ob_get_contents());
fclose($fp);
ob_flush(); // Send the output to the browser
}
?>
Calls to file_exists() are themselves cached, so it's likely you're getting a return value of true even after the file is deleted. See:
http://us.php.net/manual/en/function.clearstatcache.php
So, you could do:
clearstatcache();
if (file_exists($cache)) {
include($cache);
} else {
// generate page
}
Alternatively, you could do something like this:
if (file_exists($cache) && #include($cache)) {
exit;
} else {
// generate page
}
Or better, if you're deleting the cache file from within a PHP process, then just call clearstatcache() after you delete the file.
Related
I am trying to make a file manager with php , so when I open it in browser it would give a list of the current directory and the file would be clickable using the anchor tag in html (which I have done so far) , and when the file is clicked , it would open it in the text mode and shows whatever the source code inside the file is.
I am facing two problems which I couldn't figure out
Problem #1:
The first problem is that I want my file manager to read any source code weather its an image or pdf , just like the tinyfilemanager that I found here this master piece can read any file, even if you open an image with a notepad and insert some php code at the very end of the file it will read render that too, so here's my source code:
<?php
function list_all_files($directory){
//opening the dir
if($handle=opendir($directory.'/')){
echo "looking inside '$directory'"."<br>";
}
while($file=readdir($handle)){
//listing all the directories without ".." (dots)
if($file!='.'&&$file!='..') {
echo ''.$file.'<br>';
} //if ends here
} //while loop endds here
} //list_all_files ends here
function read_file($file)
{
$handle = fopen($file, "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
echo($line);
}
fclose($handle);
} else {
echo "error opening the file";
}
}
//main function
if(!isset($_GET['dir'])) {
$dir='images';
}else{
$dir=$_GET['dir'];
}
list_all_files($dir);
if(isset($_GET['read'])){
$file1 = $_GET['read'];
read_file($file1);
}
?>
the above program I made can also read files code but when I click on any PHP file that contains an html code, it just displays it rather than giving its source code in text mode, image below:
and not only this, if I put some php code at the very end of the image file using a notepad it wouldn't display it. check this:
I did a lot of research on why my code isn't working while the tinyFilemanager is perfect with any of the above mention cases , and I found that the whenever I execute the page file via browser it by default uses this
header("Content-Type: text/html");
so If I wanted to do what I wanted , then I would have to use this:
header("Content-Type: text/x-php");
which covers both of the above cases, but leads to the 2nd problem.
Problem #2:
<?php
function list_all_files($directory){
//opening the dir
if($handle=opendir($directory.'/')){
echo "looking inside '$directory'"."<br>";
}
while($file=readdir($handle)){
//listing all the directories without ".." (dots)
if($file!='.'&&$file!='..') {
echo ''.$file.'<br>';
} //if ends here
} //while loop endds here
} //list_all_files ends here
function read_file($file)
{
$handle = fopen($file, "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
echo($line);
}
fclose($handle);
} else {
echo "error opening the file";
}
}
//main function
if(!isset($_GET['dir'])) {
$dir=getcwd();
}else{
$dir=$_GET['dir'];
}
//listing all the directories and files in text/html format so that our anchor tag would be available.
ob_start();
header('Content-Type: text/html; charset=UTF-8');
list_all_files($dir);
ob_end_flush();
if(isset($_GET['read'])){
//changing the header to text/php-x so that the php code in any jpg file can be viewed clearly
ob_clean();
header('Content-Type: text/x-php; charset=UTF-8');
ob_start();
$file1 = $_GET['read'];
read_file($file1);
ob_end_flush();
}
?>
The above codes works perfectly fine, but there is this one problem. since its content-type is not text/html anymore, it wouldn't display the html content on the web page. which is good but bad at the same time because then I wouldn't get the list of directory in the anchor tag form, because I thought ob_start and ob_end_flush(). if I use these two, it would just solve the problem by creating a buffer for each of the function separately and executes it. so when it executes it the above function would be render with the content-type text/html and would show the directory listing with anchor tag, and the 2nd would just be in text/x-php which would solve the above two cases, but I was soooooo wrong.
With the grace and help of God , and suggestion from kikoSoftware in the Comments , the Problem is solved, there's a function name show_source(); ,which takes two arguement , the 2nd argument however is optional , hence we don't need to do filing or send a content-type response with the header() function , we can just use that function , source codes are below.
<?php
function list_all_files($directory){
//opening the dir
if($handle=opendir($directory.'/')){
echo "looking inside '$directory'"."<br>";
}
while($file=readdir($handle)){
//listing all the directories without ".." (dots)
if($file!='.'&&$file!='..') {
echo ''.$file.'<br>';
} //if ends here
} //while loop endds here
} //list_all_files ends here
function read_file($file)
{
$handle = fopen($file, "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
echo($line);
}
fclose($handle);
} else {
echo "error opening the file";
}
}
//main function
if(!isset($_GET['dir'])) {
$dir=getcwd();
}else{
$dir=$_GET['dir'];
}
//listing all the directories and files in text/html format so that our anchor tag would be available.
list_all_files($dir);
if(isset($_GET['read'])){
//changing the header to text/php-x so that the php code in any jpg file can be viewed clearly
$file1 = $_GET['read'];
show_source($file1);
}
?>
appreciate ya guys for helping out ♥
I am trying to create a cache file from a menu that takes random data called 'includes/menu.php' the random data is created when I run that file manually, it works. Now I want to cache this data into a file for a certain amount of time and then recache it. I am running into 2 problems, from my code cache is created, but it caches the full php page, it does not cache the result, only the code without executing it. What am I doing wrong ? Here is what I have until now :
<?php
$cache_file = 'cachemenu/content.cache';
if(file_exists($cache_file)) {
if(time() - filemtime($cache_file) > 86400) {
// too old , re-fetch
$cache = file_get_contents('includes/menu.php');
file_put_contents($cache_file, $cache);
} else {
// cache is still fresh
}
} else {
// no cache, create one
$cache = file_get_contents('includes/menu.php');
file_put_contents($cache_file, $cache);
}
?>
This line
file_get_contents('includes/menu.php');
will just read the php file, without executing it. Use this code instead (which will execute the php file and save the result into a variable):
ob_start();
include 'includes/menu.php';
$buffer = ob_get_clean();
And then, just save the retrieved content ($buffer) into file
file_put_contents($cache_file, $buffer);
file_get_contents() gets the contents of a file, it doesn't execute it in any way. include() will execute the PHP, but you have to use an output buffer to grab its output.
ob_start();
include('includes/menu.php');
$cache = ob_get_flush();
file_put_contents($cache_file, $cache);
Nowdays there are a lot of websites for files hosting (uploading websites) and it count for example point per complete download of certain file.
My question
I want to understand what is the idea they are using !
How does it only count on complete downloading of the file ?!
i mean if i canceled downloading of the file after it started , it won't count point!
how does it knew ! is there any php function that able to know if i canceled downloading certain exact file or not !
that question was all time in my mind and thinking about it but i can't understand how does it works or what is the idea behind it. ~ thanks
This can be done by using my other answer as base How can I give download access to files outside public_html directory? and replacing readfile( $filename )
with readfileWhileConnected( $filename ):
Read file until EOF or disconnect:
/** Read $filename until EOF or disconnect,
* if disconnect then error_log() count of bytes read already
*/
function readfileWhileConnected( $filename ) {
// Save and set ini values:
$user_abort = ignore_user_abort();
ignore_user_abort(false);
// Get file size and set bytes_sent to zero:
$fsize = filesize($filename);
$bytes_sent = 0;
// Open file:
$f = fopen($filename, 'r');
// Read file:
while($chunk = fread($f, 1024)) {
// Check if connection is still open:
if(!connection_aborted()) {
// Send $chunk to buffer (if any), then flush() buffers:
echo $chunk;
flush();
// Add $chunk length to $bytes_sent
$bytes_sent += strlen($chunk);
} else {
// Close file:
fclose($f);
error_log("Connection closed at $bytes_sent/$fsize");
exit();
}
// Close file:
fclose($f);
// Reset ini values:
ignore_user_abort($user_abort);
return $bytes_sent;
}
}
After you have your new shiny class myNewSuperDownloadHandlerClass { ... } ready, then make sure you only serve downloads through filedownload.php described here or if have done good myNewSuperDownloadHandlerClass(), then use that, just make sure that readfileWhileConnected() is used for every download requiring connection status polling.
You can easily add callback to be triggered if user closes connection, only 2 exit points here. (seen many functions that have every often return false; return true; return null; return false; return true; and so on..)
i have read a bit around in the internet about the php cache.
at the moment i am using, this system to cache my pages:
This is putted on the start of the page
<?php
// Settings
$cachedir = 'cache/'; // Directory to cache files in (keep outside web root)
$cachetime = 600; // Seconds to cache files for
$cacheext = 'html'; // Extension to give cached files (usually cache, htm, txt)
// Ignore List
$ignore_list = array(
'addedbytes.com/rss.php',
'addedbytes.com/search/'
);
// Script
$page = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // Requested page
$cachefile = $cachedir . md5($page) . '.' . $cacheext; // Cache file to either load or create
$ignore_page = false;
for ($i = 0; $i < count($ignore_list); $i++) {
$ignore_page = (strpos($page, $ignore_list[$i]) !== false) ? true : $ignore_page;
}
$cachefile_created = ((#file_exists($cachefile)) and ($ignore_page === false)) ? #filemtime($cachefile) : 0;
#clearstatcache();
// Show file from cache if still valid
if (time() - $cachetime < $cachefile_created) {
//ob_start('ob_gzhandler');
#readfile($cachefile);
//ob_end_flush();
exit();
}
// If we're still here, we need to generate a cache file
ob_start();
?>
MY HTML CODE Goes here .............
and the code below is at the footer of my page.
<?php
// Now the script has run, generate a new cache file
$fp = #fopen($cachefile, 'w');
// save the contents of output buffer to the file
#fwrite($fp, ob_get_contents());
#fclose($fp);
ob_end_flush();
?>
There are some things that i need and this code dont have them :
gzip
the expired cache is not autodeleted after it expire.
Also wanted to ask, if this code is secure to use , if some one can suggest a better one or something to improve the current code it will be just great
Thank you fro reading this post.
Best Regards
Meo
….
// Show file from cache if still valid
if (time() - $cachetime < $cachefile_created) {
//ob_start('ob_gzhandler');
echo gzuncompress(file_get_contents($cachefile));
//ob_end_flush();
exit();
} else {
if(file_exists($cachefile) && is_writable($cachefile)) unlink($cachefile)
}
….
and
// Now the script has run, generate a new cache file
$fp = #fopen($cachefile, 'w');
// save the contents of output buffer to the file
#fwrite($fp, gzcompress(ob_get_contents(), 9));
#fclose($fp);
ob_end_flush();
?>
Use ob_start("ob_gzhandler"); to initiate gzipped buffering (it'll take care of determining if the client can actually accept/wants gzipped data and adjust things accordingly).
To delete the cached files:
if (time() - $cachetime < $cachefile_created) {
#readfile($cachefile);
//ob_end_flush();
exit();
} else {
unlink($cachefile);
exit();
}
But there can be delay or maybe error when the file is being written and someone requests for that page. You should use flock to overcome such problems as mentioned at Error during file write in simple PHP caching
Something like this at the end of page
<?php
$fp = #fopen($cachefile, 'w');
if (flock($fp, LOCK_EX | LOCK_NB)) {
fwrite($fp, gzcompress(ob_get_contents(), 9));
flock($fp, LOCK_UN);
fclose($fp);
}
ob_end_flush(); ?>
hi when i execute this code nothing happen in browser but when i delete lines with star,the contents printed correctly,whats wrong??
/////////////////
$documentroot=$_SERVER['DOCUMENT_ROOT'];
$handle=fopen("$documentroot/order/order.txt",'r+');
if(!$handle) {
echo 'error opening file';
}
$content="pepsi\ncola\npeperoni";
$write=fwrite($handle,$content); //*
if(!$write){ //*
echo 'error writing'; //*
} //*
while(!feof($handle)) {
$string=fgets($handle);
echo $string;
}
this line should be like this.
$handle=fopen("$documentroot/order/order.txt",'w');
file should be open in the write mode.try this.
Thanks.
/* This is the opening tag on PHP and it needs to be closed with another */ but the * in front this time. You can stick with // for just one line of commenting.
You are opening the file in r+ mode which means read+write mode. But if the file orders.txt does not exist, it'll not be created. So ensure file exists.
Also when there is problem with opening the file, you immediately exit.
if(!$handle) {
echo 'error opening file';
exit; // MISSING
}
Assuming the file already exists, it's contents will be wiped after the fopen. Next the fwrite will write the contents. Now the file pointer is at the end of the file so your call to feof() in the while loop will return true and the while is never entered.
To fix this you rewind the file pointer before you start reading from the file:
rewind($handle); // ADD THIS
while(!feof($handle)) {
...
}
$documentroot=$_SERVER['DOCUMENT_ROOT'];
$handle=fopen("$documentroot/order/order.txt",'r+');
if(!$handle) {
echo 'error opening file';
}
$content="pepsi\ncola\npeperoni";
$write=fwrite($handle,$content);
if(!$write){
echo 'error writing';
}
fseek($handle, 0);
while(!feof($handle)) {
$string=fgets($handle);
echo $string;
}
After file write operation, your file pointer sets to the end of written data which needs to set to the start position for fgets. fseek does that.
fseek($handle, 0);
This will take your pointer to the beginning so that fgets now can read from file. fgets function needs valid file pointer to read which in this case is the start position.