Unlink sometimes fails - needs improvements - php

I use this custom, simple script I made, somehow it's failing but it always returns true.
This class unlink the files that are placed in an array which goes through them then increments the counter on success of a file that was deleted, this is my script:
<?php
class Delete
{
function deleteFiles($array)
{
if(is_array($array))
{
$filecount = count($array);
$count = 0;
foreach($array as $file)
{
if(file_exists($file))
{
$remove = unlink($file);
if($remove)
{
$count++;
}
}
else
{
return false;
}
}
if($count == $filecount)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
}
?>
Basically I need improvements on how to make it foolproof so that the images in the array are completely deleted not returning true once an unlink has deleted the file when it hasn't, so I have no idea why it's not actually deleting the files properly.
Sometimes it works perfectly.

change if($remove) to if($remove && !file_exists($file))
Also, be aware that sometimes an unlink will fail on Windows: http://ie.php.net/manual/en/function.unlink.php#100580

you could add a call to is_file() after the unlink to check if the file is still there

Related

SugarCRM v6.5 anything after $bean->save stops working

I have this code:
function saveField($field, $id, $module, $value)
{
$bean = BeanFactory::getBean($module, $id);
if (is_object($bean) && $bean->id != "") {
if ($bean->field_defs[$field]['type'] == "multienum") {
$bean->$field = encodeMultienumValue($value);
}else if ($bean->field_defs[$field]['type'] == "relate" || $bean->field_defs[$field]['type'] == 'parent'){
$save_field = $bean->field_defs[$field]['id_name'];
$bean->$save_field = $value;
if ($bean->field_defs[$field]['type'] == 'parent') {
$bean->parent_type = $_REQUEST['parent_type'];
$bean->fill_in_additional_parent_fields(); // get up to date parent info as need it to display name
}
}else{
$bean->$field = $value;
}
//return here will work
$bean->save(); //this works
//nothing works here
return getDisplayValue($bean, $field);
} else {
return false;
}
}
The problem here is that anything under
$bean->save()
will not work. But I know that save is working as the values are being updated. So how can I debug this problem?
I already tried:
return var_dump($bean->save());
return print_r($bean->save());
if($bean->save()){
return "1";
}else{
return "2";
}
And none of those in the above worked I still get nothing in my return.
There is likely something such as an after_save logic hook that is executing and either causing a fatal error or doing an exit.
Try using xdebug, it should allow you to investigate further into the save method that fails.

php function return blank value on return statement and print right on echo

i create this function for search resume file from directory, if resume is available then function return full path, problem is function return nothing if i use "return", if i use "echo" then it will print right path
function search_resume($resume,$dir="uploads/resumes")
{
$root = scandir($dir);
foreach($root as $value)
{
/* echo $value."<br/>"; */
if($value === '.' || $value === '..') {continue;}
if(is_file("$dir/$value"))
{
if($value==$resume)
{
$path="$dir/$value";
return $path;
}
}
else
{
search_resume($resume,"$dir/$value");
}
}
}
A very typical, basic problem with recursive functions: you need to return recursive calls as well, they're not going to return themselves.
...
else {
$path = search_resume($resume,"$dir/$value");
if ($path) {
return $path;
}
}

PHP deleting wrong directory

I am working on a prototype of an online storage with PHP and I got this problem. I call the delete_file() function from the client, the function checks if the item to be deleted is a file or a directory and deletes it accordingly. If the item is a directory then it will call another function that will delete all its' contents and the directory itself.
function delete_file (){
global $directory;
$rec_data = trim($_POST['selected']);
$selected_items = explode(";", $rec_data);
if (count($selected_items) < 1){
echo "0";
}
else {
foreach ($selected_items as $item){
if (is_dir("{$directory}/{$item}")){
recursiveRemoveDirectory("{$directory}/{$item}");
}
else {
unlink("{$directory}/{$item}");
}
}
echo "1";
}
}
function recursiveRemoveDirectory($rm_directory){
foreach(scandir($rm_directory) as $file){
if($file != "." && $file != ".."){
if(is_dir($file)) {
recursiveRemoveDirectory($file);
}
else {
unlink($file);
}
}
}
rmdir($rm_directory);
}
Problem: It works but, this also deletes the parent directory .e.g data > username > dir, if I want to delete dir, it will also delete username. I've tried with various other methods with no success.
function recursiveRemoveDirectory($rm_directory){
foreach(scandir($rm_directory) as $file){
if($file != "." && $file != ".."){
if(is_dir($file)) { <--- error starts here!
recursiveRemoveDirectory($file);
}
else {
unlink($file); <--- error ends here!
}
}
}
rmdir($rm_directory);
}
Replace the marked lines with
if(is_dir("$rm_directory/$file")) {
recursiveRemoveDirectory("$rm_directory/$file");
else {
unlink("$rm_directory/$file");
}
You got that right in your delete_file function, but missed it in the recursive one.
Try this:
function recursiveRemoveDirectory($dir) {
foreach(scandir($dir) as $file) {
if ('.' === $file || '..' === $file) continue;
if (is_dir("$dir/$file")) recursiveRemoveDirectory("$dir/$file");
else unlink("$dir/$file");
}
rmdir($dir);
}
I tried both answers, they did solve a problem I had with the code but it did not solve the issue I was having in which the parent directory was being deleted along with the selected items.
After looking and changing the code for some time I finally realized that the problem wasn't in the recursiveDeleteDirectory() function but in the delete_file() function itself.
The $selected_itemsvariable gets a concatenated string of the names of the items to be selected, it trims any unnecessary whitespaces and makes an array from the string. The problem was that somehow $selected_items got an additional empty entry which meant that I was then executing recursiveRemoveDirectory("{$directory}/"); instead of recursiveRemoveDirectory("{$directory}/{$item}");.
I solved all this by adding:
if (empty($item)){
continue;
}
Here is how the code looks like:
function delete_file (){
global $directory;
$selected_items = explode(";", trim($_POST['selected']));
if (count($selected_items) < 1){
echo "0";
}
else {
foreach ($selected_items as $item){
if (empty($item)){
continue;
}
if (is_dir("{$directory}/{$item}")){
recursiveRemoveDirectory("{$directory}/{$item}");
}
else if (is_file("{$directory}/{$item}")){
unlink("{$directory}/{$item}");
}
}
echo "1";
}
}
function recursiveRemoveDirectory($rm_directory){
$files = file_explore();
if(count($files) > 0){
foreach($files as $file){
if(is_dir("{$rm_directory}/{$file}")) {
recursiveRemoveDirectory("{$rm_directory}/{$file}");
}
else if (is_file("{$rm_directory}/{$file}")) {
unlink("{$rm_directory}/{$file}");
}
}
}
rmdir($rm_directory);
Now my problem, which isn't really a stack overflow problem is the naming conversions of php functions, I never used underscore on function names but recently that have changed and I feel that's a bad habit, if someone wants to comment about that, you are free to do so, I really want to know how things must be done in php.
Cheers!

php get variables

I'm new to php and need some help with "GET" variables.
Here an extraction of my Code for index.php:
$array = array("section","view","sub","cat","point");
$i = 0;
$check = true;
foreach ($_GET as $position => $wert) {
if ($position != $array[$i]) {
//if GET doesnt exist in the array set check to false
$check = false;
break;
}
$i++;
}
//if GET variables exists
if ($check == true) {
if (isset($_GET['section'], $_GET['view'], $_GET['sub'], $_GET['cat'], $_GET['point'], $point[$_GET['point']])) {
$path = $path_dynamic.$_GET['section']."/".$_GET['view']."/".$_GET['sub']."/".$_GET['cat']."/".$point[$_GET['point']];
check($path);
} else if (isset($_GET['section'], $_GET['view'], $_GET['sub'], $_GET['cat'], $cat[$_GET['cat']])) {
$path = $path_dynamic.$_GET['section']."/".$_GET['view']."/".$_GET['sub']."/".$cat[$_GET['cat']];
check($path);
} else if (isset($_GET['section'], $_GET['view'], $_GET['sub'], $sub[$_GET['sub']])) {
$path = $path_dynamic.$_GET['section']."/".$_GET['view']."/".$sub[$_GET['sub']];
check($path);
} else if (isset($_GET['section'], $_GET['view'], $view[$_GET['view']])) {
$path = $path_dynamic.$_GET['section']."/".$view[$_GET['view']];
check($path);
} else if (isset($_GET['section'], $section[$_GET['section']])) {
$path = $path_dynamic.$section[$_GET['section']];
check($path);
//if section isn't set
} else if (!isset($_GET['section'])) {
include ($path_dynamic.$section['news']);
}
} else {
echo "GET doesn't exist";
include ($path_static.$section['error']);
}
//check if GET exists
function check($path) {
if (file_exists($path)) {
echo "File imported<br />";
include ($path);
} else {
echo "GET set correct but file doens't exist";
include ('include/static/fehler.html');
}
}
Example of section.php (view, sub, cat and point is the same):
$section = array();
$section['error'] = 'fehler.html';
My problem is that if i set this link:
index.php?section=verein&view=vorstande
"vorstande" doesn't exist in my view array. So the code checks for the section "verein" and include "verein". But it should give an error.
So it seems that this code
} else if (isset($_GET['section'], $_GET['view'], $view[$_GET['view']])) {
is ignored and it jumps to
} else if (isset($_GET['section'], $section[$_GET['section']])) {
Also if I change my url to this:
index.php?section=vereine&view=vorstande
nothing happens. I even don't know where the code is right now.
But if I change the url to this:
index.php?section=vereine&view=vorstand
everything works fine.
So "verein" and "vorstand" is defined by me. "vereine" and "vorstande" doens't exist.
Any suggestions? Sry for comments in german. The echo only gives me a hint where the code is right now!
Link to my HP:
Edit:
- translated comments for better conversation
- deleted all "$...[$_GET['...']]" structures to show the error I will get instead.
"vorstande" doesn't exist in my view array. So the code checks for the
section "verein" and include "verein". But it should give an error.
By "give an error" you mean $check = false;?
} else if (isset($_GET['section'], $_GET['view'], $view[$_GET['view']])) {
If in your $view the key vorstande does not exist, this the whole condition will evaluate to false and next condition will be checked:
} else if (isset($_GET['section'], $section[$_GET['section']])) {
Edit:
Your code:
else if (isset($_GET['section'], $_GET['view'], $view[$_GET['view']])) {
$path = $path_dynamic.$_GET['section']."/".$view[$_GET['view']];
check($path);
}
Your requirement:
if (!isset($view[$_GET['view']]))
check(/* something invalid to display fehler.html */ false);
What actually happens:
isset($_GET['section']) // true
isset($_GET['view']) // true
isset($view[$_GET['view']]) // FALSE
=> isset($_GET['section'], $_GET['view'], $view[$_GET['view']]) // FALSE
If the $_GET['view'] does not exist in $view, the block which would call check is not executed. If you want it to be executed regardless, simply remove the condition isset($view[$_GET['view']]):
else if (isset($_GET['section'], $_GET['view'])) {
$path = $path_dynamic.$_GET['section']."/".#$view[$_GET['view']]; // # to suppress errors from accessing
check($path);
}
If you don't like this approach, work on your cases. You have one case for section isset AND view isset AND view is valid. The next case ignores the view parameter. So if your view parameter is not valid, your code handles it like it was not set. The requirement though is to have a case for section isset AND view isset AND view is invalid:
else if (isset($_GET['section'], $_GET['view']) && !isset($view[$_GET['view']])) {
check(false);
}
This is of course pretty much redundant checking so just nest it to something like:
else if (isset($_GET['section'], $_GET['view']))
{
// section and view have been passed
if (isset($view[$_GET['view']])
// view is actually valid
$path = $path_dynamic.$_GET['section']."/".$view[$_GET['view']];
else
// view has been passed but is invalid. show fehler.html
$path = false;
check($path);
}
Alternate Example
If I understand you correctly, you have the following requirement: If the user passes a parameter section, view, sub, cat or point, you want that this value is also in your list of valid values. If it isn't, you want to display fehler.html.
We now first ensure that if the parameter is set, it is also valid:
foreach ($array as $param)
{
// example for $param == "view":
// !isset( $view[$_GET["view"]] )
if (!isset( ${$param}[$_GET[$param]] ))
{
$check = false;
break;
}
}
We then check all your combinations of parameters and build a $path
$path = false;
if ($check)
{
// your long if isset else if isset block where
// isset($_GET['view']) also implies isset($view[$_GET['view']])
// so you don't have to check for it.
// just set the $path variable with some string.
// we are going to check it later
}
If now the initial $check failed or we built an invalid $path, display fehler.html
if ($check === false || !file_exists($path))
{
// display fehler.html
}
else
include($path);
The problem is here:
} else if (isset($_GET['section'], $_GET['view'], $view[$_GET['view']])) {
Each parameter of isset must be true for the statement to return true. In your example, $_GET['section'] and $_GET['view'] are set, but $view[$_GET['view']] is not, so execution continues on the next else if line.
To fix the problem, either set $view[$_GET['view']] previously, or remove that parameter.

index files from a folder with subfolders and store location and filename

Hi I am looking for help to write a short script which will locate all files in a folder (which has sub-folders) list the path and filename in two seperate values before submitting to a database.
Can anyone help?
i have a recursive function to delete a folder, you'd have to change it so instead of calling the ´unlink´ function you could save it in a variable or in a database..
public function deleteFolder($dirname) {
if (is_dir($dirname)){
$dir_handle = opendir($dirname);
}
if (!isset($dir_handle) || !$dir_handle){
return false;
}
while($file = readdir($dir_handle)) {
if ($file != "." && $file != "..") {
if (!is_dir($dirname."/".$file)){
//change this line
unlink($dirname."/".$file);
} else {
//recursive call
$this->deleteFolder($dirname.'/'.$file);
}
}
}
closedir($dir_handle);
//also change this one
rmdir($dirname);
return true;
}
hope this helps.. good luck!
<?php
print_r(getPathFiles("./"));
function getPathFiles($dir) {
$ite=new RecursiveDirectoryIterator($dir);
$foo=new RecursiveIteratorIterator($ite);
$ret=array();
foreach ($foo as $path=>$cur) {
$ret[]=array('dir'=>dirname($path),'file'=>basename($path));
}
return $ret;
}
?>

Categories