php unlink problems - file exists - php

I am having trouble with unlink in php... The files in the directory are uploaded with php form.
ls -l of /files/uploads/
total 6976
-rw-r--r-- 1 alex admin 689030 15 Aug 11:40 01805_goneclubbing_1680x1050.jpg
-rwxrwxrwx 1 alex admin 174932 15 Aug 11:52 4vvF60D.tmp.jpg
-rw-r--r-- 1 alex admin 2699554 15 Aug 12:16 example.JPG
php script (cakePHP framework):
$file_path = '/files/uploads/';
$file_name = $file['Upload']['path'];
$classroom_id = $file['Upload']['classroom_id'];
if (unlink($file_path . $file_name)) {
if ($this->Upload->delete($id)) {
$this->setFlash('File deleted');
$this->redirect(array('controller' => 'classrooms', 'action' => 'view', $classroom_id));
}
}
php error:
Warning (2): unlink(/files/uploads/example.JPG) [function.unlink]: No such file or directory [APP/controllers/uploads_controller.php, line 55]
I searched on stackoverflow, tried giving 777 permissions and still not working. I can access the image through the browser at that path.
Thanks for the help!

On any UNIX system, / is your system root. So when you try to access /files, you try to access a folder files located at your system root. I think you want to access /path_to_www/files, so either use a variable which stores your base path or use a relative path.
On the other hand, when you try to access /files from your web browser, it reaches the / of your web directory (or an alias path). So it is totally normal that you can access your image from your browser but not from php.

The error tells you what the problem is - the file $file_path . $file_name doesn't exist. Echo it out - does it equal what you think it should?
You are referencing the storage location cannonically ('relative' to the root directory /) - did you mean to? Is there actually a directory called /files on your box? If there is I would be surprised...
You should make it if (is_file($file_path . $file_name) && unlink($file_path . $file_name)) in case the file has gone missing because of an external cause to get rid of the ugly error message, and probably also do $file_name = ltrim($file['Upload']['path'],'/'); to get rid of any stray leading slashes...

You have an opening slash in your file path which is telling the application to look at root, not from your current location. You should change your path to include a .,so that it is
./files/uploads/example.JPG.

Try echoing getcwd() to make sure you're in the directory you think you are.

ls -l of /files/uploads/You did this with your user account/shell, didn't you?
Maybe the process running php "sees" the file system differently than your user account does (e.g. a chroot environment or something like that).
<?php
$file_path = '/files/uploads/';
$file_name = $file['Upload']['path'];
$classroom_id = $file['Upload']['classroom_id'];
// <-- debug
echo '<pre>files in ', $file_path, ":\n";
foreach( glob($file_path.'*') as $f) {
echo "'", $f, "'\n";
}
echo "----\n</pre>\n";
// debug -->
if (unlink($file_path . $file_name)) {
if ($this->Upload->delete($id)) {
$this->setFlash('File deleted');
$this->redirect(array('controller' => 'classrooms', 'action' => 'view', $classroom_id));
}
}

Related

File does not exist though the path seems right

