t3lib/class.t3lib_tcemain.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00163 // *******************************
00164 // Including necessary libraries
00165 // *******************************
00166 require_once (PATH_t3lib.'class.t3lib_loaddbgroup.php');
00167 require_once (PATH_t3lib.'class.t3lib_parsehtml_proc.php');
00168 require_once (PATH_t3lib.'class.t3lib_stdgraphic.php');
00169 require_once (PATH_t3lib.'class.t3lib_basicfilefunc.php');
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00199 class t3lib_TCEmain     {
00200         var $log_table = 'sys_log';
00201 
00202         var $checkStoredRecords = 1;    // This will read the record after having updated or inserted it. If anything is not properly submitted an error is written to the log. This feature consumes extra time by selecting records
00203         var $checkStoredRecords_loose=1;        // If set, values '' and 0 will equal each other when the stored records are checked.
00204         var $sortIntervals = 256;               // The interval between sorting numbers used with tables with a 'sorting' field defined. Min 1
00205 
00206         var $deleteTree = 0;                    // Boolean. If this is set, then a page is deleted by deleting the whole branch under it (user must have deletepermissions to it all). If not set, then the page is delete ONLY if it has no branch
00207         var $copyTree = 0;                              // int. If 0 then branch is NOT copied. If 1 then pages on the 1st level is copied. If 2 then pages on the second level is copied ... and so on
00208         var $versionizeTree = 0;                // int. If 0 then branch is NOT versionized. If 1 then pages on the 1st level is versionized. If 2 then pages on the second level is versionized ... and so on
00209         var $neverHideAtCopy = 0;               // Boolean. If set, then the 'hideAtCopy' flag for tables will be ignored.
00210         var $reverseOrder=0;                    // boolean. If set, the dataarray is reversed in the order, which is a nice thing if you're creating a whole new bunch of records.
00211         var $copyWhichTables = '*';             // This list of tables decides which tables will be copied. If empty then none will. If '*' then all will (that the user has permission to of course)
00212         var $stripslashes_values=1;             // If set, incoming values in the data-array have their slashes stripped. ALWAYS SET THIS TO ZERO and supply an unescaped data array instead. This switch may totally disappear in future versions of this class!
00213         var $storeLogMessages=1;                // If set, the default log-messages will be stored. This should not be necessary if the locallang-file for the log-display is properly configured. So disabling this will just save some database-space as the default messages are not saved.
00214         var $enableLogging=1;                   // If set, actions are logged.
00215 
00216         var $callBackObj;                               // Call back object for flex form traversation. Useful when external classes wants to use the iteration functions inside tcemain for traversing a FlexForm structure.
00217 
00218 //      var $history=1;                                 // Bit-array: Bit0: History on/off. DEPENDS on checkSimilar to be set!
00219         var $checkSimilar=1;                    // Boolean: If set, only fields which are different from the database values are saved! In fact, if a whole input array is similar, it's not saved then.
00220         var $dontProcessTransformations=0;      // Boolean: If set, then transformations are NOT performed on the input.
00221 #       var $disableRTE = 0;                    // Boolean: If set, the RTE is expected to have been disabled in the interface which submitted information. Thus transformations related to the RTE is not done.
00222 
00223         var $pMap = Array(              // Permission mapping
00224                 'show' => 1,                    // 1st bit
00225                 'edit' => 2,                    // 2nd bit
00226                 'delete' => 4,                  // 3rd bit
00227                 'new' => 8,                             // 4th bit
00228                 'editcontent' => 16             // 5th bit
00229         );
00230         var $defaultPermissions = array(                // Can be overridden from $TYPO3_CONF_VARS
00231                 'user' => 'show,edit,delete,new,editcontent',
00232                 'group' => 'show,edit,new,editcontent',
00233                 'everybody' => ''
00234         );
00235 
00236 
00237         var $alternativeFileName=array();               // Use this array to force another name onto a file. Eg. if you set ['/tmp/blablabal'] = 'my_file.txt' and '/tmp/blablabal' is set for a certain file-field, then 'my_file.txt' will be used as the name instead.
00238         var $data_disableFields=array();                // If entries are set in this array corresponding to fields for update, they are ignored and thus NOT updated. You could set this array from a series of checkboxes with value=0 and hidden fields before the checkbox with 1. Then an empty checkbox will disable the field.
00239         var $defaultValues=array();                             // You can set this array on the form $defaultValues[$table][$field] = $value to override the default values fetched from TCA. You must set this externally.
00240         var $overrideValues=array();                    // You can set this array on the form $overrideValues[$table][$field] = $value to override the incoming data. You must set this externally. You must make sure the fields in this array are also found in the table, because it's not checked. All columns can be set by this array!
00241         var $suggestedInsertUids=array();               // Use this array to validate suggested uids for tables by setting [table]:[uid]. This is a dangerous option since it will force the inserted record to have a certain UID. The value just have to be true, but if you set it to "DELETE" it will make sure any record with that UID will be deleted first (raw delete). The option is used for import of T3D files when synchronizing between two mirrored servers. As a security measure this feature is available only for Admin Users (for now)
00242 
00243                 // *********
00244                 // internal
00245                 // *********
00246         var $fileFunc;          // May contain an object
00247         var $last_log_id;
00248         var $BE_USER;           // The user-object the script uses. If not set from outside, this is set to the current global $BE_USER.
00249         var $userid;            // will be set to uid of be_user executing this script
00250         var $username;          // will be set to username of be_user executing this script
00251         var $admin;                     // will be set if user is admin
00252         var $exclude_array;     // the list of <table>-<fields> that cannot be edited. This is compiled from TCA/exclude-flag combined with non_exclude_fields for the user.
00253 
00254         var $data = Array();
00255         var $datamap = Array();
00256         var $cmd = Array();
00257         var $cmdmap = Array();
00258         var $uploadedFileArray = array();
00259 
00260         var $cachedTSconfig = array();
00261         var $substNEWwithIDs = Array();
00262         var $substNEWwithIDs_table = Array();
00263         var $recUpdateAccessCache = Array();    // Used by function checkRecordUpdateAccess() to store whether a record is updateable or not.
00264         var $recInsertAccessCache = Array();
00265         var $isRecordInWebMount_Cache=array();
00266         var $isInWebMount_Cache=array();
00267         var $pageCache = Array();                                       // Used for caching page records in pageInfo()
00268         var $copyMappingArray = Array();                        // Use by the copy action to track the ids of new pages so subpages are correctly inserted!
00269         var $copyMappingArray_merged = Array();         // This array is the sum of all copying operations in this class. May be READ from outside, thus partly public.
00270         var $registerDBList=array();
00271         var $dbAnalysisStore=array();
00272         var $removeFilesStore=array();
00273         var $copiedFileMap=array();
00274 
00275         var $checkValue_currentRecord=array();          // Set to "currentRecord" during checking of values.
00276 
00277 
00288         function start($data,$cmd,$altUserObject='')    {
00289                         // Initializing BE_USER
00290                 $this->BE_USER = is_object($altUserObject) ? $altUserObject : $GLOBALS['BE_USER'];
00291                 $this->userid = $this->BE_USER->user['uid'];
00292                 $this->username = $this->BE_USER->user['username'];
00293                 $this->admin = $this->BE_USER->user['admin'];
00294 
00295                         // Initializing default permissions for pages
00296                 $defaultPermissions = $GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPermissions'];
00297                 if (isset($defaultPermissions['user']))         {$this->defaultPermissions['user'] = $defaultPermissions['user'];}
00298                 if (isset($defaultPermissions['group']))                {$this->defaultPermissions['group'] = $defaultPermissions['group'];}
00299                 if (isset($defaultPermissions['everybody']))            {$this->defaultPermissions['everybody'] = $defaultPermissions['everybody'];}
00300 
00301                         // generates the excludelist, based on TCA/exclude-flag and non_exclude_fields for the user:
00302                 $this->exclude_array = ($this->admin) ? array() : $this->getExcludeListArray();
00303 
00304                         // Setting the data and cmd arrays
00305                 if (is_array($data)) {
00306                         reset($data);
00307                         $this->datamap = $data;
00308                 }
00309                 if (is_array($cmd))     {
00310                         reset($cmd);
00311                         $this->cmdmap = $cmd;
00312                 }
00313         }
00314 
00321         function setMirror($mirror)     {
00322                 if (is_array($mirror))  {
00323                         reset($mirror);
00324                         while(list($table,$uid_array)=each($mirror))    {
00325                                 if (isset($this->datamap[$table]))      {
00326                                         reset($uid_array);
00327                                         while (list($id,$uidList) = each($uid_array))   {
00328                                                 if (isset($this->datamap[$table][$id])) {
00329                                                         $theIdsInArray = t3lib_div::trimExplode(',',$uidList,1);
00330                                                         while(list(,$copyToUid)=each($theIdsInArray))   {
00331                                                                 $this->datamap[$table][$copyToUid] = $this->datamap[$table][$id];
00332                                                         }
00333                                                 }
00334                                         }
00335                                 }
00336                         }
00337                 }
00338         }
00339 
00346         function setDefaultsFromUserTS($userTS) {
00347                 global $TCA;
00348                 if (is_array($userTS))  {
00349                         foreach($userTS as $k => $v)    {
00350                                 $k = substr($k,0,-1);
00351                                 if ($k && is_array($v) && isset($TCA[$k]))      {
00352                                         if (is_array($this->defaultValues[$k])) {
00353                                                 $this->defaultValues[$k] = array_merge($this->defaultValues[$k],$v);
00354                                         } else {
00355                                                 $this->defaultValues[$k] = $v;
00356                                         }
00357                                 }
00358                         }
00359                 }
00360         }
00361 
00369         function process_uploads($postFiles)    {
00370                 if (is_array($postFiles))       {
00371                         reset($postFiles);
00372                         $subA = current($postFiles);
00373                         if (is_array($subA))    {
00374                                 if (is_array($subA['name']) && is_array($subA['type']) && is_array($subA['tmp_name']) && is_array($subA['size']))       {
00375                                                 // Initialize the uploadedFilesArray:
00376                                         $this->uploadedFileArray=array();
00377 
00378                                                 // For each entry:
00379                                         foreach($subA as $key => $values)       {
00380                                                 $this->process_uploads_traverseArray($this->uploadedFileArray,$values,$key);
00381                                         }
00382                                 } else {
00383                                         $this->uploadedFileArray=$subA;
00384                                 }
00385                         }
00386                 }
00387         }
00388 
00399         function process_uploads_traverseArray(&$outputArr,$inputArr,$keyToSet) {
00400                 if (is_array($inputArr))        {
00401                         foreach($inputArr as $key => $value)    {
00402                                 $this->process_uploads_traverseArray($outputArr[$key],$inputArr[$key],$keyToSet);
00403                         }
00404                 } else {
00405                         $outputArr[$keyToSet]=$inputArr;
00406                 }
00407         }
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 
00417 
00418 
00419 
00420 
00421 
00422 
00423         /*********************************************
00424          *
00425          * PROCESSING DATA
00426          *
00427          *********************************************/
00428 
00435         function process_datamap() {
00436 //              debug(array('process_datamap'));
00437                 global $TCA, $TYPO3_CONF_VARS;
00438 
00439                         // First prepare user defined objects (if any) for hooks which extend this function:
00440                 $hookObjectsArr = array();
00441                 if (is_array ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'])) {
00442                         foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'] as $classRef) {
00443                                 $hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
00444                         }
00445                 }
00446 
00447                         // Organize tables so that the pages-table are always processed first. This is required if you want to make sure that content pointing to a new page will be created.
00448                 $orderOfTables = Array();
00449                 if (isset($this->datamap['pages']))     {               // Set pages first.
00450                         $orderOfTables[]='pages';
00451                 }
00452                 reset($this->datamap);
00453                 while (list($table,) = each($this->datamap))    {
00454                         if ($table!='pages')    {
00455                                 $orderOfTables[]=$table;
00456                         }
00457                 }
00458 
00459                         // Process the tables...
00460                 foreach($orderOfTables as $table)       {
00461                                 /* Check if
00462                                         - table is set in $TCA,
00463                                         - table is NOT readOnly,
00464                                         - the table is set with content in the data-array (if not, there's nothing to process...)
00465                                         - permissions for tableaccess OK
00466                                 */
00467                         $modifyAccessList = $this->checkModifyAccessList($table);
00468                         if (!$modifyAccessList) {
00469                                 $this->log($table,$id,2,0,1,"Attempt to modify table '%s' without permission",1,array($table));
00470                         }
00471                         if (isset($TCA[$table]) && !$this->tableReadOnly($table) && is_array($this->datamap[$table]) && $modifyAccessList)      {
00472                                 if ($this->reverseOrder)        {
00473                                         $this->datamap[$table] = array_reverse($this->datamap[$table], 1);
00474                                 }
00475 
00476                                         // For each record from the table, do:
00477                                         // $id is the record uid, may be a string if new records...
00478                                         // $incomingFieldArray is the array of fields
00479                                 foreach($this->datamap[$table] as $id => $incomingFieldArray)   {
00480                                         if (is_array($incomingFieldArray))      {
00481 
00482                                                         // Hook: processDatamap_preProcessIncomingFieldArray
00483                                                 foreach($hookObjectsArr as $hookObj)    {
00484                                                         if (method_exists($hookObj, 'processDatamap_preProcessFieldArray')) {
00485                                                                 $hookObj->processDatamap_preProcessFieldArray($incomingFieldArray, $table, $id, $this);
00486                                                         }
00487                                                 }
00488 
00489                                                         // ******************************
00490                                                         // Checking access to the record
00491                                                         // ******************************
00492                                                 $recordAccess = 0;
00493                                                 $old_pid_value = '';
00494                                                 if (!t3lib_div::testInt($id)) {               // Is it a new record? (Then Id is a string)
00495                                                         $fieldArray = $this->newFieldArray($table);     // Get a fieldArray with default values
00496                                                         if (isset($incomingFieldArray['pid']))  {       // A pid must be set for new records.
00497                                                                         // $value = the pid
00498                                                                 $pid_value = $incomingFieldArray['pid'];
00499 
00500                                                                         // Checking and finding numerical pid, it may be a string-reference to another value
00501                                                                 $OK = 1;
00502                                                                 if (strstr($pid_value,'NEW'))   {       // If a NEW... id
00503                                                                         if (substr($pid_value,0,1)=='-') {$negFlag=-1;$pid_value=substr($pid_value,1);} else {$negFlag=1;}
00504                                                                         if (isset($this->substNEWwithIDs[$pid_value]))  {       // Trying to find the correct numerical value as it should be mapped by earlier processing of another new record.
00505                                                                                 $old_pid_value = $pid_value;
00506                                                                                 $pid_value=intval($negFlag*$this->substNEWwithIDs[$pid_value]);
00507                                                                         } else {$OK = 0;}       // If not found in the substArray we must stop the proces...
00508                                                                 }
00509                                                                 $pid_value = intval($pid_value);
00510 
00511                                                                         // The $pid_value is now the numerical pid at this point
00512                                                                 if ($OK)        {
00513                                                                         $sortRow = $TCA[$table]['ctrl']['sortby'];
00514                                                                         if ($pid_value>=0)      {       // Points to a page on which to insert the element, possibly in the top of the page
00515                                                                                 if ($sortRow)   {       // If this table is sorted we better find the top sorting number
00516                                                                                         $fieldArray[$sortRow] = $this->getSortNumber($table,0,$pid_value);
00517                                                                                 }
00518                                                                                 $fieldArray['pid'] = $pid_value;        // The numerical pid is inserted in the data array
00519                                                                         } else {        // points to another record before ifself
00520                                                                                 if ($sortRow)   {       // If this table is sorted we better find the top sorting number
00521                                                                                         $tempArray=$this->getSortNumber($table,0,$pid_value);   // Because $pid_value is < 0, getSortNumber returns an array
00522                                                                                         $fieldArray['pid'] = $tempArray['pid'];
00523                                                                                         $fieldArray[$sortRow] = $tempArray['sortNumber'];
00524                                                                                 } else {        // Here we fetch the PID of the record that we point to...
00525                                                                                         $tempdata = $this->recordInfo($table,abs($pid_value),'pid');
00526                                                                                         $fieldArray['pid']=$tempdata['pid'];
00527                                                                                 }
00528                                                                         }
00529                                                                 }
00530                                                         }
00531                                                         $theRealPid = $fieldArray['pid'];
00532                                                                 // Now, check if we may insert records on this pid.
00533                                                         if ($theRealPid>=0)     {
00534                                                                 $recordAccess = $this->checkRecordInsertAccess($table,$theRealPid);     // Checks if records can be inserted on this $pid.
00535                                                         } else {
00536                                                                 debug('Internal ERROR: pid should not be less than zero!');
00537                                                         }
00538                                                         $status = 'new';                                                // Yes new record, change $record_status to 'insert'
00539                                                 } else {        // Nope... $id is a number
00540                                                         $fieldArray = Array();
00541                                                         $recordAccess = $this->checkRecordUpdateAccess($table,$id);
00542                                                         if (!$recordAccess)             {
00543                                                                 $propArr = $this->getRecordProperties($table,$id);
00544                                                                 $this->log($table,$id,2,0,1,"Attempt to modify record '%s' (%s) without permission. Or non-existing page.",2,array($propArr['header'],$table.':'.$id),$propArr['event_pid']);
00545                                                         } else {        // Next check of the record permissions (internals)
00546                                                                 $recordAccess = $this->BE_USER->recordEditAccessInternals($table,$id);
00547                                                                 if (!$recordAccess)             {
00548                                                                         $propArr = $this->getRecordProperties($table,$id);
00549                                                                         $this->log($table,$id,2,0,1,"recordEditAccessInternals() check failed. [".$this->BE_USER->errorMsg."]",2,array($propArr['header'],$table.':'.$id),$propArr['event_pid']);
00550                                                                 } else {        // Here we fetch the PID of the record that we point to...
00551                                                                         $tempdata = $this->recordInfo($table,$id,'pid');
00552                                                                         $theRealPid = $tempdata['pid'];
00553                                                                 }
00554                                                         }
00555                                                         $status = 'update';     // the default is 'update'
00556                                                 }
00557 
00558                                                         // **************************************
00559                                                         // If access was granted above, proceed:
00560                                                         // **************************************
00561                                                 if ($recordAccess)      {
00562 
00563                                                         list($tscPID) = t3lib_BEfunc::getTSCpid($table,$id,$old_pid_value ? $old_pid_value : $fieldArray['pid']);       // Here the "pid" is sent IF NOT the old pid was a string pointing to a place in the subst-id array.
00564                                                         $TSConfig = $this->getTCEMAIN_TSconfig($tscPID);
00565                                                         if ($status=='new' && $table=='pages' && is_array($TSConfig['permissions.']))   {
00566                                                                 $fieldArray = $this->setTSconfigPermissions($fieldArray,$TSConfig['permissions.']);
00567                                                         }
00568 
00569                                                         $fieldArray = $this->fillInFieldArray($table,$id,$fieldArray,$incomingFieldArray,$theRealPid,$status,$tscPID);
00570 
00571                                                                 // NOTICE! All manipulation beyond this point bypasses both "excludeFields" AND possible "MM" relations / file uploads to field!
00572 
00573                                                         $fieldArray = $this->overrideFieldArray($table,$fieldArray);    // NOTICE: This overriding is potentially dangerous; permissions per field is not checked!!!
00574 
00575                                                                 // Setting system fields
00576                                                         if ($status=='new')     {
00577                                                                 if ($TCA[$table]['ctrl']['crdate'])     {
00578                                                                         $fieldArray[$TCA[$table]['ctrl']['crdate']]=time();
00579                                                                 }
00580                                                                 if ($TCA[$table]['ctrl']['cruser_id'])  {
00581                                                                         $fieldArray[$TCA[$table]['ctrl']['cruser_id']]=$this->userid;
00582                                                                 }
00583                                                         } elseif ($this->checkSimilar) {        // Removing fields which are equal to the current value:
00584                                                                 $fieldArray = $this->compareFieldArrayWithCurrentAndUnset($table,$id,$fieldArray);
00585                                                         }
00586                                                         if ($TCA[$table]['ctrl']['tstamp'])     {
00587                                                                 $fieldArray[$TCA[$table]['ctrl']['tstamp']]=time();
00588                                                         }
00589 
00590                                                                 // Hook: processDatamap_postProcessFieldArray
00591                                                         foreach($hookObjectsArr as $hookObj)    {
00592                                                                 if (method_exists($hookObj, 'processDatamap_postProcessFieldArray')) {
00593                                                                         $hookObj->processDatamap_postProcessFieldArray($status, $table, $id, $fieldArray, $this);
00594                                                                 }
00595                                                         }
00596 
00597                                                                 // Performing insert/update. If fieldArray has been unset by some userfunction (see hook above), don't do anything
00598                                                                 // Kasper: Unsetting the fieldArray is dangerous; MM relations might be saved already and files could have been uploaded that are now "lost"
00599                                                         if (is_array($fieldArray)) {
00600                                                                 if ($status=='new')     {
00601         //                                                              if ($pid_value<0)       {$fieldArray = $this->fixCopyAfterDuplFields($table,$id,abs($pid_value),0,$fieldArray);}        // Out-commented 02-05-02: I couldn't understand WHY this is needed for NEW records. Obviously to proces records being copied? Problem is that the fields are not set anyways and the copying function should basically take care of this!
00602                                                                         $this->insertDB($table,$id,$fieldArray,FALSE,$incomingFieldArray['uid']);
00603                                                                 } else {
00604                                                                         $this->updateDB($table,$id,$fieldArray);
00605                                                                 }
00606                                                         }
00607 
00608                                                                 // Hook: processDatamap_afterDatabaseOperations
00609                                                         foreach($hookObjectsArr as $hookObj)    {
00610                                                                 if (method_exists($hookObj, 'processDatamap_afterDatabaseOperations')) {
00611                                                                         $hookObj->processDatamap_afterDatabaseOperations($status, $table, $id, $fieldArray, $this);
00612                                                                 }
00613                                                         }
00614                                                 }       // if ($recordAccess)   {
00615                                         }       // if (is_array($incomingFieldArray))   {
00616                                 }
00617                         }
00618                 }
00619                 $this->dbAnalysisStoreExec();
00620                 $this->removeRegisteredFiles();
00621         }
00622 
00636         function fillInFieldArray($table,$id,$fieldArray,$incomingFieldArray,$realPid,$status,$tscPID)  {
00637                 global $TCA;
00638 
00639                         // Initialize:
00640                 t3lib_div::loadTCA($table);
00641                 unset($originalLanguageRecord);
00642                 unset($originalLanguage_diffStorage);
00643                 $diffStorageFlag = FALSE;
00644 
00645                         // Setting 'currentRecord' and 'checkValueRecord':
00646                 if (strstr($id,'NEW'))  {
00647                         $currentRecord = $checkValueRecord = $fieldArray;       // must have the 'current' array - not the values after processing below...
00648 
00649                                 // IF $incomingFieldArray is an array, overlay it.
00650                                 // The point is that when new records are created as copies with flex type fields there might be a field containing information about which DataStructure to use and without that information the flexforms cannot be correctly processed.... This should be OK since the $checkValueRecord is used by the flexform evaluation only anyways...
00651                         if (is_array($incomingFieldArray) && is_array($checkValueRecord))       {
00652                                 $checkValueRecord = t3lib_div::array_merge_recursive_overrule($checkValueRecord, $incomingFieldArray);
00653                         }
00654                 } else {
00655                         $currentRecord = $checkValueRecord = $this->recordInfo($table,$id,'*'); // We must use the current values as basis for this!
00656 
00657                                 // Get original language record if available:
00658                         if (is_array($currentRecord)
00659                                         && $TCA[$table]['ctrl']['transOrigDiffSourceField']
00660                                         && $TCA[$table]['ctrl']['languageField']
00661                                         && $currentRecord[$TCA[$table]['ctrl']['languageField']] > 0
00662                                         && $TCA[$table]['ctrl']['transOrigPointerField']
00663                                         && intval($currentRecord[$TCA[$table]['ctrl']['transOrigPointerField']]) > 0)   {
00664 
00665                                 $lookUpTable = $TCA[$table]['ctrl']['transOrigPointerTable'] ? $TCA[$table]['ctrl']['transOrigPointerTable'] : $table;
00666                                 $originalLanguageRecord = $this->recordInfo($lookUpTable,$currentRecord[$TCA[$table]['ctrl']['transOrigPointerField']],'*');
00667                                 $originalLanguage_diffStorage = unserialize($currentRecord[$TCA[$table]['ctrl']['transOrigDiffSourceField']]);
00668                         }
00669                 }
00670                 $this->checkValue_currentRecord = $checkValueRecord;
00671 
00672                         /*
00673                                 In the following all incoming value-fields are tested:
00674                                 - Are the user allowed to change the field?
00675                                 - Is the field uid/pid (which are already set)
00676                                 - perms-fields for pages-table, then do special things...
00677                                 - If the field is nothing of the above and the field is configured in TCA, the fieldvalues are evaluated by ->checkValue
00678 
00679                                 If everything is OK, the field is entered into $fieldArray[]
00680                         */
00681                 foreach($incomingFieldArray as $field => $fieldValue)   {
00682                         if (!in_array($table.'-'.$field, $this->exclude_array) && !$this->data_disableFields[$table][$id][$field])      {       // The field must be editable.
00683 
00684                                         // Checking language:
00685                                 $languageDeny = $TCA[$table]['ctrl']['languageField'] && !strcmp($TCA[$table]['ctrl']['languageField'], $field) && !$this->BE_USER->checkLanguageAccess($fieldValue);
00686 
00687                                 if (!$languageDeny)     {
00688                                                 // Stripping slashes - will probably be removed the day $this->stripslashes_values is removed as an option...
00689                                         if ($this->stripslashes_values) {
00690                                                 if (is_array($fieldValue))      {
00691                                                         t3lib_div::stripSlashesOnArray($fieldValue);
00692                                                 } else $fieldValue = stripslashes($fieldValue);
00693                                         }
00694 
00695                                         switch ($field) {
00696                                                 case 'uid':
00697                                                 case 'pid':
00698                                                         // Nothing happens, already set
00699                                                 break;
00700                                                 case 'perms_userid':
00701                                                 case 'perms_groupid':
00702                                                 case 'perms_user':
00703                                                 case 'perms_group':
00704                                                 case 'perms_everybody':
00705                                                                 // Permissions can be edited by the owner or the administrator
00706                                                         if ($table=='pages' && ($this->admin || $status=='new' || $this->pageInfo($id,'perms_userid')==$this->userid) ) {
00707                                                                 $value=intval($fieldValue);
00708                                                                 switch($field)  {
00709                                                                         case 'perms_userid':
00710                                                                                 $fieldArray[$field]=$value;
00711                                                                         break;
00712                                                                         case 'perms_groupid':
00713                                                                                 $fieldArray[$field]=$value;
00714                                                                         break;
00715                                                                         default:
00716                                                                                 if ($value>=0 && $value<pow(2,5))       {
00717                                                                                         $fieldArray[$field]=$value;
00718                                                                                 }
00719                                                                         break;
00720                                                                 }
00721                                                         }
00722                                                 break;
00723                                                 case 't3ver_oid':
00724                                                 case 't3ver_id':
00725                                                         // t3ver_label is not here because it CAN be edited as a regular field!
00726                                                 break;
00727                                                 default:
00728                                                         if (isset($TCA[$table]['columns'][$field]))     {
00729                                                                         // Evaluating the value.
00730                                                                 $res = $this->checkValue($table,$field,$fieldValue,$id,$status,$realPid,$tscPID);
00731                                                                 if (isset($res['value']))       {
00732                                                                         $fieldArray[$field]=$res['value'];
00733 
00734                                                                                 // Add the value of the original record to the diff-storage content:
00735                                                                         if ($TCA[$table]['ctrl']['transOrigDiffSourceField'])   {
00736                                                                                 $originalLanguage_diffStorage[$field] = $originalLanguageRecord[$field];
00737                                                                                 $diffStorageFlag = TRUE;
00738                                                                         }
00739                                                                 }
00740                                                         }
00741 
00742 
00743                                                 break;
00744                                         }
00745                                 }       // Checking language.
00746                         }       // Check exclude fields / disabled fields...
00747                 }
00748 
00749                         // Add diff-storage information:
00750                 if ($diffStorageFlag && !isset($fieldArray[$TCA[$table]['ctrl']['transOrigDiffSourceField']]))  {       // If the field is set it would probably be because of an undo-operation - in which case we should not update the field of course...
00751                          $fieldArray[$TCA[$table]['ctrl']['transOrigDiffSourceField']] = serialize($originalLanguage_diffStorage);
00752                 }
00753 
00754                         // Checking for RTE-transformations of fields:
00755                 $types_fieldConfig = t3lib_BEfunc::getTCAtypes($table,$currentRecord);
00756                 $theTypeString = t3lib_BEfunc::getTCAtypeValue($table,$currentRecord);
00757                 if (is_array($types_fieldConfig))       {
00758                         reset($types_fieldConfig);
00759                         while(list(,$vconf) = each($types_fieldConfig)) {
00760                                         // Write file configuration:
00761                                 $eFile = t3lib_parsehtml_proc::evalWriteFile($vconf['spec']['static_write'],array_merge($currentRecord,$fieldArray));   // inserted array_merge($currentRecord,$fieldArray) 170502
00762 
00763                                         // RTE transformations:
00764                                 if (!$this->dontProcessTransformations) {
00765                                         if (isset($fieldArray[$vconf['field']]))        {
00766                                                         // Look for transformation flag:
00767                                                 switch((string)$incomingFieldArray['_TRANSFORM_'.$vconf['field']])      {
00768                                                         case 'RTE':
00769                                                                 $RTEsetup = $this->BE_USER->getTSConfig('RTE',t3lib_BEfunc::getPagesTSconfig($tscPID));
00770                                                                 $thisConfig = t3lib_BEfunc::RTEsetup($RTEsetup['properties'],$table,$vconf['field'],$theTypeString);
00771 
00772                                                                         // Set alternative relative path for RTE images/links:
00773                                                                 $RTErelPath = is_array($eFile) ? dirname($eFile['relEditFile']) : '';
00774 
00775                                                                         // Get RTE object, draw form and set flag:
00776                                                                 $RTEobj = &t3lib_BEfunc::RTEgetObj();
00777                                                                 if (is_object($RTEobj)) {
00778                                                                         $fieldArray[$vconf['field']] = $RTEobj->transformContent('db',$fieldArray[$vconf['field']],$table,$vconf['field'],$currentRecord,$vconf['spec'],$thisConfig,$RTErelPath,$currentRecord['pid']);
00779                                                                 } else {
00780                                                                         debug('NO RTE OBJECT FOUND!');
00781                                                                 }
00782                                                         break;
00783                                                 }
00784                                         }
00785                                 }
00786 
00787                                         // Write file configuration:
00788                                 if (is_array($eFile))   {
00789                                         $mixedRec = array_merge($currentRecord,$fieldArray);
00790                                         $SW_fileContent = t3lib_div::getUrl($eFile['editFile']);
00791                                         $parseHTML = t3lib_div::makeInstance('t3lib_parsehtml_proc');
00792                                         $parseHTML->init('','');
00793 
00794                                         $eFileMarker = $eFile['markerField']&&trim($mixedRec[$eFile['markerField']]) ? trim($mixedRec[$eFile['markerField']]) : '###TYPO3_STATICFILE_EDIT###';
00795                                         $insertContent = str_replace($eFileMarker,'',$mixedRec[$eFile['contentField']]);        // must replace the marker if present in content!
00796 
00797                                         $SW_fileNewContent = $parseHTML->substituteSubpart($SW_fileContent, $eFileMarker, chr(10).$insertContent.chr(10), 1, 1);
00798                                         t3lib_div::writeFile($eFile['editFile'],$SW_fileNewContent);
00799 
00800                                                 // Write status:
00801                                         if (!strstr($id,'NEW') && $eFile['statusField'])        {
00802                                                 $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
00803                                                         $table,
00804                                                         'uid='.intval($id),
00805                                                         array(
00806                                                                 $eFile['statusField'] => $eFile['relEditFile'].' updated '.date('d-m-Y H:i:s').', bytes '.strlen($mixedRec[$eFile['contentField']])
00807                                                         )
00808                                                 );
00809                                         }
00810                                 } elseif ($eFile && is_string($eFile))  {
00811                                         $this->log($insertTable,$id,2,0,1,"Write-file error: '%s'",13,array($eFile),$realPid);
00812                                 }
00813                         }
00814                 }
00815                         // Return fieldArray
00816                 return $fieldArray;
00817         }
00818 
00827         function checkModifyAccessList($table)  {
00828                 $res = ($this->admin || (!$this->tableAdminOnly($table) && t3lib_div::inList($this->BE_USER->groupData['tables_modify'],$table)));
00829                 return $res;
00830         }
00831 
00839         function isRecordInWebMount($table,$id) {
00840                 if (!isset($this->isRecordInWebMount_Cache[$table.':'.$id]))    {
00841                         $recP=$this->getRecordProperties($table,$id);
00842                         $this->isRecordInWebMount_Cache[$table.':'.$id]=$this->isInWebMount($recP['event_pid']);
00843                 }
00844                 return $this->isRecordInWebMount_Cache[$table.':'.$id];
00845         }
00846 
00853         function isInWebMount($pid)     {
00854                 if (!isset($this->isInWebMount_Cache[$pid]))    {
00855                         $this->isInWebMount_Cache[$pid]=$this->BE_USER->isInWebMount($pid);
00856                 }
00857 //debug($this->isInWebMount_Cache);
00858                 return $this->isInWebMount_Cache[$pid];
00859         }
00860 
00870         function checkRecordUpdateAccess($table,$id)    {
00871                 global $TCA;
00872                 $res = 0;
00873                 if ($TCA[$table] && intval($id)>0)      {
00874                         if (isset($this->recUpdateAccessCache[$table][$id]))    {       // If information is cached, return it
00875                                 return $this->recUpdateAccessCache[$table][$id];
00876                                 // Check if record exists and 1) if 'pages' the page may be edited, 2) if page-content the page allows for editing
00877                         } elseif ($this->doesRecordExist($table,$id,'edit'))    {
00878                                 $res = 1;
00879                         }
00880                         $this->recUpdateAccessCache[$table][$id]=$res;  // Cache the result
00881                 }
00882                 return $res;
00883         }
00884 
00895         function checkRecordInsertAccess($insertTable,$pid,$action=1)   {
00896                 global $TCA;
00897                 $res = 0;
00898                 $pid = intval($pid);
00899                 if ($pid>=0)    {
00900                         if (isset($this->recInsertAccessCache[$insertTable][$pid]))     {       // If information is cached, return it
00901                                 return $this->recInsertAccessCache[$insertTable][$pid];
00902                         } else {
00903                                         // If either admin and root-level or if page record exists and 1) if 'pages' you may create new ones 2) if page-content, new content items may be inserted on the $pid page
00904                                 if ( (!$pid && $this->admin) || $this->doesRecordExist('pages',$pid,($insertTable=='pages'?$this->pMap['new']:$this->pMap['editcontent'])) )    {               // Check permissions
00905                                         if ($this->isTableAllowedForThisPage($pid, $insertTable))       {
00906                                                 $res = 1;
00907                                                 $this->recInsertAccessCache[$insertTable][$pid]=$res;   // Cache the result
00908                                         } else {
00909                                                 $propArr = $this->getRecordProperties('pages',$pid);
00910                                                 $this->log($insertTable,$pid,$action,0,1,"Attempt to insert record on page '%s' (%s) where this table, %s, is not allowed",11,array($propArr['header'],$pid,$insertTable),$propArr['event_pid']);
00911                                         }
00912                                 } else {
00913                                         $propArr = $this->getRecordProperties('pages',$pid);
00914                                         $this->log($insertTable,$pid,$action,0,1,"Attempt to insert a record on page '%s' (%s) from table '%s' without permissions. Or non-existing page.",12,array($propArr['header'],$pid,$insertTable),$propArr['event_pid']);
00915                                 }
00916                         }
00917                 }
00918                 return $res;
00919         }
00920 
00931         function isTableAllowedForThisPage($page_uid, $checkTable)      {
00932                 global $TCA, $PAGES_TYPES;
00933                 $page_uid = intval($page_uid);
00934 
00935                         // Check if rootLevel flag is set and we're trying to insert on rootLevel - and reversed - and that the table is not "pages" which are allowed anywhere.
00936                 if (($TCA[$checkTable]['ctrl']['rootLevel'] xor !$page_uid) && $TCA[$checkTable]['ctrl']['rootLevel']!=-1 && $checkTable!='pages')      {
00937                         return false;
00938                 }
00939 
00940                         // Check root-level
00941                 if (!$page_uid) {
00942                         if ($this->admin)       {
00943                                 return true;
00944                         }
00945                 } else {
00946                                 // Check non-root-level
00947                         $doktype = $this->pageInfo($page_uid,'doktype');
00948                         $allowedTableList = isset($PAGES_TYPES[$doktype]['allowedTables']) ? $PAGES_TYPES[$doktype]['allowedTables'] : $PAGES_TYPES['default']['allowedTables'];
00949                         $allowedArray = t3lib_div::trimExplode(',',$allowedTableList,1);
00950                         if (strstr($allowedTableList,'*') || in_array($checkTable,$allowedArray))       {               // If all tables or the table is listed as a allowed type, return true
00951                                 return true;
00952                         }
00953                 }
00954         }
00955 
00966         function doesRecordExist($table,$id,$perms)     {
00967                 global $TCA;
00968 
00969                 $res = 0;
00970                 $id = intval($id);
00971 
00972                         // Processing the incoming $perms (from possible string to integer that can be AND'ed)
00973                 if (!t3lib_div::testInt($perms))        {
00974                         if ($table!='pages')    {
00975                                 switch($perms)  {
00976                                         case 'edit':
00977                                         case 'delete':
00978                                         case 'new':
00979                                                 $perms = 'editcontent';         // This holds it all in case the record is not page!!
00980                                         break;
00981                                 }
00982                         }
00983                         $perms = intval($this->pMap[$perms]);
00984                 } else {
00985                         $perms = intval($perms);
00986                 }
00987 
00988                 if (!$perms)    {debug('Internal ERROR: no permissions to check for non-admin user.');}
00989 
00990                         // For all tables: Check if record exists:
00991                         // Notice: If $perms are 0 (zero) no perms-clause is added!
00992                 if (is_array($TCA[$table]) && $id>0 && ($this->isRecordInWebMount($table,$id) || $this->admin)) {
00993                         if ($table != 'pages')  {
00994 
00995                                         // Find record without checking page:
00996                                 $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,pid', $table, 'uid='.intval($id).$this->deleteClause($table));
00997                                 $output = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres);
00998                                 t3lib_BEfunc::fixVersioningPid($table,$output);
00999 
01000                                         // If record found, check page as well:
01001                                 if (is_array($output))  {
01002 
01003                                                 // Looking up the page for record:
01004                                         $mres = $this->doesRecordExist_pageLookUp($output['pid'], $perms);
01005                                         $pageRec = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres);
01006 
01007                                                 // Return true if either a page was found OR if the PID is zero AND the user is ADMIN (in which case the record is at root-level):
01008                                         if (is_array($pageRec) || (!$output['pid'] && $this->admin))    {
01009                                                 return TRUE;
01010                                         }
01011                                 }
01012                                 return FALSE;
01013                         } else {
01014                                 $mres = $this->doesRecordExist_pageLookUp($id, $perms);
01015                                 return $GLOBALS['TYPO3_DB']->sql_num_rows($mres);
01016                         }
01017                 }
01018         }
01019 
01029         function doesRecordExist_pageLookUp($id, $perms)        {
01030                 global $TCA;
01031 
01032                 return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
01033                         'uid',
01034                         'pages',
01035                         'uid='.intval($id).
01036                                 $this->deleteClause('pages').
01037                                 ($perms && !$this->admin ? ' AND '.$this->BE_USER->getPagePermsClause($perms) : '').
01038                                 (!$this->admin && $TCA['pages']['ctrl']['editlock'] && ($perms & (2+4+16)) ? ' AND '.$TCA['pages']['ctrl']['editlock'].'=0':'') // admin users don't need check
01039                 );
01040         }
01041 
01055         function doesBranchExist($inList,$pid,$perms, $recurse) {
01056                 global $TCA;
01057                 $pid = intval($pid);
01058                 $perms = intval($perms);
01059                 if ($pid>=0)    {
01060                         $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
01061                                                 'uid, perms_userid, perms_groupid, perms_user, perms_group, perms_everybody',
01062                                                 'pages',
01063                                                 'pid='.intval($pid).$this->deleteClause('pages'),
01064                                                 '',
01065                                                 'sorting'
01066                                         );
01067                         while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres))     {
01068                                 if ($this->admin || $this->BE_USER->doesUserHaveAccess($row,$perms))    {       // IF admin, then it's OK
01069                                         $inList.=$row['uid'].',';
01070                                         if ($recurse)   {       // Follow the subpages recursively...
01071                                                 $inList = $this->doesBranchExist($inList, $row['uid'], $perms, $recurse);
01072                                                 if ($inList == -1)      {return -1;}            // No permissions somewhere in the branch
01073                                         }
01074                                 } else {
01075                                         return -1;              // No permissions
01076                                 }
01077                         }
01078                 }
01079                 return $inList;
01080         }
01081 
01090         function pageInfo($id,$field)   {
01091                 if (!isset($this->pageCache[$id]))      {
01092                         $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'pages', 'uid='.intval($id));
01093                         if ($GLOBALS['TYPO3_DB']->sql_num_rows($res))   {
01094                                 $this->pageCache[$id] = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
01095                         }
01096                         $GLOBALS['TYPO3_DB']->sql_free_result($res);
01097                 }
01098                 return $this->pageCache[$id][$field];
01099         }
01100 
01110         function recordInfo($table,$id,$fieldList)      {
01111                 global $TCA;
01112                 if (is_array($TCA[$table]))     {
01113                         $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fieldList, $table, 'uid='.intval($id));
01114                         if ($GLOBALS['TYPO3_DB']->sql_num_rows($res))   {
01115                                 return $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
01116                         }
01117                 }
01118         }
01119 
01127         function getRecordProperties($table,$id)        {
01128                 $row = ($table=='pages' && !$id) ? array('title'=>'[root-level]', 'uid' => 0, 'pid' => 0) :$this->recordInfo($table,$id,'*');
01129                 t3lib_BEfunc::fixVersioningPid($table,$row);
01130                 return $this->getRecordPropertiesFromRow($table,$row);
01131         }
01132 
01140         function getRecordPropertiesFromRow($table,$row)        {
01141                 global $TCA;
01142                 if ($TCA[$table])       {
01143                         $out = array(
01144                                 'header' => $row[$TCA[$table]['ctrl']['label']],
01145                                 'pid' => $row['pid'],
01146                                 'event_pid' => ($table=='pages'?$row['uid']:$row['pid'])
01147                         );
01148                         return $out;
01149                 }
01150         }
01151 
01159         function setTSconfigPermissions($fieldArray,$TSConfig_p)        {
01160                 if (strcmp($TSConfig_p['userid'],''))   $fieldArray['perms_userid']=intval($TSConfig_p['userid']);
01161                 if (strcmp($TSConfig_p['groupid'],''))  $fieldArray['perms_groupid']=intval($TSConfig_p['groupid']);
01162                 if (strcmp($TSConfig_p['user'],''))                     $fieldArray['perms_user']=t3lib_div::testInt($TSConfig_p['user']) ? $TSConfig_p['user'] : $this->assemblePermissions($TSConfig_p['user']);
01163                 if (strcmp($TSConfig_p['group'],''))            $fieldArray['perms_group']=t3lib_div::testInt($TSConfig_p['group']) ? $TSConfig_p['group'] : $this->assemblePermissions($TSConfig_p['group']);
01164                 if (strcmp($TSConfig_p['everybody'],''))        $fieldArray['perms_everybody']=t3lib_div::testInt($TSConfig_p['everybody']) ? $TSConfig_p['everybody'] : $this->assemblePermissions($TSConfig_p['everybody']);
01165 
01166                 return $fieldArray;
01167         }
01168 
01175         function newFieldArray($table)  {
01176                 global $TCA;
01177                 t3lib_div::loadTCA($table);
01178                 $fieldArray=Array();
01179                 if (is_array($TCA[$table]['columns']))  {
01180                         reset ($TCA[$table]['columns']);
01181                         while (list($field,$content)=each($TCA[$table]['columns']))     {
01182                                 if (isset($this->defaultValues[$table][$field]))        {
01183                                         $fieldArray[$field] = $this->defaultValues[$table][$field];
01184                                 } elseif (isset($content['config']['default'])) {
01185                                         $fieldArray[$field] = $content['config']['default'];
01186                                 }
01187                         }
01188                 }
01189                 if ($table=='pages')    {               // Set default permissions for a page.
01190                         $fieldArray['perms_userid'] = $this->userid;
01191                         $fieldArray['perms_groupid'] = intval($this->BE_USER->firstMainGroup);
01192                         $fieldArray['perms_user'] = $this->assemblePermissions($this->defaultPermissions['user']);
01193                         $fieldArray['perms_group'] = $this->assemblePermissions($this->defaultPermissions['group']);
01194                         $fieldArray['perms_everybody'] = $this->assemblePermissions($this->defaultPermissions['everybody']);
01195                 }
01196                 return $fieldArray;
01197         }
01198 
01206         function overrideFieldArray($table,$data)       {
01207                 if (is_array($this->overrideValues[$table]))    {
01208                         $data = array_merge($data,$this->overrideValues[$table]);                       // Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
01209                 }
01210                 return $data;
01211         }
01212 
01219         function assemblePermissions($string)   {
01220                 $keyArr = t3lib_div::trimExplode(',',$string,1);
01221                 $value=0;
01222                 while(list(,$key)=each($keyArr))        {
01223                         if ($key && isset($this->pMap[$key]))   {
01224                                 $value |= $this->pMap[$key];
01225                         }
01226                 }
01227                 return $value;
01228         }
01229 
01230 
01231 
01232 
01233 
01234 
01235 
01236 
01237