ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
ilLTIViewGUI Class Reference

class for ILIAS ViewLTI More...

+ Collaboration diagram for ilLTIViewGUI:

Public Member Functions

 __construct ()
 
 init ()
 Init LTI mode for lti authenticated users. More...
 
 executeCommand ()
 
 isActive ()
 
 initGUI ()
 
 getPostData ()
 
 getExternalCss ()
 
 getTitle ()
 
 getTitleForExitPage ()
 
 getShortTitle ()
 
 exitLti ()
 exit LTI session and if defined redirecting to returnUrl ToDo: Standard Template with delos ... More...
 
 logout (bool $force_ilias_logout=false)
 logout ILIAS and destroys Session and ilClientId cookie if no consumer is still open in the LTI User Session More...
 
 getCmdLink (String $cmd)
 

Static Public Member Functions

static getInstance ()
 for compatiblity with ilLTIRouterGUI More...
 

Data Fields

const CHECK_HTTP_REFERER = true
 contstants More...
 
ilLanguage $lng = null
 public variables More...
 

Protected Member Functions

 getContextId ()
 

Private Member Functions

 isLTIUser ()
 get LTI Mode from Users->getAuthMode More...
 
 getSessionValue (string $sess_key)
 
 getCookieValue (string $cookie_key)
 
 removeContextFromSession (string $context_id)
 
 findEffectiveRefId (?string $url=null)
 Find effective ref_id for request. More...
 

Private Attributes

ILIAS DI Container $dic = null
 private variables More...
 
int $user = null
 
ilLogger $log = null
 
string $link_dir = ""
 
int $effectiveRefId = null
 
ILIAS HTTP Wrapper WrapperFactory $wrapper
 
ILIAS Refinery KindlyTo Group $kindlyTo
 
ilLocatorGUI $locator
 

Detailed Description

class for ILIAS ViewLTI

Author
Stefan Schneider <schne.nosp@m.ider.nosp@m.@hrz..nosp@m.uni-.nosp@m.marbu.nosp@m.rg.d.nosp@m.e
Version
$id$

ilLTIViewGUI: ilLTIRouterGUI

Definition at line 32 of file class.ilLTIViewGUI.php.

Constructor & Destructor Documentation

◆ __construct()

ilLTIViewGUI::__construct ( )

Definition at line 60 of file class.ilLTIViewGUI.php.

References $DIC, ilLoggerFactory\getLogger(), ILIAS\Repository\lng(), and ILIAS\Repository\locator().

61  {
62  global $DIC;
63  $this->dic = $DIC;
64  $this->log = ilLoggerFactory::getLogger('ltis');
65  $this->lng = $this->dic->language();
66  $this->lng->loadLanguageModule('lti');
67  $this->wrapper = $DIC->http()->wrapper();
68  $this->kindlyTo = $DIC->refinery()->kindlyTo();
69  $this->locator = $DIC['ilLocator'];
70  }
static getLogger(string $a_component_id)
Get component logger.
global $DIC
Definition: feed.php:28
+ Here is the call graph for this function:

Member Function Documentation

◆ executeCommand()

ilLTIViewGUI::executeCommand ( )
Returns
void

Definition at line 113 of file class.ilLTIViewGUI.php.

References exitLti().

113  : void
114  {
115  global $ilCtrl;
116  $cmd = $ilCtrl->getCmd();
117  switch ($cmd) {
118  case 'exit':
119  $this->exitLti();
120  break;
121  }
122  }
exitLti()
exit LTI session and if defined redirecting to returnUrl ToDo: Standard Template with delos ...
+ Here is the call graph for this function:

◆ exitLti()

ilLTIViewGUI::exitLti ( )

exit LTI session and if defined redirecting to returnUrl ToDo: Standard Template with delos ...

Definition at line 347 of file class.ilLTIViewGUI.php.

References $tpl, ilSession\clear(), getContextId(), getPostData(), ilSession\has(), ILIAS\Repository\lng(), logout(), and removeContextFromSession().

Referenced by executeCommand().

