Подтвердить что ты не робот

Sys_get_temp_dir в среде совместного размещения

Примечание. Это может также соответствовать суперпользователю.

Я устанавливаю PHP 5.3.10 на общий хост с apache2 mpm itk и open_basedir таким образом, что каждый пользователь может не видеть или изменять файлы другого пользователя. В настройках vhost apache2 я добавляю соответствующие записи, чтобы ограничить пользователя:

    AssignUserId     userA userA
    php_admin_value  open_basedir      /home/userA/www/
    php_admin_value  upload_tmp_dir    /home/userA/www/tmp/
    php_admin_value  session.save_path /home/userA/www/tmp/
    SetEnv           TMPDIR            /home/userA/www/tmp/

Теперь первая строка устанавливает, что пользователь linux будет использовать для apache2, следующие три строки определяют каталог, загружающий файлы, и каталог сохранения сеанса, которые будут находиться в каталоге пользователя. Я вернусь к последней строке за секунду.

Теперь для проблемы: sys_get_temp_dir() должен вернуть временный каталог для php, который /tmp будет использоваться по умолчанию в системе linux. По соображениям безопасности этот каталог должен находиться в open_basedir пользователя. Согласно php-источнику 5.3.10, функция sys_get_temp_dir() использует переменную среды TMPDIR для получения этой директории:

     // php-src/main/php_open_temporary_file.c:217-219
     /* On Unix use the (usual) TMPDIR environment variable. */
     {
             char* s = getenv("TMPDIR");

Это то, что должна сделать пятая строка в приведенной выше конфигурации. Однако sys_get_temp_dir() просто возвращает глобальный системный каталог, игнорируя переменную окружения (которая отлично установлена ​​в $_SERVER, также просматривается через phpinfo()).

Это приводит к некоторым неприятным ошибкам с различным программным обеспечением, основанным на sys_get_temp_dir(), поскольку этот каталог находится за пределами параметра open_basedir. Я попытался установить переменную непосредственно в $_ENV и $_SERVER без изменения поведения. Я пробовал putenv('TMPDIR=/home/userA/www/tmp') без изменений.

Однако я могу изменить вывод, указав переменную в /etc/apache 2/envvars - это бесполезно для меня, поскольку я хочу, чтобы каждый VHOST имел свою временную папку.

Единственное решение, которое я нашел до сих пор, - это переписать внутренний sys_get_temp_dir() через расширение, например runkit, и обеспечить его включение через auto_prepend_file. Но это решение настолько грязно, я просто не могу поверить, что нет лучшего решения.

Итак, мой вопрос: есть ли способ изменить результат sys_get_temp_dir(), который должен быть установлен в настройке vache apache2, без переопределения функции с помощью runkit?

Изменить: Версия Apache 2.2.22, и в настоящее время я использую mod_php. Поскольку мне придется добавлять всех пользователей вручную, возможно, также будет возможна настройка fcgi или аналогичная.

4b9b3361

Ответ 1

Запуск putenv('TMPDIR=/foo/bar') внутри PHP, похоже, может повлиять на результат sys_get_temp_dir(). У вас может быть директива auto_prepend_file, предназначенная для запуска фрагмента PHP для настройки TMPDIR и избежания возиться с переопределением sys_get_temp_dir().

Изменить: Кроме того, вы можете легко использовать putenv('TMPDIR='.ini_get('open_basedir').'/tmp'), чтобы установить временный каталог в структуру каталогов, которую вы указали в вопросе.

Забавно, что это тоже работает (учитывая, что вы сохраняете SetEnv TMPDIR /foo/bar в своей конфигурации Apache):

putenv('TMPDIR='.getenv('TMPDIR'));

Кажется, что нет-op, но на самом деле имеет эффект на sys_get_temp_dir(). Я начинаю подозревать, что это должна быть некоторая ошибка обработки среды в PHP.

Ответ 2

Вы отметили свой вопрос , однако вы используете

 php_admin_value  open_basedir      /home/userA/www/
 ^^^^^^^^^^^^^^^

который является настройкой для версии модуля apache PHP, Mod_PHP. В этом случае PHP загружается после запуска веб-сервера.

Затем вы используете SetEnv:

 SetEnv           TMPDIR            /home/userA/www/tmp/

это настройка внутренней переменной среды. Он передается другим модулям apache, однако я думаю, что вам это нужно с запросом, а не с виртуальным сервером. Я не знаю этого конкретно, но я предположил бы согласно вашему описанию, что эта переменная среды получает reset до вызова PHP скрипт.

Итак, комментарий больше, чем реальный ответ, но, надеюсь, он поможет вам прояснить некоторые вещи.

Обычно я использую FCGI для многопользовательских сред, чтобы я мог лучше разделить пользователей. У меня никогда не было проблем с настройкой переменных среды для каждого пользователя. Но это еще один комментарий, я не хочу сказать, что вы тоже должны его использовать. Просто выделите, что вам нужно найти нужное место в apache для установки переменной среды, чтобы она была (установлена) при выполнении script.


Также вы можете не устанавливать правильную переменную окружения. Согласно Документация Apache о переменных окружения:

Хотя эти переменные называются переменными среды, они не совпадают с переменными среды, управляемыми базовой операционной системой. Вместо этого эти переменные хранятся и обрабатываются во внутренней структуре Apache. Они становятся реальными переменными среды операционной системы, когда они предоставляются сценариям CGI и скриптам на стороне сервера. Если вы хотите управлять средой операционной системы, в которой работает сам сервер, вы должны использовать стандартные механизмы управления средой, предоставляемые оболочкой вашей операционной системы.

Вы хотите установить переменную среды операционной системы для PHP. Но вы устанавливаете только внутреннюю переменную среды.

Mod_PHP может импортировать их в script, поэтому, если вы используете getenv('TMPDIR'), используется конкретная реализация PHP SAPI, которая позволяет вам видеть эти внутренние переменные среды, однако функция php_get_temporary_directory не использует ее - это выглядит.

Пожалуйста, добавьте версию Apache и PHP на ваш вопрос.

Ответ 3

Согласно this - 4 year old - bug, sys_get_temp_dir() не будет работать с виртуальными хостами; так

  • вы можете попробовать использовать только библиотеки, которые исправили эту проблему (& open ошибка для тех, кто этого не сделал)
  • или append /tmp (или независимо от того, что использует ваша ОС) в open_basedir, поскольку может содержать несколько каталогов (например, include_path - отделить его ; от Windows, : в противном случае)

Ответ 4

Глядя на источник PHP, sys_get_temp_dir() работает со следующим приоритетом:

Путь, указанный переменной среды TEMP. Путь, указанный переменной среды USERPROFILE. Каталог Windows. В * nix используются следующие (в этом порядке):
  • Переменная среды TMPDIR.
  • Макрос P_tmpdir
  • /tmp (согласно источнику, это последнее усилие, которое никогда не должно происходить).

Это должно дать вам достаточно возможностей для управления результатом sys_get_temp_dir (например, ini_set('sys_temp_dir', $tmpPath) или putenv('TMPDIR=/foo/bar'), как упоминалось выше) Если ранее не было рассчитано, в этом случае вы являетесь SOL насколько я знаю, и кешированное значение будет использоваться (но у меня есть нулевые знания в PHP, поэтому хотелось бы услышать иначе).

Ответ 5

Это ошибка в php 5.2 - указать temp dir по php.ini
Он зафиксирован в 5.5
Используйте это как временное решение:

<?php
putenv('TMPDIR=/path/to/your/tmp');
          ...your code here ...
?>

Ответ 6

В случае, если люди оказываются здесь, кто не справляется с проблемой putenv...

... для меня он работал, чтобы установить sys_temp_dir, используя php ini_set следующим образом:

$tmpPath = realpath(__DIR__.'/../app/tmp');
ini_set('sys_temp_dir', $tmpPath);

Я запускаю PHP 5.5.9 (cli) на машине windows8.

Ответ 7

Похоже, вы можете изменить значение, возвращаемое sys_get_temp_dir(), я только что попробовал apache 2.4 и php 5.6.27.

Добавить sys_temp_dir в виртуальном хосте:

php_admin_value sys_temp_dir "/var/www/alternc/f/fser/tmp"

Перезапустите apache и распечатайте значение на веб-странице с помощью sys_get_temp_dir():

<?php 
echo sys_get_temp_dir () ;

Производит ожидаемый результат: /var/www/alternc/f/fser/tmp.