Fixed bug #14050: CleanUp - CGL format of t3lib files - t3lib_positionmap
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_userauthgroup.php
index 8199238..cd89783 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 1999-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  (c) 1999-2010 Kasper Skårhøj (kasperYYYY@typo3.com)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -28,9 +28,9 @@
  * Contains an extension class specifically for authentication/initialization of backend users in TYPO3
  *
  * $Id$
- * Revised for TYPO3 3.6 July/2003 by Kasper Skaarhoj
+ * Revised for TYPO3 3.6 July/2003 by Kasper Skårhøj
  *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  */
 /**
  * [CLASS/FUNCTION INDEX of SCRIPT]
@@ -99,8 +99,6 @@
  *
  */
 
-       // Need this for parsing User TSconfig
-require_once (PATH_t3lib.'class.t3lib_tsparser.php');
 
 
 
@@ -128,7 +126,7 @@ require_once (PATH_t3lib.'class.t3lib_tsparser.php');
  * Actually this class is extended again by t3lib_beuserauth which is the actual backend user class that will be instantiated.
  * In fact the two classes t3lib_beuserauth and this class could just as well be one, single class since t3lib_userauthgroup is not - to my knowledge - used separately elsewhere. But for historical reasons they are two separate classes.
  *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  * @package TYPO3
  * @subpackage t3lib
  */
@@ -269,9 +267,8 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
                                }
                        }
                }
-               if ($exitOnError)       {
-                       t3lib_BEfunc::typo3PrintError ('Access Error','This page is not within your DB-mounts',0);
-                       exit;
+               if ($exitOnError) {
+                       throw new RuntimeException('Access Error: This page is not within your DB-mounts');
                }
        }
 
@@ -284,9 +281,8 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
         */
        function modAccess($conf,$exitOnError)  {
                if (!t3lib_BEfunc::isModuleSetInTBE_MODULES($conf['name']))     {
-                       if ($exitOnError)       {
-                               t3lib_BEfunc::typo3PrintError ('Fatal Error','This module "'.$conf['name'].'" is not enabled in TBE_MODULES',0);
-                               exit;
+                       if ($exitOnError) {
+                               throw new RuntimeException('Fatal Error: This module "'.$conf['name'].'" is not enabled in TBE_MODULES');
                        }
                        return FALSE;
                }
@@ -298,9 +294,8 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
                                ($this->workspace>0 && t3lib_div::inList($conf['workspaces'],'custom')))        {
                                        // ok, go on...
                        } else {
-                               if ($exitOnError)       {
-                                       t3lib_BEfunc::typo3PrintError ('Workspace Error','This module "'.$conf['name'].'" is not available under the current workspace',0);
-                                       exit;
+                               if ($exitOnError) {
+                                       throw new RuntimeException('Workspace Error: This module "'.$conf['name'].'" is not available under the current workspace');
                                }
                                return FALSE;
                        }
@@ -314,9 +309,10 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
                        $acs = $this->check('modules',$conf['name']);
                }
                if (!$acs && $exitOnError)      {
-                       t3lib_BEfunc::typo3PrintError ('Access Error','You don\'t have access to this module.',0);
-                       exit;
-               } else return $acs;
+                       throw new RuntimeException('Access Error: You don\'t have access to this module.');
+               } else {
+                       return $acs;
+               }
        }
 
        /**
@@ -424,7 +420,7 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
 
 
                        // Acquire RTE object:
-               $RTE = &t3lib_BEfunc::RTEgetObj();
+               $RTE = t3lib_BEfunc::RTEgetObj();
                if (!is_object($RTE))   {
                        $this->RTE_errors = array_merge($this->RTE_errors, $RTE);
                }
@@ -446,12 +442,13 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
         * @param       string          String to search for in the groupData-list
         * @return      boolean         True if permission is granted (that is, the value was found in the groupData list - or the BE_USER is "admin")
         */
