PHP overwriting file issues - php

I have a problem while overwriting a file. I tried everthing but SOMETIMES (maybe for a matter of time) nothings seems to work as it should. Here's the code:
include_once "changevar.php";
changevar("O",$seguimedia,$filename,0);
changevar("o",$offerta,$filename,0);
$seguimedia, $filename and $offerta are correctly set.
changevar.php:
function changevar($varname,$newval,$filename,$type)
{
while(!$fp=fopen($filename,"c+"))
{
usleep(100000);
}
while(!flock($fp,LOCK_EX))
{
usleep(100000);
}
while(!include($filename))
{
usleep(100000);
}
ftruncate($fp,0);
rewind($fp);
$$varname=$newval;
if($type==0)
{
foreach(array("u","p","t","d") as $v){$$v=str_replace("\\","\\\\",$$v);}
$text="<?\$o=$o;\$u=\"$u\";\$c=$c;\$m=$m;\$p=\"$p\";\$C=$C;\$id=\"$id\";\$t=\"$t\";\$d=\"$d\";\$O=$O;?>";
}
else
{
$text="<?\$impressions=$impressions;\$clickunici=$clickunici;\$clicknulli=$clicknulli;\$creditiguadagnati=$creditiguadagnati;\$creditiacquistati=$creditiacquistati;\$creditiutilizzati=$creditiutilizzati;?>";
}
fwrite($fp,$text);
flock($fp,LOCK_UN);
fclose($fp);
}
In this case the function changevar() has to change two variables ($o and $O) in the file $filename but often it fails and nothing changes. How can I fix this?

Make sure you have write permissions and correct user set to change the file content. You can do that with chown and chmod in linux systems. Not sure if its an issue on windows boxes.
see http://php.net/manual/en/function.chmod.php and http://www.php.net/manual/en/function.chown.php

Related

Using phpseclib to check if file already exists

