1

I wrote validation function that tests file's mimetype. I commented out my old validators to avoid validation by extension:

'DownloadFile' => array(
  '#type' => 'managed_file',
  '#title' => t("Download"),
  '#title_display' => 'invisible',
  //'#description' => t('Allowed extensions: pdf zip exe.'),
  '#upload_validators' => array(
    //'file_validate_extensions' => array('pdf zip exe'),
    'file_validate_size' => array(variable_get('mymodule_image_size', 2 * 1024 * 1024)),
  ),
  '#upload_location' => 'public://mymodule/download',
  '#default_value' => $item->DownloadFile,
  '#required' => TRUE,
  '#theme' => 'preview_upload',
),

Now when I'm trying to upload exe, I get:

The specified file putty.exe could not be uploaded. Only files with the following extensions are allowed: jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp.

Now, I will have files without extensions there. And with extensions I cannot predict. And all I want sometimes is to test for a proper MIME type match, not even an exact mimetypes sometimes. So, how can I get rid of extension validation and turn it into "everything goes"?

I managed to find issue that seemed to be about this problem, but it tells to unset($element['#upload_validators']['file_validate_extensions']); - does not make sense to me as I'm creating brand new array and this isn't set at all.

I tried to use #process property to add a function that will unset default validators later, like shown there in issue, but dpr($element) shows there is nothing to unset:

[#upload_validators] => Array
    (
        [file_validate_size] => Array
            (
                [0] => 2097152
            )

    )
  • 1
    I remember this - file_save_upload() is to blame, but I can't remember how I got around it – Clive Sep 6 '13 at 9:48
  • 1
    @Clive To be honest I expected you or other of the experienced users to simply vote it a duplicate. I remember this problem reappears, but cannot find a solution that works. @ ALL if hacking core is the only way (you know), so be it. I'm open about that if I have to. Just please help me do it safely. – Mołot Sep 6 '13 at 9:51
2

The answer comes from the following code used by file_save_upload().

  if (isset($validators['file_validate_extensions'])) {
    if (isset($validators['file_validate_extensions'][0])) {
      // Build the list of non-munged extensions if the caller provided them.
      $extensions = $validators['file_validate_extensions'][0];
    }
    else {
      // If 'file_validate_extensions' is set and the list is empty then the
      // caller wants to allow any extension. In this case we have to remove the
      // validator or else it will reject all extensions.
      unset($validators['file_validate_extensions']);
    }
  }
  else {
    // No validator was provided, so add one using the default list.
    // Build a default non-munged safe list for file_munge_filename().
    $extensions = 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp';
    $validators['file_validate_extensions'] = array();
    $validators['file_validate_extensions'][0] = $extensions;
  }

In your case you should use the following array.

  'DownloadFile' => array(
    '#upload_validators' => array(
      'file_validate_extensions' => array(),
      'file_validate_size' => array(variable_get('mymodule_image_size', 2 * 1024 * 1024)),
    ),
  );

In that way $validators['file_validate_extensions'] is set, but $validators['file_validate_extensions'][0] is not. As result, the code will not set $extensions, and the following code will not be executed either.

  if (!empty($extensions)) {
    // Munge the filename to protect against possible malicious extension hiding
    // within an unknown file type (ie: filename.html.foo).
    $file->filename = file_munge_filename($file->filename, $extensions);
  }

The code has a strange way to check if the list is empty; it assumes the array is empty of there isn't an item with index equal to 0. I would have rather used the following one, which would not make assumptions about the lower array index being used.

  if (isset($validators['file_validate_extensions'])) {
    if (empty($validators['file_validate_extensions'])) {
      // If 'file_validate_extensions' is set and the list is empty then the
      // caller wants to allow any extension. In this case we have to remove the
      // validator or else it will reject all extensions.
      unset($validators['file_validate_extensions']);
    }
    else {
      // Build the list of non-munged extensions if the caller provided them.
      $extensions = array_shift($validators['file_validate_extensions']);
    }
  }

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.