0

I am in the lengthy process of modernizing a lot of code on my website to make it php 8.x compliant. I have never really gotten the hang of user defined functions, so the following code was not created by me.

I am trying to change create_function, which has been removed as of php 8.0, to an anonymous function.

I removed the security lines as they were irrelevant.

Any hints as to how I should proceed?

Code:

print_r($_FILES)

##produces

$_FILES is Array ( [pix] => Array ( [name] => christmas every day.jpg [type] => image/jpeg [tmp_name] => /tmp/phpWPefKh [error] => 0 [size] => 91284 ) )
Here is the outdated code:

Code:
<?php
$end=substr($_FILES['pix']['name'],-3,3);
$end=strtolower($end);
if($end=="jpg"||$end=="peg"||$end=="gif"||$end=="png") {}
else {echo"<script type=\"text/javascript\">
 window.location = \"http://www.animeviews.com\"
 </script>";
exit;
}

function or_f($a, $b) {
  return $a || $b;
}

function file_has_extension($fn, $ext) {
  if(is_array($ext))
    return array_reduce(array_map(create_function('$a', 'return file_has_extension(\'' . $fn . '\', $a);'), $ext), 'or_f', false);
  else
    return stripos($fn, '.' . strtolower($ext)) === strlen($fn) - strlen($ext) + 1;
}

$image_extensions = array(
  'png',
  'jpg',
  'jpeg',
  'gif'
);
  if(!isset($_POST['Upload']) and !isset($_POST['Overwrite']))
  {
    include("picform.php");
  } # endif
  else
  {
    if($_FILES['pix']['tmp_name'] == "none")
    {
      echo "<b>File did not successfully upload. Check the
            file size. File must be less than 500K.<br>";
      include("picform.php");
      exit();
    }
if(file_has_extension($_FILES['pix']['name'], $image_extensions))
    {
      echo "<b>File is not a picture. Please try another
            file.</b><br>";
      include("picform.php");
      exit();
    }
    else
    {
      $destination = $_FILES['pix']['name'];
      $destination = strtolower($destination);
      $temp_file = $_FILES['pix']['tmp_name'];
if (file_exists($destination) and $_POST['Overwrite']!="Overwrite") {
    echo "The file $destination already exists.";exit();
}
#########
      move_uploaded_file($temp_file,$destination);
      echo "<p><b>The file has successfully uploaded:</b>
            {$destination}
            ({$_FILES['pix']['size']})</p>";

$img="http://www.animeviews.com/images/$destination";

$img    = $destination;
$width  = "180px";
$height = "";

// Get new dimensions
list($width1, $height1) = getimagesize($img);
if ($width =="") {$j=$height/$height1; $width  = $width1  * $j;}
if ($height=="") {$j=$width/$width1;   $height = $height1 * $j;}
$new_width = $width;
$new_height = $height;

// Resample
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($img);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width1, $height1);

// Output
$img=preg_replace('/h.*\//','',$img);
$img=strtolower($img);
$dest="thumbs/$img";
imagejpeg($image_p,$dest);

    }
  }
?>

2 Answers 2

1

The purpose was to make sure that only images are uploaded, so create_function() or function() are not really needed. In fact, all I really needed was the following code snippet:

Code:

$end=substr($_FILES['pix']['type'], 0, 6);
$end=strtolower($end);

In short, the following code will check to see if the image being uploaded is an image. Not displayed is the code to be sure the user of the script is me. The script will overwrite the image if the same filename already exists and Overwrite was selected. A thumbnail is created and, lastly, a message is displayed saying that the file was successfully uploaded with the size.

Here is the full code:

Code:

<?php
$end=substr($_FILES['pix']['type'], 0, 6);
$end=strtolower($end);
if($end=="image/") {}
else {echo"<script type=\"text/javascript\">
 window.location = \"http://www.animeviews.com/images/picform.php\"
 </script>";
exit;
}
  if(!isset($_POST['Upload']) and !isset($_POST['Overwrite']))
  {
    include("picform.php");
  } # endif
  else
  {
    if($_FILES['pix']['tmp_name'] == "none")
    {
      echo "<b>File did not successfully upload. Check the
            file size. File must be less than 500K.<br>";
      include("picform.php");
      exit();
    }

      $destination = $_FILES['pix']['name'];
      $destination = strtolower($destination);
      $temp_file = $_FILES['pix']['tmp_name'];
if (file_exists($destination) and $_POST['Overwrite']!="Overwrite") {
    echo "The file $destination already exists.";exit();
}
#########
      move_uploaded_file($temp_file,$destination);
      echo "<p><b>The file has successfully uploaded:</b>
            {$destination}
            ({$_FILES['pix']['size']})</p>";

$img="http://www.animeviews.com/images/$destination";

$img    = $destination;
$width  = "180";
##$height = "";

// Get new dimensions
list($width1, $height1) = getimagesize($img);
if (!isset($width)) {$j=$height/$height1; $width  = $width1  * $j;}
if (!isset($height)) {$j=$width/$width1;   $height = $height1 * $j;}
$new_width = $width;
$new_height = $height;

// Resample
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($img);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width1, $height1);

// Output
$img=preg_replace('/h.*\//','',$img);
$img=strtolower($img);
$dest="thumbs/$img";
imagejpeg($image_p,$dest);
  }
Sign up to request clarification or add additional context in comments.

1 Comment

A note of security: Don't ever trust $_FILES["image"]["type"]. It takes whatever is sent from the browser, so don't trust this for the image type. Use finfo_file php.net/manual/en/function.finfo-file.php or at least getimagesize to check if file is a valid image.
0

i'll try to describe the solution:

  1. Legacy code: create_function('$a', 'return file_has_extension(\'' . $fn . '\', $a);')
  2. Perfect code: function ($a) use ($fn) { return file_has_extension ($fn, $a); }

Explanation: in the first case, you can see the removed function named create_function, which creates a new closure (example of simple closue: function ($args) use ($extraArg - here is extra vars. which you need into the closure, 'use' - construction can be ummitted) { return ...$args }. Closure is equals type callable, you can read this documentation and see, that the first argument of previous function (it's array_map) will be the callable type, all you need pass the same type with the same behavior).

In the second case, you can see some strange construction like this use ($fn), it's necessary, because the closure|callable type has the own variable scope (more here).

More, about Closure and him scope here.


Rewritten file_has_extension function:

function file_has_extension($fn, $ext) {
    if (is_array($ext)){
        return array_reduce(
            array_map(
                function ($a) use ($fn) {
                    return file_has_extension($fn, $a);
                },
                $ext
            ),
            function ($a, $b) {
                return $a || $b;
            },
            false
        );
    }

    return stripos($fn, '.' . strtolower($ext)) === strlen($fn) - strlen($ext) + 1;
}

2 Comments

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
I added more detailed answer and at the same time i apologize for possible mistakes in translation (I'm actively raising the level of the English, please treat with understanding).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.