-       function check($type,$value)    {
-               if (isset($this->groupData[$type]))     {
-                       if ($this->isAdmin() || $this->inList($this->groupData[$type],$value)) {
-                               return 1;
+       function check($type, $value) {
+               if (isset($this->groupData[$type])) {
+                       if ($this->isAdmin() || $this->inList($this->groupData[$type], $value)) {
+                               return TRUE;
                        }
                }
+               return FALSE;
        }
 
        /**
@@ -473,7 +470,7 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
                if (!strcmp($value,'')) return TRUE;
 
                        // Certain characters are not allowed in the value
-               if (ereg('[:|,]',$value))       {
+               if (preg_match('/[:|,]/',$value))       {
                        return FALSE;
                }
 
@@ -540,6 +537,56 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
        }
 
        /**
+        * Check if user has access to all existing localizations for a certain record
+        *
+        * @param string        the table
+        * @param array         the current record
+        * @return boolean
+        */
+       function checkFullLanguagesAccess($table, $record) {
+               $recordLocalizationAccess = $this->checkLanguageAccess(0);
+               if ($recordLocalizationAccess
+                                && (
+                                       t3lib_BEfunc::isTableLocalizable($table)
+                                       || isset($GLOBALS['TCA'][$table]['ctrl']['transForeignTable'])
+                               )
+               ) {
+
+                       if (isset($GLOBALS['TCA'][$table]['ctrl']['transForeignTable'])) {
+                               $l10nTable = $GLOBALS['TCA'][$table]['ctrl']['transForeignTable'];
+                               $pointerField = $GLOBALS['TCA'][$l10nTable]['ctrl']['transOrigPointerField'];
+                               $pointerValue = $record['uid'];
+                       } else {
+                               $l10nTable = $table;
+                               $pointerField = $GLOBALS['TCA'][$l10nTable]['ctrl']['transOrigPointerField'];
+                               $pointerValue = $record[$pointerField] > 0 ? $record[$pointerField] : $record['uid'];
+                       }
+
+                       $recordLocalizations = t3lib_BEfunc::getRecordsByField(
+                               $l10nTable,
+                               $pointerField,
+                               $pointerValue,
+                               '',
+                               '',
+                               '',
+                               '1'
+                       );
+
+                       if (is_array($recordLocalizations)) {
+                               foreach($recordLocalizations as $localization) {
+                                       $recordLocalizationAccess = $recordLocalizationAccess
+                                               && $this->checkLanguageAccess($localization[$GLOBALS['TCA'][$l10nTable]['ctrl']['languageField']]);
+                                       if (!$recordLocalizationAccess) {
+                                               break;
+                                       }
+                               }
+                       }
+
+               }
+               return $recordLocalizationAccess;
+       }
+
+       /**
         * Checking if a user has editing access to a record from a $TCA table.
         * The checks does not take page permissions and other "environmental" things into account. It only deal with record internals; If any values in the record fields disallows it.
         * For instance languages settings, authMode selector boxes are evaluated (and maybe more in the future).
@@ -549,9 +596,11 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
         * @param       string          Table name
         * @param       mixed           If integer, then this is the ID of the record. If Array this just represents fields in the record.
         * @param       boolean         Set, if testing a new (non-existing) record array. Will disable certain checks that doesn't make much sense in that context.
+        * @param       boolean         Set, if testing a deleted record array.
+        * @param       boolean         Set, whenever access to all translations of the record is required
         * @return      boolean         True if OK, otherwise false
         */
-       function recordEditAccessInternals($table,$idOrRow,$newRecord=FALSE)    {
+       function recordEditAccessInternals($table, $idOrRow, $newRecord = FALSE, $deletedRecord = FALSE, $checkFullLanguageAccess = FALSE) {
                global $TCA;
 
                if (isset($TCA[$table]))        {
@@ -562,7 +611,11 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
 
                                // Fetching the record if the $idOrRow variable was not an array on input:
                        if (!is_array($idOrRow))        {
-                               $idOrRow = t3lib_BEfunc::getRecord($table, $idOrRow);
+                               if ($deletedRecord) {
+                                       $idOrRow = t3lib_BEfunc::getRecord($table, $idOrRow, '*', '', FALSE);
+                               } else {
+                                       $idOrRow = t3lib_BEfunc::getRecord($table, $idOrRow);
+                               }
                                if (!is_array($idOrRow))        {
                                        $this->errorMsg = 'ERROR: Record could not be fetched.';
                                        return FALSE;
@@ -575,20 +628,25 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
                                        if (!$this->checkLanguageAccess($idOrRow[$TCA[$table]['ctrl']['languageField']]))       {
                                                $this->errorMsg = 'ERROR: Language was not allowed.';
                                                return FALSE;
+                                       } elseif ($checkFullLanguageAccess && $idOrRow[$TCA[$table]['ctrl']['languageField']]==0 && !$this->checkFullLanguagesAccess($table, $idOrRow)) {
+                                               $this->errorMsg = 'ERROR: Related/affected language was not allowed.';
+                                               return FALSE;
                                        }
                                } else {
                                        $this->errorMsg = 'ERROR: The "languageField" field named "'.$TCA[$table]['ctrl']['languageField'].'" was not found in testing record!';
                                        return FALSE;
                                }
+                       } elseif (isset($TCA[$table]['ctrl']['transForeignTable']) && $checkFullLanguageAccess && !$this->checkFullLanguagesAccess($table, $idOrRow)) {
+                               return FALSE;
                        }
 
                                // Checking authMode fields:
                        if (is_array($TCA[$table]['columns']))  {
-                               foreach($TCA[$table]['columns'] as $fN => $fV)  {
-                                       if (isset($idOrRow[$fN]))       {       //
-                                               if ($fV['config']['type']=='select' && $fV['config']['authMode'] && !strcmp($fV['config']['authMode_enforce'],'strict')) {
-                                                       if (!$this->checkAuthMode($table,$fN,$idOrRow[$fN],$fV['config']['authMode']))  {
-                                                               $this->errorMsg = 'ERROR: authMode "'.$fV['config']['authMode'].'" failed for field "'.$fN.'" with value "'.$idOrRow[$fN].'" evaluated';
+                               foreach ($TCA[$table]['columns'] as $fieldName => $fieldValue) {
+                                       if (isset($idOrRow[$fieldName])) {
+                                               if ($fieldValue['config']['type'] == 'select' && $fieldValue['config']['authMode'] && !strcmp($fieldValue['config']['authMode_enforce'], 'strict')) {
+                                                       if (!$this->checkAuthMode($table, $fieldName, $idOrRow[$fieldName], $fieldValue['config']['authMode'])) {
+                                                               $this->errorMsg = 'ERROR: authMode "' . $fieldValue['config']['authMode'] . '" failed for field "' . $fieldName . '" with value "' . $idOrRow[$fieldName] . '" evaluated';
                                                                return FALSE;
                                                        }
                                                }
@@ -632,24 +690,40 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
        }
 
        /**
-        * Will check a type of permission against the compiled permission integer, $lCP, and in relation to table, $table
+        * Checks a type of permission against the compiled permission integer, $compiledPermissions, and in relation to table, $tableName
         *
-        * @param       integer         $lCP could typically be the "compiled permissions" integer returned by ->calcPerms
-        * @param       string          $table is the tablename to check: If "pages" table then edit,new,delete and editcontent permissions can be checked. Other tables will be checked for "editcontent" only (and $type will be ignored)
-        * @param       string          For $table='pages' this can be 'edit' (2), 'new' (8 or 16), 'delete' (4), 'editcontent' (16). For all other tables this is ignored. (16 is used)
+        * @param       integer         $compiledPermissions could typically be the "compiled permissions" integer returned by ->calcPerms
+        * @param       string          $tableName is the tablename to check: If "pages" table then edit,new,delete and editcontent permissions can be checked. Other tables will be checked for "editcontent" only (and $type will be ignored)
+        * @param       string          For $tableName='pages' this can be 'edit' (2), 'new' (8 or 16), 'delete' (4), 'editcontent' (16). For all other tables this is ignored. (16 is used)
         * @return      boolean
-        * @access private
+        * @access public (used by typo3/alt_clickmenu.php)
         */
-       function isPSet($lCP,$table,$type='')   {
-               if ($this->isAdmin())   return true;
-               if ($table=='pages')    {
-                       if ($type=='edit')      return $lCP & 2;
-                       if ($type=='new')       return ($lCP & 8) || ($lCP & 16);       // Create new page OR pagecontent
-                       if ($type=='delete')    return $lCP & 4;
-                       if ($type=='editcontent')       return $lCP & 16;
+       public function isPSet($compiledPermissions, $tableName, $actionType = '') {
+               if ($this->isAdmin()) {
+                       $result = TRUE;
+               }
+               elseif ($tableName == 'pages') {
+                       switch($actionType) {
+                               case 'edit':
+                                       $result = ($compiledPermissions & 2) !== 0;
+                                       break;
+                               case 'new':
+                                       // Create new page OR page content
+                                       $result = ($compiledPermissions & (8 + 16)) !== 0;
+                                       break;
+                               case 'delete':
+                                       $result = ($compiledPermissions & 4) !== 0;
+                                       break;
+                               case 'editcontent':
+                                       $result = ($compiledPermissions & 16) !== 0;
+                                       break;
+                               default:
+                                       $result = FALSE;
+                       }
                } else {
-                       return $lCP & 16;
+                       $result = ($compiledPermissions & 16) !== 0;
                }
+               return $result;
        }
 
        /**
@@ -658,7 +732,12 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
         * @return      boolean
         */
        function mayMakeShortcut()      {
-               return $this->getTSConfigVal('options.shortcutFrame') && !$this->getTSConfigVal('options.mayNotCreateEditShortcuts');
+                       // "Shortcuts" have been renamed to "Bookmarks"
+                       // @deprecated remove shortcuts code in TYPO3 4.7
+               return  ($this->getTSConfigVal('options.enableShortcuts')
+                               || $this->getTSConfigVal('options.enableBookmarks'))
+                               &&      (!$this->getTSConfigVal('options.mayNotCreateEditShortcuts')
+                               && !$this->getTSConfigVal('options.mayNotCreateEditBookmarks'));
        }
 
        /**
@@ -799,11 +878,35 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
 
                if ($this->workspace>0) {
                        $stat = $this->checkWorkspaceCurrent();
-                       $memberStageLimit = $this->workspaceRec['review_stage_edit'] ? 1 : 0;
-                       if (($stage<=$memberStageLimit && $stat['_ACCESS']==='member') ||
-                               ($stage<=1 && $stat['_ACCESS']==='reviewer') ||
-                               ($stat['_ACCESS']==='owner')) {
-                                       return TRUE;    // OK for these criteria
+
+                               // Check if custom staging is activated
+                       $workspaceRec = t3lib_BEfunc::getRecord('sys_workspace', $stat['uid']);
+                       if ($workspaceRec['custom_stages'] > 0  && $stage !== '0' && $stage !== '-10') {
+
+                                       // Get custom stage record
+                               $workspaceStageRec = t3lib_BEfunc::getRecord('sys_workspace_stage', $stage);
+                                       // Check if the user is responsible for the current stage
+                               if ((t3lib_div::inList($workspaceStageRec['responsible_persons'], 'be_users_' . $this->user['uid'])
+                                               && $stat['_ACCESS'] === 'member')
+                                       || $stat['_ACCESS'] === 'owner') {
+                                       return TRUE; // OK for these criteria
+                               }
+
+                                       // Check if the user is in a group which is responsible for the current stage
+                               foreach ($this->userGroupsUID as $groupUid) {
+                                       if ((t3lib_div::inList($workspaceStageRec['responsible_persons'], 'be_groups_' . $groupUid)
+                                                       && $stat['_ACCESS'] === 'member')
+                                               || $stat['_ACCESS'] === 'owner') {
+                                               return TRUE; // OK for these criteria
+                                       }
+                               }
+                       } else {
+                               $memberStageLimit = $this->workspaceRec['review_stage_edit'] ? 1 : 0;
+                               if (($stage <= $memberStageLimit && $stat['_ACCESS'] === 'member')
+                                               || ($stage <= 1 && $stat['_ACCESS'] === 'reviewer')
+                                               || $stat['_ACCESS'] === 'owner') {
+                                               return TRUE;    // OK for these criteria
+                               }
                        }
                } else return TRUE;     // Always OK for live and draft workspaces.
        }
@@ -853,9 +956,14 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
        }
 
        /**
-        * Workspace Versioning type access?
+        * Workspace Versioning type access. Check wether the requsted type of versioning (element/page/branch) is allowd in current workspace
+        *   (element/pages/branches type of versioning can/could be set on custom workspaces on filed "vtype")
         *
+        * @todo workspacecleanup: this seems mostly obsolete and should be removed
         * @param       integer         Versioning type to evaluation: -1, 0, >1
+        *                                              0 = page (deprecated)
+        *                                              -1 = element
+        *                                              >1 = branch (deprecated), indicating the "nesting" level
         * @return      boolean         TRUE if OK
         */
        function workspaceVersioningTypeAccess($type)   {
@@ -892,6 +1000,7 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
        /**
         * Finding "closest" versioning type, used for creation of new records.
         *
+        * @see workspaceVersioningTypeAccess() for hints on $type
         * @param       integer         Versioning type to evaluation: -1, 0, >1
         * @return      integer         Returning versioning type
         */
@@ -1027,7 +1136,7 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
         * @return      integer         File operation permission bitmask
         */
        public function getFileoperationPermissions() {
-               if ($this->isAdmin()) { 
+               if ($this->isAdmin()) {
                        return 31;
                } else {
                        return $this->groupData['fileoper_perms'];
@@ -1104,7 +1213,6 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
                        if ($this->isAdmin())   {
                                $this->TSdataArray[]=$this->addTScomment('"admin" user presets:').'
                                        admPanel.enable.all = 1
-                                       options.shortcutFrame = 1
                                ';
                                if (t3lib_extMgm::isLoaded('sys_note')) {
                                        $this->TSdataArray[]='
@@ -1145,19 +1253,30 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
                                // Check include lines.
                        $this->TSdataArray = t3lib_TSparser::checkIncludeLines_array($this->TSdataArray);
 
-                               // Parsing the user TSconfig (or getting from cache)
-                       $this->userTS_text = implode(chr(10).'[GLOBAL]'.chr(10),$this->TSdataArray);    // Imploding with "[global]" will make sure that non-ended confinements with braces are ignored.
-                       $hash = md5('userTS:'.$this->userTS_text);
-                       $cachedContent = t3lib_BEfunc::getHash($hash);
-                       if (isset($cachedContent) && !$this->userTS_dontGetCached)      {
-                               $this->userTS = unserialize($cachedContent);
+                       $this->userTS_text = implode(LF.'[GLOBAL]'.LF,$this->TSdataArray);      // Imploding with "[global]" will make sure that non-ended confinements with braces are ignored.
+
+                       if ($GLOBALS['TYPO3_CONF_VARS']['BE']['TSconfigConditions'] && !$this->userTS_dontGetCached) {
+                                       // Perform TS-Config parsing with condition matching
+                               $parseObj = t3lib_div::makeInstance('t3lib_TSparser_TSconfig');
+                               $res = $parseObj->parseTSconfig($this->userTS_text, 'userTS');
+                               if ($res) {
+                                       $this->userTS = $res['TSconfig'];
+                                       $this->userTSUpdated = ($res['cached'] ? 0 : 1);
+                               }
                        } else {
-                               $parseObj = t3lib_div::makeInstance('t3lib_TSparser');
-                               $parseObj->parse($this->userTS_text);
-                               $this->userTS = $parseObj->setup;
-                               t3lib_BEfunc::storeHash($hash,serialize($this->userTS),'BE_USER_TSconfig');
-                                       // Update UC:
-                               $this->userTSUpdated=1;
+                                       // Parsing the user TSconfig (or getting from cache)
+                               $hash = md5('userTS:' . $this->userTS_text);
+                               $cachedContent = t3lib_BEfunc::getHash($hash);
+                               if (isset($cachedContent) && !$this->userTS_dontGetCached) {
+                                       $this->userTS = unserialize($cachedContent);
+                               } else {
+                                       $parseObj = t3lib_div::makeInstance('t3lib_TSparser');
+                                       $parseObj->parse($this->userTS_text);
+                                       $this->userTS = $parseObj->setup;
+                                       t3lib_BEfunc::storeHash($hash, serialize($this->userTS), 'BE_USER_TSconfig');
+                                               // Update UC:
+                                       $this->userTSUpdated=1;
+                               }
                        }
 
                                // Processing webmounts
@@ -1166,9 +1285,11 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
                        }
 
                                // Processing filemounts
+                       t3lib_div::loadTCA('sys_filemounts');
+                       $orderBy = $GLOBALS['TCA']['sys_filemounts']['ctrl']['default_sortby'] ? $GLOBALS['TYPO3_DB']->stripOrderBy($GLOBALS['TCA']['sys_filemounts']['ctrl']['default_sortby']) : 'sorting';
                        $this->dataLists['filemount_list'] = t3lib_div::uniqueList($this->dataLists['filemount_list']);
                        if ($this->dataLists['filemount_list']) {
-                               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_filemounts', 'deleted=0 AND hidden=0 AND pid=0 AND uid IN ('.$this->dataLists['filemount_list'].')');
+                               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_filemounts', 'deleted=0 AND hidden=0 AND pid=0 AND uid IN ('.$this->dataLists['filemount_list'].')', '', $orderBy);
                                while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {
                                        $this->addFileMount($row['title'], $row['path'], $row['path'], $row['base']?1:0, '');
                                }
@@ -1229,12 +1350,12 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
 
                        // Hook for manipulation of the WHERE sql sentence which controls which BE-groups are included
                if (is_array ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['fetchGroupQuery'])) {
-                   foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['fetchGroupQuery'] as $classRef) {
-                       $hookObj = &t3lib_div::getUserObj($classRef);
+                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['fetchGroupQuery'] as $classRef) {
+                       $hookObj = t3lib_div::getUserObj($classRef);
                        if(method_exists($hookObj,'fetchGroupQuery_processQuery')){
-                           $whereSQL = $hookObj->fetchGroupQuery_processQuery($this, $grList, $idList, $whereSQL);
+                               $whereSQL = $hookObj->fetchGroupQuery_processQuery($this, $grList, $idList, $whereSQL);
+                       }
                        }
-                   }
                }
 
                $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $this->usergroup_table, $whereSQL);
@@ -1246,8 +1367,8 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
 
                        // Traversing records in the correct order
                $include_staticArr = t3lib_div::intExplode(',',$grList);
-               reset($include_staticArr);
-               while(list(,$uid)=each($include_staticArr))     {       // traversing list
+                       // traversing list
+               foreach ($include_staticArr as $key => $uid) {
 
                                // Get row:
                        $row=$this->userGroups[$uid];
@@ -1390,12 +1511,12 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
        function addTScomment($str)     {
                $delimiter = '# ***********************************************';
 
-               $out = $delimiter.chr(10);
-               $lines = t3lib_div::trimExplode(chr(10),$str);
+               $out = $delimiter.LF;
+               $lines = t3lib_div::trimExplode(LF,$str);
                foreach($lines as $v)   {
-                       $out.= '# '.$v.chr(10);
+                       $out.= '# '.$v.LF;
                }
-               $out.= $delimiter.chr(10);
+               $out.= $delimiter.LF;
                return $out;
        }
 
@@ -1428,35 +1549,66 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
                        // Initializing workspace by evaluating and setting the workspace, possibly updating it in the user record!
                $this->setWorkspace($this->user['workspace_id']);
 
-                       // Setting up the db mount points of the (custom) workspace, if any:
-               if ($this->workspace>0 && trim($this->workspaceRec['db_mountpoints'])!=='')     {
-
-                               // Initialize:
-                       $newMounts = array();
+                       // Limiting the DB mountpoints if there any selected in the workspace record
+               $dbMountpoints = trim($this->workspaceRec['db_mountpoints']);
+               if ($this->workspace > 0 && $dbMountpoints != '') {
+                       $filteredDbMountpoints = array();
                        $readPerms = '1=1'; // Notice: We cannot call $this->getPagePermsClause(1); as usual because the group-list is not available at this point. But bypassing is fine because all we want here is check if the workspace mounts are inside the current webmounts rootline. The actual permission checking on page level is done elsewhere as usual anyway before the page tree is rendered.
 
                                // Traverse mount points of the
-                       $mountPoints = t3lib_div::intExplode(',',$this->workspaceRec['db_mountpoints']);
-                       foreach($mountPoints as $mpId)  {
-                               if ($this->isInWebMount($mpId,$readPerms))      {
-                                       $newMounts[] = $mpId;
+                       $dbMountpoints = t3lib_div::intExplode(',', $dbMountpoints);
+                       foreach ($dbMountpoints as $mpId) {
+                               if ($this->isInWebMount($mpId, $readPerms)) {
+                                       $filteredDbMountpoints[] = $mpId;
                                }
                        }
 
                                // Re-insert webmounts:
-                       $this->groupData['webmounts'] = implode(',',array_unique($newMounts));
+                       $filteredDbMountpoints = array_unique($filteredDbMountpoints);
+                       $this->groupData['webmounts'] = implode(',', $filteredDbMountpoints);
                }
 
-                       // Setting up the file mount points of the (custom) workspace, if any:
-               if ($this->workspace!==0)       $this->groupData['filemounts'] = array();
-               if ($this->workspace>0 && trim($this->workspaceRec['file_mountpoints'])!=='')   {
+                       // Filtering the file mountpoints
+                       // if there some selected in the workspace record
+               if ($this->workspace !== 0) {
+                       $usersFileMounts = $this->groupData['filemounts'];
+                       $this->groupData['filemounts'] = array();
+               }
+               $fileMountpoints = trim($this->workspaceRec['file_mountpoints']);
+               if ($this->workspace > 0) {
 
-                               // Processing filemounts
-                       $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_filemounts', 'deleted=0 AND hidden=0 AND pid=0 AND uid IN ('.$GLOBALS['TYPO3_DB']->cleanIntList($this->workspaceRec['file_mountpoints']).')');
-                       while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {
-                               $this->addFileMount($row['title'], $row['path'], $row['path'], $row['base']?1:0, '');
+                               // no custom filemounts that should serve as filter
+                               // so all user mountpoints are re-applied
+                       if ($fileMountpoints === '') {
+                               $this->groupData['filemounts'] = $usersFileMounts;
+                       } else {
+                                       // Fetching all filemounts from the workspace
+                               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+                                       '*',
+                                       'sys_filemounts',
+                                       'deleted = 0 AND hidden = 0 AND pid = 0 AND uid IN (' . $GLOBALS['TYPO3_DB']->cleanIntList($fileMountpoints) . ')'
+                               );
+
+                               while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
+                                               // add every filemount of this workspace record
+                                       $this->addFileMount($row['title'], $row['path'], $row['path'], ($row['base'] ? 1 : 0), '');
+
+                                               // get the added entry, and check if it was in the users' original filemounts
+                                               // if not, remove it from the new filemount list again
+                                               // see self::addFileMount
+                                       end($this->groupData['filemounts']);
+                                       $md5hash = key($this->groupData['filemounts']);
+                                       if (!array_key_exists($md5hash, $usersFileMounts)) {
+                                               unset($this->groupData['filemounts'][$md5hash]);
+                                       }
+                               }
                        }
                }
+
+               if ($allowed_languages = $this->getTSConfigVal('options.workspaces.allowed_languages.'.$this->workspace))       {
+                       $this->groupData['allowed_languages'] = $allowed_languages;
+                       $this->groupData['allowed_languages'] = t3lib_div::uniqueList($this->groupData['allowed_languages']);
+               }
        }
 
        /**
@@ -1469,6 +1621,22 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
        function checkWorkspace($wsRec,$fields='uid,title,adminusers,members,reviewers,publish_access,stagechg_notification')   {
                $retVal = FALSE;
 
+                       // Show draft workspace only if it's enabled in version extension
+               if (t3lib_extMgm::isLoaded('version')) {
+                       $versionExtConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['version']);
+                       if (!$versionExtConf['showDraftWorkspace']) {
+                               if (!is_array($wsRec)) {
+                                       if ((string) $wsRec === '-1') {
+                                               return FALSE;
+                                       }
+                               } else {
+                                       if ((string) $wsRec['uid'] === '-1') {
+                                               return FALSE;
+                                       }
+                               }
+                       }
+               }
+
                        // If not array, look up workspace record:
                if (!is_array($wsRec))  {
                        switch((string)$wsRec)  {
@@ -1504,9 +1672,15 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
                                        break;
                                        default:
                                                        // Checking if the guy is admin:
-                                               if (t3lib_div::inList($wsRec['adminusers'],$this->user['uid'])) {
+                                               if (t3lib_div::inList($wsRec['adminusers'], 'be_users_' . $this->user['uid'])) {
                                                        return array_merge($wsRec, array('_ACCESS' => 'owner'));
                                                }
+                                                       // Checking if he is owner through a user group of his:
+                                               foreach ($this->userGroupsUID as $groupUid) {
+                                                       if (t3lib_div::inList($wsRec['adminusers'], 'be_groups_' . $groupUid)) {
+                                                               return array_merge($wsRec, array('_ACCESS' => 'owner'));
+                                                       }
+                                               }
                                                        // Checking if he is reviewer user:
                                                if (t3lib_div::inList($wsRec['reviewers'],'be_users_'.$this->user['uid']))      {
                                                        return array_merge($wsRec, array('_ACCESS' => 'reviewer'));
@@ -1701,7 +1875,7 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
                if ($email)     {
 
                                // get last flag set in the log for sending
-                       $theTimeBack = time()-$secondsBack;
+                       $theTimeBack = $GLOBALS['EXEC_TIME'] - $secondsBack;
                        $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
                                                        'tstamp',
                                                        'sys_log',
@@ -1735,9 +1909,9 @@ This is a dump of the failures:
                                while($testRows = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))  {
                                        $theData = unserialize($testRows['log_data']);
                                        $email_body.= date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'].' '.$GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'],$testRows['tstamp']).':  '.@sprintf($testRows['details'],''.$theData[0],''.$theData[1],''.$theData[2]);
-                                       $email_body.= chr(10);
+                                       $email_body.= LF;
                                }
-                               mail(   $email,
+                               t3lib_utility_Mail::mail($email,
                                        $subject,
                                        $email_body,
                                        'From: TYPO3 Login WARNING<>'
@@ -1754,4 +1928,4 @@ if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class
        include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_userauthgroup.php']);
 }
 
-?>
\ No newline at end of file
+?>