I can't figure out why file_exists() don't find my file though the path seem right.
Here is my script :
if($_POST['delete-avatar'] == 'on') {
$q = execute_query("SELECT avatar FROM gj_customers WHERE id_customer = '$_GET[id]'");
$customer = $q->fetch_assoc();
$img_path = $_SERVER['DOCUMENT_ROOT'] . WEBSITE_ROOT . $customer['avatar'];
var_dump($img_path);
if(!empty($customer['avatar']) && file_exists($img_path)){
unlink($img_path);
}
}
I'm on MAMP, my website is in htdocs/gamejutsu/www/ , WEBSITE_ROOT contains '/gamejutsu/www/' and avatars are in img/avatars/ .
var_dump on $img_path returns me : /Applications/MAMP/htdocs/gamejutsu/www/img/avatars/Sonik_avatar.jpg.
If I go on localhost:8888/gamejutsu/www/img/avatars/Sonik_avatar.jpg the image is displayed.
I never enter in the if bloc. If I remove the file_exists test I have a warning : unlink(/Applications/MAMP/htdocs/gamejutsu/www/img/avatars/Sonik_avatar.jpg): No such file or directory in /Applications/MAMP/htdocs/gamejutsu/www/admin/members.php on line 67
I'm pretty sure i'm missing something but everything seems ok for me and I use the same method somewhere else on my website without any problem.
Thank you for your help.
It is complicated debug your application without access but you can try what return realpath();
var_dump(realpath($img_path))
If returns null file doesn't exists or your application haven't acces to it.
Try open your console and this command:
cd /Applications/MAMP/htdocs/gamejutsu/www/img/avatars/
If you have error you have bad path and must manualy check it (easiest will be by console) if you can cd in this directory. Please add here your ls of this directory for check permissions:
ls -la /Applications/MAMP/htdocs/gamejutsu/www/img/avatars/
And if everything look good try change your console user to webserver user (usually www-data) and try acces to file
sudo su
su www-data
cat /Applications/MAMP/htdocs/gamejutsu/www/img/avatars/Sonik_avatar.jpg
If you can acces to this file (it will be binary data) permissions are ok, in other case check if you have right permission to file and if you good owner and group of file.
Try just use website root and do not use $_SERVER['DOCUMENT_ROOT'].
Another way is by identifying the path.
if($_POST['delete-avatar'] == 'on') {
$q = execute_query("SELECT avatar FROM gj_customers WHERE id_customer = '$_GET[id]'");
$customer = $q->fetch_assoc();
$img_path =' filename' . WEBSITE_ROOT . $customer['avatar'];
var_dump($img_path);
if(!empty($customer['avatar']) && file_exists($img_path)) {
unlink($img_path);
}
}

Writint to a .txt file with php in unix enviroment where file need root permisions

okay now this is utterly bewildering to me and I can't figure out why this script is not working basically I am attempting to write a line of data to a .txt file in php
here is the part of the script which matters:
set_include_path('/etc/apache2/rewrite/');
if($_GET['type']=="14"){ //video is documentary
$file = '/etc/apache2/rewrite/Documentaries.txt';
$line= clean_url($content[0]['title']) . " " . $content[0]['content_id'] ."\n";
file_put_contents($file, $line, FILE_APPEND);
echo "inseted into documentaries <br>" . $line;
}else if ($_GET['type']=="17"){//video is a talk
$file = '/etc/apache2/rewrite/Talks.txt';
$line= clean_url($content[0]['title']) . " " . $content[0]['content_id'] ."\n";
file_put_contents($file, $line, FILE_APPEND);
echo "inseted into talks";
}else if($_GET['type']=="15"){//video is debate
$file = '/etc/apache2/rewrite/Debates.txt';
$line= clean_url($content[0]['title']) . " " . $content[0]['content_id'] ."\n";
file_put_contents($file, $line, FILE_APPEND);
echo "inseted into debates";
}
and note that after this block i echo the $line which is something like this
inside-nature-s-giants-the-leatherback-turtle 13443
and also the echo's inside the if statement are also echoe'd however nothing is modified in any of the files for a reason I can't seem to figure out I have given the script both write and execute permission and still can't seem to get this to work .. I am unsure what is going on As I use similar logic in other scripts without problem any help would be greatly greatly appreciated as I've sworn at my terminal a little to much for my liking
Thanks,
Brendan
*Update * I do not have the correct file permisions thanks to #SyntaxLAMP for reminding me to check error logs
okay here is the permision for the php file
-rwxrwxrwx 1 root root 9202 Jan 25 07:48 update_untagged.php
and the permisions of the three files I am attempting to write to
-rw-r--r-- 1 root root 7 Jan 25 05:05 Debates.txt
-rw-r--r-- 1 root root 110691 Jan 25 07:16 Documentaries.txt
-rw-r--r-- 1 root root 45747 Jan 25 05:05 Talks.txt
they both have the same permisions so I dont understand why this still isn't working any help with this would be greatly appreciated stil
You need to give the user the script is running as access to those files. You can either give everyone access to them like this:
chmod 666 Debates.txt Documentaries.txt Talks.txt
Or set the owner to whatever the script runs as (possibly www-data):
chown www-data Debates.txt Documentaries.txt Talks.txt
Edit:
Just to be clear, don't give everyone access unless there's a valid reason to do so, it's a lot safer just to change the owner to whatever the script runs as.

