Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,14 @@ class XAccelResponseBuilder implements ResponseBuilder
{
private const DATA = 'data';
private const SECURED_DATA = 'secured-data';
private const SECURED_EXT_DATA = 'secured-ext-data';
private const X_ACCEL_REDIRECT_HEADER = 'X-Accel-Redirect';

public function __construct(private string $external_data_dir)
{
$this->external_data_dir = rtrim($this->external_data_dir, '/') . '/';
}

public function getName(): string
{
return 'x-accel';
Expand All @@ -51,6 +57,12 @@ public function buildForStream(
. '/',
$path_to_file
);
} elseif (str_starts_with((string) $path_to_file, $this->external_data_dir)) {
$path_to_file = str_replace(
$this->external_data_dir,
'/' . self::SECURED_EXT_DATA . '/',
$path_to_file
);
}

return $response->withHeader(
Expand Down
6 changes: 5 additions & 1 deletion components/ILIAS/FileDelivery/src/Init.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,13 @@ public static function init(Container $c): void

switch ($settings[DeliveryMethodObjective::SETTINGS] ?? null) {
case DeliveryMethodObjective::XACCEL:
return new XAccelResponseBuilder();
return new XAccelResponseBuilder(
$settings[DeliveryMethodObjective::SETTINGS_EXTERNAL_DATA_DIR]
);

case DeliveryMethodObjective::XSENDFILE:
return new XSendFileResponseBuilder();

case DeliveryMethodObjective::PHP:
default:
return new PHPResponseBuilder();
Expand Down
76 changes: 59 additions & 17 deletions components/ILIAS/FileDelivery/src/Setup/DeliveryMethodObjective.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,62 +23,104 @@
use ILIAS\Setup\Artifact;
use ILIAS\Setup\Artifact\ArrayArtifact;
use ILIAS\Setup\Environment;
use ILIAS\Setup\Artifact\BuildArtifactObjective;
use ILIAS\Setup\CLI\IOWrapper;
use ILIAS\Setup\UnachievableException;

/**
* @author Fabian Schmid <fabian@sr.solutions>
*/
class DeliveryMethodObjective extends BuildStaticConfigStoredObjective
{
public const SETTINGS = 'delivery_method';
public const SETTINGS_EXTERNAL_DATA_DIR = 'ext_data_dir';
public const XSENDFILE = 'xsendfile';
public const XACCEL = 'xaccel';
public const PHP = 'php';

private ?string $ext_data_dir = null;
private ?IOWrapper $io = null;

public function getArtifactName(): string
{
return "delivery_method";
return 'delivery_method';
}

public function getPreconditions(Environment $environment): array
{
return array_merge(
parent::getPreconditions($environment),
[
new \ilIniFilesPopulatedObjective()
]
);
}

public function achieve(Environment $environment): Environment
{
/** @var \ilIniFile $ini */
$ini = $environment->getResource(Environment::RESOURCE_ILIAS_INI);
if ($ini instanceof \ilIniFile && $ini->variableExists('clients', 'datadir')) {
$this->ext_data_dir = $ini->readVariable('clients', 'datadir');
} else {
throw new UnachievableException(
'Could not determine external data directory from ILIAS ini file'
);
}

$io = $environment->getResource(Environment::RESOURCE_ADMIN_INTERACTION);
if ($io instanceof IOWrapper) {
$this->io = $io;
}

return parent::achieve($environment);
}

public function build(): Artifact
{
// check if mod_xsendfile is loaded
$delivery_method = self::PHP;

if (file_exists(self::PATH())) {
$settings = (@include self::PATH()) ?? [];
$delivery_method = $settings[self::SETTINGS] ?? self::PHP;
}

if ($this->isModXSendFileLoaded()) {
return new ArrayArtifact([
self::SETTINGS => self::XSENDFILE
]);
$delivery_method = self::XSENDFILE;
}

return new ArrayArtifact([
self::SETTINGS => self::PHP
]);
return new ArrayArtifact(array_filter([
self::SETTINGS => $delivery_method,
self::SETTINGS_EXTERNAL_DATA_DIR => $this->ext_data_dir
]));
}

private function isModXSendFileLoaded(): bool
{
if (function_exists('apache_get_modules') && in_array('mod_xsendfile', apache_get_modules(), true)) {
if (\function_exists('apache_get_modules') && \in_array('mod_xsendfile', apache_get_modules(), true)) {
return true;
}

try {
$command_exists = shell_exec("which apache2ctl");
if ($command_exists === null || empty($command_exists)) {
$command_exists = shell_exec('which apache2ctl');
if (empty($command_exists)) {
return false;
}

$loaded_modules = array_map(
static fn(string $module): string => explode(" ", trim($module))[0] ?? "",
explode("\n", shell_exec("apache2ctl -M 2>/dev/null") ?? '')
static fn(string $module): string => explode(' ', trim($module))[0] ?? '',
explode("\n", shell_exec('apache2ctl -M 2>/dev/null') ?? '')
);
} catch (\Throwable $e) {
$this->io?->error($e->getMessage());
$this->io?->error($e->getTraceAsString());
$loaded_modules = [];
}
return in_array('xsendfile_module', $loaded_modules, true);

return \in_array('xsendfile_module', $loaded_modules, true);
}

public function isApplicable(Environment $environment): bool
{
return !file_exists(BuildArtifactObjective::PATH());
return true;
}

}