TYPO3 CMS  TYPO3_6-2
BackendUserAuthentication.php
Go to the documentation of this file.
1 <?php
3 
20 
32 
38  public $usergroup_column = 'usergroup';
39 
45  public $usergroup_table = 'be_groups';
46 
53  public $groupData = array(
54  'filemounts' => array()
55  );
56 
62  public $userGroups = array();
63 
69  public $userGroupsUID = array();
70 
76  public $groupList = '';
77 
87  public $workspace = -99;
88 
94  public $workspaceRec = array();
95 
104  public $dataLists = array(
105  'webmount_list' => '',
106  'filemount_list' => '',
107  'file_permissions' => '',
108  'modList' => '',
109  'tables_select' => '',
110  'tables_modify' => '',
111  'pagetypes_select' => '',
112  'non_exclude_fields' => '',
113  'explicit_allowdeny' => '',
114  'allowed_languages' => '',
115  'workspace_perms' => '',
116  'custom_options' => ''
117  );
118 
124  public $includeHierarchy = array();
125 
131  public $includeGroupArray = array();
132 
138  public $OS = '';
139 
145  public $TSdataArray = array();
146 
152  public $userTS_text = '';
153 
159  public $userTS = array();
160 
166  public $userTSUpdated = FALSE;
167 
173  public $userTS_dontGetCached = FALSE;
174 
180  public $RTE_errors = array();
181 
187  public $errorMsg = '';
188 
195 
199  protected $fileStorages;
200 
204  protected $filePermissions;
205 
211  public $session_table = 'be_sessions';
212 
218  public $user_table = 'be_users';
219 
225  public $username_column = 'username';
226 
232  public $userident_column = 'password';
233 
239  public $userid_column = 'uid';
240 
245  public $lastLogin_column = 'lastlogin';
246 
251  public $enablecolumns = array(
252  'rootLevel' => 1,
253  'deleted' => 'deleted',
254  'disabled' => 'disable',
255  'starttime' => 'starttime',
256  'endtime' => 'endtime'
257  );
258 
264  public $formfield_uname = 'username';
265 
271  public $formfield_uident = 'userident';
272 
278  public $formfield_chalvalue = 'challenge';
279 
285  public $formfield_status = 'login_status';
286 
292  public $writeStdLog = TRUE;
293 
299  public $writeAttemptLog = TRUE;
300 
308  public $auth_timeout_field = 6000;
309 
315 
319  public $firstMainGroup = 0;
320 
326  public $uc;
327 
338  public $uc_default = array(
339  'interfaceSetup' => '',
340  // serialized content that is used to store interface pane and menu positions. Set by the logout.php-script
341  'moduleData' => array(),
342  // user-data for the modules
343  'thumbnailsByDefault' => 1,
344  'emailMeAtLogin' => 0,
345  'noMenuMode' => 0,
346  'startModule' => 'help_aboutmodules',
347  'hideSubmoduleIcons' => 0,
348  'helpText' => 1,
349  'titleLen' => 50,
350  'edit_showFieldHelp' => 'icon',
351  'edit_RTE' => '1',
352  'edit_docModuleUpload' => '1',
353  'navFrameWidth' => '',
354  // Default is 245 pixels
355  'navFrameResizable' => 0,
356  'resizeTextareas' => 1,
357  'resizeTextareas_MaxHeight' => 500,
358  'resizeTextareas_Flexible' => 0
359  );
360 
364  public function __construct() {
365  parent::__construct();
366  $this->name = self::getCookieName();
367  $this->loginType = 'BE';
368  }
369 
377  public function isAdmin() {
378  return is_array($this->user) && ($this->user['admin'] & 1) == 1;
379  }
380 
390  public function isMemberOfGroup($groupId) {
391  $groupId = (int)$groupId;
392  if ($this->groupList && $groupId) {
393  return GeneralUtility::inList($this->groupList, $groupId);
394  }
395  return FALSE;
396  }
397 
414  public function doesUserHaveAccess($row, $perms) {
415  $userPerms = $this->calcPerms($row);
416  return ($userPerms & $perms) == $perms;
417  }
418 
436  public function isInWebMount($id, $readPerms = '', $exitOnError = 0) {
437  if (!$GLOBALS['TYPO3_CONF_VARS']['BE']['lockBeUserToDBmounts'] || $this->isAdmin()) {
438  return 1;
439  }
440  $id = (int)$id;
441  // Check if input id is an offline version page in which case we will map id to the online version:
442  $checkRec = BackendUtility::getRecord('pages', $id, 'pid,t3ver_oid');
443  if ($checkRec['pid'] == -1) {
444  $id = (int)$checkRec['t3ver_oid'];
445  }
446  if (!$readPerms) {
447  $readPerms = $this->getPagePermsClause(1);
448  }
449  if ($id > 0) {
450  $wM = $this->returnWebmounts();
451  $rL = BackendUtility::BEgetRootLine($id, ' AND ' . $readPerms);
452  foreach ($rL as $v) {
453  if ($v['uid'] && in_array($v['uid'], $wM)) {
454  return $v['uid'];
455  }
456  }
457  }
458  if ($exitOnError) {
459  throw new \RuntimeException('Access Error: This page is not within your DB-mounts', 1294586445);
460  }
461  return NULL;
462  }
463 
473  public function modAccess($conf, $exitOnError) {
474  if (!BackendUtility::isModuleSetInTBE_MODULES($conf['name'])) {
475  if ($exitOnError) {
476  throw new \RuntimeException('Fatal Error: This module "' . $conf['name'] . '" is not enabled in TBE_MODULES', 1294586446);
477  }
478  return FALSE;
479  }
480  // Workspaces check:
481  if (
482  !empty($conf['workspaces'])
483  && \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('workspaces')
484  && ($this->workspace !== 0 || !GeneralUtility::inList($conf['workspaces'], 'online'))
485  && ($this->workspace !== -1 || !GeneralUtility::inList($conf['workspaces'], 'offline'))
486  && ($this->workspace <= 0 || !GeneralUtility::inList($conf['workspaces'], 'custom'))
487  ) {
488  if ($exitOnError) {
489  throw new \RuntimeException('Workspace Error: This module "' . $conf['name'] . '" is not available under the current workspace', 1294586447);
490  }
491  return FALSE;
492  }
493  // Returns TRUE if conf[access] is not set at all or if the user is admin
494  if (!$conf['access'] || $this->isAdmin()) {
495  return TRUE;
496  }
497  // If $conf['access'] is set but not with 'admin' then we return TRUE, if the module is found in the modList
498  $acs = FALSE;
499  if (!strstr($conf['access'], 'admin') && $conf['name']) {
500  $acs = $this->check('modules', $conf['name']);
501  }
502  if (!$acs && $exitOnError) {
503  throw new \RuntimeException('Access Error: You don\'t have access to this module.', 1294586448);
504  } else {
505  return $acs;
506  }
507  }
508 
525  public function getPagePermsClause($perms) {
526  if (is_array($this->user)) {
527  if ($this->isAdmin()) {
528  return ' 1=1';
529  }
530  $perms = (int)$perms;
531  // Make sure it's integer.
532  $str = ' (' . '(pages.perms_everybody & ' . $perms . ' = ' . $perms . ')' . ' OR (pages.perms_userid = '
533  . $this->user['uid'] . ' AND pages.perms_user & ' . $perms . ' = ' . $perms . ')';
534  // User
535  if ($this->groupList) {
536  // Group (if any is set)
537  $str .= ' OR (pages.perms_groupid in (' . $this->groupList . ') AND pages.perms_group & '
538  . $perms . ' = ' . $perms . ')';
539  }
540  $str .= ')';
541  // ****************
542  // getPagePermsClause-HOOK
543  // ****************
544  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['getPagePermsClause'])) {
545  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['getPagePermsClause'] as $_funcRef) {
546  $_params = array('currentClause' => $str, 'perms' => $perms);
547  $str = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
548  }
549  }
550  return $str;
551  } else {
552  return ' 1=0';
553  }
554  }
555 
566  public function calcPerms($row) {
567  // Return 31 for admin users.
568  if ($this->isAdmin()) {
569  return 31;
570  }
571  // Return 0 if page is not within the allowed web mount
572  if (!$this->isInWebMount($row['uid'])) {
573  return 0;
574  }
575  $out = 0;
576  if (
577  isset($row['perms_userid']) && isset($row['perms_user']) && isset($row['perms_groupid'])
578  && isset($row['perms_group']) && isset($row['perms_everybody']) && isset($this->groupList)
579  ) {
580  if ($this->user['uid'] == $row['perms_userid']) {
581  $out |= $row['perms_user'];
582  }
583  if ($this->isMemberOfGroup($row['perms_groupid'])) {
584  $out |= $row['perms_group'];
585  }
586  $out |= $row['perms_everybody'];
587  }
588  // ****************
589  // CALCPERMS hook
590  // ****************
591  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['calcPerms'])) {
592  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['calcPerms'] as $_funcRef) {
593  $_params = array(
594  'row' => $row,
595  'outputPermissions' => $out
596  );
597  $out = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
598  }
599  }
600  return $out;
601  }
602 
612  public function isRTE() {
613  // Start:
614  $this->RTE_errors = array();
615  if (!$this->uc['edit_RTE']) {
616  $this->RTE_errors[] = 'RTE is not enabled for user!';
617  }
618  if (!$GLOBALS['TYPO3_CONF_VARS']['BE']['RTEenabled']) {
619  $this->RTE_errors[] = 'RTE is not enabled in $TYPO3_CONF_VARS["BE"]["RTEenabled"]';
620  }
621  // Acquire RTE object:
622  $RTE = BackendUtility::RTEgetObj();
623  if (!is_object($RTE)) {
624  $this->RTE_errors = array_merge($this->RTE_errors, $RTE);
625  }
626  if (!count($this->RTE_errors)) {
627  return TRUE;
628  } else {
629  return FALSE;
630  }
631  }
632 
644  public function check($type, $value) {
645  if (isset($this->groupData[$type])) {
646  if ($this->isAdmin() || GeneralUtility::inList($this->groupData[$type], $value)) {
647  return TRUE;
648  }
649  }
650  return FALSE;
651  }
652 
663  public function checkAuthMode($table, $field, $value, $authMode) {
664  // Admin users can do anything:
665  if ($this->isAdmin()) {
666  return TRUE;
667  }
668  // Allow all blank values:
669  if ((string)$value === '') {
670  return TRUE;
671  }
672  // Certain characters are not allowed in the value
673  if (preg_match('/[:|,]/', $value)) {
674  return FALSE;
675  }
676  // Initialize:
677  $testValue = $table . ':' . $field . ':' . $value;
678  $out = TRUE;
679  // Checking value:
680  switch ((string) $authMode) {
681  case 'explicitAllow':
682  if (!GeneralUtility::inList($this->groupData['explicit_allowdeny'], ($testValue . ':ALLOW'))) {
683  $out = FALSE;
684  }
685  break;
686  case 'explicitDeny':
687  if (GeneralUtility::inList($this->groupData['explicit_allowdeny'], $testValue . ':DENY')) {
688  $out = FALSE;
689  }
690  break;
691  case 'individual':
692  if (is_array($GLOBALS['TCA'][$table]) && is_array($GLOBALS['TCA'][$table]['columns'][$field])) {
693  $items = $GLOBALS['TCA'][$table]['columns'][$field]['config']['items'];
694  if (is_array($items)) {
695  foreach ($items as $iCfg) {
696  if ((string)$iCfg[1] === (string)$value && $iCfg[4]) {
697  switch ((string)$iCfg[4]) {
698  case 'EXPL_ALLOW':
699  if (!GeneralUtility::inList($this->groupData['explicit_allowdeny'], ($testValue . ':ALLOW'))) {
700  $out = FALSE;
701  }
702  break;
703  case 'EXPL_DENY':
704  if (GeneralUtility::inList($this->groupData['explicit_allowdeny'], $testValue . ':DENY')) {
705  $out = FALSE;
706  }
707  break;
708  }
709  break;
710  }
711  }
712  }
713  }
714  break;
715  }
716  return $out;
717  }
718 
726  public function checkLanguageAccess($langValue) {
727  // The users language list must be non-blank - otherwise all languages are allowed.
728  if (trim($this->groupData['allowed_languages']) !== '') {
729  $langValue = (int)$langValue;
730  // Language must either be explicitly allowed OR the lang Value be "-1" (all languages)
731  if ($langValue != -1 && !$this->check('allowed_languages', $langValue)) {
732  return FALSE;
733  }
734  }
735  return TRUE;
736  }
737 
746  public function checkFullLanguagesAccess($table, $record) {
747  $recordLocalizationAccess = $this->checkLanguageAccess(0);
748  if ($recordLocalizationAccess && (BackendUtility::isTableLocalizable($table) || isset($GLOBALS['TCA'][$table]['ctrl']['transForeignTable']))) {
749  if (isset($GLOBALS['TCA'][$table]['ctrl']['transForeignTable'])) {
750  $l10nTable = $GLOBALS['TCA'][$table]['ctrl']['transForeignTable'];
751  $pointerField = $GLOBALS['TCA'][$l10nTable]['ctrl']['transOrigPointerField'];
752  $pointerValue = $record['uid'];
753  } else {
754  $l10nTable = $table;
755  $pointerField = $GLOBALS['TCA'][$l10nTable]['ctrl']['transOrigPointerField'];
756  $pointerValue = $record[$pointerField] > 0 ? $record[$pointerField] : $record['uid'];
757  }
758  $recordLocalizations = BackendUtility::getRecordsByField($l10nTable, $pointerField, $pointerValue, '', '', '', '1');
759  if (is_array($recordLocalizations)) {
760  foreach ($recordLocalizations as $localization) {
761  $recordLocalizationAccess = $recordLocalizationAccess
762  && $this->checkLanguageAccess($localization[$GLOBALS['TCA'][$l10nTable]['ctrl']['languageField']]);
763  if (!$recordLocalizationAccess) {
764  break;
765  }
766  }
767  }
768  }
769  return $recordLocalizationAccess;
770  }
771 
788  public function recordEditAccessInternals($table, $idOrRow, $newRecord = FALSE, $deletedRecord = FALSE, $checkFullLanguageAccess = FALSE) {
789  if (!isset($GLOBALS['TCA'][$table])) {
790  return FALSE;
791  }
792  // Always return TRUE for Admin users.
793  if ($this->isAdmin()) {
794  return TRUE;
795  }
796  // Fetching the record if the $idOrRow variable was not an array on input:
797  if (!is_array($idOrRow)) {
798  if ($deletedRecord) {
799  $idOrRow = BackendUtility::getRecord($table, $idOrRow, '*', '', FALSE);
800  } else {
801  $idOrRow = BackendUtility::getRecord($table, $idOrRow);
802  }
803  if (!is_array($idOrRow)) {
804  $this->errorMsg = 'ERROR: Record could not be fetched.';
805  return FALSE;
806  }
807  }
808  // Checking languages:
809  if ($GLOBALS['TCA'][$table]['ctrl']['languageField']) {
810  // Language field must be found in input row - otherwise it does not make sense.
811  if (isset($idOrRow[$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
812  if (!$this->checkLanguageAccess($idOrRow[$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
813  $this->errorMsg = 'ERROR: Language was not allowed.';
814  return FALSE;
815  } elseif (
816  $checkFullLanguageAccess && $idOrRow[$GLOBALS['TCA'][$table]['ctrl']['languageField']] == 0
817  && !$this->checkFullLanguagesAccess($table, $idOrRow)
818  ) {
819  $this->errorMsg = 'ERROR: Related/affected language was not allowed.';
820  return FALSE;
821  }
822  } else {
823  $this->errorMsg = 'ERROR: The "languageField" field named "'
824  . $GLOBALS['TCA'][$table]['ctrl']['languageField'] . '" was not found in testing record!';
825  return FALSE;
826  }
827  } elseif (
828  isset($GLOBALS['TCA'][$table]['ctrl']['transForeignTable']) && $checkFullLanguageAccess &&
829  !$this->checkFullLanguagesAccess($table, $idOrRow)
830  ) {
831  return FALSE;
832  }
833  // Checking authMode fields:
834  if (is_array($GLOBALS['TCA'][$table]['columns'])) {
835  foreach ($GLOBALS['TCA'][$table]['columns'] as $fieldName => $fieldValue) {
836  if (isset($idOrRow[$fieldName])) {
837  if (
838  $fieldValue['config']['type'] === 'select' && $fieldValue['config']['authMode']
839  && $fieldValue['config']['authMode_enforce'] === 'strict'
840  ) {
841  if (!$this->checkAuthMode($table, $fieldName, $idOrRow[$fieldName], $fieldValue['config']['authMode'])) {
842  $this->errorMsg = 'ERROR: authMode "' . $fieldValue['config']['authMode']
843  . '" failed for field "' . $fieldName . '" with value "'
844  . $idOrRow[$fieldName] . '" evaluated';
845  return FALSE;
846  }
847  }
848  }
849  }
850  }
851  // Checking "editlock" feature (doesn't apply to new records)
852  if (!$newRecord && $GLOBALS['TCA'][$table]['ctrl']['editlock']) {
853  if (isset($idOrRow[$GLOBALS['TCA'][$table]['ctrl']['editlock']])) {
854  if ($idOrRow[$GLOBALS['TCA'][$table]['ctrl']['editlock']]) {
855  $this->errorMsg = 'ERROR: Record was locked for editing. Only admin users can change this state.';
856  return FALSE;
857  }
858  } else {
859  $this->errorMsg = 'ERROR: The "editLock" field named "' . $GLOBALS['TCA'][$table]['ctrl']['editlock']
860  . '" was not found in testing record!';
861  return FALSE;
862  }
863  }
864  // Checking record permissions
865  // THIS is where we can include a check for "perms_" fields for other records than pages...
866  // Process any hooks
867  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['recordEditAccessInternals'])) {
868  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['recordEditAccessInternals'] as $funcRef) {
869  $params = array(
870  'table' => $table,
871  'idOrRow' => $idOrRow,
872  'newRecord' => $newRecord
873  );
874  if (!GeneralUtility::callUserFunction($funcRef, $params, $this)) {
875  return FALSE;
876  }
877  }
878  }
879  // Finally, return TRUE if all is well.
880  return TRUE;
881  }
882 
893  public function isPSet($compiledPermissions, $tableName, $actionType = '') {
894  if ($this->isAdmin()) {
895  $result = TRUE;
896  } elseif ($tableName == 'pages') {
897  switch ($actionType) {
898  case 'edit':
899  $result = ($compiledPermissions & 2) !== 0;
900  break;
901  case 'new':
902  // Create new page OR page content
903  $result = ($compiledPermissions & 8 + 16) !== 0;
904  break;
905  case 'delete':
906  $result = ($compiledPermissions & 4) !== 0;
907  break;
908  case 'editcontent':
909  $result = ($compiledPermissions & 16) !== 0;
910  break;
911  default:
912  $result = FALSE;
913  }
914  } else {
915  $result = ($compiledPermissions & 16) !== 0;
916  }
917  return $result;
918  }
919 
926  public function mayMakeShortcut() {
927  return $this->getTSConfigVal('options.enableBookmarks')
928  && !$this->getTSConfigVal('options.mayNotCreateEditBookmarks');
929  }
930 
943  public function workspaceCannotEditRecord($table, $recData) {
944  // Only test offline spaces:
945  if ($this->workspace !== 0) {
946  if (!is_array($recData)) {
947  $recData = BackendUtility::getRecord(
948  $table,
949  $recData,
950  'pid' . ($GLOBALS['TCA'][$table]['ctrl']['versioningWS'] ? ',t3ver_wsid,t3ver_stage' : '')
951  );
952  }
953  if (is_array($recData)) {
954  // We are testing a "version" (identified by a pid of -1): it can be edited provided
955  // that workspace matches and versioning is enabled for the table.
956  if ((int)$recData['pid'] === -1) {
957  // No versioning, basic error, inconsistency even! Such records should not have a pid of -1!
958  if (!$GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
959  return 'Versioning disabled for table';
960  } elseif ((int)$recData['t3ver_wsid'] !== $this->workspace) {
961  // So does workspace match?
962  return 'Workspace ID of record didn\'t match current workspace';
963  } else {
964  // So is the user allowed to "use" the edit stage within the workspace?
965  return $this->workspaceCheckStageForCurrent(0)
966  ? FALSE
967  : 'User\'s access level did not allow for editing';
968  }
969  } else {
970  // We are testing a "live" record:
971  // For "Live" records, check that PID for table allows editing
972  if ($res = $this->workspaceAllowLiveRecordsInPID($recData['pid'], $table)) {
973  // Live records are OK in this branch, but what about the stage of branch point, if any:
974  // OK
975  return $res > 0
976  ? FALSE
977  : 'Stage for versioning root point and users access level did not allow for editing';
978  } else {
979  // If not offline and not in versionized branch, output error:
980  return 'Online record was not in versionized branch!';
981  }
982  }
983  } else {
984  return 'No record';
985  }
986  } else {
987  // OK because workspace is 0
988  return FALSE;
989  }
990  }
991 
1001  public function workspaceCannotEditOfflineVersion($table, $recData) {
1002  if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
1003  if (!is_array($recData)) {
1004  $recData = BackendUtility::getRecord($table, $recData, 'uid,pid,t3ver_wsid,t3ver_stage');
1005  }
1006  if (is_array($recData)) {
1007  if ((int)$recData['pid'] === -1) {
1008  return $this->workspaceCannotEditRecord($table, $recData);
1009  } else {
1010  return 'Not an offline version';
1011  }
1012  } else {
1013  return 'No record';
1014  }
1015  } else {
1016  return 'Table does not support versioning.';
1017  }
1018  }
1019 
1032  public function workspaceAllowLiveRecordsInPID($pid, $table) {
1033  // Always for Live workspace AND if live-edit is enabled
1034  // and tables are completely without versioning it is ok as well.
1035  if (
1036  $this->workspace === 0
1037  || $this->workspaceRec['live_edit'] && !$GLOBALS['TCA'][$table]['ctrl']['versioningWS']
1038  || $GLOBALS['TCA'][$table]['ctrl']['versioningWS_alwaysAllowLiveEdit']
1039  ) {
1040  // OK to create for this table.
1041  return 2;
1042  } else {
1043  // If the answer is FALSE it means the only valid way to create or edit records in the PID is by versioning
1044  return FALSE;
1045  }
1046  }
1047 
1056  public function workspaceCreateNewRecord($pid, $table) {
1057  if ($res = $this->workspaceAllowLiveRecordsInPID($pid, $table)) {
1058  // If LIVE records cannot be created in the current PID due to workspace restrictions, prepare creation of placeholder-record
1059  if ($res < 0) {
1060  // Stage for versioning root point and users access level did not allow for editing
1061  return FALSE;
1062  }
1063  } elseif (!$GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
1064  // So, if no live records were allowed, we have to create a new version of this record:
1065  return FALSE;
1066  }
1067  return TRUE;
1068  }
1069 
1079  public function workspaceAllowAutoCreation($table, $id, $recpid) {
1080  // Auto-creation of version: In offline workspace, test if versioning is
1081  // enabled and look for workspace version of input record.
1082  // If there is no versionized record found we will create one and save to that.
1083  if (
1084  $this->workspace !== 0 && !$this->workspaceRec['disable_autocreate']
1085  && $GLOBALS['TCA'][$table]['ctrl']['versioningWS'] && $recpid >= 0
1086  && !BackendUtility::getWorkspaceVersionOfRecord($this->workspace, $table, $id, 'uid')
1087  ) {
1088  // There must be no existing version of this record in workspace.
1089  return TRUE;
1090  } elseif ($this->workspaceRec['disable_autocreate']) {
1091  GeneralUtility::deprecationLog('Usage of disable_autocreate feature is deprecated since 4.5.');
1092  }
1093  return FALSE;
1094  }
1095 
1106  public function workspaceCheckStageForCurrent($stage) {
1107  // Always allow for admins
1108  if ($this->isAdmin()) {
1109  return TRUE;
1110  }
1111  if ($this->workspace !== 0 && \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('workspaces')) {
1112  $stage = (int)$stage;
1113  $stat = $this->checkWorkspaceCurrent();
1114  // Check if custom staging is activated
1115  $workspaceRec = BackendUtility::getRecord('sys_workspace', $stat['uid']);
1116  if ($workspaceRec['custom_stages'] > 0 && $stage !== 0 && $stage !== -10) {
1117  // Get custom stage record
1118  $workspaceStageRec = BackendUtility::getRecord('sys_workspace_stage', $stage);
1119  // Check if the user is responsible for the current stage
1120  if (
1121  $stat['_ACCESS'] === 'owner'
1122  || $stat['_ACCESS'] === 'member'
1123  && GeneralUtility::inList($workspaceStageRec['responsible_persons'], 'be_users_' . $this->user['uid'])
1124  ) {
1125  return TRUE;
1126  }
1127  // Check if the user is in a group which is responsible for the current stage
1128  foreach ($this->userGroupsUID as $groupUid) {
1129  if (
1130  $stat['_ACCESS'] === 'owner'
1131  || $stat['_ACCESS'] === 'member'
1132  && GeneralUtility::inList($workspaceStageRec['responsible_persons'], 'be_groups_' . $groupUid)
1133  ) {
1134  return TRUE;
1135  }
1136  }
1137  } elseif ($stage == -10 || $stage == -20) {
1138  if ($stat['_ACCESS'] === 'owner') {
1139  return TRUE;
1140  } else {
1141  return FALSE;
1142  }
1143  } else {
1144  $memberStageLimit = $this->workspaceRec['review_stage_edit'] ? 1 : 0;
1145  if (
1146  $stat['_ACCESS'] === 'owner'
1147  || $stat['_ACCESS'] === 'reviewer' && $stage <= 1
1148  || $stat['_ACCESS'] === 'member' && $stage <= $memberStageLimit
1149  ) {
1150  return TRUE;
1151  }
1152  }
1153  } else {
1154  // Always OK for live workspace.
1155  return TRUE;
1156  }
1157  return FALSE;
1158  }
1159 
1171  public function workspacePublishAccess($wsid) {
1172  if ($this->isAdmin()) {
1173  return TRUE;
1174  }
1175  // If no access to workspace, of course you cannot publish!
1176  $retVal = FALSE;
1177  $wsAccess = $this->checkWorkspace($wsid);
1178  if ($wsAccess) {
1179  switch ($wsAccess['uid']) {
1180  case 0:
1181  // Live workspace
1182  // If access to Live workspace, no problem.
1183  $retVal = TRUE;
1184  break;
1185  default:
1186  // Custom workspace
1187  $retVal = $wsAccess['_ACCESS'] === 'owner' || $this->checkWorkspace(0) && !($wsAccess['publish_access'] & 2);
1188  // Either be an adminuser OR have access to online
1189  // workspace which is OK as well as long as publishing
1190  // access is not limited by workspace option.
1191  }
1192  }
1193  return $retVal;
1194  }
1195 
1202  public function workspaceSwapAccess() {
1203  if ($this->workspace > 0 && (int)$this->workspaceRec['swap_modes'] === 2) {
1204  return FALSE;
1205  } else {
1206  return TRUE;
1207  }
1208  }
1209 
1219  public function getTSConfig($objectString, $config = '') {
1220  if (!is_array($config)) {
1221  // Getting Root-ts if not sent
1222  $config = $this->userTS;
1223  }
1224  $TSConf = array('value' => NULL, 'properties' => NULL);
1225  $parts = GeneralUtility::trimExplode('.', $objectString, TRUE, 2);
1226  $key = $parts[0];
1227  if (strlen($key) > 0) {
1228  if (count($parts) > 1 && strlen($parts[1]) > 0) {
1229  // Go on, get the next level
1230  if (is_array($config[$key . '.'])) {
1231  $TSConf = $this->getTSConfig($parts[1], $config[$key . '.']);
1232  }
1233  } else {
1234  $TSConf['value'] = $config[$key];
1235  $TSConf['properties'] = $config[$key . '.'];
1236  }
1237  }
1238  return $TSConf;
1239  }
1240 
1249  public function getTSConfigVal($objectString) {
1250  $TSConf = $this->getTSConfig($objectString);
1251  return $TSConf['value'];
1252  }
1253 
1262  public function getTSConfigProp($objectString) {
1263  $TSConf = $this->getTSConfig($objectString);
1264  return $TSConf['properties'];
1265  }
1266 
1276  public function returnWebmounts() {
1277  return (string) $this->groupData['webmounts'] != '' ? explode(',', $this->groupData['webmounts']) : array();
1278  }
1279 
1294  public function jsConfirmation($bitmask) {
1295  $alertPopup = $this->getTSConfig('options.alertPopups');
1296  if (empty($alertPopup['value'])) {
1297  // Default: show all warnings
1298  $alertPopup = 255;
1299  } else {
1300  $alertPopup = (int)$alertPopup['value'];
1301  }
1302  // Show confirmation
1303  return ($alertPopup & $bitmask) == $bitmask;
1304  }
1305 
1317  public function fetchGroupData() {
1318  if ($this->user['uid']) {
1319  // Get lists for the be_user record and set them as default/primary values.
1320  // Enabled Backend Modules
1321  $this->dataLists['modList'] = $this->user['userMods'];
1322  // Add Allowed Languages
1323  $this->dataLists['allowed_languages'] = $this->user['allowed_languages'];
1324  // Set user value for workspace permissions.
1325  $this->dataLists['workspace_perms'] = $this->user['workspace_perms'];
1326  // User mount points are only added if the user is not an admin as admins do not have visible
1327  // mountpoints fields. Processing them loads mountpoints defined when the user was a non-admin.
1328  if (!$this->isAdmin()) {
1329  // Database mountpoints
1330  $this->dataLists['webmount_list'] = $this->user['db_mountpoints'];
1331  // File mountpoints
1332  $this->dataLists['filemount_list'] = $this->user['file_mountpoints'];
1333  }
1334  // Fileoperation permissions
1335  $this->dataLists['file_permissions'] = $this->user['file_permissions'];
1336  // Setting default User TSconfig:
1337  $this->TSdataArray[] = $this->addTScomment('From $GLOBALS["TYPO3_CONF_VARS"]["BE"]["defaultUserTSconfig"]:')
1338  . $GLOBALS['TYPO3_CONF_VARS']['BE']['defaultUserTSconfig'];
1339  // Default TSconfig for admin-users
1340  if ($this->isAdmin()) {
1341  $this->TSdataArray[] = $this->addTScomment('"admin" user presets:') . '
1342  admPanel.enable.all = 1
1343  ';
1344  if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('sys_note')) {
1345  $this->TSdataArray[] = '
1346  // Setting defaults for sys_note author / email...
1347  TCAdefaults.sys_note.author = ' . $this->user['realName'] . '
1348  TCAdefaults.sys_note.email = ' . $this->user['email'] . '
1349  ';
1350  }
1351  }
1352  // BE_GROUPS:
1353  // Get the groups...
1354  if (!empty($this->user[$this->usergroup_column])) {
1355  // Fetch groups will add a lot of information to the internal arrays: modules, accesslists, TSconfig etc.
1356  // Refer to fetchGroups() function.
1357  $this->fetchGroups($this->user[$this->usergroup_column]);
1358  }
1359 
1360  // Populating the $this->userGroupsUID -array with the groups in the order in which they were LAST included.!!
1361  $this->userGroupsUID = array_reverse(array_unique(array_reverse($this->includeGroupArray)));
1362  // Finally this is the list of group_uid's in the order they are parsed (including subgroups!)
1363  // and without duplicates (duplicates are presented with their last entrance in the list,
1364  // which thus reflects the order of the TypoScript in TSconfig)
1365  $this->groupList = implode(',', $this->userGroupsUID);
1366  $this->setCachedList($this->groupList);
1367 
1368  // Add the TSconfig for this specific user:
1369  $this->TSdataArray[] = $this->addTScomment('USER TSconfig field') . $this->user['TSconfig'];
1370  // Check include lines.
1371  $this->TSdataArray = \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::checkIncludeLines_array($this->TSdataArray);
1372  // Imploding with "[global]" will make sure that non-ended confinements with braces are ignored.
1373  $this->userTS_text = implode(LF . '[GLOBAL]' . LF, $this->TSdataArray);
1374  if (!$this->userTS_dontGetCached) {
1375  // Perform TS-Config parsing with condition matching
1376  $parseObj = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Configuration\\TsConfigParser');
1377  $res = $parseObj->parseTSconfig($this->userTS_text, 'userTS');
1378  if ($res) {
1379  $this->userTS = $res['TSconfig'];
1380  $this->userTSUpdated = (bool)$res['cached'];
1381  }
1382  } else {
1383  // Parsing the user TSconfig (or getting from cache)
1384  $hash = md5('userTS:' . $this->userTS_text);
1385  $cachedContent = BackendUtility::getHash($hash);
1386  if (is_array($cachedContent) && !$this->userTS_dontGetCached) {
1387  $this->userTS = $cachedContent;
1388  } else {
1389  $parseObj = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\Parser\\TypoScriptParser');
1390  $parseObj->parse($this->userTS_text);
1391  $this->userTS = $parseObj->setup;
1392  BackendUtility::storeHash($hash, $this->userTS, 'BE_USER_TSconfig');
1393  // Update UC:
1394  $this->userTSUpdated = TRUE;
1395  }
1396  }
1397  // Processing webmounts
1398  // Admin's always have the root mounted
1399  if ($this->isAdmin() && !$this->getTSConfigVal('options.dontMountAdminMounts')) {
1400  $this->dataLists['webmount_list'] = '0,' . $this->dataLists['webmount_list'];
1401  }
1402  // The lists are cleaned for duplicates
1403  $this->groupData['webmounts'] = GeneralUtility::uniqueList($this->dataLists['webmount_list']);
1404  $this->groupData['pagetypes_select'] = GeneralUtility::uniqueList($this->dataLists['pagetypes_select']);
1405  $this->groupData['tables_select'] = GeneralUtility::uniqueList($this->dataLists['tables_modify'] . ',' . $this->dataLists['tables_select']);
1406  $this->groupData['tables_modify'] = GeneralUtility::uniqueList($this->dataLists['tables_modify']);
1407  $this->groupData['non_exclude_fields'] = GeneralUtility::uniqueList($this->dataLists['non_exclude_fields']);
1408  $this->groupData['explicit_allowdeny'] = GeneralUtility::uniqueList($this->dataLists['explicit_allowdeny']);
1409  $this->groupData['allowed_languages'] = GeneralUtility::uniqueList($this->dataLists['allowed_languages']);
1410  $this->groupData['custom_options'] = GeneralUtility::uniqueList($this->dataLists['custom_options']);
1411  $this->groupData['modules'] = GeneralUtility::uniqueList($this->dataLists['modList']);
1412  $this->groupData['file_permissions'] = GeneralUtility::uniqueList($this->dataLists['file_permissions']);
1413  $this->groupData['workspace_perms'] = $this->dataLists['workspace_perms'];
1414 
1415  // Checking read access to webmounts:
1416  if (trim($this->groupData['webmounts']) !== '') {
1417  $webmounts = explode(',', $this->groupData['webmounts']);
1418  // Explode mounts
1419  // Selecting all webmounts with permission clause for reading
1420  $where = 'deleted=0 AND uid IN (' . $this->groupData['webmounts'] . ') AND ' . $this->getPagePermsClause(1);
1421  $MProws = $this->db->exec_SELECTgetRows('uid', 'pages', $where, '', '', '', 'uid');
1422  foreach ($webmounts as $idx => $mountPointUid) {
1423  // If the mount ID is NOT found among selected pages, unset it:
1424  if ($mountPointUid > 0 && !isset($MProws[$mountPointUid])) {
1425  unset($webmounts[$idx]);
1426  }
1427  }
1428  // Implode mounts in the end.
1429  $this->groupData['webmounts'] = implode(',', $webmounts);
1430  }
1431  // Setting up workspace situation (after webmounts are processed!):
1432  $this->workspaceInit();
1433  }
1434  }
1435 
1446  public function fetchGroups($grList, $idList = '') {
1447  // Fetching records of the groups in $grList (which are not blocked by lockedToDomain either):
1448  $lockToDomain_SQL = ' AND (lockToDomain=\'\' OR lockToDomain IS NULL OR lockToDomain=' . $this->db->fullQuoteStr(GeneralUtility::getIndpEnv('HTTP_HOST'), $this->usergroup_table) . ')';
1449  $grList = $this->db->cleanIntList($grList);
1450  $whereSQL = 'deleted=0 AND hidden=0 AND pid=0 AND uid IN (' . $grList . ')' . $lockToDomain_SQL;
1451  // Hook for manipulation of the WHERE sql sentence which controls which BE-groups are included
1452  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['fetchGroupQuery'])) {
1453  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['fetchGroupQuery'] as $classRef) {
1454  $hookObj = GeneralUtility::getUserObj($classRef);
1455  if (method_exists($hookObj, 'fetchGroupQuery_processQuery')) {
1456  $whereSQL = $hookObj->fetchGroupQuery_processQuery($this, $grList, $idList, $whereSQL);
1457  }
1458  }
1459  }
1460  $res = $this->db->exec_SELECTquery('*', $this->usergroup_table, $whereSQL);
1461  // The userGroups array is filled
1462  while ($row = $this->db->sql_fetch_assoc($res)) {
1463  $this->userGroups[$row['uid']] = $row;
1464  }
1465  $this->db->sql_free_result($res);
1466  // Traversing records in the correct order
1467  foreach (explode(',', $grList) as $uid) {
1468  // Get row:
1469  $row = $this->userGroups[$uid];
1470  // Must be an array and $uid should not be in the idList, because then it is somewhere previously in the grouplist
1471  if (is_array($row) && !GeneralUtility::inList($idList, $uid)) {
1472  // Include sub groups
1473  if (trim($row['subgroup'])) {
1474  // Make integer list
1475  $theList = implode(',', GeneralUtility::intExplode(',', $row['subgroup']));
1476  // Call recursively, pass along list of already processed groups so they are not recursed again.
1477  $this->fetchGroups($theList, $idList . ',' . $uid);
1478  }
1479  // Add the group uid, current list, TSconfig to the internal arrays.
1480  $this->includeGroupArray[] = $uid;
1481  $this->includeHierarchy[] = $idList;
1482  $this->TSdataArray[] = $this->addTScomment('Group "' . $row['title'] . '" [' . $row['uid'] . '] TSconfig field:') . $row['TSconfig'];
1483  // Mount group database-mounts
1484  if (($this->user['options'] & 1) == 1) {
1485  $this->dataLists['webmount_list'] .= ',' . $row['db_mountpoints'];
1486  }
1487  // Mount group file-mounts
1488  if (($this->user['options'] & 2) == 2) {
1489  $this->dataLists['filemount_list'] .= ',' . $row['file_mountpoints'];
1490  }
1491  // The lists are made: groupMods, tables_select, tables_modify, pagetypes_select, non_exclude_fields, explicit_allowdeny, allowed_languages, custom_options
1492  $this->dataLists['modList'] .= ',' . $row['groupMods'];
1493  $this->dataLists['tables_select'] .= ',' . $row['tables_select'];
1494  $this->dataLists['tables_modify'] .= ',' . $row['tables_modify'];
1495  $this->dataLists['pagetypes_select'] .= ',' . $row['pagetypes_select'];
1496  $this->dataLists['non_exclude_fields'] .= ',' . $row['non_exclude_fields'];
1497  $this->dataLists['explicit_allowdeny'] .= ',' . $row['explicit_allowdeny'];
1498  $this->dataLists['allowed_languages'] .= ',' . $row['allowed_languages'];
1499  $this->dataLists['custom_options'] .= ',' . $row['custom_options'];
1500  $this->dataLists['file_permissions'] .= ',' . $row['file_permissions'];
1501  // Setting workspace permissions:
1502  $this->dataLists['workspace_perms'] |= $row['workspace_perms'];
1503  // If this function is processing the users OWN group-list (not subgroups) AND
1504  // if the ->firstMainGroup is not set, then the ->firstMainGroup will be set.
1505  if ($idList === '' && !$this->firstMainGroup) {
1506  $this->firstMainGroup = $uid;
1507  }
1508  }
1509  }
1510  // HOOK: fetchGroups_postProcessing
1511  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['fetchGroups_postProcessing'])) {
1512  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['fetchGroups_postProcessing'] as $_funcRef) {
1513  $_params = array();
1514  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
1515  }
1516  }
1517  }
1518 
1531  public function setCachedList($cList) {
1532  if ((string) $cList != (string) $this->user['usergroup_cached_list']) {
1533  $this->db->exec_UPDATEquery('be_users', 'uid=' . (int)$this->user['uid'], array('usergroup_cached_list' => $cList));
1534  }
1535  }
1536 
1543  protected function initializeFileStorages() {
1544  $this->fileStorages = array();
1546  $storageRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository');
1547  // Admin users have all file storages visible, without any filters
1548  if ($this->isAdmin()) {
1549  $storageObjects = $storageRepository->findAll();
1550  foreach ($storageObjects as $storageObject) {
1551  $this->fileStorages[$storageObject->getUid()] = $storageObject;
1552  }
1553  } else {
1554  // Regular users only have storages that are defined in their filemounts
1555  // Permissions and file mounts for the storage are added in StoragePermissionAspect
1556  foreach ($this->getFileMountRecords() as $row) {
1557  if (!array_key_exists((int)$row['base'], $this->fileStorages)) {
1558  $storageObject = $storageRepository->findByUid($row['base']);
1559  if ($storageObject) {
1560  $this->fileStorages[$storageObject->getUid()] = $storageObject;
1561  }
1562  }
1563  }
1564  }
1565 
1566  // This has to be called always in order to set certain filters
1568  }
1569 
1576  public function getCategoryMountPoints() {
1577  $categoryMountPoints = '';
1578 
1579  // Category mounts of the groups
1580  if (is_array($this->userGroups)) {
1581  foreach ($this->userGroups as $group) {
1582  if ($group['category_perms']) {
1583  $categoryMountPoints .= ',' . $group['category_perms'];
1584  }
1585  }
1586  }
1587 
1588  // Category mounts of the user record
1589  if ($this->user['category_perms']) {
1590  $categoryMountPoints .= ',' . $this->user['category_perms'];
1591  }
1592 
1593  // Make the ids unique
1594  $categoryMountPoints = GeneralUtility::trimExplode(',', $categoryMountPoints);
1595  $categoryMountPoints = array_filter($categoryMountPoints); // remove empty value
1596  $categoryMountPoints = array_unique($categoryMountPoints); // remove unique value
1597 
1598  return $categoryMountPoints;
1599  }
1600 
1608  public function getFileMountRecords() {
1609  static $fileMountRecordCache = array();
1610 
1611  if (!empty($fileMountRecordCache)) {
1612  return $fileMountRecordCache;
1613  }
1614 
1615  // Processing file mounts (both from the user and the groups)
1616  $fileMounts = array_unique(GeneralUtility::intExplode(',', $this->dataLists['filemount_list'], TRUE));
1617 
1618  // Limit file mounts if set in workspace record
1619  if ($this->workspace > 0 && !empty($this->workspaceRec['file_mountpoints'])) {
1620  $workspaceFileMounts = GeneralUtility::intExplode(',', $this->workspaceRec['file_mountpoints'], TRUE);
1621  $fileMounts = array_intersect($fileMounts, $workspaceFileMounts);
1622  }
1623 
1624  if (!empty($fileMounts)) {
1625  $orderBy = isset($GLOBALS['TCA']['sys_filemounts']['ctrl']['default_sortby'])
1626  ? $this->db->stripOrderBy($GLOBALS['TCA']['sys_filemounts']['ctrl']['default_sortby'])
1627  : 'sorting';
1628  $fileMountRecords = $this->db->exec_SELECTgetRows(
1629  // Select read_only as (int)0, as there is no real database field for this.
1630  // Don't select as false as this is not supported by DBAL!
1631  '*,0 as read_only',
1632  'sys_filemounts',
1633  'deleted=0 AND hidden=0 AND pid=0 AND uid IN (' . implode(',', $fileMounts) . ')',
1634  '',
1635  $orderBy
1636  );
1637  foreach ($fileMountRecords as $fileMount) {
1638  $fileMountRecordCache[$fileMount['base'] . $fileMount['path']] = $fileMount;
1639  }
1640  }
1641 
1642  // Read-only file mounts
1643  $readOnlyMountPoints = trim($GLOBALS['BE_USER']->getTSConfigVal('options.folderTree.altElementBrowserMountPoints'));
1644  if ($readOnlyMountPoints) {
1645  // We cannot use the API here but need to fetch the default storage record directly
1646  // to not instantiate it (which directly applies mount points) before all mount points are resolved!
1647  $whereClause = 'is_default=1 ' . BackendUtility::BEenableFields('sys_file_storage') . BackendUtility::deleteClause('sys_file_storage');
1648  $defaultStorageRow = $this->db->exec_SELECTgetSingleRow('uid', 'sys_file_storage', $whereClause);
1649  $readOnlyMountPointArray = GeneralUtility::trimExplode(',', $readOnlyMountPoints);
1650  foreach ($readOnlyMountPointArray as $readOnlyMountPoint) {
1651  $readOnlyMountPointConfiguration = GeneralUtility::trimExplode(':', $readOnlyMountPoint);
1652  if (count($readOnlyMountPointConfiguration) === 2) {
1653  // A storage is passed in the configuration
1654  $storageUid = (int)$readOnlyMountPointConfiguration[0];
1655  $path = $readOnlyMountPointConfiguration[1];
1656  } else {
1657  if (empty($defaultStorageRow)) {
1658  throw new \RuntimeException('Read only mount points have been defined in User TsConfig without specific storage, but a default storage could not be resolved.', 1404472382);
1659  }
1660  // Backwards compatibility: If no storage is passed, we use the default storage
1661  $storageUid = $defaultStorageRow['uid'];
1662  $path = $readOnlyMountPointConfiguration[0];
1663  }
1664  $fileMountRecordCache[$storageUid . $path] = array(
1665  'base' => $storageUid,
1666  'title' => $path,
1667  'path' => $path,
1668  'read_only' => TRUE
1669  );
1670  }
1671  }
1672 
1673 
1674  // Personal or Group filemounts are not accessible if file mount list is set in workspace record
1675  if ($this->workspace <= 0 || empty($this->workspaceRec['file_mountpoints'])) {
1676  // If userHomePath is set, we attempt to mount it
1677  if ($GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath']) {
1678  list($userHomeStorageUid, $userHomeFilter) = explode(':', $GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath'], 2);
1679  $userHomeStorageUid = (int)$userHomeStorageUid;
1680  $userHomeFilter = '/' . ltrim($userHomeFilter, '/');
1681  if ($userHomeStorageUid > 0) {
1682  // Try and mount with [uid]_[username]
1683  $path = $userHomeFilter . $this->user['uid'] . '_' . $this->user['username'] . $GLOBALS['TYPO3_CONF_VARS']['BE']['userUploadDir'];
1684  $fileMountRecordCache[$userHomeStorageUid . $path] = array(
1685  'base' => $userHomeStorageUid,
1686  'title' => $this->user['username'],
1687  'path' => $path,
1688  'read_only' => FALSE,
1689  'user_mount' => TRUE
1690  );
1691  // Try and mount with only [uid]
1692  $path = $userHomeFilter . $this->user['uid'] . $GLOBALS['TYPO3_CONF_VARS']['BE']['userUploadDir'];
1693  $fileMountRecordCache[$userHomeStorageUid . $path] = array(
1694  'base' => $userHomeStorageUid,
1695  'title' => $this->user['username'],
1696  'path' => $path,
1697  'read_only' => FALSE,
1698  'user_mount' => TRUE
1699  );
1700  }
1701  }
1702 
1703  // Mount group home-dirs
1704  if ((is_array($this->user) && $this->user['options'] & 2) == 2 && $GLOBALS['TYPO3_CONF_VARS']['BE']['groupHomePath'] != '') {
1705  // If groupHomePath is set, we attempt to mount it
1706  list($groupHomeStorageUid, $groupHomeFilter) = explode(':', $GLOBALS['TYPO3_CONF_VARS']['BE']['groupHomePath'], 2);
1707  $groupHomeStorageUid = (int)$groupHomeStorageUid;
1708  $groupHomeFilter = '/' . ltrim($groupHomeFilter, '/');
1709  if ($groupHomeStorageUid > 0) {
1710  foreach ($this->userGroups as $groupData) {
1711  $path = $groupHomeFilter . $groupData['uid'];
1712  $fileMountRecordCache[$groupHomeStorageUid . $path] = array(
1713  'base' => $groupHomeStorageUid,
1714  'title' => $groupData['title'],
1715  'path' => $path,
1716  'read_only' => FALSE,
1717  'user_mount' => TRUE
1718  );
1719  }
1720  }
1721  }
1722  }
1723 
1724  return $fileMountRecordCache;
1725  }
1726 
1735  public function getFileStorages() {
1736  // Initializing file mounts after the groups are fetched
1737  if ($this->fileStorages === NULL) {
1738  $this->initializeFileStorages();
1739  }
1740  return $this->fileStorages;
1741  }
1742 
1751  // Add the option for also displaying the non-hidden files
1752  if ($this->uc['showHiddenFilesAndFolders']) {
1754  }
1755  }
1756 
1794  public function getFilePermissions() {
1795  if (!isset($this->filePermissions)) {
1796  $filePermissions = array(
1797  // File permissions
1798  'addFile' => FALSE,
1799  'readFile' => FALSE,
1800  'writeFile' => FALSE,
1801  'copyFile' => FALSE,
1802  'moveFile' => FALSE,
1803  'renameFile' => FALSE,
1804  'unzipFile' => FALSE,
1805  'deleteFile' => FALSE,
1806  // Folder permissions
1807  'addFolder' => FALSE,
1808  'readFolder' => FALSE,
1809  'writeFolder' => FALSE,
1810  'copyFolder' => FALSE,
1811  'moveFolder' => FALSE,
1812  'renameFolder' => FALSE,
1813  'deleteFolder' => FALSE,
1814  'recursivedeleteFolder' => FALSE
1815  );
1816  if ($this->isAdmin()) {
1817  $filePermissions = array_map('is_bool', $filePermissions);
1818  } else {
1819  $userGroupRecordPermissions = GeneralUtility::trimExplode(',', $this->groupData['file_permissions'], TRUE);
1820  array_walk(
1821  $userGroupRecordPermissions,
1822  function($permission) use (&$filePermissions) {
1823  $filePermissions[$permission] = TRUE;
1824  }
1825  );
1826 
1827  // Finally overlay any userTSconfig
1828  $permissionsTsConfig = $this->getTSConfigProp('permissions.file.default');
1829  if (!empty($permissionsTsConfig)) {
1830  array_walk(
1831  $permissionsTsConfig,
1832  function($value, $permission) use (&$filePermissions) {
1833  $filePermissions[$permission] = (bool) $value;
1834  }
1835  );
1836  }
1837  }
1838  $this->filePermissions = $filePermissions;
1839  }
1840  return $this->filePermissions;
1841  }
1842 
1853  public function getFilePermissionsForStorage(\TYPO3\CMS\Core\Resource\ResourceStorage $storageObject) {
1854  $finalUserPermissions = $this->getFilePermissions();
1855  if (!$this->isAdmin()) {
1856  $storageFilePermissions = $this->getTSConfigProp('permissions.file.storage.' . $storageObject->getUid());
1857  if (!empty($storageFilePermissions)) {
1858  array_walk(
1859  $storageFilePermissions,
1860  function($value, $permission) use (&$finalUserPermissions) {
1861  $finalUserPermissions[$permission] = (bool) $value;
1862  }
1863  );
1864  }
1865  }
1866  return $finalUserPermissions;
1867  }
1868 
1883  public function getDefaultUploadFolder() {
1884  $uploadFolder = $this->getTSConfigVal('options.defaultUploadFolder');
1885  if ($uploadFolder) {
1886  $uploadFolder = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFolderObjectFromCombinedIdentifier($uploadFolder);
1887  } else {
1888  foreach($this->getFileStorages() as $storage) {
1889  if ($storage->isDefault() && $storage->isWritable()) {
1890  try {
1891  $uploadFolder = $storage->getDefaultFolder();
1892  if ($uploadFolder->checkActionPermission('add')) {
1893  break;
1894  }
1895  $uploadFolder = NULL;
1896  } catch (\TYPO3\CMS\Core\Resource\Exception $folderAccessException) {
1897  // If the folder is not accessible (no permissions / does not exist) we skip this one.
1898  }
1899  break;
1900  }
1901  }
1902  if (!$uploadFolder instanceof \TYPO3\CMS\Core\Resource\Folder) {
1904  foreach ($this->getFileStorages() as $storage) {
1905  if ($storage->isWritable()) {
1906  try {
1907  $uploadFolder = $storage->getDefaultFolder();
1908  if ($uploadFolder->checkActionPermission('add')) {
1909  break;
1910  }
1911  $uploadFolder = NULL;
1912  } catch (\TYPO3\CMS\Core\Resource\Exception $folderAccessException) {
1913  // If the folder is not accessible (no permissions / does not exist) try the next one.
1914  }
1915  }
1916  }
1917  }
1918  }
1919  if ($uploadFolder instanceof \TYPO3\CMS\Core\Resource\Folder) {
1920  return $uploadFolder;
1921  } else {
1922  return FALSE;
1923  }
1924  }
1925 
1935  $defaultTemporaryFolder = NULL;
1936  $defaultFolder = $this->getDefaultUploadFolder();
1937 
1938  if ($defaultFolder !== FALSE) {
1939  $tempFolderName = '_temp_';
1940  $createFolder = !$defaultFolder->hasFolder($tempFolderName);
1941  if ($createFolder === TRUE) {
1942  try {
1943  $defaultTemporaryFolder = $defaultFolder->createFolder($tempFolderName);
1944  } catch (\TYPO3\CMS\Core\Resource\Exception $folderAccessException) {}
1945  } else {
1946  $defaultTemporaryFolder = $defaultFolder->getSubfolder($tempFolderName);
1947  }
1948  }
1949 
1950  return $defaultTemporaryFolder;
1951  }
1952 
1960  public function addTScomment($str) {
1961  $delimiter = '# ***********************************************';
1962  $out = $delimiter . LF;
1963  $lines = GeneralUtility::trimExplode(LF, $str);
1964  foreach ($lines as $v) {
1965  $out .= '# ' . $v . LF;
1966  }
1967  $out .= $delimiter . LF;
1968  return $out;
1969  }
1970 
1979  public function workspaceInit() {
1980  // Initializing workspace by evaluating and setting the workspace, possibly updating it in the user record!
1981  $this->setWorkspace($this->user['workspace_id']);
1982  // Limiting the DB mountpoints if there any selected in the workspace record
1984  if ($allowed_languages = $this->getTSConfigVal('options.workspaces.allowed_languages.' . $this->workspace)) {
1985  $this->groupData['allowed_languages'] = $allowed_languages;
1986  $this->groupData['allowed_languages'] = GeneralUtility::uniqueList($this->groupData['allowed_languages']);
1987  }
1988  }
1989 
1995  protected function initializeDbMountpointsInWorkspace() {
1996  $dbMountpoints = trim($this->workspaceRec['db_mountpoints']);
1997  if ($this->workspace > 0 && $dbMountpoints != '') {
1998  $filteredDbMountpoints = array();
1999  // Notice: We cannot call $this->getPagePermsClause(1);
2000  // as usual because the group-list is not available at this point.
2001  // But bypassing is fine because all we want here is check if the
2002  // workspace mounts are inside the current webmounts rootline.
2003  // The actual permission checking on page level is done elsewhere
2004  // as usual anyway before the page tree is rendered.
2005  $readPerms = '1=1';
2006  // Traverse mount points of the
2007  $dbMountpoints = GeneralUtility::intExplode(',', $dbMountpoints);
2008  foreach ($dbMountpoints as $mpId) {
2009  if ($this->isInWebMount($mpId, $readPerms)) {
2010  $filteredDbMountpoints[] = $mpId;
2011  }
2012  }
2013  // Re-insert webmounts:
2014  $filteredDbMountpoints = array_unique($filteredDbMountpoints);
2015  $this->groupData['webmounts'] = implode(',', $filteredDbMountpoints);
2016  }
2017  }
2018 
2027  public function checkWorkspace($wsRec, $fields = 'uid,title,adminusers,members,reviewers,publish_access,stagechg_notification') {
2028  $retVal = FALSE;
2029  // If not array, look up workspace record:
2030  if (!is_array($wsRec)) {
2031  switch ((string) $wsRec) {
2032  case '0':
2033  $wsRec = array('uid' => $wsRec);
2034  break;
2035  default:
2036  if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('workspaces')) {
2037  $wsRec = $this->db->exec_SELECTgetSingleRow($fields,
2038  'sys_workspace',
2039  'pid=0 AND uid=' . (int)$wsRec . BackendUtility::deleteClause('sys_workspace'),
2040  '',
2041  'title'
2042  );
2043  }
2044  }
2045  }
2046  // If wsRec is set to an array, evaluate it:
2047  if (is_array($wsRec)) {
2048  if ($this->isAdmin()) {
2049  return array_merge($wsRec, array('_ACCESS' => 'admin'));
2050  } else {
2051  switch ((string) $wsRec['uid']) {
2052  case '0':
2053  $retVal = $this->groupData['workspace_perms'] & 1
2054  ? array_merge($wsRec, array('_ACCESS' => 'online'))
2055  : FALSE;
2056  break;
2057  default:
2058  // Checking if the guy is admin:
2059  if (GeneralUtility::inList($wsRec['adminusers'], 'be_users_' . $this->user['uid'])) {
2060  return array_merge($wsRec, array('_ACCESS' => 'owner'));
2061  }
2062  // Checking if he is owner through a user group of his:
2063  foreach ($this->userGroupsUID as $groupUid) {
2064  if (GeneralUtility::inList($wsRec['adminusers'], 'be_groups_' . $groupUid)) {
2065  return array_merge($wsRec, array('_ACCESS' => 'owner'));
2066  }
2067  }
2068  // Checking if he is reviewer user:
2069  if (GeneralUtility::inList($wsRec['reviewers'], 'be_users_' . $this->user['uid'])) {
2070  return array_merge($wsRec, array('_ACCESS' => 'reviewer'));
2071  }
2072  // Checking if he is reviewer through a user group of his:
2073  foreach ($this->userGroupsUID as $groupUid) {
2074  if (GeneralUtility::inList($wsRec['reviewers'], 'be_groups_' . $groupUid)) {
2075  return array_merge($wsRec, array('_ACCESS' => 'reviewer'));
2076  }
2077  }
2078  // Checking if he is member as user:
2079  if (GeneralUtility::inList($wsRec['members'], 'be_users_' . $this->user['uid'])) {
2080  return array_merge($wsRec, array('_ACCESS' => 'member'));
2081  }
2082  // Checking if he is member through a user group of his:
2083  foreach ($this->userGroupsUID as $groupUid) {
2084  if (GeneralUtility::inList($wsRec['members'], 'be_groups_' . $groupUid)) {
2085  return array_merge($wsRec, array('_ACCESS' => 'member'));
2086  }
2087  }
2088  }
2089  }
2090  }
2091  return $retVal;
2092  }
2093 
2102  public function checkWorkspaceCurrent() {
2103  if (!isset($this->checkWorkspaceCurrent_cache)) {
2104  $this->checkWorkspaceCurrent_cache = $this->checkWorkspace($this->workspace);
2105  }
2107  }
2108 
2116  public function setWorkspace($workspaceId) {
2117  // Check workspace validity and if not found, revert to default workspace.
2118  if (!$this->setTemporaryWorkspace($workspaceId)) {
2119  $this->setDefaultWorkspace();
2120  }
2121  // Unset access cache:
2122  $this->checkWorkspaceCurrent_cache = NULL;
2123  // If ID is different from the stored one, change it:
2124  if ((int)$this->workspace !== (int)$this->user['workspace_id']) {
2125  $this->user['workspace_id'] = $this->workspace;
2126  $this->db->exec_UPDATEquery('be_users', 'uid=' . (int)$this->user['uid'], array('workspace_id' => $this->user['workspace_id']));
2127  $this->simplelog('User changed workspace to "' . $this->workspace . '"');
2128  }
2129  }
2130 
2137  public function setTemporaryWorkspace($workspaceId) {
2138  $result = FALSE;
2139  $workspaceRecord = $this->checkWorkspace($workspaceId, '*');
2140 
2141  if ($workspaceRecord) {
2142  $this->workspaceRec = $workspaceRecord;
2143  $this->workspace = (int)$workspaceId;
2144  $result = TRUE;
2145  }
2146 
2147  return $result;
2148  }
2149 
2155  public function setDefaultWorkspace() {
2156  $this->workspace = (int)$this->getDefaultWorkspace();
2157  $this->workspaceRec = $this->checkWorkspace($this->workspace, '*');
2158  }
2159 
2167  public function setWorkspacePreview($previewState) {
2168  $this->user['workspace_preview'] = $previewState;
2169  $this->db->exec_UPDATEquery('be_users', 'uid=' . (int)$this->user['uid'], array('workspace_preview' => $this->user['workspace_preview']));
2170  }
2171 
2180  public function getDefaultWorkspace() {
2181  $defaultWorkspace = -99;
2182  if (!\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('workspaces') || $this->checkWorkspace(0)) {
2183  // Check online
2184  $defaultWorkspace = 0;
2185  } elseif ($this->checkWorkspace(-1)) {
2186  // Check offline
2187  $defaultWorkspace = -1;
2188  } elseif (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('workspaces')) {
2189  // Traverse custom workspaces:
2190  $workspaces = $this->db->exec_SELECTgetRows('uid,title,adminusers,members,reviewers', 'sys_workspace', 'pid=0' . BackendUtility::deleteClause('sys_workspace'), '', 'title');
2191  foreach ($workspaces as $rec) {
2192  if ($this->checkWorkspace($rec)) {
2193  $defaultWorkspace = $rec['uid'];
2194  break;
2195  }
2196  }
2197  }
2198  return $defaultWorkspace;
2199  }
2200 
2220  public function writelog($type, $action, $error, $details_nr, $details, $data, $tablename = '', $recuid = '', $recpid = '', $event_pid = -1, $NEWid = '', $userId = 0) {
2221  if (!$userId && isset($this->user['uid'])) {
2222  $userId = $this->user['uid'];
2223  }
2224 
2225  $fields_values = array(
2226  'userid' => (int)$userId,
2227  'type' => (int)$type,
2228  'action' => (int)$action,
2229  'error' => (int)$error,
2230  'details_nr' => (int)$details_nr,
2231  'details' => $details,
2232  'log_data' => serialize($data),
2233  'tablename' => $tablename,
2234  'recuid' => (int)$recuid,
2235  'IP' => (string)GeneralUtility::getIndpEnv('REMOTE_ADDR'),
2236  'tstamp' => time(),
2237  'event_pid' => (int)$event_pid,
2238  'NEWid' => $NEWid,
2239  'workspace' => $this->workspace
2240  );
2241  $this->db->exec_INSERTquery('sys_log', $fields_values);
2242  return $this->db->sql_insert_id();
2243  }
2244 
2254  public function simplelog($message, $extKey = '', $error = 0) {
2255  return $this->writelog(4, 0, $error, 0, ($extKey ? '[' . $extKey . '] ' : '') . $message, array());
2256  }
2257 
2271  public function checkLogFailures($email, $secondsBack = 3600, $max = 3) {
2272  if ($email) {
2273  // Get last flag set in the log for sending
2274  $theTimeBack = $GLOBALS['EXEC_TIME'] - $secondsBack;
2275  $res = $this->db->exec_SELECTquery('tstamp', 'sys_log', 'type=255 AND action=4 AND tstamp>' . (int)$theTimeBack, '', 'tstamp DESC', '1');
2276  if ($testRow = $this->db->sql_fetch_assoc($res)) {
2277  $theTimeBack = $testRow['tstamp'];
2278  }
2279  $this->db->sql_free_result($res);
2280  // Check for more than $max number of error failures with the last period.
2281  $res = $this->db->exec_SELECTquery('*', 'sys_log', 'type=255 AND action=3 AND error<>0 AND tstamp>' . (int)$theTimeBack, '', 'tstamp');
2282  if ($this->db->sql_num_rows($res) > $max) {
2283  // OK, so there were more than the max allowed number of login failures - so we will send an email then.
2284  $subject = 'TYPO3 Login Failure Warning (at ' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . ')';
2285  $email_body = 'There have been some attempts (' . $this->db->sql_num_rows($res) . ') to login at the TYPO3
2286 site "' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '" (' . GeneralUtility::getIndpEnv('HTTP_HOST') . ').
2287 
2288 This is a dump of the failures:
2289 
2290 ';
2291  while ($testRows = $this->db->sql_fetch_assoc($res)) {
2292  $theData = unserialize($testRows['log_data']);
2293  $email_body .= date(
2294  $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' ' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'],
2295  $testRows['tstamp']
2296  ) . ': ' . @sprintf($testRows['details'], (string)$theData[0], (string)$theData[1], (string)$theData[2]);
2297  $email_body .= LF;
2298  }
2301  $mail = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');
2302  $mail->setTo($email)->setFrom($from)->setSubject($subject)->setBody($email_body);
2303  $mail->send();
2304  // Logout written to log
2305  $this->writelog(255, 4, 0, 3, 'Failure warning (%s failures within %s seconds) sent by email to %s', array($this->db->sql_num_rows($res), $secondsBack, $email));
2306  $this->db->sql_free_result($res);
2307  }
2308  }
2309  }
2310 
2317  static public function getCookieName() {
2318  $configuredCookieName = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['cookieName']);
2319  if (empty($configuredCookieName)) {
2320  $configuredCookieName = 'be_typo_user';
2321  }
2322  return $configuredCookieName;
2323  }
2324 
2333  public function checkLockToIP() {
2334  $out = 1;
2335  if ($GLOBALS['TYPO3_CONF_VARS']['BE']['enabledBeUserIPLock']) {
2336  $IPList = $this->getTSConfigVal('options.lockToIP');
2337  if (trim($IPList)) {
2338  $baseIP = GeneralUtility::getIndpEnv('REMOTE_ADDR');
2339  $out = GeneralUtility::cmpIP($baseIP, $IPList);
2340  }
2341  }
2342  return $out;
2343  }
2344 
2356  public function backendCheckLogin() {
2357  if (empty($this->user['uid'])) {
2358  if (!defined('TYPO3_PROCEED_IF_NO_USER') || !TYPO3_PROCEED_IF_NO_USER) {
2360  }
2361  } else {
2362  // ...and if that's the case, call these functions
2363  $this->fetchGroupData();
2364  // The groups are fetched and ready for permission checking in this initialization.
2365  // Tables.php must be read before this because stuff like the modules has impact in this
2366  if ($this->checkLockToIP()) {
2367  if ($this->isUserAllowedToLogin()) {
2368  // Setting the UC array. It's needed with fetchGroupData first, due to default/overriding of values.
2369  $this->backendSetUC();
2370  // Email at login - if option set.
2371  $this->emailAtLogin();
2372  } else {
2373  throw new \RuntimeException('Login Error: TYPO3 is in maintenance mode at the moment. Only administrators are allowed access.', 1294585860);
2374  }
2375  } else {
2376  throw new \RuntimeException('Login Error: IP locking prevented you from being authorized. Can\'t proceed, sorry.', 1294585861);
2377  }
2378  }
2379  }
2380 
2387  public function checkCLIuser() {
2388  // First, check if cliMode is enabled:
2389  if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI) {
2390  if (!$this->user['uid']) {
2391  if (substr($GLOBALS['MCONF']['name'], 0, 5) == '_CLI_') {
2392  $userName = strtolower($GLOBALS['MCONF']['name']);
2393  $this->setBeUserByName($userName);
2394  if ($this->user['uid']) {
2395  if (!$this->isAdmin()) {
2396  return TRUE;
2397  } else {
2398  fwrite(STDERR, 'ERROR: CLI backend user "' . $userName . '" was ADMIN which is not allowed!' . LF . LF);
2399  die(3);
2400  }
2401  } else {
2402  fwrite(STDERR, 'ERROR: No backend user named "' . $userName . '" was found!' . LF . LF);
2403  die(3);
2404  }
2405  } else {
2406  fwrite(STDERR, 'ERROR: Module name, "' . $GLOBALS['MCONF']['name'] . '", was not prefixed with "_CLI_"' . LF . LF);
2407  die(3);
2408  }
2409  } else {
2410  fwrite(STDERR, 'ERROR: Another user was already loaded which is impossible in CLI mode!' . LF . LF);
2411  die(3);
2412  }
2413  }
2414  return FALSE;
2415  }
2416 
2425  public function backendSetUC() {
2426  // UC - user configuration is a serialized array inside the user object
2427  // If there is a saved uc we implement that instead of the default one.
2428  $temp_theSavedUC = unserialize($this->user['uc']);
2429  if (is_array($temp_theSavedUC)) {
2430  $this->unpack_uc($temp_theSavedUC);
2431  }
2432  // Setting defaults if uc is empty
2433  $updated = FALSE;
2434  $originalUc = array();
2435  if (is_array($this->uc) && isset($this->uc['ucSetByInstallTool'])) {
2436  $originalUc = $this->uc;
2437  unset($originalUc['ucSetByInstallTool'], $this->uc);
2438  }
2439  if (!is_array($this->uc)) {
2440  $this->uc = array_merge(
2441  $this->uc_default,
2442  (array)$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultUC'],
2443  GeneralUtility::removeDotsFromTS((array)$this->getTSConfigProp('setup.default')),
2444  $originalUc
2445  );
2446  $this->overrideUC();
2447  $updated = TRUE;
2448  }
2449  // If TSconfig is updated, update the defaultUC.
2450  if ($this->userTSUpdated) {
2451  $this->overrideUC();
2452  $updated = TRUE;
2453  }
2454  // Setting default lang from be_user record.
2455  if (!isset($this->uc['lang'])) {
2456  $this->uc['lang'] = $this->user['lang'];
2457  $updated = TRUE;
2458  }
2459  // Setting the time of the first login:
2460  if (!isset($this->uc['firstLoginTimeStamp'])) {
2461  $this->uc['firstLoginTimeStamp'] = $GLOBALS['EXEC_TIME'];
2462  $updated = TRUE;
2463  }
2464  // Saving if updated.
2465  if ($updated) {
2466  $this->writeUC();
2467  }
2468  }
2469 
2478  public function overrideUC() {
2479  $this->uc = array_merge((array) $this->uc, (array) $this->getTSConfigProp('setup.override'));
2480  }
2481 
2489  public function resetUC() {
2490  $this->user['uc'] = '';
2491  $this->uc = '';
2492  $this->backendSetUC();
2493  }
2494 
2502  private function emailAtLogin() {
2503  if ($this->loginSessionStarted) {
2504  // Send notify-mail
2505  $subject = 'At "' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '"' . ' from '
2506  . GeneralUtility::getIndpEnv('REMOTE_ADDR')
2507  . (GeneralUtility::getIndpEnv('REMOTE_HOST') ? ' (' . GeneralUtility::getIndpEnv('REMOTE_HOST') . ')' : '');
2508  $msg = sprintf(
2509  'User "%s" logged in from %s (%s) at "%s" (%s)',
2510  $this->user['username'],
2511  GeneralUtility::getIndpEnv('REMOTE_ADDR'),
2512  GeneralUtility::getIndpEnv('REMOTE_HOST'),
2513  $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'],
2514  GeneralUtility::getIndpEnv('HTTP_HOST')
2515  );
2516  // Warning email address
2517  if ($GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr']) {
2518  $warn = 0;
2519  $prefix = '';
2520  if ((int)$GLOBALS['TYPO3_CONF_VARS']['BE']['warning_mode'] & 1) {
2521  // first bit: All logins
2522  $warn = 1;
2523  $prefix = $this->isAdmin() ? '[AdminLoginWarning]' : '[LoginWarning]';
2524  }
2525  if ($this->isAdmin() && (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['warning_mode'] & 2) {
2526  // second bit: Only admin-logins
2527  $warn = 1;
2528  $prefix = '[AdminLoginWarning]';
2529  }
2530  if ($warn) {
2533  $mail = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');
2534  $mail->setTo($GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr'])->setFrom($from)->setSubject($prefix . ' ' . $subject)->setBody($msg);
2535  $mail->send();
2536  }
2537  }
2538  // If An email should be sent to the current user, do that:
2539  if ($this->uc['emailMeAtLogin'] && strstr($this->user['email'], '@')) {
2542  $mail = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');
2543  $mail->setTo($this->user['email'])->setFrom($from)->setSubject($subject)->setBody($msg);
2544  $mail->send();
2545  }
2546  }
2547  }
2548 
2560  protected function isUserAllowedToLogin() {
2561  $isUserAllowedToLogin = FALSE;
2562  $adminOnlyMode = $GLOBALS['TYPO3_CONF_VARS']['BE']['adminOnly'];
2563  // Backend user is allowed if adminOnly is not set or user is an admin:
2564  if (!$adminOnlyMode || $this->isAdmin()) {
2565  $isUserAllowedToLogin = TRUE;
2566  } elseif ($adminOnlyMode == 2 && TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI) {
2567  $isUserAllowedToLogin = TRUE;
2568  } elseif ($this->user['ses_backuserid']) {
2569  $backendUserId = (int)$this->user['ses_backuserid'];
2570  $whereAdmin = 'uid=' . $backendUserId . ' AND admin=1' . BackendUtility::BEenableFields('be_users');
2571  if ($this->db->exec_SELECTcountRows('uid', 'be_users', $whereAdmin) > 0) {
2572  $isUserAllowedToLogin = TRUE;
2573  }
2574  }
2575  return $isUserAllowedToLogin;
2576  }
2577 
2581  public function logoff() {
2582  if (isset($GLOBALS['BE_USER'])) {
2584  }
2585  parent::logoff();
2586  }
2587 
2588 }
static uniqueList($in_list, $secondParameter=NULL)
static getWorkspaceVersionOfRecord($workspace, $table, $uid, $fields=' *')
checkWorkspace($wsRec, $fields='uid, title, adminusers, members, reviewers, publish_access, stagechg_notification')
$configuredCookieName
Definition: index_ts.php:39
writelog($type, $action, $error, $details_nr, $details, $data, $tablename='', $recuid='', $recpid='', $event_pid=-1, $NEWid='', $userId=0)
static getRecordsByField($theTable, $theField, $theValue, $whereClause='', $groupBy='', $orderBy='', $limit='', $useDeleteClause=TRUE)
static BEgetRootLine($uid, $clause='', $workspaceOL=FALSE)
static setShowHiddenFilesAndFolders($showHiddenFilesAndFolders)
isPSet($compiledPermissions, $tableName, $actionType='')
static intExplode($delimiter, $string, $removeEmptyValues=FALSE, $limit=0)
$uid
Definition: server.php:36
static getUserObj($classRef, $checkPrefix='', $silent=FALSE)
die
Definition: index.php:6
static storeHash($hash, $data, $ident)
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
const TYPO3_PROCEED_IF_NO_USER
Definition: index.php:20
recordEditAccessInternals($table, $idOrRow, $newRecord=FALSE, $deletedRecord=FALSE, $checkFullLanguageAccess=FALSE)
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
static redirect($url, $httpStatus=self::HTTP_STATUS_303)
Definition: HttpUtility.php:76
getFilePermissionsForStorage(\TYPO3\CMS\Core\Resource\ResourceStorage $storageObject)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
static deleteClause($table, $tableAlias='')