0

I use the Fox Contact component on my website, and through that component users send me photos (as an attachment) I had to make a few modifications in the upload form itself and make filters for file name (only certain names are allowed). This filter works without any problems. I still have to do validation to check the size of the photo but I have no success. Even though the photo is larger than 1000px I don’t get a warning. This is my code:

    //Name validation (this is OK)

    $realname = $this->getFileName();
    $realname = Normalizer::normalize($realname);
    setlocale(LC_ALL,'bs_BA.UTF-8'); 
    $onlyname = pathinfo($realname, PATHINFO_FILENAME); 
    //Create list of all names
    $db = JFactory::getDbo();
    $query = $db->getQuery(true);
    $query->select('eio3k_peaks.peak_name');
    $query->from($db->quoteName('#__peaks'));
    $db->setQuery($query);
    $peaks_list = $db->loadColumn();

    if (!in_array($onlyname, $peaks_list))
    {

        return array('error' => JText::_('The name of this photo "' .$onlyname. '" is incorrect.'));
        
    }
    
    
    //Size validation (this is not ok)

    $dir = 'https://mysite.com/uploads/';
    $image_filename = $dir . $realname;
    list($width, $height) = getimagesize($image_filename);
    if (($width > 1000) OR ($height > 1000))
        {
        return array('error' => JText::_('The photo is larger than 1000px'));
        }

Where I went wrong? This is just the code I added. I can set up a complete file, but it's more than 250 lines of code

  • You are selecting from a single table, so eio3k_peaks. is unnecessary. In fact, you can refine your error checking process, by applying the in_array() logic into your query as a where() condition -- this way you can return a count and just check if loadResult() is truthy/falsey. As for the second half of that snippet, can you verify that the $image_filename value is as expected? Are $width and $height as expected? I don't recommend the OR operator, I would always use || for consistency. Or skip the list() and use if(max(getimagesize($image_filename)) > 1000) – mickmackusa Jun 20 at 21:27
  • Thanks for your reply Are you sure about if(max(getimagesize($image_filename)) > 1000)? In any case, the result is the same for me – Midhat Jun 21 at 9:52
  • Hmm, getimagesize(): Returns an array with up to 7 elements., which means there may be additional elements that will have a higher value that I am not expecting to see. For reliability, the array elements would need to be truncated by array_slice(). ideone.com/uefwuk – mickmackusa Jun 21 at 12:22
  • Please provide the exact data provided by getimagesize() when it fails to work as expected. This should make your question complete and satisfy my requirements to upvote the question. – mickmackusa Jun 21 at 12:26
2

I think I have a good idea where the error is. You are using $this->getFileName() to get the files original name, then you mutate the filename using normalize(). At this point you have a new file name, but the system doesn't realise that this is the filename to be used forevermore.

Basically, you will either need to rename the file in your file system to the new normalised filename, or you will need to reference the old/original filename when you want to fetch the dimensions. ...At some point you are going to need to save the new file name to the system.

I recommend that you implement your peak_name check purely in sql instead of extracting all peak names from your database and making the in_array() check in php.

Also, for performance reasons, I recommend that you check the dimensions BEFORE making a trip to the database. In general terms, I write "less expensive" processes before processes that consume more resources.

Finally, I will urge you to check the file type before doing either of these checks.

Untested suggestion...

$fileName = $this->getFileName();

if (max(array_slice(getimagesize('https://mysite.com/uploads/' . $fileName), 0, 2)) > 1000) {
    return [
        'error' => JText::_('The photo is larger than 1000px'
    ];
}

$newName = Normalizer::normalize($fileName);
setlocale(LC_ALL, 'bs_BA.UTF-8'); 
$newNameNoExtension = pathinfo($newName, PATHINFO_FILENAME); 

$db = JFactory::getDbo();
$query = $db
    ->getQuery(true)
    ->select("COUNT(1)")
    ->from($db->quoteName("#__peaks"))
    ->where($db->quoteName("peak_name") . " = " . $db->quote($newNameNoExtension));
$db->setQuery($query);

if (!$db->loadResult) {
    return [
        'error' => JText::_('The name of this photo "' . $newNameNoExtension . '" is invalid.'
    ];
}

Relevant notes from the PHP Docs:

getimagesize():

Caution This function expects filename to be a valid image file. If a non-image file is supplied, it may be incorrectly detected as an image and the function will return successfully, but the array may contain nonsensical values.

Do not use getimagesize() to check that a given file is a valid image. Use a purpose-built solution such as the Fileinfo extension instead.

and

Returns an array with up to 7 elements. Not all image types will include the channels and bits elements.

Index 0 and 1 contains respectively the width and the height of the image.

| improve this answer | |
  • There is a problem that constantly occurs to me and I cannot fix it. Image location is always correct $full_filename = $upload_directory . $filename; , but $width and $height are always empty. I tried with if (max(array_slice(getimagesize... and list($width, $height)... and without Normalizer but nothing. For some reason $width and $height are always empty. I also tried a new code to check the image name and it shows me in any case that the name is not correct. Thanks for help. – Midhat Jun 21 at 17:58
  • 1
    So there is no file that matches the name that you are trying to process? Then you need to keep working backward in your flow to find out where the breakage is. Joomla has some beautiful methods to aid image processing: api.joomla.org/cms-3/classes/Joomla.Image.Image.html Please read this Joomla Docs page for instructions on how to grab an uploaded image file: docs.joomla.org/How_to_use_the_filesystem_package – mickmackusa Jun 21 at 22:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.