Forcing file-creation in public directory?

Here's an idea. I'm trying to create file from PHP script. File may be created in any public place on server (in public root or in its subdirectories). Bottom of line, I want to write function like this (it must work on both unix and windows servers).
function create_file($path, $filename, $content, $overwrite=false) {
# body
...
}
Parameters:
$path - file-path (empty or ends with /)
$filename - any valid file-name (requires dot+extension)
$content - file-content (anything)
$overwrite - if set true, existing file will be overwritten (default. false).
Result:
Function returns TRUE and creates file with content, or FALSE if file-creation was not possible for any reason.
Description of problem:
I expect this function to return true and create file $filename on path $path, or false if it wasn't possible for any reason. Also if file was successfully opened for writing, need to put $content in it.
Argument $path is relative path to public directory, and $filename is any valid filename. Of course, I want to avoid creating files if path points outside of public directory. Function may be called from subdirectory-scripts like this example
# php script: /scripts/test.php
create_file('../data/', 'test.info', 'some contents');
# result file: /data/test.info
What have I tried so far?
I’ve tried doing this with fopen() and fwrite() functions and that works on some servers, and doesn’t work on some. I guess there’s problem with writing privileges and chmod() but to be honest I’m not very familiar with chmod attributes. Also I couldn't check if $path points outside of server's public directory.
In short, I want this function to create file and return TRUE if file doesn't exist, or file exists and $owerwrite=true. Otherwise, nothing happens and function returns FALSE.
Additionally, I would like to know reason why file can't be created on some path (just in theory). Incorrect path/filename is only thing I have on my mind and I'm sure there's more about this problem.
Thanks in advance for any sample/example/suggestion.
update code
So far I have this code...
function create_file($path, $filename, $content, $overwrite=false) {
$reldir = explode('/', trim(str_replace('\\', '/', dirname($_SERVER['PHP_SELF'])), '/'));
$dirdepth = sizeof($reldir);
$rpadd = $dirdepth > 0 ? '(\.\./){0,' . $dirdepth . '}' : '';
$ptpath = '#^/?' . $rpadd . '([a-z0-9]\w*/)*$#i';
$ptname = '/^[a-z]\w*\.[a-z0-9]+$/i';
if ($res = preg_match($ptpath, $path) && preg_match($ptname, $filename)) {
$res = false;
if ($overwrite === true || !file_exists($path.$filename)) {
if ($f = #fopen($path.$filename, 'w')) {
fwrite($f, $content);
fclose($f);
$res = true;
}
}
}
return $res;
}
Some suggestions:
set the owner of the web server document root: chown -R apache:apache /var/www (i suppose /var/www is your document root and that the web server apache runs with user apache). Set the privilegies of the document root like this in order to have all directories under document look with privilegies 755 (only owner which is user apache can write in folders /var/www and sub folders)
Block paths that point out of your /var/www document root: you are under the issue known as http://en.wikipedia.org/wiki/Directory_traversal_attack. What about if the $path is something like: /var/www/../../../etc/passwd?
Basename php function can help you identifying this kind of malignous paths. Look this post: php directory traversal issue
To check wheter a file already exists or not: http://php.net/manual/en/function.file-exists.php
All file functions in php will not work properly in two circumstances
If you don't have enough user privileges for applications, then
You may not used/passed the arguements/parameters correctly .

php unlink file renovated