I'm trying to create a script that will send across files from one server to another. My script successfully does that as well as checks if the file has something in it or not. My next step is to check whether the file already exists on the server; if the file already exists it does not send and if it does not exist, it does send.
I've tried a few different things and can't seem to get my head around it. How can I get it to check whether the file already exists or not? Any help would be appreciated!
(I had a look at some similar questions but couldn't find anything specific to my issue.)
require('constants.php');
$files = $sftp->nlist('out/');
foreach($files as $file) {
if(basename((string) $file)) {
if(strpos($file,".") > 1) { //Checks if file
$filesize = $sftp->size('out/'.$file); //gets filesize
if($filesize > 1){
if (file_exists('import/'.$file)){
echo $file.' already exists';
}
else {
$sftp->get('out/'.$file, 'import/'.$file); //Sends file over
//$sftp->delete('out/'.$file); //Deletes file from out folder
}
else {
echo $file. ' is empty.</br>';
}
}
}
}
}
EDIT: To try and get this to work, I wrote the following if statement to see if it was finding the file test.php;
if (file_exists('test.txt')){
echo 'True';
} else {
echo 'False';
}
This returned true (a good start) but as soon as I put this into my code, I just get a 500 Internal Server Error (extremely unhelpful). I cannot turn on errors as it is on a server that multiple people use.
I also tried changing the file_exists line to;
if (file_exists('test.txt'))
in the hopes that would work but still didn't work.
Just to clarify, I'm sending the files from the remote server to my local server.
There is a closing curly brace missing right before the second else keyword.
Please try to use a code editor with proper syntax highlighting and code formatting to spot such mistakes on the fly while you are still editing the PHP file.
The corrected and formatted code:
require('constants.php');
$files = $sftp->nlist('out/');
foreach ($files as $file) {
if (basename((string)$file)) {
if (strpos($file, ".") > 1) { //Checks if file
$filesize = $sftp->size('out/' . $file); //gets filesize
if ($filesize > 1) {
if (file_exists('import/' . $file)) {
echo $file . ' already exists';
} else {
$sftp->get('out/' . $file, 'import/' . $file); //Sends file over
}
} else {
echo $file . ' is empty.</br>';
}
}
}
}
Your code checks the file exist in your local server not in remote server.
if (file_exists('import/'.$file)){
echo $file.' already exists';
}
You need to check in remote server using sftp object like
if($sftp->file_exists('import/'.$file)){
echo $file.' already exists';
}
Edit:
Add clearstatcache() before checking file_exists() function as the results of the function get cached.
Refer: file_exists

Why in Windows might attempting to delete a file twice work?

I've been pulling my hair out trying to write a continuous integration script with PHP for the Windows machine I develop on.
Having cloned a Git repository, I was unable to make a script that deleted it all. (The .git folder and everything in them). I was getting "Permission denied" errors.
It seemed intermittent. I tried Phing, but that failed but lead me to this Phing ticket, so I'm not alone - but that solution using attrib didn't work for me.
I finally realised that it was just taking two attempts to delete some folders and/or files within it. So my PHP code that finally worked, was this:
<?php
function delTree($dir, $ignore = array()) {
// no need to continue if $dir doesn't exist
if (!file_exists($dir))
return true;
// must not continue if it's a link. trigger an error.
if (is_link($dir)) {
trigger_error("Cannot delete $dir: it's a link.", E_ERROR);
return false;
}
// if it's a file, delete it and return.
if (is_file($dir)) {
return tryUnlink($dir, 2);
}
// it's a directory. so...
// build an array of files/directories within it to delete
$files = array_diff(
scandir($dir), array('.', '..'), $ignore
);
// delete each directory within $dir
foreach ($files as $file) {
delTree("$dir/$file", $ignore);
}
// delete $dir itself
return tryRmdir($dir, 2);
}
function tryUnlink($file, $attempts = 2){
$result = unlink($file);
if (!$result) {
if ($attempts > 1){
return tryUnlink($file, $attempts--);
} else {
trigger_error("Cannot delete file $file", E_ERROR);
return false;
}
}
return true;
}
function tryRmdir($dir, $attempts = 2){
$result = rmdir($dir);
if (!$result) {
if ($attempts > 1){
return tryRmdir($dir, $attempts--);
} else {
trigger_error("Cannot delete directory $dir", E_ERROR);
return false;
}
}
return true;
}
And calling them with the $attempts argument set to 2 solved everything (12 hours later).
I'd tried things like chmoding the file to 0666, closing the IDE, closing SourceTree, any open explorer windows, wearing a tin foil hat, and even calling exec() with commands like:
rm -r .git -Force
rmdir .git /s /q
and probably 10 others that are buried somewhere in my repo now.
What might the cause have been?
Both you functions tryUnlink() and tryRmdir() will cause an infinite loop (unless it's actually deleted). Look at the following snippet + output.
code:
<?php
function foo ($attempts = 2) {
echo "attempts = $attempts\n";
if ($attempts > 1) {
foo ($attempts--);
} else {
echo "returning with \$attempts <= 1\n";
}
}
foo(2);
output:
attempts = 2
attempts = 2
attempts = 2
[...many many many dupes...]
attempts = 2
attempts = 2
attempts = 2
Segmentation fault (core dumped)
Given that it's not said that deletion kicks in on the second run.
As of Windows 7 (or perhaps Vista?) it is rare, but not abnormal, for the first attempt to remove a directory tree to fail. I think this due to a race condition due to the deletions being processed asynchronously by the file system.
As you've already discovered, you can work around this by retrying the operation; personally, I've never seen it fail twice in a row, though I usually allow it to retry three or four times to be on the safe side.

PHP unlink fails to unlink zip-file - still returns true

UPDATE: The embarrassing reason why it "didn't work" just was based on the fact that i was looking at the wrong directory.
I need to unlink/delete all files inside a folder. To achieve this, I have modified a method I've found here on SO:
public function deleteDirContent($dirPath)
{
if (!is_dir($dirPath))
{
throw new InvalidArgumentException("$dirPath must be a directory");
}
if (substr($dirPath, strlen($dirPath) - 1, 1) != '/')
{
$dirPath .= '/';
}
$files = glob($dirPath . '*', GLOB_MARK);
foreach ($files as $file)
{
if (is_dir($file))
{
$this->deleteDirContent($file);
}
else
{
print_r($file);
if(unlink($file))
{
echo " - SUCCESS";
}
else
{
echo " - ERROR !";
}
echo PHP_EOL;
}
}
}
The method works fine for all files, except for *.zip files, as it seems. And what's even more strange about it: unlink() still returns true without deleting the file.
Maybe the problem is related to my PHP version and/or the fact that it's running on a Windows Server.
Relevant specs:
PHP Version: 5.3.1
XAMPP Version: xampp-win32-1.7.3
OS: Windows 2008 Server
Any help would be appreciated.
Try changing the permissions with chmod:
// Read and write for owner, nothing for everybody else
chmod("/somedir/somefile", 0600);
The embarrassing reason why it "didn't work" just was based on the fact that i was looking at the wrong directory.

PHP - Function to read and write a TXT file

I'm making a function on WordPress to get the content of the robots.txt file. If the file doesn't exist, create it with default content. I will use it for my options page. Well, this is my code, it should work almost creating the file, but it doesn't:
function get_robots($robots_file) {
$robots_file = get_home_path() . 'robots.txt'; //The robots file.
$dir = get_home_path(); //The root directory
if(is_file($robots_file)){
$handle = fopen($robots_file, "r");
$robots_content = fread($handle, filesize($robots_file));
fclose($handle);
} else {
$default_content = "User-agent: *\nDisallow:";
chmod($dir, 0777);
$handle = fopen($robots_file, "w+");
$robots_content = fwrite($handle, $default_content);
fclose($handle);
}
chmod($dir, 0744);
return $robots_content;
}
I'm not sure if the problem is is_file, or the fopen($robots_file, "w+" (should it be "r"?) after the else. And I'm not sure about the permissions. Is the 777 needed? Is the 744 the default for the root directory of WordPress?
And I use the return to use it as variable later; I suppose the fopen is already creating the file. Am I right?
Thanks in advance.
The first thing, I would use completely different functions, you have file_put_contents() and file_get_contents() for such simple operations.
So possible simpler solution is:
function get_robots() {
$robots_file = get_home_path() . 'robots.txt'; //The robots file.
if(file_exists($robots_file)){
return file_get_contents($robots_file);
} else {
$default_content = "User-agent: *\nDisallow:";
file_put_contents($robots_file, $default_content);
return $default_content;
}
}
I don't see any point to pass $robots_file as function argument so I removed it. You should check if this code simple works.
I also don't see any reason to change $dir permissions as you showed in your code. It should be rather set manually and you definitely shouldn't change your root directory permission in such function.
EDIT
Because this function uses get_home_path() and this one is available probably only on admin panel you have to do it in different way. You may add the following code to the end of your index.php file:
function get_robots($path)
{
$robots_file = $path . DIRECTORY_SEPARATOR . 'robots.txt'; //The robots file.
if(file_exists($robots_file)){
return file_get_contents($robots_file);
} else {
$default_content = "User-agent: *\nDisallow:";
file_put_contents($robots_file, $default_content);
return $default_content;
}
}
get_robots(getcwd());
(Of course if you want, you may move get_robots() function to some other files.
However you should consider if this is the best approach. You will run this function each time your site will be viewed and it's tiny waste (in fact you will probably want to create robots.txt file just once). You could for example create robots.php file and if you want to run it you can run http://yourwordpressurl/robots.php. It's of course your call.

php file is writable but cannot be deleted

I am using this function. is_file and is_writable return true, but when I true to unlink, it gives an error. This is on windows server.
if(is_file($fileToDelete)) {
if(is_writable($fileToDelete)) {
unlink($fileToDelete);
}
}
The file is a PDF document, which I have open. I thought is_writable would return false in this case, but it doesn't.
So how can I tell if a file can be deleted or not?
Thank you
What about doing it the other way around? Just try to delete the file and check whether it is really gone?
#unlink($fileToDelete);
if(is_file($fileToDelete)) {
// file was locked (or permissions error)
}
Not sure whether this is workable in your specific case though, but judging by the code in your question this should be what you want.
Are you using the file? I mean, did you open it by doing fopen($file)?
Do a fclose($file) before trying to delete the file.
For them who don't want to delete the file before the check, the solution is here :
$file = "test.pdf";
if (!is_file($file)) {
print "File doesn't exist.";
} else {
$fh = #fopen($file, "r+");
if ($fh) {
print "File is not opened and seems able to be deleted.";
fclose($fh);
} else {
print "File seems to be opened somewhere and can't be deleted.";
}
}
Simple, and efficient.

Categories