347  : void
348  {
349  $this->log->info("exitLTI");
350  $force_ilias_logout = false;
351  $context_id = $this->getContextId();
352  if ($context_id == 0) {
353  $this->log->warning("could not find any valid context_id!");
354  $force_ilias_logout = true;
355  }
356  $post_data = $this->getPostData();
357 
358  $return_url = '';
359  if (isset($post_data['launch_presentation_return_url'])) {
360  $return_url = $post_data['launch_presentation_return_url'];
361  }
362  $this->removeContextFromSession((string) $context_id);
363 
364  if (ilSession::has('lti_' . $context_id . '_post_data')) {
365  ilSession::clear('lti_' . $context_id . '_post_data');
366  $this->log->debug('unset SESSION["' . 'lti_' . $context_id . '_post_data"]');
367  }
368 
369  if (!isset($return_url) || $return_url === '') {
370  $cc = $this->dic->globalScreen()->tool()->context()->current();
371  $cc->addAdditionalData(LtiViewLayoutProvider::GS_EXIT_LTI, true);
372  $ui_factory = $this->dic->ui()->factory();
373  $renderer = $this->dic->ui()->renderer();
374  $content = [
375  $ui_factory->messageBox()->info($this->lng->txt('lti_exited_info'))
376  ];
377  $tpl = $this->dic["tpl"];
378  $tpl->setContent($renderer->render($content));
379  $this->logout($force_ilias_logout);
380  $tpl->printToStdout();
381  } else {
382  $this->logout($force_ilias_logout);
383  header('Location: ' . $return_url);
384  }
385  }
logout(bool $force_ilias_logout=false)
logout ILIAS and destroys Session and ilClientId cookie if no consumer is still open in the LTI User ...
removeContextFromSession(string $context_id)
static has($a_var)
if($DIC->http() ->request() ->getMethod()=="GET" &&isset($DIC->http() ->request() ->getQueryParams()['tex'])) $tpl
Definition: latex.php:41
static clear(string $a_var)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ findEffectiveRefId()

ilLTIViewGUI::findEffectiveRefId ( ?string  $url = null)
private

Find effective ref_id for request.

Parameters
string | null$url

Definition at line 457 of file class.ilLTIViewGUI.php.

References $query, $target_arr, $url, ilSession\get(), ilSession\has(), ILIAS\Repository\int(), and ilSession\set().

Referenced by getContextId().

457  : void
458  {
459  $query = [];
460  if ($url === null) {
461  if ($this->wrapper->query()->has('ref_id')) {
462  $query['ref_id'] = $this->wrapper->query()->retrieve('ref_id', $this->kindlyTo->string());
463  }
464  if ($this->wrapper->query()->has('target')) {
465  $query['target'] = $this->wrapper->query()->retrieve('target', $this->kindlyTo->string());
466  }
467  } else {
468  parse_str((string) parse_url($url, PHP_URL_QUERY), $query);
469  }
470  if (isset($query['ref_id']) && (int) $query['ref_id']) {
471  $this->effectiveRefId = (int) $query['ref_id'];
472  return;
473  }
474  if (ilSession::has('lti_init_target') && ilSession::get('lti_init_target') != "") {
475  $target_arr = explode('_', ilSession::get('lti_init_target'));
476  ilSession::set('lti_init_target', "");
477  } else {
478  if (isset($query['target'])) {
479  $target_arr = explode('_', (string) $query['target']);
480  }
481  }
482  if (isset($target_arr[1]) and (int) $target_arr[1]) {
483  $this->effectiveRefId = (int) $target_arr[1];
484  }
485  }
static get(string $a_var)
$target_arr
Definition: goto.php:50
static has($a_var)
$query
$url
static set(string $a_var, $a_val)
Set a value.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getCmdLink()

ilLTIViewGUI::getCmdLink ( String  $cmd)
Parameters
String$cmd
Returns
String
Exceptions
ilCtrlException

Definition at line 417 of file class.ilLTIViewGUI.php.

References getContextId().

417  : String
418  {
419  global $ilCtrl;
420  $lti_context_id = $this->getContextId();
421  $lti_context_id_param = ($lti_context_id != '') ? "&lti_context_id=" . $lti_context_id : '';
422  $targetScript = "";
423  return $this->link_dir . $targetScript . $this->dic->ctrl()->getLinkTargetByClass(array('illtiroutergui',strtolower(get_class($this))), $cmd) . "&baseClass=illtiroutergui" . $lti_context_id_param;
424  }
+ Here is the call graph for this function:

