ILIAS  trunk Revision v13.0_alpha-62-g3b72d83f2e5
ILIAS\FileDelivery\Delivery\StreamDelivery Class Reference
+ Inheritance diagram for ILIAS\FileDelivery\Delivery\StreamDelivery:
+ Collaboration diagram for ILIAS\FileDelivery\Delivery\StreamDelivery:

Public Member Functions

 __construct (private DataSigning $data_signer, GlobalHttpState $http, ResponseBuilder $response_builder, ResponseBuilder $fallback_response_builder, IsolationConfig $isolation=new IsolationConfig(false, null, null),)
 
 attached (FileStream $stream, string $download_file_name, ?string $mime_type=null)
 
 inline (FileStream $stream, string $download_file_name, ?string $mime_type=null)
 
 deliver (FileStream $stream, string $download_file_name, ?string $mime_type=null, Disposition $disposition=Disposition::INLINE)
 
 deliverFromToken (string $token)
 
- Public Member Functions inherited from ILIAS\FileDelivery\Delivery\BaseDelivery
 __construct (protected GlobalHttpState $http, protected ResponseBuilder $response_builder, protected ResponseBuilder $fallback_response_builder, protected IsolationConfig $isolation=new IsolationConfig(false, null, null),)
 

Data Fields

const SUBREQUEST_SEPARATOR = '/-/'
 

Private Member Functions

 isTemporaryFile (string $uri)
 
 determineMimeType (string $filename)
 

Additional Inherited Members

