Message d’erreur
PHP Warning: realpath() [<a href='function.realpath'>function.realpath</a>]: open_basedir restriction in effect. File(/tmp) is not within the allowed path(s): .... in /PHPExcel/PHPExcel/Shared/File.php on line 141
Configuration
PHP 5.3.9
PHPExcel 1.7.6
Même problème sous Unix et Windows.
Le problème
La librairie PHPExcel échoue lorsqu’elle essaie de créer des fichiers sous le répertoire temporaire d’Unix (ou windows) et que ces 2 conditions sont réunies :
– la directive open_basedir est activée (Cette directive contient la liste des répertoires accessibles par le programme PHP),
– le répertoire temporaire de l’OS n’est pas cité dans la directive open_basedir
.
Pour récupérer la valeur du répertoire temporaire de l’OS, PHPExcel utilise la fonction PHP sys_get_temp_dir()
, qui lui retourne /tmp
(et c:\windows\temp
pour windows). Si il n’est pas possible de rajouter /tmp
dans open_basedir
(peut être interdit sur des machines de production), vous trouverez ci-dessous les solutions que j’ai mises en oeuvre. Voici le code de la librairie PHPExcel qui pose problème :
Fichier PHPExcel/PHPExcel/Shared/File.php (1.7.6)
class PHPExcel_Shared_File {
. . .
public static function sys_get_temp_dir() {
// sys_get_temp_dir is only available since PHP 5.2.1
// http://php.net/manual/en/function.sys-get-temp-dir.php#94119
if ( !function_exists('sys_get_temp_dir')) {
if ($temp = getenv('TMP') ) {
if (file_exists($temp)) { return realpath($temp); }
}
if ($temp = getenv('TEMP') ) {
if (file_exists($temp)) { return realpath($temp); }
}
if ($temp = getenv('TMPDIR') ) {
if (file_exists($temp)) { return realpath($temp); }
}
// trick for creating a file in system's temporary dir
// without knowing the path of the system's temporary dir
$temp = tempnam(FILE, '');
if (file_exists($temp)) {
unlink($temp);
return realpath(dirname($temp));
}
return null;
}
// use ordinary built-in PHP function
// There should be no problem with the 5.2.4 Suhosin realpath() bug, because this line should only
// be called if we're running 5.2.1 or earlier return realpath(sys_get_temp_dir()); // Erreur PHP ICI (ligne 141)
}
Solutions possibles
1ère solution
Mettre à jour la librairie avec la version PHPExcel 1.8
: Les concepteurs ont ajouté une portion de code permettant d’utiliser la valeur de la directive PHP upload_tmp_dir
, à la place du répertoire temporaire de l’OS. Le répertoire upload_tmp_dir
devra être cité dans open_basedir
, si il n’y est pas déjà.
Fichier PHPExcel/PHPExcel/Shared/File.php (1.8)
public static function sys_get_temp_dir()
{
if (self::$_useUploadTempDirectory) {
// use upload-directory when defined to allow
// running on environments having very restricted
// open_basedir configs
if (ini_get('upload_tmp_dir') !== FALSE) {
if ($temp = ini_get('upload_tmp_dir')) {
if (file_exists($temp))
return realpath($temp);
}
}
}
// sys_get_temp_dir is only available since PHP 5.2.1
// http://php.net/manual/en/function.sys-get-temp-dir.php#94119
if ( !function_exists('sys_get_temp_dir')) {
if ($temp = getenv('TMP') ) {
if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); }
}
if ($temp = getenv('TEMP') ) {
if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); }
}
if ($temp = getenv('TMPDIR') ) {
if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); }
}
// trick for creating a file in system's temporary dir
// without knowing the path of the system's temporary dir
$temp = tempnam(FILE, '');
if (file_exists($temp)) {
unlink($temp);
return realpath(dirname($temp));
}
return null;
}
// use ordinary built-in PHP function
// There should be no problem with the 5.2.4 Suhosin realpath() bug,
// because this line should only
// be called if we're running 5.2.1 or earlier
return realpath(sys_get_temp_dir());
}
La fonction teste la variable statique self::$_useUploadTempDirectory
qui est initialisée à False par défaut. Nous devons initialiser cette statique à true, quelque part dans notre code (avant d’utiliser PHPExcel).
. . .
PHPExcel_Shared_File::setUseUploadTempDirectory(true);
...
2ème solution
Si vous ne pouvez pas mettre à jour tout de suite la librairie, vous pouvez juste modifier la fonction pour qu’elle utilise systématiquement upload_tmp_dir sur le modèle ci-dessous . J’ai repris le même code que ci-dessus, mais sans le test.
Fichier PHPExcel/PHPExcel/Shared/File.php (1.7.6 MODIFIE)
public static function sys_get_temp_dir()
{
// use upload-directory when defined to allow running
// on environments having very restricted
// open_basedir configs
if (ini_get('upload_tmp_dir') !== FALSE) {
if ($temp = ini_get('upload_tmp_dir')) {
if (file_exists($temp))
return realpath($temp);
}
}
// sys_get_temp_dir is only available since PHP 5.2.1
// http://php.net/manual/en/function.sys-get-temp-dir.php#94119
if ( !function_exists('sys_get_temp_dir')) {
if ($temp = getenv('TMP') ) {
if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); }
}
if ($temp = getenv('TEMP') ) {
if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); }
}
if ($temp = getenv('TMPDIR') ) {
if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); }
}
// trick for creating a file in system's temporary dir
// without knowing the path of the system's temporary dir
$temp = tempnam(FILE, '');
if (file_exists($temp)) {
unlink($temp);
return realpath(dirname($temp));
}
return null;
}
// use ordinary built-in PHP function
// There should be no problem with the 5.2.4 Suhosin realpath() bug, because this line should only
// be called if we're running 5.2.1 or earlier
return realpath(sys_get_temp_dir());
}
Autres solutions (PHP < 5.2.1 ou PHP >= 5.4)
- Si vous utilisez
PHP < 5.2.1
, la fonction sys_get_temp_dir()
n’existe pas encore, PHPExcel se sert (comme on le voit dans le code de la fonction) de la valeur d’une variable d’environnement TMP, TEMP ou TMPDIR. Cette variable peut donc être initialisée au préalable dans l’environnement. Par exemple :
Dans httpd.conf ou .htaccess :
SetEnv TMPDIR chemin_mon_rep_temporaire
Dans les sources PHP :
putenv("TMPDIR", chemin_mon_rep_temporaire) ;
- si vous utilisez
PHP >= 5.4
, vous pouvez paramétrer le répertoire temporaire du SE dans la directive PHP sys_temp_dir
. Cette valeur sera retournée par la fonction PHP sys_get_temp_dir()
.