◆ getContextId()

ilLTIViewGUI::getContextId ( )
protected
Returns
int|null

Definition at line 153 of file class.ilLTIViewGUI.php.

References $_SERVER, $DIC, $effectiveRefId, $i, $path, $ref_id, ilObject\_lookupType(), CHECK_HTTP_REFERER, findEffectiveRefId(), ilSession\get(), ilSession\has(), ILIAS\Repository\int(), ILIAS\Repository\locator(), ilUtil\redirect(), and ilSession\set().

Referenced by exitLti(), getCmdLink(), and getPostData().

153  : ?int
154  {
155  global $DIC;
156 
157  // forced lti_context_id for example request command in exitLTI
158  if ($this->wrapper->query()->has('lti_context_id') &&
159  $this->wrapper->query()->retrieve('lti_context_id', $this->kindlyTo->string()) !== '') {
160  $contextId = (int) $this->wrapper->query()->retrieve('lti_context_id', $this->kindlyTo->int());
161  $this->log->debug("find context_id by GET param: " . (string) $contextId);
162  return $contextId;
163  }
164 
165  $this->findEffectiveRefId();
166 
167  if (
168  (
169  $this->wrapper->query()->has('baseClass') &&
170  $this->wrapper->query()->retrieve('baseClass', $this->kindlyTo->string()) === 'ilDashboardGUI'
171  )
172  &&
173  (
174  $this->wrapper->query()->has('cmd') &&
175  $this->wrapper->query()->retrieve('cmd', $this->kindlyTo->string()) === 'jumpToSelectedItems'
176  )
177  ) {
178  $this->log->debug("jumpToSelectedItems");
179  if (ilSession::get('lti_ref_id_at_init') != "") {
180  $this->effectiveRefId = (int) ilSession::get('lti_ref_id_at_init');
181  ilSession::set('lti_ref_id_at_init', "");
182  }
183  }
184 
186  if (empty($ref_id)) {
187  $this->log->debug("empty ref_id");
188  return 0;
189  }
190 
191  $this->log->debug("Effective ref_id: " . $ref_id);
192  //check
193  ilSession::set('lti_ref_id_at_init', (string) $ref_id);
194 
195 
196  // context_id = ref_id in request
197  if (ilSession::has('lti_' . $ref_id . '_post_data')) {
198  $this->log->debug("lti context session exists for " . $ref_id);
199  // return $ref_id;
200  }
201  // sub item request
202  $this->log->debug("ref_id not exists as context_id, walking tree backwards to find a valid context_id");
203  $locator_items = $this->locator->getItems();
204  if (is_array($locator_items) && count($locator_items) > 0) {
205  for ($i = count($locator_items) - 1;$i >= 0;$i--) {
206  if (ilSession::has('lti_' . $locator_items[$i]['ref_id'] . '_post_data')) {
207  $this->log->debug("found valid ref_id in locator: " . $locator_items[$i]['ref_id']);
208  return $locator_items[$i]['ref_id'];
209  }
210  }
211  }
212  $this->log->warning("no valid context_id found for ref_id request: " . $ref_id);
213 
216  $obj_type = ilObject::_lookupType($ref_id, true);
217  $context_id = 0;
218  $referer = 0;
219 
220  // first try to get real http referer
221  if (isset($_SERVER['HTTP_REFERER'])) {
222  $this->findEffectiveRefId($_SERVER['HTTP_REFERER']);
223  } else { // only fallback and not reliable on multiple browser LTi contexts
224  if (ilSession::has('referer_ref_id')) {
225  $this->effectiveRefId = ilSession::get('referer_ref_id');
226  }
227  }
228 
229  $referrer = (int) $this->effectiveRefId;
230 
231  if ($referer > 0) {
232  if (ilSession::has('lti_' . $referer . '_post_data')) {
233  $ref_id = $referer;
234  $context_id = $referer;
235  $obj_type = ilObject::_lookupType($ref_id, true);
236  $this->log->debug("referer obj_type: " . $obj_type);
237  } else {
238  $this->log->debug("search tree of referer...");
239  if ($this->dic->repositoryTree()->isInTree($referer)) {
240  $path = $this->dic->repositoryTree()->getPathId($referer);
241  for ($i = count($path) - 1;$i >= 0;$i--) {
242  if (ilSession::has('lti_' . $path[$i] . '_post_data')) {
243  // redirect to referer, because it is valid
244  $ref_id = $referer;
245  $context_id = $path[$i];
246  $obj_type = ilObject::_lookupType($ref_id, true);
247  break;
248  }
249  }
250  }
251  }
252  }
253  if ($ref_id > 0 && $obj_type != '') {
254  if (
255  (
256  $this->wrapper->query()->has('baseClass') &&
257  $this->wrapper->query()->retrieve('baseClass', $this->kindlyTo->string()) === 'ilDashboardGUI'
258  )
259  &&
260  (
261  $this->wrapper->query()->has('cmdClass') &&
262  $this->wrapper->query()->retrieve('cmdClass', $this->kindlyTo->string()) === 'ilpersonalprofilegui'
263  )
264  ) {
265  return $context_id;
266  }
267  // $this->dic->ui()->mainTemplate()->setOnScreenMessage('failure', $this->lng->txt('permission_denied'), true);
268  $redirect = $this->link_dir . "goto.php?target=" . $obj_type . "_" . $ref_id . "&lti_context_id=" . $context_id;
269  $this->log->debug("redirect: " . $redirect);
270  ilUtil::redirect($redirect);
271  }
272  }
273  $lti_context_ids = ilSession::get('lti_context_ids');
274  if (is_array($lti_context_ids) && count($lti_context_ids) > 0) {
275  if (count($lti_context_ids) == 1) {
276  $this->log->debug("using context_id from only LTI session");
277  return $lti_context_ids[0];
278  } else {
279  $this->log->warning("Multiple LTI sessions exists. The context_id can not be clearly detected");
280  }
281  }
282  return null;
283  }
static get(string $a_var)
$path
Definition: ltiservices.php:32
global $DIC
Definition: feed.php:28
$ref_id
Definition: ltiauth.php:67
$_SERVER['HTTP_HOST']
Definition: raiseError.php:10
static has($a_var)
static redirect(string $a_script)
const CHECK_HTTP_REFERER
contstants
static _lookupType(int $id, bool $reference=false)
static set(string $a_var, $a_val)
Set a value.
$i
Definition: metadata.php:41
findEffectiveRefId(?string $url=null)
Find effective ref_id for request.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getCookieValue()

ilLTIViewGUI::getCookieValue ( string  $cookie_key)
private

Definition at line 435 of file class.ilLTIViewGUI.php.

435  : string
436  {
437  if ($this->dic->wrapper->cookie()->has($cookie_key) && $this->dic->wrapper->cookie()->retrieve($cookie_key, $this->dic->refinery()->kindlyTo()->string() != '')) {
438  return $this->dic->wrapper->cookie()->retrieve($cookie_key, $this->dic->refinery()->kindlyTo()->string());
439  } else {
440  return '';
441  }
442  }

◆ getExternalCss()

ilLTIViewGUI::getExternalCss ( )
Returns
string

Definition at line 306 of file class.ilLTIViewGUI.php.

References getPostData().

306  : string
307  {
308  $post_data = $this->getPostData();
309  if ($post_data !== null) {
310  return (isset($post_data['launch_presentation_css_url'])) ? $post_data['launch_presentation_css_url'] : '';
311  }
312  return '';
313  }
+ Here is the call graph for this function:

◆ getInstance()

static ilLTIViewGUI::getInstance ( )
static

for compatiblity with ilLTIRouterGUI

Returns
mixed

Definition at line 89 of file class.ilLTIViewGUI.php.

References $DIC.

90  {
91  global $DIC;
92  return $DIC["lti"];
93  }
global $DIC
Definition: feed.php:28

◆ getPostData()

ilLTIViewGUI::getPostData ( )
Returns
array|null

Definition at line 288 of file class.ilLTIViewGUI.php.

References ilSession\get(), and getContextId().

Referenced by exitLti(), getExternalCss(), and getTitle().