- Protected Member Functions inherited from ILIAS\FileDelivery\Delivery\BaseDelivery
 isRequestHostAllowed ()
 When user content isolation is active, only requests targeting the configured content domain may be served. More...
 
 isRequestOnContentHost ()
 Inverse of {. More...
 
 notFound (ResponseInterface $r)
 Send an empty 404 response and terminate. More...
 
 saveAndClose (ResponseInterface $r, ?string $path_to_delete=null)
 
 setGeneralHeaders (ResponseInterface $r, string $uri, string $mime_type, string $file_name, Disposition $disposition=Disposition::INLINE, bool $isolated=true)
 
 applyIsolationHeaders (ResponseInterface $r)
 When isolation is active, harden delivery responses: More...
 
- Protected Attributes inherited from ILIAS\FileDelivery\Delivery\BaseDelivery
const MIME_TYPE_MAP = __DIR__ . '/../../../FileUpload/src/mime_type_map.php'
 
array $mime_type_map
 

Detailed Description

Author
Fabian Schmid fabia.nosp@m.n@sr.nosp@m..solu.nosp@m.tion.nosp@m.s

Definition at line 36 of file StreamDelivery.php.

Constructor & Destructor Documentation

◆ __construct()

ILIAS\FileDelivery\Delivery\StreamDelivery::__construct ( private DataSigning  $data_signer,
GlobalHttpState  $http,
ResponseBuilder  $response_builder,
ResponseBuilder  $fallback_response_builder,
IsolationConfig  $isolation = new IsolationConfig(false, null, null) 
)

Definition at line 43 of file StreamDelivery.php.

49 {
50 parent::__construct($http, $response_builder, $fallback_response_builder, $isolation);
51 }
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc

References ILIAS\BookingManager\Common\Table\$http, and ILIAS\GlobalScreen\Provider\__construct().

+ Here is the call graph for this function:

Member Function Documentation

◆ attached()

ILIAS\FileDelivery\Delivery\StreamDelivery::attached ( FileStream  $stream,
string  $download_file_name,
?string  $mime_type = null 
)

Definition at line 53 of file StreamDelivery.php.

57 : never {
58 $this->deliver(
59 $stream,
62 Disposition::ATTACHMENT
63 );
64 }
deliver(FileStream $stream, string $download_file_name, ?string $mime_type=null, Disposition $disposition=Disposition::INLINE)

◆ deliver()

ILIAS\FileDelivery\Delivery\StreamDelivery::deliver ( FileStream  $stream,
string  $download_file_name,
?string  $mime_type = null,
Disposition  $disposition = Disposition::INLINE 
)

Definition at line 79 of file StreamDelivery.php.

84 : never {
85 $r = $this->http->response();
86 $uri = $stream->getMetadata()['uri'];
87
88 // Temporary files (e.g. ZIPs built by ILIAS\Filesystem\Util\Archive\Zip) are removed by a
89 // shutdown function as soon as this request exits. Header based delivery (X-Sendfile,
90 // X-Accel-Redirect) opens the file only after PHP has finished, so it would no longer exist.
91 // Such files must be streamed by PHP itself, see https://mantis.ilias.de/view.php?id=48367
92 if (
93 $stream instanceof ZIPStream
94 || $uri === 'php://memory'
95 || $this->isTemporaryFile((string) $uri)
96 ) {
97 $this->response_builder = $this->fallback_response_builder;
98 }
99
100 $r = $this->setGeneralHeaders(
101 $r,
102 $uri,
103 $mime_type ?? mime_content_type($uri),
106 );
107
108 $r = $this->response_builder->buildForStream(
109 $this->http->request(),
110 $r,
111 $stream
112 );
113 $this->saveAndClose($r);
114 }
saveAndClose(ResponseInterface $r, ?string $path_to_delete=null)
setGeneralHeaders(ResponseInterface $r, string $uri, string $mime_type, string $file_name, Disposition $disposition=Disposition::INLINE, bool $isolated=true)
static http()
Fetches the global http state from ILIAS.

◆ deliverFromToken()

ILIAS\FileDelivery\Delivery\StreamDelivery::deliverFromToken ( string  $token)

Definition at line 134 of file StreamDelivery.php.

134 : never
135 {
136 $r = $this->http->response();
137
138 // check if $token has a sub-request, such as .../index.html
139 $parts = explode(self::SUBREQUEST_SEPARATOR, $token);
140 $sub_request = null;
141 if (count($parts) > 1) {
142 $token = $parts[0];
143 $sub_request = implode('/', array_slice($parts, 1));
144 }
145
146 $payload = $this->data_signer->verifyStreamToken($token);
147
148 // a token signed for the ILIAS domain is served there only, all others only on the content domain
149 $isolated = !$payload instanceof ShortFilePayload || $payload->isIsolated();
150 $host_allowed = $isolated ? $this->isRequestHostAllowed() : !$this->isRequestOnContentHost();
151 if (!$host_allowed) {
152 $this->notFound($r);
153 }
154
155 switch (true) {
156 case $payload instanceof FilePayload:
157 $uri = $payload->getUri();
158 $mime_type = $payload->getMimeType();
159 $file_name = $payload->getFilename();
160 $disposition = Disposition::tryFrom($payload->getDisposition()) ?? Disposition::INLINE;
161 break;
162 case $payload instanceof ShortFilePayload:
163 $uri = $payload->getUri();
164 $mime_type = $this->determineMimeType($uri);
165 $file_name = $payload->getFilename();
166 $disposition = Disposition::INLINE;
167 break;
168 default:
169 $this->notFound($r);
170 }
171 unset($payload);
172
173 // handle direct access to file
174
175 if ($sub_request === null) {
176 $r = $this->setGeneralHeaders(
177 $r,
178 $uri,
180 $file_name,
182 $isolated
183 );
184
185 $this->http->saveResponse(
186 $this->response_builder->buildForStream(
187 $this->http->request(),
188 $r,
189 Streams::ofResource(fopen($uri, 'rb'))
190 )
191 );
192 } else { // handle subrequest, aka file in a ZIP
193 $requested_zip = $uri;
194 $sub_request = urldecode($sub_request);
195 // remove query
196 $sub_request = explode('?', $sub_request)[0];
197
198 try {
199 $file_inside_ZIP = Streams::ofFileInsideZIP($requested_zip, $sub_request);
200 } catch (\Throwable) {
201 $this->notFound($r);
202 }
203 $file_inside_zip_uri = $file_inside_ZIP->getMetadata()['uri'];
204 $file_inside_zip_stream = fopen($file_inside_zip_uri, 'rb');
205
206 if ($file_inside_zip_stream === false) {
207 $this->notFound($r);
208 }
209
210 // we must use PHPResponseBuilder here, because the streams inside zips cant be delivered using XSendFile or others
211 $this->response_builder = $this->fallback_response_builder;
212
213 $mime_type = $this->determineMimeType($file_inside_zip_uri);
214 $r = $this->setGeneralHeaders(
215 $r,
216 $file_inside_zip_uri,
218 basename($sub_request),
219 Disposition::INLINE, // subrequests are always inline per default, browsers may change this to download
220 $isolated
221 );
222
223
224 $this->http->saveResponse(
225 $this->response_builder->buildForStream(
226 $this->http->request(),
227 $r,
228 $file_inside_ZIP
229 )
230 );
231 }
232 $this->http->sendResponse();
233 $this->http->close();
234 }
isRequestHostAllowed()
When user content isolation is active, only requests targeting the configured content domain may be s...
notFound(ResponseInterface $r)
Send an empty 404 response and terminate.
static ofFileInsideZIP(string $path_to_zip, string $path_inside_zip)
Definition: Streams.php:84
static ofResource($resource)
Wraps an already created resource with the stream abstraction.
Definition: Streams.php:64
$token
Definition: xapitoken.php:69

References $token, ILIAS\FileDelivery\Token\Signer\Payload\FilePayload\getUri(), ILIAS\FileDelivery\Token\Signer\Payload\ShortFilePayload\getUri(), ILIAS\FileDelivery\http(), and ILIAS\FileDelivery\Token\Signer\Payload\ShortFilePayload\isIsolated().

Referenced by ILIAS\Tests\FileDelivery\Delivery\StreamDeliveryIsolationTest\deliverFromToken().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ determineMimeType()

ILIAS\FileDelivery\Delivery\StreamDelivery::determineMimeType ( string  $filename)
private

Definition at line 236 of file StreamDelivery.php.

236 : string
237 {
238 $suffix = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
239 if (isset($this->mime_type_map[$suffix])) {
240 if (is_array($this->mime_type_map[$suffix]) && isset($this->mime_type_map[$suffix][0])) {
241 return $this->mime_type_map[$suffix][0];
242 }
243
244 return $this->mime_type_map[$suffix];
245 }
246
247 $mime_type = mime_content_type($filename);
248 if ($mime_type === 'application/octet-stream') {
249 $mime_type = mime_content_type(substr($filename, 64));
250 }
251 return $mime_type ?: 'application/octet-stream';
252 }
$filename
Definition: buildRTE.php:78

References $filename.

◆ inline()

ILIAS\FileDelivery\Delivery\StreamDelivery::inline ( FileStream  $stream,
string  $download_file_name,
?string  $mime_type = null 
)

Definition at line 66 of file StreamDelivery.php.

70 : never {
71 $this->deliver(
72 $stream,
75 Disposition::INLINE
76 );
77 }

References ILIAS\FileDelivery\Delivery\$download_file_name, ILIAS\FileDelivery\Delivery\$mime_type, and ILIAS\FileDelivery\Delivery\deliver().

+ Here is the call graph for this function:

◆ isTemporaryFile()

ILIAS\FileDelivery\Delivery\StreamDelivery::isTemporaryFile ( string  $uri)
private

Definition at line 116 of file StreamDelivery.php.

116 : bool
117 {
118 $real_path = realpath($uri);
119 if ($real_path === false) {
120 return false;
121 }
122 $temp_dirs = array_filter([
123 defined('CLIENT_DATA_DIR') ? realpath(\CLIENT_DATA_DIR . '/temp') : false,
124 realpath(sys_get_temp_dir()),
125 ]);
126 foreach ($temp_dirs as $temp_dir) {
127 if (str_starts_with($real_path, rtrim($temp_dir, '/') . '/')) {
128 return true;
129 }
130 }
131 return false;
132 }
const CLIENT_DATA_DIR
Definition: constants.php:46

References CLIENT_DATA_DIR.

Field Documentation

◆ SUBREQUEST_SEPARATOR

const ILIAS\FileDelivery\Delivery\StreamDelivery::SUBREQUEST_SEPARATOR = '/-/'

The documentation for this class was generated from the following file: