Creating a temporary file with a specific extension is a common requirement on dynamic websites. Largely this need arises from Microsoft browsers that identify a downloaded file's mimetype based on the file's extension.
No single PHP function creates a temporary filename with a specific extension, and, as has been shown, there are race conditions involved unless you use the PHP atomic primitives.
I use only primitives below and exploit OS dependent behaviour to securely create a file with a specific postfix, prefix, and directory. Enjoy.
<?php
function secure_tmpname($postfix = '.tmp', $prefix = 'tmp', $dir = null) {
if (! (isset($postfix) && is_string($postfix))) {
return false;
}
if (! (isset($prefix) && is_string($prefix))) {
return false;
}
if (! isset($dir)) {
$dir = getcwd();
}
$tries = 1;
do {
$sysFileName = tempnam($dir, $prefix);
if ($sysFileName === false) {
return false;
}
$newFileName = $sysFileName . $postfix;
if ($sysFileName == $newFileName) {
return $sysFileName;
}
$newFileCreated = (isWindows() ? @rename($sysFileName, $newFileName) : @link($sysFileName, $newFileName));
if ($newFileCreated) {
return $newFileName;
}
unlink ($sysFileName);
$tries++;
} while ($tries <= 5);
return false;
}
?>
The isWindows function is mostly left as an exercise for the reader. A starting point is below:
<?php
function isWindows() {
return (DIRECTORY_SEPARATOR == '\\' ? true : false);
}
?>
Like tempnam(), this function requires you to cleanup your own files later. Under UNIX (where you can rename onto an extant file and so I used link), you will have to remove both the link and the link's target. Cleanup is left entirely to the reader.