Chyba v OpenCart instalátoru

Publikováno 06.10 2025 v 10:52 hod.

Václav Ambrož

Pokud při instalaci OpenCartu narazíte na varování typu:

Warning: open_basedir needs to allow access to /home/www/example.com/www/opencart/

přestože máte open_basedir správně nastavený, pravděpodobně nejde o chybu v PHP konfiguraci, ale o bug přímo v instalačním skriptu OpenCartu.

Co je open_basedir a proč na něm instalátor padá

Direktiva open_basedir v PHP omezuje, do jakých adresářů může PHP skript přistupovat. Správné nastavení může například vypadat takto:

open_basedir = /home/www/tmp:/home/www/example.com/www:/etc/ssl/certs:/usr/share/php

Toto říká PHP, že může pracovat pouze s těmito cestami. Pokud zkusí přistoupit jinam, dostane chybu typu open_basedir restriction in effect.

OpenCart při instalaci kontroluje, zda je cesta instalace v rámci povolených adresářů. Bohužel v některých verzích (např. 4.x a část 3.x) je tato kontrola chybně implementovaná.

Kde je chyba v kódu

V souboru:

install/controller/install/step_2.php

se používá tento kód:

$directories = explode(',', $open_basedir, 1);

foreach ($directories as $directory) {
if (str_starts_with($directory, $required)) {
$data['open_basedir'] = true;
}
}

To má hned dva problémy:

  1. na Linuxu se open_basedir odděluje dvojtečkou (:), ne čárkou
  2. parametr 1 znamená, že se použije jen první hodnota – ostatní cesty se ignorují

Výsledkem je, že test selže, i když je cesta správně povolená. PHP samotné přístup neblokuje, ale OpenCart instalátor si myslí, že ano.

Možnosti řešení

  1. dočasně vypnout open_basedir při instalaci (pokud máte přístup k PHP konfiguraci), po instalaci OpenCart už open_basedir dále nekontroluje
  2. pokud chcete mít kontrolu funkční i při zapnuté ochraně a udělat rychlý bugfix, upravte část kódu v souboru install/controller/install/step_2.php následovně:

    $directories = explode(‚,‘, $open_basedir, 1);

    Nahraďte za:

    // Correct parsing of open_basedir (supports ":" on Linux and ";" on Windows)
    $directories = preg_split('/[:;,]/', $open_basedir);

    foreach ($directories as $directory) {
    $directory = rtrim($directory, '/');
    if (str_starts_with($required, $directory)) {
    $data['open_basedir'] = true;
    break;
    }
    }

    Stejnou úpravu proveďte i v metodě save() v tom samém souboru.