gremo
gremo

Reputation: 48909

File naming convention and allowed characters between different OS

I'm wring a piece of code in PHP for saving email attachments. Can i assume that this will never fail because different allowed characters between OS?

foreach($message->attachments as $a)
{
   // Make dir if not exists
   $dir = __DIR__ . "/saved/$uid"; // Message id
   if (!file_exists($dir)) mkdir($dir) or die("Cannot create: $dir");

   // Save the attachment using original!!! filename as found in email
   $fp = fopen($dir . '/' . $a->filename, 'w+');
   fwrite($fp, $a->data);
   fclose($fp);
}

Upvotes: 0

Views: 478

Answers (3)

tony gil
tony gil

Reputation: 9554

NO, you should assume that this will have a high probability of failing. for 2 reasons:

  1. what if 2 emails have files named the same (selfie.jpg, for example)?
  2. what if filename contains unacceptable characters?

you should use an internal naming convention (user+datetime+sequential, for example) and save names in a MySQL table with at least 3 fields:

  1. Id - Autonumbered
  2. filename - as saved by your php
  3. original name - as in the original email
  4. optional username - or usercode or email address of whomever sent email
  5. optional datetime stamp

save the original filename as a VARCHAR and you will be able to keep track of original name and even show it, search for it, etc.

Upvotes: 0

zuloo
zuloo

Reputation: 1330

it is good practice to replace certain characters that may occur in filenames on windows.

Unix can handle almost any character in a file name (but not "/" and 0x00 [the null Character]), but to prevent encoding problems and difficulties on downloading a file I would suggest to replace anything that does not match /[A-Za-Z0-9_-\.]/g, which satisfies the POSIX fully portable filename format.

so a preg_replace("/[^A-Za-Z0-9_-\.]/g","_",$filename); will do a good job.

a more generous approach would be to replace only |\?*<":>+[]\x00/ which leaves special language characters like öäü untouched and is compatible with FAT32, NTFS, any Unix and Mac OS X.

in that case use preg_replace("/[\|\\\?\*<\":>\+\[\]\/]\x00/g","_",$filename);

Upvotes: 0

jeroen
jeroen

Reputation: 91744

You should never use a name that you have no control over, it can contain all sorts of characters, like ../../...

You can use a function like basename to clean it up and a constant like DIRECTORY_SEPARATOR to separate directories.

Personally I would rename the file but you can also filter the variables before using them.

Upvotes: 2

Related Questions