288  : ?array
289  {
290  $context_id = $this->getContextId();
291  if ($context_id == 0) {
292  $this->log->warning("could not find any valid context_id!");
293  return null;
294  }
295  $post_data = ilSession::get('lti_' . $context_id . '_post_data');
296  if (!is_array($post_data)) {
297  $this->log->warning("no session post_data: " . "lti_" . $context_id . "_post_data");
298  return null;
299  }
300  return $post_data;
301  }
static get(string $a_var)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getSessionValue()

ilLTIViewGUI::getSessionValue ( string  $sess_key)
private

Definition at line 426 of file class.ilLTIViewGUI.php.

References ilSession\get(), and ilSession\has().

426  : string
427  {
428  if (ilSession::has($sess_key) && ilSession::get($sess_key) != '') {
429  return ilSession::get($sess_key);
430  } else {
431  return '';
432  }
433  }
static get(string $a_var)
static has($a_var)
+ Here is the call graph for this function:

◆ getShortTitle()

ilLTIViewGUI::getShortTitle ( )
Returns
string

Definition at line 338 of file class.ilLTIViewGUI.php.

References ILIAS\Repository\lng().

338  : string
339  {
340  return $this->lng->txt('lti_mode');
341  }
+ Here is the call graph for this function:

◆ getTitle()

ilLTIViewGUI::getTitle ( )
Returns
string

Definition at line 318 of file class.ilLTIViewGUI.php.

References getPostData().

318  : string
319  {
320  $post_data = $this->getPostData();
321  if ($post_data !== null) {
322  return (isset($post_data['resource_link_title'])) ? "LTI - " . $post_data['resource_link_title'] : "LTI";
323  }
324  return "LTI";
325  }
+ Here is the call graph for this function:

◆ getTitleForExitPage()

ilLTIViewGUI::getTitleForExitPage ( )
Returns
string

Definition at line 330 of file class.ilLTIViewGUI.php.

References ILIAS\Repository\lng().

330  : string
331  {
332  return $this->lng->txt('lti_exited');
333  }
+ Here is the call graph for this function:

◆ init()

ilLTIViewGUI::init ( )

Init LTI mode for lti authenticated users.

Definition at line 75 of file class.ilLTIViewGUI.php.

References $context, initGUI(), and isLTIUser().

75  : void
76  {
77  $this->link_dir = (defined("ILIAS_MODULE")) ? "../" : "";
78  if ($this->isLTIUser()) {
79  $context = $this->dic->globalScreen()->tool()->context();
80  $context->claim()->lti();
81  $this->initGUI();
82  }
83  }
$context
Definition: webdav.php:29
isLTIUser()
get LTI Mode from Users->getAuthMode
+ Here is the call graph for this function:

◆ initGUI()

ilLTIViewGUI::initGUI ( )
Returns
void

Definition at line 135 of file class.ilLTIViewGUI.php.

Referenced by init().

135  : void
136  {
137  $this->log->debug("initGUI");
138  $baseclass = '';
139  if ($this->wrapper->query()->has('baseClass')) {
140  $baseclass = strtolower($this->wrapper->query()->retrieve('baseClass', $this->kindlyTo->string()));
141  }
142  if ($this->wrapper->query()->has('cmdClass')) {
143  $cmdclass = strtolower($this->wrapper->query()->retrieve('cmdClass', $this->kindlyTo->string()));
144  }
145  if ($baseclass == 'illtiroutergui') {
146  return;
147  }
148  }
+ Here is the caller graph for this function:

◆ isActive()

ilLTIViewGUI::isActive ( )
Returns
bool

Definition at line 127 of file class.ilLTIViewGUI.php.

References isLTIUser().

127  : bool
128  {
129  return $this->isLTIUser();
130  }
isLTIUser()
get LTI Mode from Users->getAuthMode
+ Here is the call graph for this function:

◆ isLTIUser()

ilLTIViewGUI::isLTIUser ( )
private

get LTI Mode from Users->getAuthMode

Returns
bool

Definition at line 99 of file class.ilLTIViewGUI.php.

Referenced by init(), and isActive().

99  : bool
100  {
101  if (!$this->dic->user() instanceof ilObjUser) {
102  return false;
103  }
104  if ($this->dic->user()->getAuthMode() == null) {
105  return false;
106  }
107  return (strpos($this->dic->user()->getAuthMode(), 'lti_') === 0);
108  }
+ Here is the caller graph for this function:

◆ logout()

ilLTIViewGUI::logout ( bool  $force_ilias_logout = false)

logout ILIAS and destroys Session and ilClientId cookie if no consumer is still open in the LTI User Session

Definition at line 390 of file class.ilLTIViewGUI.php.

References $auth, ilAuthUtils\AUTH_LOCAL, ilSession\get(), and ilUtil\setCookie().

Referenced by exitLti().

390  : void
391  {
392  if ($force_ilias_logout) {
393  $this->log->warning("forcing logout ilias session, maybe a broken LTI context");
394  } else {
395  if (is_array(ilSession::get('lti_context_ids')) && count(ilSession::get('lti_context_ids')) > 0) {
396  $this->log->debug("there is another valid consumer session: ilias session logout refused.");
397  return;
398  }
399  }
400  $this->log->info("logout");
401  $this->dic->user()->setAuthMode((string) ilAuthUtils::AUTH_LOCAL);
402  //ilSession::setClosingContext(ilSession::SESSION_CLOSE_USER); // needed?
403  $auth = $this->dic['ilAuthSession'];
404  //$auth->logout(); // needed?
405  // $auth->setExpired($auth::SESSION_AUTH_EXPIRED, ilAuthStatus::STATUS_UNDEFINED);
406  $auth->setExpired(true);
407  session_destroy();
408  ilUtil::setCookie("ilClientId", "");
409  ilUtil::setCookie("PHPSESSID", "");
410  }
static get(string $a_var)
$auth
Definition: metadata.php:76
static setCookie(string $a_cookie_name, string $a_cookie_value='', bool $a_also_set_super_global=true, bool $a_set_cookie_invalid=false)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ removeContextFromSession()

ilLTIViewGUI::removeContextFromSession ( string  $context_id)
private

Definition at line 444 of file class.ilLTIViewGUI.php.

References ilSession\get(), and ilSession\set().

Referenced by exitLti().

444  : void
445  {
446  $lti_context_ids = ilSession::get('lti_context_ids');
447  if (is_array($lti_context_ids) && in_array($context_id, $lti_context_ids)) {
448  array_splice($lti_context_ids, array_search($context_id, $lti_context_ids), 1);
449  ilSession::set('lti_context_ids', $lti_context_ids);
450  }
451  }
static get(string $a_var)
static set(string $a_var, $a_val)
Set a value.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Field Documentation

◆ $dic

ILIAS DI Container ilLTIViewGUI::$dic = null
private

private variables

Definition at line 42 of file class.ilLTIViewGUI.php.

◆ $effectiveRefId

int ilLTIViewGUI::$effectiveRefId = null
private

Definition at line 47 of file class.ilLTIViewGUI.php.

Referenced by getContextId().

◆ $kindlyTo

ILIAS Refinery KindlyTo Group ilLTIViewGUI::$kindlyTo
private

Definition at line 49 of file class.ilLTIViewGUI.php.

◆ $link_dir

string ilLTIViewGUI::$link_dir = ""
private

Definition at line 45 of file class.ilLTIViewGUI.php.

◆ $lng

ilLanguage ilLTIViewGUI::$lng = null

public variables

Definition at line 55 of file class.ilLTIViewGUI.php.

◆ $locator

ilLocatorGUI ilLTIViewGUI::$locator
private

Definition at line 50 of file class.ilLTIViewGUI.php.

◆ $log

ilLogger ilLTIViewGUI::$log = null
private

Definition at line 44 of file class.ilLTIViewGUI.php.

◆ $user

int ilLTIViewGUI::$user = null
private

Definition at line 43 of file class.ilLTIViewGUI.php.

◆ $wrapper

ILIAS HTTP Wrapper WrapperFactory ilLTIViewGUI::$wrapper
private

Definition at line 48 of file class.ilLTIViewGUI.php.

◆ CHECK_HTTP_REFERER

const ilLTIViewGUI::CHECK_HTTP_REFERER = true

contstants

Definition at line 37 of file class.ilLTIViewGUI.php.

Referenced by getContextId().


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