ILIAS  release_8 Revision v8.23
class.ilWACSignedPath.php
Go to the documentation of this file.
1 <?php
2 
19 // declare(strict_types=1);
25 
33 {
34  public const WAC_TOKEN_ID = 'il_wac_token';
35  public const WAC_TIMESTAMP_ID = 'il_wac_ts';
36  public const WAC_TTL_ID = 'il_wac_ttl';
37  public const TS_SUFFIX = 'ts';
38  public const TTL_SUFFIX = 'ttl';
39  public const MAX_LIFETIME = 600;
40 
41  protected ?ilWACPath $path_object = null;
42  protected ?ilWACToken $token_instance = null;
43  protected int $type = PathType::FILE;
44  protected static int $token_max_lifetime_in_seconds = 3;
45  protected static int $cookie_max_lifetime_in_seconds = 300;
46  protected bool $checked = false;
49 
53  public function __construct(ilWACPath $ilWACPath, GlobalHttpState $httpState, CookieFactory $cookieFactory)
54  {
55  $this->setPathObject($ilWACPath);
56  $this->httpService = $httpState;
57  $this->cookieFactory = $cookieFactory;
58  }
59 
63  public function getSignedPath(): string
64  {
65  if ($this->getType() !== PathType::FILE) {
67  }
68  if ($this->getPathObject()->getOriginalRequest() === '' || $this->getPathObject()->getOriginalRequest() === '0') {
69  return '';
70  }
71  if (!$this->getPathObject()->fileExists()) {
72  // return $this->getPathObject()->getOriginalRequest();
73  }
74 
75  if (strpos($this->getPathObject()->getPath(), '?')) {
76  $path = $this->getPathObject()->getPath() . '&' . self::WAC_TOKEN_ID . '='
77  . $this->getTokenInstance()->getToken();
78  } else {
79  $path = $this->getPathObject()->getPath() . '?' . self::WAC_TOKEN_ID . '='
80  . $this->getTokenInstance()->getToken();
81  }
82 
83  $path .= '&' . self::WAC_TTL_ID . '=' . $this->getTokenInstance()->getTTL();
84 
85  return $path . '&' . self::WAC_TIMESTAMP_ID . '='
86  . $this->getTokenInstance()->getTimestamp();
87  }
88 
89  public function isFolderSigned(): bool
90  {
91  $this->httpService->cookieJar();
92 
93  $this->setType(PathType::FOLDER);
94  $plain_token = $this->buildTokenInstance();
95  $name = $plain_token->getHashedId();
96 
97  // Token
98  $default_token = '';
99  $token_cookie_value = $this->httpService->request()->getCookieParams()[$name] ?? $default_token;
100  // Timestamp
101  $default_timestamp = 0;
102  $timestamp_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TS_SUFFIX] ?? $default_timestamp;
103  $timestamp_cookie_value = (int) $timestamp_cookie_value;
104  // TTL
105  $default_ttl = 0;
106  $ttl_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TTL_SUFFIX] ?? $default_ttl;
107  $ttl_cookie_value = (int) $ttl_cookie_value;
108 
109  $this->getPathObject()->setToken($token_cookie_value);
110  $this->getPathObject()->setTimestamp($timestamp_cookie_value);
111  $this->getPathObject()->setTTL($ttl_cookie_value);
112  $this->buildAndSetTokenInstance();
113 
114  return $this->getPathObject()->hasToken();
115  }
116 
120  public function isFolderTokenValid(): bool
121  {
122  if (!$this->isFolderSigned()) {
123  return false;
124  }
125 
126  return $this->checkToken();
127  }
128 
129  protected function saveFolderToken(): void
130  {
131  $ttl = $this->getPathObject()->getTTL();
132  $cookie_lifetime = $ttl !== 0 ? $ttl : self::getCookieMaxLifetimeInSeconds();
133  $id = $this->getTokenInstance()->getHashedId();
134  $expire = time() + $cookie_lifetime + 3600;
135  $secure = true;
136  $domain = null;
137  $http_only = true;
138  $path = '/';
139 
140  $tokenCookie = $this->cookieFactory->create($id, $this->getTokenInstance()->getToken())
141  ->withExpires($expire)
142  ->withPath($path)
143  ->withSecure($secure)
144  ->withDomain($domain)
145  ->withHttpOnly($http_only);
146 
147  $timestampCookie = $this->cookieFactory->create($id . self::TS_SUFFIX, time())
148  ->withExpires($expire)
149  ->withPath($path)
150  ->withDomain($domain)
151  ->withSecure($secure)
152  ->withHttpOnly($http_only);
153 
154  $ttlCookie = $this->cookieFactory->create($id . self::TTL_SUFFIX, $cookie_lifetime)
155  ->withExpires($expire)
156  ->withPath($path)
157  ->withDomain($domain)
158  ->withSecure($secure)
159  ->withHttpOnly($http_only);
160 
161  $jar = $this->httpService->cookieJar()->with($tokenCookie)
162  ->with($timestampCookie)
163  ->with($ttlCookie);
164 
165  // FIX: currently the cookies are never stored, we must use setcookie
166  foreach ($jar->getAll() as $cookie) {
167  setcookie(
168  $cookie->getName(),
169  $cookie->getValue(),
170  $cookie->getExpires(),
171  $cookie->getPath(),
172  $cookie->getDomain(),
173  $cookie->getSecure(),
174  $cookie->getHttpOnly()
175  );
176  }
177  }
178 
179  public function revalidatingFolderToken(): bool
180  {
181  if ($this->getType() !== PathType::FOLDER) {
182  return false;
183  }
184  $this->buildAndSetTokenInstance(time(), $this->getPathObject()->getTTL());
185  $this->getPathObject()->setTTL($this->getTokenInstance()->getTTL());
186  $this->getPathObject()->setTimestamp($this->getTokenInstance()->getTimestamp());
187  $this->getPathObject()->setToken($this->getTokenInstance()->getToken());
188 
189  $this->saveFolderToken();
190 
191  return true;
192  }
193 
194  public function isSignedPath(): bool
195  {
196  return ($this->getPathObject()->hasToken() && $this->getPathObject()->hasTimestamp()
197  && $this->getPathObject()->hasTTL());
198  }
199 
203  public function isSignedPathValid(): bool
204  {
205  $this->buildAndSetTokenInstance($this->getPathObject()->getTimestamp(), $this->getPathObject()->getTTL());
206 
207  return $this->checkToken();
208  }
209 
215  public static function signFile(string $path_to_file): string
216  {
217  global $DIC;
218  if ($path_to_file === '' || $path_to_file === '0') {
219  return '';
220  }
221  $ilWACPath = new ilWACPath($path_to_file, false);
222  if ($ilWACPath->getClient() === '' || $ilWACPath->getClient() === '0') {
223  return $path_to_file;
224  }
225  $obj = new self($ilWACPath, $DIC->http(), new CookieFactoryImpl());
226  $obj->setType(PathType::FILE);
227  $obj->buildAndSetTokenInstance(time(), self::getTokenMaxLifetimeInSeconds());
228 
229  return $obj->getSignedPath();
230  }
231 
232  public static function signFolderOfStartFile(string $start_file_path): void
233  {
234  global $DIC;
235  $obj = new self(new ilWACPath($start_file_path, false), $DIC->http(), new CookieFactoryImpl());
236  $obj->setType(PathType::FOLDER);
237  $obj->buildAndSetTokenInstance(time(), self::getCookieMaxLifetimeInSeconds());
238  $obj->saveFolderToken();
239  }
240 
241  public function getTokenInstance(): ?\ilWACToken
242  {
243  return $this->token_instance;
244  }
245 
246  public function setTokenInstance(ilWACToken $token_instance): void
247  {
248  $this->token_instance = $token_instance;
249  }
250 
251  public function getType(): int
252  {
253  return $this->type;
254  }
255 
256  public function setType(int $type): void
257  {
258  $this->type = $type;
259  }
260 
261  public function getPathObject(): ?\ilWACPath
262  {
263  return $this->path_object;
264  }
265 
266  public function setPathObject(ilWACPath $path_object): void
267  {
268  $this->path_object = $path_object;
269  }
270 
274  protected function checkToken(): bool
275  {
276  $request_token_string = $this->getPathObject()->getToken();
277  $request_ttl = $this->getPathObject()->getTTL();
278  $request_timestamp = $this->getPathObject()->getTimestamp();
279  $current_timestamp = time();
280 
281  $timestamp_valid = ($current_timestamp < ($request_timestamp + $request_ttl));
282 
283  if (!$timestamp_valid) {
284  $this->setChecked(true);
285 
286  return false;
287  }
288 
289  $simulated_token = $this->buildTokenInstance($request_timestamp, $request_ttl);
290  $simulated_token_string = $simulated_token->getToken();
291  $token_valid = ($simulated_token_string === $request_token_string);
292 
293  if (!$token_valid) {
294  $this->setChecked(true);
295 
296  return false;
297  }
298 
299  return true;
300  }
301 
306  protected function buildTokenInstance(int $timestamp = 0, int $ttl = 0): \ilWACToken
307  {
308  if ($this->getType() === 0) {
310  }
311 
312  switch ($this->getType()) {
313  case PathType::FOLDER:
314  $path = $this->getPathObject()->getSecurePath();
315  break;
316  default:
317  $path = $this->getPathObject()->getPathWithoutQuery();
318  break;
319  }
320 
321  $client = $this->getPathObject()->getClient();
322  $timestamp = $timestamp !== 0 ? $timestamp : $this->getPathObject()->getTimestamp();
323  $ttl = $ttl !== 0 ? $ttl : $this->getPathObject()->getTTL();
324 
325  return new ilWACToken($path, $client, $timestamp, $ttl);
326  }
327 
332  public function buildAndSetTokenInstance(int $timestamp = 0, int $ttl = 0): void
333  {
334  $this->setTokenInstance($this->buildTokenInstance($timestamp, $ttl));
335  }
336 
337  public static function getTokenMaxLifetimeInSeconds(): int
338  {
339  return self::$token_max_lifetime_in_seconds;
340  }
341 
346  public static function setTokenMaxLifetimeInSeconds(int $token_max_lifetime_in_seconds): void
347  {
348  if ($token_max_lifetime_in_seconds > self::MAX_LIFETIME) {
350  }
351  self::$token_max_lifetime_in_seconds = $token_max_lifetime_in_seconds;
352  }
353 
354  public static function getCookieMaxLifetimeInSeconds(): int
355  {
356  return self::$cookie_max_lifetime_in_seconds;
357  }
358 
364  public static function setCookieMaxLifetimeInSeconds(int $cookie_max_lifetime_in_seconds): void
365  {
366  if ($cookie_max_lifetime_in_seconds > self::MAX_LIFETIME) {
368  }
369  self::$cookie_max_lifetime_in_seconds = $cookie_max_lifetime_in_seconds;
370  }
371 
372  protected function getRelevantLifeTime(): int
373  {
374  $request_ttl = $this->getPathObject()->getTTL();
375  if ($request_ttl > 0) {
376  return $request_ttl;
377  }
378  switch ($this->getType()) {
379  case PathType::FOLDER:
380  $life_time = self::getCookieMaxLifetimeInSeconds();
381  break;
382  case PathType::FILE:
383  $life_time = self::getTokenMaxLifetimeInSeconds();
384  break;
385  default:
386  $life_time = 0;
387  break;
388  }
389 
390  return $life_time;
391  }
392 
393  public function isChecked(): bool
394  {
395  return $this->checked;
396  }
397 
398  public function setChecked(bool $checked): void
399  {
400  $this->checked = $checked;
401  }
402 }
Interface GlobalHttpState.
static getCookieMaxLifetimeInSeconds()
setTokenInstance(ilWACToken $token_instance)
buildAndSetTokenInstance(int $timestamp=0, int $ttl=0)
__construct(ilWACPath $ilWACPath, GlobalHttpState $httpState, CookieFactory $cookieFactory)
ilWACSignedPath constructor.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static setTokenMaxLifetimeInSeconds(int $token_max_lifetime_in_seconds)
static setCookieMaxLifetimeInSeconds(int $cookie_max_lifetime_in_seconds)
static int $token_max_lifetime_in_seconds
$path
Definition: ltiservices.php:32
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
global $DIC
Definition: feed.php:28
$client
if($format !==null) $name
Definition: metadata.php:247
static signFolderOfStartFile(string $start_file_path)
setPathObject(ilWACPath $path_object)
buildTokenInstance(int $timestamp=0, int $ttl=0)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
GlobalHttpState $httpService
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
CookieFactory $cookieFactory
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:70
static int $cookie_max_lifetime_in_seconds
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
static signFile(string $path_to_file)
static getTokenMaxLifetimeInSeconds()
setChecked(bool $checked)