I want to delete with php (unlink function) file which is out of webroot. my web root is in
C:\server\webroot\project\... in webroot I have folder named project and in there I have .php files.
whats about files directory. it is situated C:\server\mp3_files...
Also I've created in httpd.conf Alias("mp3") of mp3_files directory
I am writing this script in C:\server\webroot\project\test.php
script is like so =>
function delete($filename){
if (unlink("/mp3/" . $filename)){
echo "Deleted";
} else {
echo "No";
}
}
delete("file.txt");
this script gives me in php-errors => PHP-WARNING No such file or directory
also I have in (test.php) html form this =>
Download
And this works (It opens this file.txt)
So I'm wondered why can't delete with marked function "delete($filename)" ?
"/mp3/" . $filename is an absolute filepath, not relative to the webserver root, so it's assuming that you have an mp3 directory under your filesystem root when you should be looking under /server/mp3
EDIT
And is it /server/mp3 or /server/mp3_files
your post seems to contradict your code
File function in PHP go from the file system root.
You should write:
function delete($filename){
if (unlink("C:\\server\\mp3_files\\" . $filename)){
echo "Deleted";
} else {
echo "No";
}
}
delete("file.txt");
To make sure the internal PHP file path cache gets the correct information, reset with it with clearstatcache() before and after the unlink. Normally the path cache is reseted after every PHP function which is related to file manipulation. Reseting the cache is required if you remove files with shell_exec('rm file.txt') or similar.
See http://php.net/manual/ini.core.php#ini.realpath-cache-size and http://php.net/manual/ini.core.php#ini.realpath-cache-ttl

rmdir() bug with particular filename? Permission denied

First, let's get these out of the way:
There are no open handles on the directory.
There are no files in the directory.
chmod ing the permissions to 0777 does not prevent the error.
the directory name is correct.
Now then, here's my problem. rmdir() is throwing this error when trying to delete the directory:
rmdir(098f6bcd4621d373cade4e832627b4f6) [function.rmdir]: Permission denied in path\to\administrate.php on line 124
098f6bcd4621d373cade4e832627b4f6 is the name of the directory.
Here is the relevant portion of the script.
if(is_dir($userhash)) :
foreach (new DirectoryIterator($userhash) as $fileInfo) {
$fileName = $fileInfo->getFilename();
if($fileInfo->isDot()) continue;
if(!rename($userhash.'/'.$fileName , 'trashcan/'.$username.'/'.$fileName)) {
echo '<p class="error">Could not move '.$fileName.'</p>';
$err = 1;
}
}
else :
echo '<p class="error">Unable to delete files! error: 67</p>';
$err = 1;
endif;
//JUST TO BE SURE
chmod('./',0777);
chmod($userhash,0777);
// RMDIR ONCE THE DIR IS EMPTY.
if(rmdir($userhash))
echo '<p class="success">Deleted the user directory. The files are in the trash.</p>';
else {
echo '<p class="error">Could not remove the user directory. Error: 656</p>';
$err = 1;
}
Update
I manually created the dir 'jake' in the same directory. I did rmdir('jake'); and it worked great. Now, I manually created a dir '098f6bcd4621d373cade4e832627b4f6' in the same directory. I did rmdir('098f6bcd4621d373cade4e832627b4f6'); and it errored!
Update 2
This is beginning to look like some weird rmdir() bug, as unlikely as that seems. Here are directory names I've created and then tried to remove with rmdir;
098f6bcd4621d373cade4e832627b4f6 | didn't work (quintuple checked)
098f6bcd4621d373cade4e832627b4f7 | worked
098f6bcd4621d373cade4e832627b4f | worked
098f6bcd4621d373cade4e832627b4f66 | worked
In order to be able remove file:
user should have write permissions to PARENT directory
restricted deletion flag should NOT be set for PARENT directory
UPDATE:
About restricted deletion flag - from man chmod:
RESTRICTED DELETION FLAG OR STICKY BIT
The restricted deletion flag or sticky
bit is a single bit, whose
interpretation depends on the file
type. For directories, it prevents
unprivi‐leged users from removing
or renaming a file in the directory
unless they own the file or the
directory; this is called the
restricted deletion flag for the
directory, and is commonly found on
world-writable directories like /tmp.
For regular files on some older
systems, the bit saves the program's
text image on the swap device so it
will load more quickly when run; this
is called the sticky bit.
You may SET it by adding 1 to the first octal digit in mode, for example:
chmod 1xxx dirname
UPDATE 2:
Does user, under which php is executed, has permissions to chmod parent directory?
In other words, are you sure that first chmod call returns true?
chmod('./',0777);

Categories