I have a client who uploads photos with names like 800_werk%20035.jpg to his site (with image module). Uploading and storing on the server goes fine. Displaying however fails because the html reads: <img src="800_werk%20035.jpg" ...>. When the browser requests this file the server interprets it as 800_werk 035.jpg (%20 decodes as a space) and doesn't find it.
In attachment is a small patch to escape the '%' character in the file_create_url() function.
I don't now if this is the right approach, but it works for my client. Moreover I did not test it with different browsers/platforms.

Comments

Steven’s picture

Status: Needs review » Needs work

This need proper urlencoding.

soxofaan’s picture

This need proper urlencoding.

That was also my first thought but the problem is that the slash ('/') in images/800_werk%20035.jpg will also be encoded, which is not desired. I guess you need to explode the path on '/' first, urlencode each part and implode again. This is probably a lot of overhead for just coping with a corner case?

soxofaan’s picture

Version: 5.1 » 5.x-dev
Status: Needs work » Needs review
StatusFileSize
new710 bytes

This need proper urlencoding.

This patch uses drupal_urlencode() instead of the hackish str_replace() of my original patch.
No problem with "/" characters in the path.

drumm’s picture

Version: 5.x-dev » 6.x-dev
Status: Needs review » Needs work

This would double-encode the path when using the private file download method, since url() does that for us.

soxofaan’s picture

Status: Needs work » Needs review
StatusFileSize
new761 bytes

moved it inside the FILE_DOWNLOADS_PUBLIC case branch:

function file_create_url($path) {
  // Strip file_directory_path from $path. We only include relative paths in urls.
  if (strpos($path, file_directory_path() . '/') === 0) {
    $path = trim(substr($path, strlen(file_directory_path())), '\\/');
  }
  switch (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC)) {
    case FILE_DOWNLOADS_PUBLIC:
      return $GLOBALS['base_url'] .'/'. file_directory_path() .'/'. str_replace('\\', '/', drupal_urlencode($path));
    case FILE_DOWNLOADS_PRIVATE:
      return url('system/files/'. $path, NULL, NULL, TRUE);
  }
}

At #4 where version was changed from 5.x-def to 6.x dev:
shouldn't this also be fixed in D5?

toeofdestiny’s picture

I have the same problem here, and here is my patch.

It is almost the same as the already submitted one, except that I "rawurlencode" the path because the paths containing '+' weren't working on my server for some reason.

function file_create_url($path) {
  // Strip file_directory_path from $path. We only include relative paths in urls.
  if (strpos($path, file_directory_path() . '/') === 0) {
    $path = trim(substr($path, strlen(file_directory_path())), '\\/');
  }
  switch (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC)) {
    case FILE_DOWNLOADS_PUBLIC:
      // VVVVVVVVVV PATCH HERE VVVVVVVVVV
      $fullPath = file_directory_path() .'/'. str_replace('\\', '/', $path);
      // Fake "drupal_urlencode" using "rawurlencode" (' ' --> '%20')
      $fullPath = str_replace('+', '%20', drupal_urlencode($fullPath));
      return $GLOBALS['base_url'] .'/'. $fullPath;
      // ^^^^^^^^^^ PATCH HERE ^^^^^^^^^^
    case FILE_DOWNLOADS_PRIVATE:
      return url('system/files/'. $path, NULL, NULL, TRUE);
  }
}
drewish’s picture

Status: Needs review » Closed (duplicate)
drewish’s picture

Version: 6.x-dev » 7.x-dev
Status: Closed (duplicate) » Needs work

actually this has a patch so i'll mark it as active instead. it'd need to be applied to 7 and then backported as a bug fix.

soxofaan’s picture

Status: Needs work » Needs review
StatusFileSize
new799 bytes

reroll for HEAD

soxofaan’s picture

StatusFileSize
new803 bytes

reroll for the new Drupal coding standard about string concatenation I just learned about ;)

Freso’s picture

Adding to my issue queue.

bjaspan’s picture

Subscribe. It looks like my issue http://drupal.org/node/238299 may be a duplicate of this one.

Freso’s picture

@bjaspan: That sounds very likely. Could you perhaps try the patch and see if it fixes the problem on your end?

c960657’s picture

Using drupal_urlencode() wont work for filenames containing # or & when clean_url's are enabled. I suggest using str_replace('%2F', '/', rawurlencode($prefix . $path)) instead (the same approach is used inside drupal_urlencode()).

See also the patch in #207310: Allow rewriting of file URL's using custom_url_rewrite_outbound().

c960657’s picture

Closing as duplicate of #238299: file_create_url should return valid URLs. That bug has a patch (pending review) and a unit test.

c960657’s picture

Status: Needs review » Closed (duplicate)