Main Page | Directories | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages | Examples

class.t3lib_tcemain.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2004 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 $history=1;               // Bit-array: Bit0: History on/off. DEPENDS on checkSimilar to be set!
00217    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.
00218    var $dontProcessTransformations=0;  // Boolean: If set, then transformations are NOT performed on the input.
00219 #  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.
00220 
00221    var $pMap = Array(      // Permission mapping
00222       'show' => 1,         // 1st bit
00223       'edit' => 2,         // 2nd bit
00224       'delete' => 4,       // 3rd bit
00225       'new' => 8,          // 4th bit
00226       'editcontent' => 16     // 5th bit
00227    );
00228    var $defaultPermissions = array(    // Can be overridden from $TYPO3_CONF_VARS
00229       'user' => 'show,edit,delete,new,editcontent',
00230       'group' => 'show,edit,new,editcontent',
00231       'everybody' => ''
00232    );
00233 
00234 
00235    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.
00236    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.
00237    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.
00238    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!
00239 
00240       // *********
00241       // internal
00242       // *********
00243    var $fileFunc;    // May contain an object
00244    var $last_log_id;
00245    var $BE_USER;     // The user-object the the script uses. If not set from outside, this is set to the current global $BE_USER.
00246    var $userid;      // will be set to uid of be_user executing this script
00247    var $username;    // will be set to username of be_user executing this script
00248    var $admin;       // will be set if user is admin
00249    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.
00250 
00251    var $data = Array();
00252    var $datamap = Array();
00253    var $cmd = Array();
00254    var $cmdmap = Array();
00255    var $uploadedFileArray = array();
00256 
00257    var $cachedTSconfig = array();
00258    var $substNEWwithIDs = Array();
00259    var $substNEWwithIDs_table = Array();
00260    var $recUpdateAccessCache = Array();   // Used by function checkRecordUpdateAccess() to store whether a record is updateable or not.
00261    var $recInsertAccessCache = Array();
00262    var $isRecordInWebMount_Cache=array();
00263    var $isInWebMount_Cache=array();
00264    var $pageCache = Array();              // Used for caching page records in pageInfo()
00265    var $copyMappingArray = Array();    // Use by the copy action to track the ids of new pages so subpages are correctly inserted!
00266    var $copyMappingArray_merged = Array();      // This array is the sum of all copying operations in this class
00267    var $registerDBList=array();
00268    var $dbAnalysisStore=array();
00269    var $removeFilesStore=array();
00270    var $copiedFileMap=array();
00271 
00272    var $checkValue_currentRecord=array();    // Set to "currentRecord" during checking of values.
00273 
00274 
00285    function start($data,$cmd,$altUserObject='') {
00286          // Initializing BE_USER
00287       $this->BE_USER = is_object($altUserObject) ? $altUserObject : $GLOBALS['BE_USER'];
00288       $this->userid = $this->BE_USER->user['uid'];
00289       $this->username = $this->BE_USER->user['username'];
00290       $this->admin = $this->BE_USER->user['admin'];
00291 
00292          // Initializing default permissions for pages
00293       $defaultPermissions = $GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPermissions'];
00294       if (isset($defaultPermissions['user']))      {$this->defaultPermissions['user'] = $defaultPermissions['user'];}
00295       if (isset($defaultPermissions['group']))     {$this->defaultPermissions['group'] = $defaultPermissions['group'];}
00296       if (isset($defaultPermissions['everybody']))    {$this->defaultPermissions['everybody'] = $defaultPermissions['everybody'];}
00297 
00298          // generates the excludelist, based on TCA/exclude-flag and non_exclude_fields for the user:
00299       $this->exclude_array = ($this->admin) ? array() : $this->getExcludeListArray();
00300 
00301          // Setting the data and cmd arrays
00302       if (is_array($data)) {
00303          reset($data);
00304          $this->datamap = $data;
00305       }
00306       if (is_array($cmd))  {
00307          reset($cmd);
00308          $this->cmdmap = $cmd;
00309       }
00310    }
00311 
00318    function setMirror($mirror)   {
00319       if (is_array($mirror))  {
00320          reset($mirror);
00321          while(list($table,$uid_array)=each($mirror)) {
00322             if (isset($this->datamap[$table]))  {
00323                reset($uid_array);
00324                while (list($id,$uidList) = each($uid_array))   {
00325                   if (isset($this->datamap[$table][$id]))   {
00326                      $theIdsInArray = t3lib_div::trimExplode(',',$uidList,1);
00327                      while(list(,$copyToUid)=each($theIdsInArray))   {
00328                         $this->datamap[$table][$copyToUid] = $this->datamap[$table][$id];
00329                      }
00330                   }
00331                }
00332             }
00333          }
00334       }
00335    }
00336 
00343    function setDefaultsFromUserTS($userTS)   {
00344       global $TCA;
00345       if (is_array($userTS))  {
00346          foreach($userTS as $k => $v)  {
00347             $k = substr($k,0,-1);
00348             if ($k && is_array($v) && isset($TCA[$k]))   {
00349                if (is_array($this->defaultValues[$k]))   {
00350                   $this->defaultValues[$k] = array_merge($this->defaultValues[$k],$v);
00351                } else {
00352                   $this->defaultValues[$k] = $v;
00353                }
00354             }
00355          }
00356       }
00357    }
00358 
00366    function process_uploads($postFiles)   {
00367       if (is_array($postFiles))  {
00368          reset($postFiles);
00369          $subA = current($postFiles);
00370          if (is_array($subA)) {
00371             if (is_array($subA['name']) && is_array($subA['type']) && is_array($subA['tmp_name']) && is_array($subA['size'])) {
00372                   // Initialize the uploadedFilesArray:
00373                $this->uploadedFileArray=array();
00374 
00375                   // For each entry:
00376                foreach($subA as $key => $values)   {
00377                   $this->process_uploads_traverseArray($this->uploadedFileArray,$values,$key);
00378                }
00379             } else {
00380                $this->uploadedFileArray=$subA;
00381             }
00382          }
00383       }
00384    }
00385 
00396    function process_uploads_traverseArray(&$outputArr,$inputArr,$keyToSet) {
00397       if (is_array($inputArr))   {
00398          foreach($inputArr as $key => $value)   {
00399             $this->process_uploads_traverseArray($outputArr[$key],$inputArr[$key],$keyToSet);
00400          }
00401       } else {
00402          $outputArr[$keyToSet]=$inputArr;
00403       }
00404    }
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 
00417 
00418 
00419 
00420    /*********************************************
00421     *
00422     * PROCESSING DATA
00423     *
00424     *********************************************/
00425 
00432    function process_datamap() {
00433       global $TCA, $TYPO3_CONF_VARS;
00434 
00435          // First prepare user defined objects (if any) for hooks which extend this function:
00436       $hookObjectsArr = array();
00437       if (is_array ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'])) {
00438          foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'] as $classRef) {
00439             $hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
00440          }
00441       }
00442 
00443          // 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.
00444       $orderOfTables = Array();
00445       if (isset($this->datamap['pages'])) {     // Set pages first.
00446          $orderOfTables[]='pages';
00447       }
00448       reset($this->datamap);
00449       while (list($table,) = each($this->datamap)) {
00450          if ($table!='pages') {
00451             $orderOfTables[]=$table;
00452          }
00453       }
00454 
00455          // Process the tables...
00456       foreach($orderOfTables as $table)   {
00457             /* Check if
00458                - table is set in $TCA,
00459                - table is NOT readOnly,
00460                - the table is set with content in the data-array (if not, there's nothing to process...)
00461                - permissions for tableaccess OK
00462             */
00463          $modifyAccessList = $this->checkModifyAccessList($table);
00464          if (!$modifyAccessList) {
00465             $this->log($table,$id,2,0,1,"Attempt to modify table '%s' without permission",1,array($table));
00466          }
00467          if (isset($TCA[$table]) && !$this->tableReadOnly($table) && is_array($this->datamap[$table]) && $modifyAccessList)   {
00468             if ($this->reverseOrder)   {
00469                $this->datamap[$table] = array_reverse($this->datamap[$table], 1);
00470             }
00471 
00472                // For each record from the table, do:
00473                // $id is the record uid, may be a string if new records...
00474                // $incomingFieldArray is the array of fields
00475             foreach($this->datamap[$table] as $id => $incomingFieldArray)  {
00476                if (is_array($incomingFieldArray))  {
00477 
00478                      // Hook: processDatamap_preProcessIncomingFieldArray
00479                   foreach($hookObjectsArr as $hookObj)   {
00480                      if (method_exists($hookObj, 'processDatamap_preProcessIncomingFieldArray')) {
00481                         $hookObj->processDatamap_preProcessFieldArray($incomingFieldArray, $table, $id, $this);
00482                      }
00483                   }
00484 
00485                      // ******************************
00486                      // Checking access to the record
00487                      // ******************************
00488                   $recordAccess = 0;
00489                   $old_pid_value = '';
00490                   if (!t3lib_div::testInt($id)) {               // Is it a new record? (Then Id is a string)
00491                      $fieldArray = $this->newFieldArray($table);  // Get a fieldArray with default values
00492                      if (isset($incomingFieldArray['pid'])) {  // A pid must be set for new records.
00493                            // $value = the pid
00494                         $pid_value = $incomingFieldArray['pid'];
00495 
00496                            // Checking and finding numerical pid, it may be a string-reference to another value
00497                         $OK = 1;
00498                         if (strstr($pid_value,'NEW')) {  // If a NEW... id
00499                            if (substr($pid_value,0,1)=='-') {$negFlag=-1;$pid_value=substr($pid_value,1);} else {$negFlag=1;}
00500                            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.
00501                               $old_pid_value = $pid_value;
00502                               $pid_value=intval($negFlag*$this->substNEWwithIDs[$pid_value]);
00503                            } else {$OK = 0;} // If not found in the substArray we must stop the proces...
00504                         }
00505                         $pid_value = intval($pid_value);
00506 
00507                            // The $pid_value is now the numerical pid at this point
00508                         if ($OK) {
00509                            $sortRow = $TCA[$table]['ctrl']['sortby'];
00510                            if ($pid_value>=0)   {  // Points to a page on which to insert the element, possibly in the top of the page
00511                               if ($sortRow)  {  // If this table is sorted we better find the top sorting number
00512                                  $fieldArray[$sortRow] = $this->getSortNumber($table,0,$pid_value);
00513                               }
00514                               $fieldArray['pid'] = $pid_value; // The numerical pid is inserted in the data array
00515                            } else { // points to another record before ifself
00516                               if ($sortRow)  {  // If this table is sorted we better find the top sorting number
00517                                  $tempArray=$this->getSortNumber($table,0,$pid_value); // Because $pid_value is < 0, getSortNumber returns an array
00518                                  $fieldArray['pid'] = $tempArray['pid'];
00519                                  $fieldArray[$sortRow] = $tempArray['sortNumber'];
00520                               } else { // Here we fetch the PID of the record that we point to...
00521                                  $tempdata = $this->recordInfo($table,abs($pid_value),'pid');
00522                                  $fieldArray['pid']=$tempdata['pid'];
00523                               }
00524                            }
00525                         }
00526                      }
00527                      $theRealPid = $fieldArray['pid'];
00528                         // Now, check if we may insert records on this pid.
00529                      if ($theRealPid>=0)  {
00530                         $recordAccess = $this->checkRecordInsertAccess($table,$theRealPid);  // Checks if records can be inserted on this $pid.
00531                      } else {
00532                         debug('Internal ERROR: pid should not be less than zero!');
00533                      }
00534                      $status = 'new';                 // Yes new record, change $record_status to 'insert'
00535                   } else { // Nope... $id is a number
00536                      $fieldArray = Array();
00537                      $recordAccess = $this->checkRecordUpdateAccess($table,$id);
00538                      if (!$recordAccess)     {
00539                         $propArr = $this->getRecordProperties($table,$id);
00540                         $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']);
00541                      } else { // Next check of the record permissions (internals)
00542                         $recordAccess = $this->BE_USER->recordEditAccessInternals($table,$id);
00543                         if (!$recordAccess)     {
00544                            $propArr = $this->getRecordProperties($table,$id);
00545                            $this->log($table,$id,2,0,1,"recordEditAccessInternals() check failed. [".$this->BE_USER->errorMsg."]",2,array($propArr['header'],$table.':'.$id),$propArr['event_pid']);
00546                         } else { // Here we fetch the PID of the record that we point to...
00547                            $tempdata = $this->recordInfo($table,$id,'pid');
00548                            $theRealPid = $tempdata['pid'];
00549                         }
00550                      }
00551                      $status = 'update';  // the default is 'update'
00552                   }
00553 
00554                      // **************************************
00555                      // If access was granted above, proceed:
00556                      // **************************************
00557                   if ($recordAccess)   {
00558 
00559                      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.
00560                      $TSConfig = $this->getTCEMAIN_TSconfig($tscPID);
00561                      if ($status=='new' && $table=='pages' && is_array($TSConfig['permissions.'])) {
00562                         $fieldArray = $this->setTSconfigPermissions($fieldArray,$TSConfig['permissions.']);
00563                      }
00564 
00565                      $fieldArray = $this->fillInFieldArray($table,$id,$fieldArray,$incomingFieldArray,$theRealPid,$status,$tscPID);
00566 
00567                         // NOTICE! All manipulation beyond this point bypasses both "excludeFields" AND possible "MM" relations / file uploads to field!
00568 
00569                      $fieldArray = $this->overrideFieldArray($table,$fieldArray);   // NOTICE: This overriding is potentially dangerous; permissions per field is not checked!!!
00570 
00571                         // Setting system fields
00572                      if ($status=='new')  {
00573                         if ($TCA[$table]['ctrl']['crdate']) {
00574                            $fieldArray[$TCA[$table]['ctrl']['crdate']]=time();
00575                         }
00576                         if ($TCA[$table]['ctrl']['cruser_id']) {
00577                            $fieldArray[$TCA[$table]['ctrl']['cruser_id']]=$this->userid;
00578                         }
00579                      } elseif ($this->checkSimilar) { // Removing fields which are equal to the current value:
00580                         $fieldArray = $this->compareFieldArrayWithCurrentAndUnset($table,$id,$fieldArray);
00581                      }
00582                      if ($TCA[$table]['ctrl']['tstamp']) {
00583                         $fieldArray[$TCA[$table]['ctrl']['tstamp']]=time();
00584                      }
00585 
00586                         // Hook: processDatamap_postProcessFieldArray
00587                      foreach($hookObjectsArr as $hookObj)   {
00588                         if (method_exists($hookObj, 'processDatamap_postProcessFieldArray')) {
00589                            $hookObj->processDatamap_postProcessFieldArray($status, $table, $id, $fieldArray, $this);
00590                         }
00591                      }
00592 
00593                         // Performing insert/update. If fieldArray has been unset by some userfunction (see hook above), don't do anything
00594                         // Kasper: Unsetting the fieldArray is dangerous; MM relations might be saved already and files could have been uploaded that are now "lost"
00595                      if (is_array($fieldArray)) {
00596                         if ($status=='new')  {
00597    //                      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!
00598                            $this->insertDB($table,$id,$fieldArray);
00599                         } else {
00600                            $this->updateDB($table,$id,$fieldArray);
00601                         }
00602                      }
00603                   }  // if ($recordAccess)   {
00604                }  // if (is_array($incomingFieldArray))  {
00605             }
00606          }
00607       }
00608       $this->dbAnalysisStoreExec();
00609       $this->removeRegisteredFiles();
00610    }
00611 
00625    function fillInFieldArray($table,$id,$fieldArray,$incomingFieldArray,$realPid,$status,$tscPID)  {
00626       global $TCA;
00627 
00628          // Initialize:
00629       t3lib_div::loadTCA($table);
00630       unset($originalLanguageRecord);
00631       unset($originalLanguage_diffStorage);
00632       $diffStorageFlag = FALSE;
00633 
00634          // Setting 'currentRecord' and 'checkValueRecord':
00635       if (strstr($id,'NEW'))  {
00636          $currentRecord = $checkValueRecord = $fieldArray;  // must have the 'current' array - not the values after processing below...
00637 
00638             // IF $incomingFieldArray is an array, overlay it.
00639             // 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...
00640          if (is_array($incomingFieldArray) && is_array($checkValueRecord)) {
00641             $checkValueRecord = t3lib_div::array_merge_recursive_overrule($checkValueRecord, $incomingFieldArray);
00642          }
00643       } else {
00644          $currentRecord = $checkValueRecord = $this->recordInfo($table,$id,'*'); // We must use the current values as basis for this!
00645 
00646             // Get original language record if available:
00647          if (is_array($currentRecord)
00648                && $TCA[$table]['ctrl']['transOrigDiffSourceField']
00649                && $TCA[$table]['ctrl']['languageField']
00650                && $currentRecord[$TCA[$table]['ctrl']['languageField']] > 0
00651                && $TCA[$table]['ctrl']['transOrigPointerField']
00652                && intval($currentRecord[$TCA[$table]['ctrl']['transOrigPointerField']]) > 0) {
00653 
00654             $lookUpTable = $TCA[$table]['ctrl']['transOrigPointerTable'] ? $TCA[$table]['ctrl']['transOrigPointerTable'] : $table;
00655             $originalLanguageRecord = $this->recordInfo($lookUpTable,$currentRecord[$TCA[$table]['ctrl']['transOrigPointerField']],'*');
00656             $originalLanguage_diffStorage = unserialize($currentRecord[$TCA[$table]['ctrl']['transOrigDiffSourceField']]);
00657          }
00658       }
00659       $this->checkValue_currentRecord = $checkValueRecord;
00660 
00661          /*
00662             In the following all incoming value-fields are tested:
00663             - Are the user allowed to change the field?
00664             - Is the field uid/pid (which are already set)
00665             - perms-fields for pages-table, then do special things...
00666             - If the field is nothing of the above and the field is configured in TCA, the fieldvalues are evaluated by ->checkValue
00667 
00668             If everything is OK, the field is entered into $fieldArray[]
00669          */
00670       foreach($incomingFieldArray as $field => $fieldValue) {
00671          if (!in_array($table.'-'.$field, $this->exclude_array) && !$this->data_disableFields[$table][$id][$field])  {  // The field must be editable.
00672 
00673                // Checking language:
00674             $languageDeny = $TCA[$table]['ctrl']['languageField'] && !strcmp($TCA[$table]['ctrl']['languageField'], $field) && !$this->BE_USER->checkLanguageAccess($fieldValue);
00675 
00676             if (!$languageDeny)  {
00677                   // Stripping slashes - will probably be removed the day $this->stripslashes_values is removed as an option...
00678                if ($this->stripslashes_values)  {
00679                   if (is_array($fieldValue)) {
00680                      t3lib_div::stripSlashesOnArray($fieldValue);
00681                   } else $fieldValue = stripslashes($fieldValue);
00682                }
00683 
00684                switch ($field)   {
00685                   case 'uid':
00686                   case 'pid':
00687                      // Nothing happens, already set
00688                   break;
00689                   case 'perms_userid':
00690                   case 'perms_groupid':
00691                   case 'perms_user':
00692                   case 'perms_group':
00693                   case 'perms_everybody':
00694                         // Permissions can be edited by the owner or the administrator
00695                      if ($table=='pages' && ($this->admin || $status=='new' || $this->pageInfo($id,'perms_userid')==$this->userid) )   {
00696                         $value=intval($fieldValue);
00697                         switch($field) {
00698                            case 'perms_userid':
00699                               $fieldArray[$field]=$value;
00700                            break;
00701                            case 'perms_groupid':
00702                               $fieldArray[$field]=$value;
00703                            break;
00704                            default:
00705                               if ($value>=0 && $value<pow(2,5))   {
00706                                  $fieldArray[$field]=$value;
00707                               }
00708                            break;
00709                         }
00710                      }
00711                   break;
00712                   case 't3ver_oid':
00713                   case 't3ver_id':
00714                      // t3ver_label is not here because it CAN be edited as a regular field!
00715                   break;
00716                   default:
00717                      if (isset($TCA[$table]['columns'][$field]))  {
00718                            // Evaluating the value.
00719                         $res = $this->checkValue($table,$field,$fieldValue,$id,$status,$realPid,$tscPID);
00720                         if (isset($res['value']))  {
00721                            $fieldArray[$field]=$res['value'];
00722 
00723                               // Add the value of the original record to the diff-storage content:
00724                            if ($TCA[$table]['ctrl']['transOrigDiffSourceField']) {
00725                               $originalLanguage_diffStorage[$field] = $originalLanguageRecord[$field];
00726                               $diffStorageFlag = TRUE;
00727                            }
00728                         }
00729                      }
00730 
00731 
00732                   break;
00733                }
00734             }  // Checking language.
00735          }  // Check exclude fields / disabled fields...
00736       }
00737 
00738          // Add diff-storage information:
00739       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...
00740           $fieldArray[$TCA[$table]['ctrl']['transOrigDiffSourceField']] = serialize($originalLanguage_diffStorage);
00741       }
00742 
00743          // Checking for RTE-transformations of fields:
00744       $types_fieldConfig = t3lib_BEfunc::getTCAtypes($table,$currentRecord);
00745       $theTypeString = t3lib_BEfunc::getTCAtypeValue($table,$currentRecord);
00746       if (is_array($types_fieldConfig))   {
00747          reset($types_fieldConfig);
00748          while(list(,$vconf) = each($types_fieldConfig)) {
00749                // Write file configuration:
00750             $eFile = t3lib_parsehtml_proc::evalWriteFile($vconf['spec']['static_write'],array_merge($currentRecord,$fieldArray));   // inserted array_merge($currentRecord,$fieldArray) 170502
00751 
00752                // RTE transformations:
00753             if (!$this->dontProcessTransformations)   {
00754                if (isset($fieldArray[$vconf['field']]))  {
00755                      // Look for transformation flag:
00756                   switch((string)$incomingFieldArray['_TRANSFORM_'.$vconf['field']])   {
00757                      case 'RTE':
00758                         $RTEsetup = $this->BE_USER->getTSConfig('RTE',t3lib_BEfunc::getPagesTSconfig($tscPID));
00759                         $thisConfig = t3lib_BEfunc::RTEsetup($RTEsetup['properties'],$table,$vconf['field'],$theTypeString);
00760 
00761                            // Set alternative relative path for RTE images/links:
00762                         $RTErelPath = is_array($eFile) ? dirname($eFile['relEditFile']) : '';
00763 
00764                            // Get RTE object, draw form and set flag:
00765                         $RTEobj = &t3lib_BEfunc::RTEgetObj();
00766                         if (is_object($RTEobj)) {
00767                            $fieldArray[$vconf['field']] = $RTEobj->transformContent('db',$fieldArray[$vconf['field']],$table,$vconf['field'],$currentRecord,$vconf['spec'],$thisConfig,$RTErelPath,$currentRecord['pid']);
00768                         } else {
00769                            debug('NO RTE OBJECT FOUND!');
00770                         }
00771                      break;
00772                   }
00773                }
00774             }
00775 
00776                // Write file configuration:
00777             if (is_array($eFile))   {
00778                $mixedRec = array_merge($currentRecord,$fieldArray);
00779                $SW_fileContent = t3lib_div::getUrl($eFile['editFile']);
00780                $parseHTML = t3lib_div::makeInstance('t3lib_parsehtml_proc');
00781                $parseHTML->init('','');
00782 
00783                $eFileMarker = $eFile['markerField']&&trim($mixedRec[$eFile['markerField']]) ? trim($mixedRec[$eFile['markerField']]) : '###TYPO3_STATICFILE_EDIT###';
00784                $insertContent = str_replace($eFileMarker,'',$mixedRec[$eFile['contentField']]); // must replace the marker if present in content!
00785 
00786                $SW_fileNewContent = $parseHTML->substituteSubpart($SW_fileContent, $eFileMarker, chr(10).$insertContent.chr(10), 1, 1);
00787                t3lib_div::writeFile($eFile['editFile'],$SW_fileNewContent);
00788 
00789                   // Write status:
00790                if (!strstr($id,'NEW') && $eFile['statusField'])   {
00791                   $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
00792                      $table,
00793                      'uid='.intval($id),
00794                      array(
00795                         $eFile['statusField'] => $eFile['relEditFile'].' updated '.date('d-m-Y H:i:s').', bytes '.strlen($mixedRec[$eFile['contentField']])
00796                      )
00797                   );
00798                }
00799             } elseif ($eFile && is_string($eFile)) {
00800                $this->log($insertTable,$id,2,0,1,"Write-file error: '%s'",13,array($eFile),$realPid);
00801             }
00802          }
00803       }
00804          // Return fieldArray
00805       return $fieldArray;
00806    }
00807 
00816    function checkModifyAccessList($table) {
00817       $res = ($this->admin || (!$this->tableAdminOnly($table) && t3lib_div::inList($this->BE_USER->groupData['tables_modify'],$table)));
00818       return $res;
00819    }
00820 
00828    function isRecordInWebMount($table,$id)   {
00829       if (!isset($this->isRecordInWebMount_Cache[$table.':'.$id]))   {
00830          $recP=$this->getRecordProperties($table,$id);
00831          $this->isRecordInWebMount_Cache[$table.':'.$id]=$this->isInWebMount($recP['event_pid']);
00832       }
00833       return $this->isRecordInWebMount_Cache[$table.':'.$id];
00834    }
00835 
00842    function isInWebMount($pid)   {
00843       if (!isset($this->isInWebMount_Cache[$pid])) {
00844          $this->isInWebMount_Cache[$pid]=$this->BE_USER->isInWebMount($pid);
00845       }
00846 //debug($this->isInWebMount_Cache);
00847       return $this->isInWebMount_Cache[$pid];
00848    }
00849 
00859    function checkRecordUpdateAccess($table,$id) {
00860       global $TCA;
00861       $res = 0;
00862       if ($TCA[$table] && intval($id)>0)  {
00863          if (isset($this->recUpdateAccessCache[$table][$id]))  {  // If information is cached, return it
00864             return $this->recUpdateAccessCache[$table][$id];
00865             // Check if record exists and 1) if 'pages' the page may be edited, 2) if page-content the page allows for editing
00866          } elseif ($this->doesRecordExist($table,$id,'edit'))  {
00867             $res = 1;
00868          }
00869          $this->recUpdateAccessCache[$table][$id]=$res;  // Cache the result
00870       }
00871       return $res;
00872    }
00873 
00884    function checkRecordInsertAccess($insertTable,$pid,$action=1)  {
00885       global $TCA;
00886       $res = 0;
00887       $pid = intval($pid);
00888       if ($pid>=0)   {
00889          if (isset($this->recInsertAccessCache[$insertTable][$pid])) {  // If information is cached, return it
00890             return $this->recInsertAccessCache[$insertTable][$pid];
00891          } else {
00892                // 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
00893             if ( (!$pid && $this->admin) || $this->doesRecordExist('pages',$pid,($insertTable=='pages'?$this->pMap['new']:$this->pMap['editcontent'])) ) {     // Check permissions
00894                if ($this->isTableAllowedForThisPage($pid, $insertTable))   {
00895                   $res = 1;
00896                   $this->recInsertAccessCache[$insertTable][$pid]=$res; // Cache the result
00897                } else {
00898                   $propArr = $this->getRecordProperties('pages',$pid);
00899                   $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']);
00900                }
00901             } else {
00902                $propArr = $this->getRecordProperties('pages',$pid);
00903                $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']);
00904             }
00905          }
00906       }
00907       return $res;
00908    }
00909 
00920    function isTableAllowedForThisPage($page_uid, $checkTable)  {
00921       global $TCA, $PAGES_TYPES;
00922       $page_uid = intval($page_uid);
00923 
00924          // 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.
00925       if (($TCA[$checkTable]['ctrl']['rootLevel'] xor !$page_uid) && $TCA[$checkTable]['ctrl']['rootLevel']!=-1 && $checkTable!='pages')  {
00926          return false;
00927       }
00928 
00929          // Check root-level
00930       if (!$page_uid)   {
00931          if ($this->admin) {
00932             return true;
00933          }
00934       } else {
00935             // Check non-root-level
00936          $doktype = $this->pageInfo($page_uid,'doktype');
00937          $allowedTableList = isset($PAGES_TYPES[$doktype]['allowedTables']) ? $PAGES_TYPES[$doktype]['allowedTables'] : $PAGES_TYPES['default']['allowedTables'];
00938          $allowedArray = t3lib_div::trimExplode(',',$allowedTableList,1);
00939          if (strstr($allowedTableList,'*') || in_array($checkTable,$allowedArray))  {     // If all tables or the table is listed as a allowed type, return true
00940             return true;
00941          }
00942       }
00943    }
00944 
00955    function doesRecordExist($table,$id,$perms)  {
00956       global $TCA;
00957 
00958       $res = 0;
00959       $id = intval($id);
00960 
00961          // Processing the incoming $perms (from possible string to integer that can be AND'ed)
00962       if (!t3lib_div::testInt($perms)) {
00963          if ($table!='pages') {
00964             switch($perms) {
00965                case 'edit':
00966                case 'delete':
00967                case 'new':
00968                   $perms = 'editcontent';    // This holds it all in case the record is not page!!
00969                break;
00970             }
00971          }
00972          $perms = intval($this->pMap[$perms]);
00973       } else {
00974          $perms = intval($perms);
00975       }
00976 
00977       if (!$perms)   {debug('Internal ERROR: no permissions to check for non-admin user.');}
00978 
00979          // For all tables: Check if record exists:
00980          // Notice: If $perms are 0 (zero) no perms-clause is added!
00981       if (is_array($TCA[$table]) && $id>0 && ($this->isRecordInWebMount($table,$id) || $this->admin)) {
00982          if ($table != 'pages')  {
00983 
00984                // Find record without checking page:
00985             $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,pid', $table, 'uid='.intval($id).$this->deleteClause($table));
00986             $output = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres);
00987             t3lib_BEfunc::fixVersioningPid($table,$output);
00988 
00989                // If record found, check page as well:
00990             if (is_array($output))  {
00991 
00992                   // Looking up the page for record:
00993                $mres = $this->doesRecordExist_pageLookUp($output['pid'], $perms);
00994                $pageRec = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres);
00995 
00996                   // 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):
00997                if (is_array($pageRec) || (!$output['pid'] && $this->admin))   {
00998                   return TRUE;
00999                }
01000             }
01001             return FALSE;
01002          } else {
01003             $mres = $this->doesRecordExist_pageLookUp($id, $perms);
01004             return $GLOBALS['TYPO3_DB']->sql_num_rows($mres);
01005          }
01006       }
01007    }
01008 
01018    function doesRecordExist_pageLookUp($id, $perms)   {
01019       global $TCA;
01020 
01021       return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
01022          'uid',
01023          'pages',
01024          'uid='.intval($id).
01025             $this->deleteClause('pages').
01026             ($perms && !$this->admin ? ' AND '.$this->BE_USER->getPagePermsClause($perms) : '').
01027             (!$this->admin && $TCA['pages']['ctrl']['editlock'] && ($perms & (2+4+16)) ? ' AND '.$TCA['pages']['ctrl']['editlock'].'=0':'')  // admin users don't need check
01028       );
01029    }
01030 
01044    function doesBranchExist($inList,$pid,$perms, $recurse)  {
01045       global $TCA;
01046       $pid = intval($pid);
01047       $perms = intval($perms);
01048       if ($pid>=0)   {
01049          $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
01050                   'uid, perms_userid, perms_groupid, perms_user, perms_group, perms_everybody',
01051                   'pages',
01052                   'pid='.intval($pid).$this->deleteClause('pages'),
01053                   '',
01054                   'sorting'
01055                );
01056          while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) {
01057             if ($this->admin || $this->BE_USER->doesUserHaveAccess($row,$perms)) {  // IF admin, then it's OK
01058                $inList.=$row['uid'].',';
01059                if ($recurse)  {  // Follow the subpages recursively...
01060                   $inList = $this->doesBranchExist($inList, $row['uid'], $perms, $recurse);
01061                   if ($inList == -1)   {return -1;}      // No permissions somewhere in the branch
01062                }
01063             } else {
01064                return -1;     // No permissions
01065             }
01066          }
01067       }
01068       return $inList;
01069    }
01070 
01079    function pageInfo($id,$field) {
01080       if (!isset($this->pageCache[$id]))  {
01081          $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'pages', 'uid='.intval($id));
01082          if ($GLOBALS['TYPO3_DB']->sql_num_rows($res))   {
01083             $this->pageCache[$id] = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
01084          }
01085          $GLOBALS['TYPO3_DB']->sql_free_result($res);
01086       }
01087       return $this->pageCache[$id][$field];
01088    }
01089 
01099    function recordInfo($table,$id,$fieldList)   {
01100       global $TCA;
01101       if (is_array($TCA[$table]))   {
01102          $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fieldList, $table, 'uid='.intval($id));
01103          if ($GLOBALS['TYPO3_DB']->sql_num_rows($res))   {
01104             return $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
01105          }
01106       }
01107    }
01108 
01116    function getRecordProperties($table,$id)  {
01117       $row = ($table=='pages' && !$id) ? array('title'=>'[root-level]', 'uid' => 0, 'pid' => 0) :$this->recordInfo($table,$id,'*');
01118       t3lib_BEfunc::fixVersioningPid($table,$row);
01119       return $this->getRecordPropertiesFromRow($table,$row);
01120    }
01121 
01129    function getRecordPropertiesFromRow($table,$row)   {
01130       global $TCA;
01131       if ($TCA[$table]) {
01132          $out = array(
01133             'header' => $row[$TCA[$table]['ctrl']['label']],
01134             'pid' => $row['pid'],
01135             'event_pid' => ($table=='pages'?$row['uid']:$row['pid'])
01136          );
01137          return $out;
01138       }
01139    }
01140 
01148    function setTSconfigPermissions($fieldArray,$TSConfig_p) {
01149       if (strcmp($TSConfig_p['userid'],''))  $fieldArray['perms_userid']=intval($TSConfig_p['userid']);
01150       if (strcmp($TSConfig_p['groupid'],'')) $fieldArray['perms_groupid']=intval($TSConfig_p['groupid']);
01151       if (strcmp($TSConfig_p['user'],''))       $fieldArray['perms_user']=t3lib_div::testInt($TSConfig_p['user']) ? $TSConfig_p['user'] : $this->assemblePermissions($TSConfig_p['user']);
01152       if (strcmp($TSConfig_p['group'],''))      $fieldArray['perms_group']=t3lib_div::testInt($TSConfig_p['group']) ? $TSConfig_p['group'] : $this->assemblePermissions($TSConfig_p['group']);
01153       if (strcmp($TSConfig_p['everybody'],''))  $fieldArray['perms_everybody']=t3lib_div::testInt($TSConfig_p['everybody']) ? $TSConfig_p['everybody'] : $this->assemblePermissions($TSConfig_p['everybody']);
01154 
01155       return $fieldArray;
01156    }
01157 
01164    function newFieldArray($table)   {
01165       global $TCA;
01166       t3lib_div::loadTCA($table);
01167       $fieldArray=Array();
01168       if (is_array($TCA[$table]['columns'])) {
01169          reset ($TCA[$table]['columns']);
01170          while (list($field,$content)=each($TCA[$table]['columns'])) {
01171             if (isset($this->defaultValues[$table][$field]))   {
01172                $fieldArray[$field] = $this->defaultValues[$table][$field];
01173             } elseif (isset($content['config']['default'])) {
01174                $fieldArray[$field] = $content['config']['default'];
01175             }
01176          }
01177       }
01178       if ($table=='pages') {     // Set default permissions for a page.
01179          $fieldArray['perms_userid'] = $this->userid;
01180          $fieldArray['perms_groupid'] = intval($this->BE_USER->firstMainGroup);
01181          $fieldArray['perms_user'] = $this->assemblePermissions($this->defaultPermissions['user']);
01182          $fieldArray['perms_group'] = $this->assemblePermissions($this->defaultPermissions['group']);
01183          $fieldArray['perms_everybody'] = $this->assemblePermissions($this->defaultPermissions['everybody']);
01184       }
01185       return $fieldArray;
01186    }
01187 
01195    function overrideFieldArray($table,$data) {
01196       if (is_array($this->overrideValues[$table])) {
01197          $data = array_merge($data,$this->overrideValues[$table]);         // Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
01198       }
01199       return $data;
01200    }
01201 
01208    function assemblePermissions($string)  {
01209       $keyArr = t3lib_div::trimExplode(',',$string,1);
01210       $value=0;
01211       while(list(,$key)=each($keyArr)) {
01212          if ($key && isset($this->pMap[$key]))  {
01213             $value |= $this->pMap[$key];
01214          }
01215       }
01216       return $value;
01217    }
01218 
01219 
01220 
01221 
01222 
01223 
01224 
01225 
01226 
01227 
01228 
01229 
01230 
01231 
01232 
01233 
01234 
01235 
01236 
01237 
01238    /*********************************************
01239     *
01240     * Evaluation of input values
01241     *
01242     ********************************************/
01243 
01258    function checkValue($table,$field,$value,$id,$status,$realPid,$tscPID)  {
01259       global $TCA, $PAGES_TYPES;
01260       t3lib_div::loadTCA($table);
01261 
01262       $res = Array();   // result array
01263       $recFID = $table.':'.$id.':'.$field;
01264 
01265          // Processing special case of field pages.doktype
01266       if ($table=='pages' && $field=='doktype') {
01267             // If the user may not use this specific doktype, we issue a warning
01268          if (! ($this->admin || t3lib_div::inList($this->BE_USER->groupData['pagetypes_select'],$value)))   {
01269             $propArr = $this->getRecordProperties($table,$id);
01270             $this->log($table,$id,5,0,1,"You cannot change the 'doktype' of page '%s' to the desired value.",1,array($propArr['header']),$propArr['event_pid']);
01271             return $res;
01272          };
01273          if ($status=='update')  {
01274                // This checks if 1) we should check for disallowed tables and 2) the there are records from disallowed tables on the current page
01275             $onlyAllowedTables = isset($PAGES_TYPES[$value]['onlyAllowedTables']) ? $PAGES_TYPES[$value]['onlyAllowedTables'] : $PAGES_TYPES['default']['onlyAllowedTables'];
01276             if ($onlyAllowedTables) {
01277                $theWrongTables = $this->doesPageHaveUnallowedTables($id,$value);
01278                if ($theWrongTables) {
01279                   $propArr = $this->getRecordProperties($table,$id);
01280                   $this->log($table,$id,5,0,1,"'doktype' of page '%s' could not be changed because the page contains records from disallowed tables; %s",2,array($propArr['header'],$theWrongTables),$propArr['event_pid']);
01281                   return $res;
01282                }
01283             }
01284          }
01285       }
01286 
01287          // Get current value:
01288       $curValueRec = $this->recordInfo($table,$id,$field);
01289       $curValue = $curValueRec[$field];
01290 
01291          // Getting config for the field
01292       $tcaFieldConf = $TCA[$table]['columns'][$field]['config'];
01293 
01294          // Preform processing:
01295       $res = $this->checkValue_SW($res,$value,$tcaFieldConf,$table,$id,$curValue,$status,$realPid,$recFID,$field,$this->uploadedFileArray[$table][$id][$field],$tscPID);
01296 
01297       return $res;
01298    }
01299 
01318    function checkValue_SW($res,$value,$tcaFieldConf,$table,$id,$curValue,$status,$realPid,$recFID,$field,$uploadedFiles,$tscPID) {
01319 
01320       $PP = array($table,$id,$curValue,$status,$realPid,$recFID,$tscPID);
01321 
01322       switch ($tcaFieldConf['type']) {
01323          case 'text':
01324          case 'passthrough':
01325          case 'user':
01326             $res['value'] = $value;
01327          break;
01328          case 'input':
01329             $res = $this->checkValue_input($res,$value,$tcaFieldConf,$PP,$field);
01330          break;
01331          case 'check':
01332             $res = $this->checkValue_check($res,$value,$tcaFieldConf,$PP);
01333          break;
01334          case 'radio':
01335             $res = $this->checkValue_radio($res,$value,$tcaFieldConf,$PP);
01336          break;
01337          case 'group':
01338          case 'select':
01339             $res = $this->checkValue_group_select($res,$value,$tcaFieldConf,$PP,$uploadedFiles,$field);
01340          break;
01341          case 'flex':
01342             if ($field) {  // FlexForms are only allowed for real fields.
01343                $res = $this->checkValue_flex($res,$value,$tcaFieldConf,$PP,$uploadedFiles,$field);
01344             }
01345          break;
01346          default:
01347             #debug(array($tcaFieldConf,$res,$value),'NON existing field type:');
01348          break;
01349       }
01350 
01351       return $res;
01352    }
01353 
01364    function checkValue_input($res,$value,$tcaFieldConf,$PP,$field='')   {
01365       list($table,$id,$curValue,$status,$realPid,$recFID) = $PP;
01366 
01367          // Secures the string-length to be less than max. Will probably make problems with multi-byte strings!
01368       if (intval($tcaFieldConf['max'])>0) {$value = substr($value,0,intval($tcaFieldConf['max']));}
01369 
01370          // Checking range of value:
01371       if ($tcaFieldConf['range'] && $value!=$tcaFieldConf['checkbox'])  {  // If value is not set to the allowed checkbox-value then it is checked against the ranges
01372          if (isset($tcaFieldConf['range']['upper'])&&$value>$tcaFieldConf['range']['upper']) {$value=$tcaFieldConf['range']['upper'];}
01373          if (isset($tcaFieldConf['range']['lower'])&&$value<$tcaFieldConf['range']['lower']) {$value=$tcaFieldConf['range']['lower'];}
01374       }
01375 
01376          // Process evaluation settings:
01377       $evalCodesArray = t3lib_div::trimExplode(',',$tcaFieldConf['eval'],1);
01378       $res = $this->checkValue_input_Eval($value,$evalCodesArray,$tcaFieldConf['is_in']);
01379 
01380          // Process UNIQUE settings:
01381       if ($field && $realPid>=0) {  // Field is NOT set for flexForms - which also means that uniqueInPid and unique is NOT available for flexForm fields! Also getUnique should not be done for versioning and if PID is -1 ($realPid<0) then versioning is happening...
01382          if ($res['value'] && in_array('uniqueInPid',$evalCodesArray))  {
01383             $res['value'] = $this->getUnique($table,$field,$res['value'],$id,$realPid);
01384          }
01385          if ($res['value'] && in_array('unique',$evalCodesArray)) {
01386             $res['value'] = $this->getUnique($table,$field,$res['value'],$id);
01387          }
01388       }
01389 
01390       return $res;
01391    }
01392 
01402    function checkValue_check($res,$value,$tcaFieldConf,$PP) {
01403       list($table,$id,$curValue,$status,$realPid,$recFID) = $PP;
01404 
01405       $itemC = count($tcaFieldConf['items']);
01406       if (!$itemC)   {$itemC=1;}
01407       $maxV = pow(2,$itemC);
01408 
01409       if ($value<0)  {$value=0;}
01410       if ($value>$maxV) {$value=$maxV;}
01411       $res['value'] = $value;
01412 
01413       return $res;
01414    }
01415 
01425    function checkValue_radio($res,$value,$tcaFieldConf,$PP) {
01426       list($table,$id,$curValue,$status,$realPid,$recFID) = $PP;
01427 
01428       if (is_array($tcaFieldConf['items']))  {
01429          foreach($tcaFieldConf['items'] as $set)   {
01430             if (!strcmp($set[1],$value))  {
01431                $res['value'] = $value;
01432                break;
01433             }
01434          }
01435       }
01436 
01437       return $res;
01438    }
01439 
01451    function checkValue_group_select($res,$value,$tcaFieldConf,$PP,$uploadedFiles,$field)  {
01452       list($table,$id,$curValue,$status,$realPid,$recFID) = $PP;
01453 
01454          // Detecting if value send is an array and if so, implode it around a comma:
01455       if (is_array($value))   {
01456          $value = implode(',',$value);
01457       }
01458 
01459          // This converts all occurencies of '&#123;' to the byte 123 in the string - this is needed in very rare cases where filenames with special characters (like æøå, umlaud etc) gets sent to the server as HTML entities instead of bytes. The error is done only by MSIE, not Mozilla and Opera.
01460          // Anyways, this should NOT disturb anything else:
01461       $value = $this->convNumEntityToByteValue($value);
01462 
01463          // When values are send as group or select they come as comma-separated values which are exploded by this function:
01464       $valueArray = $this->checkValue_group_select_explodeSelectGroupValue($value);
01465 
01466          // If not multiple is set, then remove duplicates:
01467       if (!$tcaFieldConf['multiple'])  {
01468          $valueArray = array_unique($valueArray);
01469       }
01470 
01471       // This could be a good spot for parsing the array through a validation-function which checks if the values are allright (except that database references are not in their final form - but that is the point, isn't it?)
01472       // NOTE!!! Must check max-items of files before the later check because that check would just leave out filenames if there are too many!!
01473 
01474          // Checking for select / authMode, removing elements from $valueArray if any of them is not allowed!
01475       if ($tcaFieldConf['type']=='select' && $tcaFieldConf['authMode']) {
01476          $preCount = count($valueArray);
01477          foreach($valueArray as $kk => $vv)  {
01478             if (!$this->BE_USER->checkAuthMode($table,$field,$vv,$tcaFieldConf['authMode'])) {
01479                unset($valueArray[$kk]);
01480             }
01481          }
01482 
01483             // During the check it turns out that the value / all values were removed - we respond by simply returning an empty array so nothing is written to DB for this field.
01484          if ($preCount && !count($valueArray))  {
01485             return array();
01486          }
01487       }
01488 
01489          // For group types:
01490       if ($tcaFieldConf['type']=='group') {
01491          switch($tcaFieldConf['internal_type']) {
01492             case 'file':
01493                $valueArray = $this->checkValue_group_select_file(
01494                   $valueArray,
01495                   $tcaFieldConf,
01496                   $curValue,
01497                   $uploadedFiles,
01498                   $status,
01499                   $table,
01500                   $id,
01501                   $recFID
01502                );
01503             break;
01504             case 'db':
01505                $valueArray = $this->checkValue_group_select_processDBdata($valueArray,$tcaFieldConf,$id,$status,'group');
01506             break;
01507          }
01508       }
01509          // For select types which has a foreign table attached:
01510       if ($tcaFieldConf['type']=='select' && $tcaFieldConf['foreign_table'])  {
01511          $valueArray = $this->checkValue_group_select_processDBdata($valueArray,$tcaFieldConf,$id,$status,'select');
01512       }
01513 
01514 // BTW, checking for min and max items here does NOT make any sense when MM is used because the above function calls will just return an array with a single item (the count) if MM is used... Why didn't I perform the check before? Probably because we could not evaluate the validity of record uids etc... Hmm...
01515 
01516          // Checking the number of items, that it is correct.
01517          // If files, there MUST NOT be too many files in the list at this point, so check that prior to this code.
01518       $valueArrayC = count($valueArray);
01519       $minI = isset($tcaFieldConf['minitems']) ? intval($tcaFieldConf['minitems']):0;
01520 
01521          // NOTE to the comment: It's not really possible to check for too few items, because you must then determine first, if the field is actual used regarding the CType.
01522       $maxI = isset($tcaFieldConf['maxitems']) ? intval($tcaFieldConf['maxitems']):1;
01523       if ($valueArrayC > $maxI)  {$valueArrayC=$maxI;}   // Checking for not too many elements
01524 
01525          // Dumping array to list
01526       $newVal=array();
01527       foreach($valueArray as $nextVal) {
01528          if ($valueArrayC==0) {break;}
01529          $valueArrayC--;
01530          $newVal[]=$nextVal;
01531       }
01532       $res['value'] = implode(',',$newVal);
01533 
01534       return $res;
01535    }
01536 
01551    function checkValue_group_select_file($valueArray,$tcaFieldConf,$curValue,$uploadedFileArray,$status,$table,$id,$recFID)   {
01552 
01553          // If any files are uploaded:
01554       if (is_array($uploadedFileArray) &&
01555          $uploadedFileArray['name'] &&
01556          strcmp($uploadedFileArray['tmp_name'],'none'))  {
01557             $valueArray[]=$uploadedFileArray['tmp_name'];
01558             $this->alternativeFileName[$uploadedFileArray['tmp_name']] = $uploadedFileArray['name'];
01559       }
01560 
01561          // Creating fileFunc object.
01562       if (!$this->fileFunc)   {
01563          $this->fileFunc = t3lib_div::makeInstance('t3lib_basicFileFunctions');
01564          $this->include_filefunctions=1;
01565       }
01566          // Setting permitted extensions.
01567       $all_files = Array();
01568       $all_files['webspace']['allow'] = $tcaFieldConf['allowed'];
01569       $all_files['webspace']['deny'] = $tcaFieldConf['disallowed'] ? $tcaFieldConf['disallowed'] : '*';
01570       $all_files['ftpspace'] = $all_files['webspace'];
01571       $this->fileFunc->init('', $all_files);
01572 
01573          // If there is an upload folder defined:
01574       if ($tcaFieldConf['uploadfolder'])  {
01575             // For logging..
01576          $propArr = $this->getRecordProperties($table,$id);
01577 
01578             // Get destrination path:
01579          $dest = $this->destPathFromUploadFolder($tcaFieldConf['uploadfolder']);
01580 
01581             // If we are updating:
01582          if ($status=='update')  {
01583 
01584                // Finding the CURRENT files listed, either from MM or from the current record.
01585             $theFileValues=array();
01586             if ($tcaFieldConf['MM'])   {  // If MM relations for the files also!
01587                $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
01588                $dbAnalysis->start('','files',$tcaFieldConf['MM'],$id);
01589                reset($dbAnalysis->itemArray);
01590                while (list($somekey,$someval)=each($dbAnalysis->itemArray))   {
01591                   if ($someval['id'])  {
01592                      $theFileValues[]=$someval['id'];
01593                   }
01594                }
01595             } else {
01596                $theFileValues=t3lib_div::trimExplode(',',$curValue,1);
01597             }
01598 
01599                // DELETE files: If existing files were found, traverse those and register files for deletion which has been removed:
01600             if (count($theFileValues)) {
01601                   // Traverse the input values and for all input values which match an EXISTING value, remove the existing from $theFileValues array (this will result in an array of all the existing files which should be deleted!)
01602                foreach($valueArray as $key => $theFile)  {
01603                   if ($theFile && !strstr(t3lib_div::fixWindowsFilePath($theFile),'/'))   {
01604                      $theFileValues = t3lib_div::removeArrayEntryByValue($theFileValues,$theFile);
01605                   }
01606                }
01607 
01608                   // This array contains the filenames in the uploadfolder that should be deleted:
01609                foreach($theFileValues as $key => $theFile)  {
01610                   $theFile = trim($theFile);
01611                   if (@is_file($dest.'/'.$theFile))   {
01612                      $this->removeFilesStore[]=$dest.'/'.$theFile;
01613                   } elseif ($theFile) {
01614                      $this->log($table,$id,5,0,1,"Could not delete file '%s' (does not exist). (%s)",10,array($dest.'/'.$theFile, $recFID),$propArr['event_pid']);
01615                   }
01616                }
01617             }
01618          }
01619 
01620             // Traverse the submitted values:
01621          foreach($valueArray as $key => $theFile)  {
01622                // NEW FILES? If the value contains '/' it indicates, that the file is new and should be added to the uploadsdir (whether its absolute or relative does not matter here)
01623             if (strstr(t3lib_div::fixWindowsFilePath($theFile),'/')) {
01624                   // Init:
01625                $maxSize = intval($tcaFieldConf['max_size']);
01626                $cmd='';
01627                $theDestFile='';     // Must be cleared. Else a faulty fileref may be inserted if the below code returns an error!! (Change: 22/12/2000)
01628 
01629                   // Check various things before copying file:
01630                if (@is_dir($dest) && (@is_file($theFile) || @is_uploaded_file($theFile))) {     // File and destination must exist
01631 
01632                      // Finding size. For safe_mode we have to rely on the size in the upload array if the file is uploaded.
01633                   if (is_uploaded_file($theFile) && $theFile==$uploadedFileArray['tmp_name'])   {
01634                      $fileSize = $uploadedFileArray['size'];
01635                   } else {
01636                      $fileSize = filesize($theFile);
01637                   }
01638 
01639                   if (!$maxSize || $fileSize<=($maxSize*1024)) {  // Check file size:
01640                         // Prepare filename:
01641                      $theEndFileName = isset($this->alternativeFileName[$theFile]) ? $this->alternativeFileName[$theFile] : $theFile;
01642                      $fI = t3lib_div::split_fileref($theEndFileName);
01643 
01644                         // Check for allowed extension:
01645                      if ($this->fileFunc->checkIfAllowed($fI['fileext'], $dest, $theEndFileName)) {
01646                         $theDestFile = $this->fileFunc->getUniqueName($this->fileFunc->cleanFileName($fI['file']), $dest);
01647 
01648                            // If we have a unique destination filename, then write the file:
01649                         if ($theDestFile) {
01650                            t3lib_div::upload_copy_move($theFile,$theDestFile);
01651                            $this->copiedFileMap[$theFile] = $theDestFile;
01652                            clearstatcache();
01653                            if (!@is_file($theDestFile))  $this->log($table,$id,5,0,1,"Copying file '%s' failed!: The destination path (%s) may be write protected. Please make it write enabled!. (%s)",16,array($theFile, dirname($theDestFile), $recFID),$propArr['event_pid']);
01654                         } else $this->log($table,$id,5,0,1,"Copying file '%s' failed!: No destination file (%s) possible!. (%s)",11,array($theFile, $theDestFile, $recFID),$propArr['event_pid']);
01655                      } else $this->log($table,$id,5,0,1,"Fileextension '%s' not allowed. (%s)",12,array($fI['fileext'], $recFID),$propArr['event_pid']);
01656                   } else $this->log($table,$id,5,0,1,"Filesize (%s) of file '%s' exceeds limit (%s). (%s)",13,array(t3lib_div::formatSize($fileSize),$theFile,t3lib_div::formatSize($maxSize*1024),$recFID),$propArr['event_pid']);
01657                } else $this->log($table,$id,5,0,1,'The destination (%s) or the source file (%s) does not exist. (%s)',14,array($dest, $theFile, $recFID),$propArr['event_pid']);
01658 
01659                   // If the destination file was created, we will set the new filename in the value array, otherwise unset the entry in the value array!
01660                if (@is_file($theDestFile))   {
01661                   $info = t3lib_div::split_fileref($theDestFile);
01662                   $valueArray[$key]=$info['file']; // The value is set to the new filename
01663                } else {
01664                   unset($valueArray[$key]);  // The value is set to the new filename
01665                }
01666             }
01667          }
01668 
01669             // If MM relations for the files, we will set the relations as MM records and change the valuearray to contain a single entry with a count of the number of files!
01670          if ($tcaFieldConf['MM'])   {
01671             $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
01672             $dbAnalysis->tableArray['files']=array(); // dummy
01673 
01674             reset($valueArray);
01675             while (list($key,$theFile)=each($valueArray))   {
01676                   // explode files
01677                   $dbAnalysis->itemArray[]['id']=$theFile;
01678             }
01679             if ($status=='update')  {
01680                $dbAnalysis->writeMM($tcaFieldConf['MM'],$id,0);
01681             } else {
01682                $this->dbAnalysisStore[] = array($dbAnalysis, $tcaFieldConf['MM'], $id, 0);   // This will be traversed later to execute the actions
01683             }
01684             $cc=count($dbAnalysis->itemArray);
01685             $valueArray = array($cc);
01686          }
01687       }
01688 
01689       return $valueArray;
01690    }
01691 
01704    function checkValue_flex($res,$value,$tcaFieldConf,$PP,$uploadedFiles,$field) {
01705       list($table,$id,$curValue,$status,$realPid,$recFID) = $PP;
01706 
01707       if (is_array($value))   {
01708 
01709             // Get current value array:
01710          $dataStructArray = t3lib_BEfunc::getFlexFormDS($tcaFieldConf,$this->checkValue_currentRecord,$table);
01711 #debug($this->checkValue_currentRecord);
01712          $currentValueArray = t3lib_div::xml2array($curValue);
01713          if (!is_array($currentValueArray))  $currentValueArray = array();
01714          if (is_array($currentValueArray['meta']['currentLangId']))     unset($currentValueArray['meta']['currentLangId']);   // Remove all old meta for languages...
01715 
01716             // Evaluation of input values:
01717          $value['data'] = $this->checkValue_flex_procInData($value['data'],$currentValueArray['data'],$uploadedFiles['data'],$dataStructArray,$PP);
01718 
01719             // Create XML and convert charsets from input value:
01720          $xmlValue = $this->checkValue_flexArray2Xml($value);
01721 
01722             // If we wanted to set UTF fixed:
01723          // $storeInCharset='utf-8';
01724          // $currentCharset=$GLOBALS['LANG']->charSet;
01725          // $xmlValue = $GLOBALS['LANG']->csConvObj->conv($xmlValue,$currentCharset,$storeInCharset,1);
01726          $storeInCharset=$GLOBALS['LANG']->charSet;
01727 
01728             // Merge them together IF they are both arrays:
01729             // Here we convert the currently submitted values BACK to an array, then merge the two and then BACK to XML again. This is needed to ensure the charsets are the same (provided that the current value was already stored IN the charset that the new value is converted to).
01730          if (is_array($currentValueArray))   {
01731             $arrValue = t3lib_div::xml2array($xmlValue);
01732             $arrValue = t3lib_div::array_merge_recursive_overrule($currentValueArray,$arrValue);
01733             $xmlValue = $this->checkValue_flexArray2Xml($arrValue);
01734          }
01735 
01736             // Temporary fix to delete elements:
01737          $deleteCMDs = t3lib_div::_GP('_DELETE_FLEX_FORMdata');
01738 
01739          if (is_array($deleteCMDs[$table][$id][$field]['data']))  {
01740             $arrValue = t3lib_div::xml2array($xmlValue);
01741             $this->_DELETE_FLEX_FORMdata($arrValue['data'],$deleteCMDs[$table][$id][$field]['data']);
01742             $xmlValue = $this->checkValue_flexArray2Xml($arrValue);
01743          }
01744 
01745             // Create the value XML:
01746          $res['value']='';
01747          $res['value'].='<?xml version="1.0" encoding="'.$storeInCharset.'" standalone="yes" ?>'.chr(10);
01748          $res['value'].=$xmlValue;
01749       } else { // Passthrough...:
01750          $res['value']=$value;
01751       }
01752 
01753       return $res;
01754    }
01755 
01762    function checkValue_flexArray2Xml($array) {
01763       $output = t3lib_div::array2xml($array,'',0,'T3FlexForms',4,array('parentTagMap' => array(
01764 /*                      'data' => 'sheets',
01765                         'sheets' => 'language',
01766                         'language' => 'fieldname',
01767                         'el' => 'fieldname'     */
01768                      )));
01769       return $output;
01770    }
01771 
01779    function _DELETE_FLEX_FORMdata(&$valueArrayToRemoveFrom,$deleteCMDS) {
01780       if (is_array($valueArrayToRemoveFrom) && is_array($deleteCMDS))   {
01781          foreach($deleteCMDS as $key => $value) {
01782             if (is_array($deleteCMDS[$key])) {
01783                $this->_DELETE_FLEX_FORMdata($valueArrayToRemoveFrom[$key],$deleteCMDS[$key]);
01784             } else {
01785                unset($valueArrayToRemoveFrom[$key]);
01786             }
01787          }
01788       }
01789    }
01790 
01791 
01792 
01793 
01794 
01795 
01796 
01797 
01798 
01799 
01800 
01801 
01802 
01803 
01804 
01805 
01806 
01807 
01808 
01809 
01810    /*********************************************
01811     *
01812     * Helper functions for evaluation functions.
01813     *
01814     ********************************************/
01815 
01816 
01827    function getUnique($table,$field,$value,$id,$newPid=0)   {
01828       global $TCA;
01829 
01830          // Initialize:
01831       t3lib_div::loadTCA($table);
01832       $whereAdd='';
01833       $newValue='';
01834       if (intval($newPid)) { $whereAdd.=' AND pid='.intval($newPid); } else { $whereAdd.=' AND pid>=0'; }   // "AND pid>=0" for versioning
01835       $whereAdd.=$this->deleteClause($table);
01836 
01837          // If the field is configured in TCA, proceed:
01838       if (is_array($TCA[$table]) && is_array($TCA[$table]['columns'][$field]))   {
01839 
01840             // Look for a record which might already have the value:
01841          $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, $field.'="'.$GLOBALS['TYPO3_DB']->quoteStr($value, $table).'" AND uid!='.intval($id).$whereAdd);
01842          $counter = 0;
01843 
01844             // For as long as records with the test-value existing, try again (with incremented numbers appended).
01845          while ($GLOBALS['TYPO3_DB']->sql_num_rows($res))   {
01846             $newValue = $value.$counter;
01847             $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, $field.'="'.$GLOBALS['TYPO3_DB']->quoteStr($newValue, $table).'" AND uid!='.intval($id).$whereAdd);
01848             $counter++;
01849             if ($counter>100) { break; }  // At "100" it will give up and accept a duplicate - should probably be fixed to a small hash string instead...!
01850          }
01851             // If the new value is there:
01852          $value = strlen($newValue) ? $newValue : $value;
01853       }
01854       return $value;
01855    }
01856 
01865    function checkValue_input_Eval($value,$evalArray,$is_in) {
01866       $res = Array();
01867       $newValue = $value;
01868       $set = true;
01869 
01870       foreach($evalArray as $func)  {
01871          switch($func)  {
01872             case 'int':
01873             case 'year':
01874             case 'date':
01875             case 'datetime':
01876             case 'time':
01877             case 'timesec':
01878                $value = intval($value);
01879             break;
01880             case 'double2':
01881                $theDec = 0;
01882                for ($a=strlen($value); $a>0; $a--) {
01883                   if (substr($value,$a-1,1)=='.' || substr($value,$a-1,1)==',')  {
01884                      $theDec = substr($value,$a);
01885                      $value = substr($value,0,$a-1);
01886                      break;
01887                   }
01888                }
01889                $theDec = ereg_replace('[^0-9]','',$theDec).'00';
01890                $value = intval(str_replace(' ','',$value)).'.'.substr($theDec,0,2);
01891             break;
01892             case 'md5':
01893                if (strlen($value)!=32){$set=false;}
01894             break;
01895             case 'trim':
01896                $value = trim($value);
01897             break;
01898             case 'upper':
01899                $value = strtoupper($value);
01900 #              $value = strtr($value, 'áéúíâêûôîæøåäöü', 'ÁÉÚÍÂÊÛÔÎÆØÅÄÖÜ');  // WILL make trouble with other charsets than ISO-8859-1, so what do we do here? PHP-function which can handle this for other charsets? Currently the browsers JavaScript will fix it.
01901             break;
01902             case 'lower':
01903                $value = strtolower($value);
01904 #              $value = strtr($value, 'ÁÉÚÍÂÊÛÔÎÆØÅÄÖÜ', 'áéúíâêûôîæøåäöü');  // WILL make trouble with other charsets than ISO-8859-1, so what do we do here? PHP-function which can handle this for other charsets? Currently the browsers JavaScript will fix it.
01905             break;
01906             case 'required':
01907                if (!$value)   {$set=0;}
01908             break;
01909             case 'is_in':
01910                $c=strlen($value);
01911                if ($c)  {
01912                   $newVal = '';
01913                   for ($a=0;$a<$c;$a++)   {
01914                      $char = substr($value,$a,1);
01915                      if (strstr($is_in,$char))  {
01916                         $newVal.=$char;
01917                      }
01918                   }
01919                   $value = $newVal;
01920                }
01921             break;
01922             case 'nospace':
01923                $value = str_replace(' ','',$value);
01924             break;
01925             case 'alpha':
01926                $value = ereg_replace('[^a-zA-Z]','',$value);
01927             break;
01928             case 'num':
01929                $value = ereg_replace('[^0-9]','',$value);
01930             break;
01931             case 'alphanum':
01932                $value = ereg_replace('[^a-zA-Z0-9]','',$value);
01933             break;
01934             case 'alphanum_x':
01935                $value = ereg_replace('[^a-zA-Z0-9_-]','',$value);
01936             break;
01937          }
01938       }
01939       if ($set)   {$res['value'] = $value;}
01940       return $res;
01941    }
01942 
01953    function checkValue_group_select_processDBdata($valueArray,$tcaFieldConf,$id,$status,$type)  {
01954       $tables = $type=='group'?$tcaFieldConf['allowed']:$tcaFieldConf['foreign_table'].','.$tcaFieldConf['neg_foreign_table'];
01955       $prep = $type=='group'?$tcaFieldConf['prepend_tname']:$tcaFieldConf['neg_foreign_table'];
01956 
01957       $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
01958       $dbAnalysis->registerNonTableValues=$tcaFieldConf['allowNonIdValues'] ? 1 : 0;
01959       $dbAnalysis->start(implode(',',$valueArray),$tables);
01960 
01961       if ($tcaFieldConf['MM'])   {
01962          if ($status=='update')  {
01963             $dbAnalysis->writeMM($tcaFieldConf['MM'],$id,$prep);
01964          } else {
01965             $this->dbAnalysisStore[] = array($dbAnalysis,$tcaFieldConf['MM'],$id,$prep);  // This will be traversed later to execute the actions
01966          }
01967          $cc=count($dbAnalysis->itemArray);
01968          $valueArray = array($cc);
01969       } else {
01970          $valueArray = $dbAnalysis->getValueArray($prep);
01971          if ($type=='select' && $prep) {
01972             $valueArray = $dbAnalysis->convertPosNeg($valueArray,$tcaFieldConf['foreign_table'],$tcaFieldConf['neg_foreign_table']);
01973          }
01974       }
01975 
01976          // Here we should se if 1) the records exist anymore, 2) which are new and check if the BE_USER has read-access to the new ones.
01977       return $valueArray;
01978    }
01979 
01986    function checkValue_group_select_explodeSelectGroupValue($value)  {
01987       $valueArray = t3lib_div::trimExplode(',',$value,1);
01988       reset($valueArray);
01989       while(list($key,$newVal)=each($valueArray))  {
01990          $temp=explode('|',$newVal,2);
01991          $valueArray[$key] = str_replace(',','',str_replace('|','',rawurldecode($temp[0])));
01992       }
01993       return $valueArray;
01994    }
01995 
02009    function checkValue_flex_procInData($dataPart,$dataPart_current,$uploadedFiles,$dataStructArray,$pParams,$callBackFunc='') {
02010 #debug(array($dataPart,$dataPart_current,$dataStructArray));
02011       if (is_array($dataPart))   {
02012          foreach($dataPart as $sKey => $sheetDef)  {
02013             list ($dataStruct,$actualSheet) = t3lib_div::resolveSheetDefInDS($dataStructArray,$sKey);
02014 #debug(array($dataStruct,$actualSheet,$sheetDef,$actualSheet,$sKey));
02015             if (is_array($dataStruct) && $actualSheet==$sKey && is_array($sheetDef))   {
02016                foreach($sheetDef as $lKey => $lData)  {
02017                   $this->checkValue_flex_procInData_travDS(
02018                      $dataPart[$sKey][$lKey],
02019                      $dataPart_current[$sKey][$lKey],
02020                      $uploadedFiles[$sKey][$lKey],
02021                      $dataStruct['ROOT']['el'],
02022                      $pParams,
02023                      $callBackFunc
02024                   );
02025                }
02026             }
02027          }
02028       }
02029 
02030       return $dataPart;
02031    }
02032 
02046    function checkValue_flex_procInData_travDS(&$dataValues,$dataValues_current,$uploadedFiles,$DSelements,$pParams,$callBackFunc='')   {
02047       if (is_array($DSelements)) {
02048 
02049             // For each DS element:
02050          foreach($DSelements as $key => $dsConf)   {
02051 
02052                   // Array/Section:
02053             if ($DSelements[$key]['type']=='array')   {
02054                if (is_array($dataValues[$key]['el'])) {
02055                   if ($DSelements[$key]['section'])   {
02056                      foreach($dataValues[$key]['el'] as $ik => $el)  {
02057                         $theKey = key($el);
02058                         if (is_array($dataValues[$key]['el'][$ik][$theKey]['el']))  {
02059                            $this->checkValue_flex_procInData_travDS(
02060                                  $dataValues[$key]['el'][$ik][$theKey]['el'],
02061                                  $dataValues_current[$key]['el'][$ik][$theKey]['el'],
02062                                  $uploadedFiles[$key]['el'][$ik][$theKey]['el'],
02063                                  $DSelements[$key]['el'][$theKey]['el'],
02064                                  $pParams,
02065                                  $callBackFunc
02066                               );
02067                         }
02068                      }
02069                   } else {
02070                      if (!isset($dataValues[$key]['el']))   $dataValues[$key]['el']=array();
02071                      $this->checkValue_flex_procInData_travDS(
02072                            $dataValues[$key]['el'],
02073                            $dataValues_current[$key]['el'],
02074                            $uploadedFiles[$key]['el'],
02075                            $DSelements[$key]['el'],
02076                            $pParams,
02077                            $callBackFunc
02078                         );
02079                   }
02080                }
02081             } else {
02082                if (is_array($dsConf['TCEforms']['config']) && is_array($dataValues[$key]))   {
02083                   foreach($dataValues[$key] as $vKey => $data) {
02084 
02085                      if ($callBackFunc)   {
02086                         $res = $this->$callBackFunc(
02087                                  $pParams,
02088                                  $dsConf['TCEforms']['config'],
02089                                  $dataValues[$key][$vKey],
02090                                  $dataValues_current[$key][$vKey],
02091                                  $uploadedFiles[$key][$vKey]
02092                               );
02093                      } else { // Default
02094                         list($CVtable,$CVid,$CVcurValue,$CVstatus,$CVrealPid,$CVrecFID,$CVtscPID) = $pParams;
02095 
02096                         $res = $this->checkValue_SW(
02097                                  array(),
02098                                  $dataValues[$key][$vKey],
02099                                  $dsConf['TCEforms']['config'],
02100                                  $CVtable,
02101                                  $CVid,
02102                                  $dataValues_current[$key][$vKey],
02103                                  $CVstatus,
02104                                  $CVrealPid,
02105                                  $CVrecFID,
02106                                  '',
02107                                  $uploadedFiles[$key][$vKey],
02108                                  array(),
02109                                  $CVtscPID
02110                               );
02111 
02112                            // Look for RTE transformation of field:
02113                         if ($dataValues[$key]['_TRANSFORM_'.$vKey] == 'RTE' && !$this->dontProcessTransformations)   {
02114 
02115                               // Unsetting trigger field - we absolutely don't want that into the data storage!
02116                            unset($dataValues[$key]['_TRANSFORM_'.$vKey]);
02117 
02118                            if (isset($res['value']))  {
02119 
02120                                  // Calculating/Retrieving some values here:
02121                               list(,,$recFieldName) = explode(':', $CVrecFID);
02122                               $theTypeString = t3lib_BEfunc::getTCAtypeValue($CVtable,$this->checkValue_currentRecord);
02123                               $specConf = t3lib_BEfunc::getSpecConfParts('',$dsConf['TCEforms']['defaultExtras']);
02124 
02125                                  // Find, thisConfig:
02126                               $RTEsetup = $this->BE_USER->getTSConfig('RTE',t3lib_BEfunc::getPagesTSconfig($CVtscPID));
02127                               $thisConfig = t3lib_BEfunc::RTEsetup($RTEsetup['properties'],$CVtable,$recFieldName,$theTypeString);
02128 
02129                                  // Get RTE object, draw form and set flag:
02130                               $RTEobj = &t3lib_BEfunc::RTEgetObj();
02131                               if (is_object($RTEobj)) {
02132                                  $res['value'] = $RTEobj->transformContent('db',$res['value'],$CVtable,$recFieldName,$this->checkValue_currentRecord,$specConf,$thisConfig,'',$CVrealPid);
02133                               } else {
02134                                  debug('NO RTE OBJECT FOUND!');
02135                               }
02136                            }
02137                         }
02138                      }
02139 
02140                         // Adding the value:
02141                      if (isset($res['value']))  {
02142                         $dataValues[$key][$vKey] = $res['value'];
02143                      }
02144                   }
02145                }
02146             }
02147          }
02148       }
02149    }
02150 
02151 
02152 
02153 
02154 
02155 
02156 
02157 
02158 
02159 
02160 
02161 
02162 
02163 
02164 
02165 
02166 
02167 
02168 
02169 
02170    /*********************************************
02171     *
02172     * Storing data to Database Layer
02173     *
02174     ********************************************/
02175 
02176 
02186    function updateDB($table,$id,$fieldArray) {
02187       global $TCA;
02188 
02189       if (is_array($fieldArray) && is_array($TCA[$table]) && intval($id))  {
02190          unset($fieldArray['uid']); // Do NOT update the UID field, ever!
02191 
02192          if (count($fieldArray)) {
02193 
02194                // Execute the UPDATE query:
02195             $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($id), $fieldArray);
02196 
02197                // If succees, do...:
02198             if (!$GLOBALS['TYPO3_DB']->sql_error())   {
02199                if ($this->checkStoredRecords)   {
02200                   $newRow = $this->checkStoredRecord($table,$id,$fieldArray,2);
02201                }
02202 
02203                   // Set log entry:
02204                $propArr = $this->getRecordPropertiesFromRow($table,$newRow);
02205                $theLogId = $this->log($table,$id,2,$recpid,0,"Record '%s' (%s) was updated.",10,array($propArr['header'],$table.':'.$id),$propArr['event_pid']);
02206 
02207                   // Set History data:
02208                $this->setHistory($table,$id,$theLogId);
02209 
02210                   // Clear cache for relavant pages:
02211                $this->clear_cache($table,$id);
02212 
02213                   // Unset the pageCache for the id if table was page.
02214                if ($table=='pages') unset($this->pageCache[$id]);
02215             } else {
02216                $this->log($table,$id,2,0,2,"SQL error: '%s' (%s)",12,array($GLOBALS['TYPO3_DB']->sql_error(),$table.':'.$id));
02217             }
02218          }
02219       }
02220    }
02221 
02232    function compareFieldArrayWithCurrentAndUnset($table,$id,$fieldArray)   {
02233 
02234          // Fetch the original record:
02235       $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, 'uid='.intval($id));
02236       $currentRecord = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
02237 
02238          // If the current record exists (which it should...), begin comparison:
02239       if (is_array($currentRecord)) {
02240 
02241             // Read all field types:
02242          $c = 0;
02243          $cRecTypes = array();
02244          foreach($currentRecord as $col => $val)   {
02245             $cRecTypes[$col] = $GLOBALS['TYPO3_DB']->sql_field_type($res,$c);
02246             $c++;
02247          }
02248 
02249             // Free result:
02250          $GLOBALS['TYPO3_DB']->sql_free_result($res);
02251 
02252             // Unset the fields which are similar:
02253          foreach($fieldArray as $col => $val)   {
02254             if (
02255                   #!isset($currentRecord[$col]) ||    // Unset fields which were NOT found in the current record! [Uncommented because NULL fields will not return an entry in the array!]
02256                   !strcmp($val,$currentRecord[$col]) ||  // Unset fields which matched exactly.
02257                   ($cRecTypes[$col]=='int' && $currentRecord[$col]==0 && !strcmp($val,''))   // Now, a situation where TYPO3 tries to put an empty string into an integer field, we should not strcmp the integer-zero and '', but rather accept them to be similar.
02258                )  {
02259                unset($fieldArray[$col]);
02260             } else {
02261                $this->historyRecords[$table.':'.$id]['oldRecord'][$col] = $currentRecord[$col];
02262                $this->historyRecords[$table.':'.$id]['newRecord'][$col] = $fieldArray[$col];
02263             }
02264          }
02265       } else { // If the current record does not exist this is an error anyways and we just return an empty array here.
02266          $fieldArray = array();
02267       }
02268 
02269       return $fieldArray;
02270    }
02271 
02282    function insertDB($table,$id,$fieldArray,$newVersion=FALSE) {
02283       global $TCA;
02284 
02285       if (is_array($fieldArray) && is_array($TCA[$table]) && isset($fieldArray['pid']))   {
02286          unset($fieldArray['uid']); // Do NOT insert the UID field, ever!
02287 
02288          if (count($fieldArray)) {
02289 
02290                // Execute the INSERT query:
02291             $GLOBALS['TYPO3_DB']->exec_INSERTquery($table, $fieldArray);
02292 
02293                // If succees, do...:
02294             if (!$GLOBALS['TYPO3_DB']->sql_error())   {
02295 
02296                   // Set mapping for NEW... -> real uid:
02297                $NEW_id = $id;    // the NEW_id now holds the 'NEW....' -id
02298                $id = $GLOBALS['TYPO3_DB']->sql_insert_id();
02299                $this->substNEWwithIDs[$NEW_id] = $id;
02300                $this->substNEWwithIDs_table[$NEW_id] = $table;
02301 
02302                   // Checking the record is properly saved and writing to log
02303                if ($this->checkStoredRecords)   {
02304                   $newRow = $this->checkStoredRecord($table,$id,$fieldArray,1);
02305                }
02306 
02307                if ($newVersion)  {
02308                   $this->log($table,$id,1,0,0,"New version created of table '%s', uid '%s'",10,array($table,$fieldArray['t3ver_oid']),$newRow['pid'],$NEW_id);
02309                } else {
02310                      // Set log entry:
02311                   if ($table=='pages') {
02312                      $thePositionID = $this->getInterfacePagePositionID($id);
02313                   } else {
02314                      $thePositionID = 0;
02315                   }
02316                   $propArr = $this->getRecordPropertiesFromRow($table,$newRow);
02317                   $page_propArr = $this->getRecordProperties('pages',$propArr['pid']);
02318                   $this->log($table,$id,1,$thePositionID,0,"Record '%s' (%s) was inserted on page '%s' (%s)",10,array($propArr['header'],$table.':'.$id,$page_propArr['header'],$newRow['pid']),$newRow['pid'],$NEW_id);
02319 
02320                      // Clear cache for relavant pages:
02321                   $this->clear_cache($table,$id);
02322                }
02323             } else {
02324                $this->log($table,$id,1,0,2,"SQL error: '%s' (%s)",12,array($GLOBALS['TYPO3_DB']->sql_error(),$table.':'.$id));
02325             }
02326          }
02327       }
02328    }
02329 
02340    function checkStoredRecord($table,$id,$fieldArray,$action)  {
02341       global $TCA;
02342 
02343       $id = intval($id);
02344       if (is_array($TCA[$table]) && $id)  {
02345          $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, 'uid='.intval($id));
02346          if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))  {
02347 
02348                // Traverse arrow of values that was inserted into the database and compare with the actually stored value:
02349             $errorString = array();
02350             foreach($fieldArray as $key => $value) {
02351                if ($this->checkStoredRecords_loose && !$value && !$row[$key]) {
02352                   // Nothing...
02353                } elseif (strcmp($value,$row[$key]))   {
02354                   $errorString[] = $key;
02355                }
02356             }
02357 
02358                // Set log message if there were fields with unmatching values:
02359             if (count($errorString))   {
02360                $this->log($table,$id,$action,0,102,'These fields are not properly updated in database: ('.implode(',',$errorString).') Probably value mismatch with fieldtype.');
02361             }
02362 
02363                // Return selected rows:
02364             return $row;
02365          }
02366          $GLOBALS['TYPO3_DB']->sql_free_result($res);
02367       }
02368    }
02369 
02375    function dbAnalysisStoreExec()   {
02376       reset($this->dbAnalysisStore);
02377       while(list($k,$v)=each($this->dbAnalysisStore)) {
02378          $id = $this->substNEWwithIDs[$v[2]];
02379          if ($id) {
02380             $v[2] = $id;
02381             $v[0]->writeMM($v[1],$v[2],$v[3]);
02382          }
02383       }
02384    }
02385 
02391    function removeRegisteredFiles() {
02392       reset($this->removeFilesStore);
02393       while(list($k,$v)=each($this->removeFilesStore))   {
02394          unlink($v);
02395 //       debug($v,1);
02396       }
02397    }
02398 
02408    function clear_cache($table,$uid) {
02409       global $TCA;
02410 
02411       $uid = intval($uid);
02412       if (is_array($TCA[$table]) && $uid > 0)   {
02413 
02414             // Get Page TSconfig relavant:
02415          list($tscPID) = t3lib_BEfunc::getTSCpid($table,$uid,'');
02416          $TSConfig = $this->getTCEMAIN_TSconfig($tscPID);
02417 
02418          if (!$TSConfig['clearCache_disable'])  {
02419                // If table is "pages":
02420             if (t3lib_extMgm::isLoaded('cms'))  {
02421                if ($table=='pages') {
02422 
02423                      // Builds list of pages on the SAME level as this page (siblings)
02424                   $res_tmp = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
02425                               'A.pid AS pid, B.uid AS uid',
02426                               'pages AS A, pages AS  B',
02427                               'A.uid='.intval($uid).' AND B.pid=A.pid AND B.deleted=0'
02428                            );
02429 
02430                   $list_cache = array();
02431                   $pid_tmp = 0;
02432                   while ($row_tmp = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res_tmp)) {
02433                      $list_cache[] = $row_tmp['uid'];
02434                      $pid_tmp = $row_tmp['pid'];
02435 
02436                         // Add children as well:
02437                      if ($TSConfig['clearCache_pageSiblingChildren'])   {
02438                         $res_tmp2 = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
02439                                     'uid',
02440                                     'pages',
02441                                     'pid='.intval($row_tmp['uid']).' AND deleted=0'
02442                                  );
02443                         while ($row_tmp2 = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res_tmp2)) {
02444                            $list_cache[] = $row_tmp2['uid'];
02445                         }
02446                      }
02447                   }
02448 
02449                      // Finally, add the parent page as well:
02450                   $list_cache[] = $pid_tmp;
02451 
02452                      // Add grand-parent as well:
02453                   if ($TSConfig['clearCache_pageGrandParent']) {
02454                      $res_tmp = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
02455                                  'pid',
02456                                  'pages',
02457                                  'uid='.intval($pid_tmp)
02458                               );
02459                      if ($row_tmp = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res_tmp))   {
02460                         $list_cache[] = $row_tmp['pid'];
02461                      }
02462                   }
02463 
02464                      // Delete cache for selected pages:
02465                   $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages','page_id IN ('.implode(',',$GLOBALS['TYPO3_DB']->cleanIntArray($list_cache)).')');
02466                   $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pagesection', 'page_id IN ('.implode(',',$GLOBALS['TYPO3_DB']->cleanIntArray($list_cache)).')');
02467                } else { // For other tables than "pages", delete cache for the records "parent page".
02468                   $uid_page = $this->getPID($table,$uid);
02469                   if ($uid_page>0)  {
02470                      $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages', 'page_id='.intval($uid_page));
02471                      $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pagesection', 'page_id='.intval($uid_page));
02472                   }
02473                }
02474             }
02475          }
02476 
02477             // Clear cache for pages entered in TSconfig:
02478          if ($TSConfig['clearCacheCmd'])  {
02479             $Commands = t3lib_div::trimExplode(',',strtolower($TSConfig['clearCacheCmd']),1);
02480             $Commands = array_unique($Commands);
02481             foreach($Commands as $cmdPart)   {
02482                $this->clear_cacheCmd($cmdPart);
02483             }
02484          }
02485 
02486             // Call post processing function for clear-cache:
02487          global $TYPO3_CONF_VARS;
02488          if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc']))  {
02489             $_params = array('table' => $table,'uid' => $uid,'uid_page' => $uid_page,'TSConfig' => $TSConfig);
02490             foreach($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc'] as $_funcRef) {
02491                t3lib_div::callUserFunction($_funcRef,$_params,$this);
02492             }
02493          }
02494       }
02495    }
02496 
02504    function getPID($table,$uid)  {
02505       $res_tmp = $GLOBALS['TYPO3_DB']->exec_SELECTquery('pid', $table, 'uid='.intval($uid));
02506       if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res_tmp)) {
02507          return $row['pid'];
02508       }
02509    }
02510 
02511 
02512 
02513 
02514 
02515 
02516 
02517 
02518 
02519 
02520 
02521 
02522 
02523 
02524 
02525 
02526 
02527 
02528 
02529 
02530 
02531 
02532 
02533 
02534 
02535    /*********************************************
02536     *
02537     * PROCESSING COMMANDS
02538     *
02539     ********************************************/
02540 
02547    function process_cmdmap() {
02548       global $TCA;
02549 
02550          // Traverse command map:
02551       reset ($this->cmdmap);
02552       while (list($table,) = each($this->cmdmap))  {
02553 
02554             // Check if the table may be modified!
02555          $modifyAccessList = $this->checkModifyAccessList($table);
02556          if (!$modifyAccessList) {
02557             $this->log($table,$id,2,0,1,"Attempt to modify table '%s' without permission",1,array($table));
02558          }
02559 
02560             // Check basic permissions and circumstances:
02561          if (isset($TCA[$table]) && !$this->tableReadOnly($table) && is_array($this->cmdmap[$table]) && $modifyAccessList) {
02562 
02563                // Traverse the command map:
02564             foreach($this->cmdmap[$table] as $id => $incomingCmdArray)  {
02565                if (is_array($incomingCmdArray)) {  // have found a command.
02566 
02567                      // Get command and value (notice, only one command is observed at a time!):
02568                   reset($incomingCmdArray);
02569                   $command = key($incomingCmdArray);
02570                   $value = current($incomingCmdArray);
02571 
02572                      // Init copyMapping array:
02573                   $this->copyMappingArray = Array();     // Must clear this array before call from here to those functions: Contains mapping information between new and old id numbers.
02574 
02575                      // Branch, based on command
02576                   switch ($command) {
02577                      case 'move':
02578                         $this->moveRecord($table,$id,$value);
02579                      break;
02580                      case 'copy':
02581                         if ($table == 'pages')  {
02582                            $this->copyPages($id,$value);
02583                         } else {
02584                            $this->copyRecord($table,$id,$value,1);
02585                         }
02586                      break;
02587                      case 'localize':
02588                         $this->copyRecord_localize($table,$id,$value);
02589                      break;
02590                      case 'version':
02591                         switch ((string)$value['action'])   {
02592                            case 'new':
02593                               $this->versionizeTree = t3lib_div::intInRange($value['treeLevels'],-1,4);  // Max 4 levels of versioning...
02594                               if ($table == 'pages' && $this->versionizeTree>=0) {
02595                                  $this->versionizePages($id,$value['label']);
02596                               } else {
02597                                  $this->versionizeRecord($table,$id,$value['label']);
02598                               }
02599                            break;
02600                            case 'swap':
02601                               $this->version_swap($table,$id,$value['swapWith'],$value['swapContent']);
02602                            break;
02603                         }
02604                      break;
02605                      case 'delete':
02606                         if ($table == 'pages')  {
02607                            $this->deletePages($id);
02608                         } else {
02609                            $this->deleteRecord($table,$id, 0);
02610                         }
02611                      break;
02612                   }
02613                      // Merging the copy-array info together for remapping purposes.
02614                   $this->copyMappingArray_merged= t3lib_div::array_merge_recursive_overrule($this->copyMappingArray_merged,$this->copyMappingArray);
02615                }
02616             }
02617          }
02618       }
02619 
02620 #debug($this->copyMappingArray_merged,'$this->copyMappingArray_merged');
02621 #debug($this->registerDBList,'$this->registerDBList');
02622 
02623          // Finally, before exit, check if there are ID references to remap. This might be the case if versioning or copying has taken place!
02624       $this->remapListedDBRecords();
02625    }
02626 
02635    function moveRecord($table,$uid,$destPid) {
02636       global $TCA;
02637 
02638          // Initialize:
02639       $sortRow = $TCA[$table]['ctrl']['sortby'];
02640       $destPid = intval($destPid);
02641       $origDestPid = $destPid;
02642 
02643       if ($TCA[$table]) {
02644          $propArr = $this->getRecordProperties($table,$uid);   // Get this before we change the pid (for logging)
02645          $resolvedPid = $this->resolvePid($table,$destPid); // This is the actual pid of the moving.
02646 
02647             // Finding out, if the record may be moved from where it is. If the record is a non-page, then it depends on edit-permissions.
02648             // If the record is a page, then there are two options: If the page is moved within itself, (same pid) it's edit-perms of the pid. If moved to another place then its both delete-perms of the pid and new-page perms on the destination.
02649          if ($table!='pages' || $resolvedPid==$propArr['pid']) {
02650             $mayMoveAccess = $this->checkRecordUpdateAccess($table,$uid);  // Edit rights for the record...
02651          } else {
02652             $mayMoveAccess = $this->doesRecordExist($table,$uid,'delete');
02653          }
02654 
02655             // Finding out, if the record may be moved TO another place. Here we check insert-rights (non-pages = edit, pages = new), unless the pages is moved on the same pid, then edit-rights are checked
02656          if ($table!='pages' || $resolvedPid!=$propArr['pid']) {
02657             $mayInsertAccess = $this->checkRecordInsertAccess($table,$resolvedPid,4);  // Edit rights for the record...
02658          } else {
02659             $mayInsertAccess = $this->checkRecordUpdateAccess($table,$uid);
02660          }
02661 
02662             // Checking if the pid is negativ, but no sorting row is defined. In that case, find the correct pid. Basically this check make the error message 4-13 meaning less... But you can always remove this check if you prefer the error instead of a no-good action (which is to move the record to its own page...)
02663          if ($destPid<0 && !$sortRow)  {
02664             $destPid = $resolvedPid;
02665          }
02666 
02667             // Timestamp field:
02668          $updateFields = array();
02669          if ($TCA[$table]['ctrl']['tstamp']) {
02670             $updateFields[$TCA[$table]['ctrl']['tstamp']] = time();
02671          }
02672 
02673             // If moving is allowed, begin the processing:
02674          if ($mayMoveAccess)  {
02675             if ($destPid>=0)  {  // insert as first element on page (where uid = $destPid)
02676                if ($mayInsertAccess)   {
02677                   if ($table!='pages' || $this->destNotInsideSelf ($destPid,$uid))  {
02678                      $this->clear_cache($table,$uid); // clear cache before moving
02679 
02680                      $updateFields['pid'] = $destPid; // Setting PID
02681 
02682                         // table is sorted by 'sortby'
02683                      if ($sortRow)  {
02684                         $sortNumber = $this->getSortNumber($table,$uid,$destPid);
02685                         $updateFields[$sortRow] = $sortNumber;
02686                      }
02687 
02688                         // Create query for update:
02689                      $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields);
02690 
02691                         // Logging...
02692                      $newPropArr = $this->getRecordProperties($table,$uid);
02693                      $oldpagePropArr = $this->getRecordProperties('pages',$propArr['pid']);
02694                      $newpagePropArr = $this->getRecordProperties('pages',$destPid);
02695 
02696                      if ($destPid!=$propArr['pid'])   {
02697                         $this->log($table,$uid,4,$destPid,0,"Moved record '%s' (%s) to page '%s' (%s)",2,array($propArr['header'],$table.':'.$uid, $newpagePropArr['header'], $newPropArr['pid']),$propArr['pid']);  // Logged to old page
02698                         $this->log($table,$uid,4,$destPid,0,"Moved record '%s' (%s) from page '%s' (%s)",3,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid); // Logged to new page
02699                      } else {
02700                         $this->log($table,$uid,4,$destPid,0,"Moved record '%s' (%s) on page '%s' (%s)",4,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid);   // Logged to new page
02701                      }
02702                      $this->clear_cache($table,$uid); // clear cache after moving
02703                      $this->fixUniqueInPid($table,$uid);
02704                         // fixCopyAfterDuplFields
02705                      if ($origDestPid<0)  {$this->fixCopyAfterDuplFields($table,$uid,abs($origDestPid),1);} // origDestPid is retrieve before it may possibly be converted to resolvePid if the table is not sorted anyway. In this way, copying records to after another records which are not sorted still lets you use this function in order to copy fields from the one before.
02706                   } else {
02707                      $destPropArr = $this->getRecordProperties('pages',$destPid);
02708                      $this->log($table,$uid,4,0,1,"Attempt to move page '%s' (%s) to inside of its own rootline (at page '%s' (%s))",10,array($propArr['header'],$uid, $destPropArr['header'], $destPid),$propArr['pid']);
02709                   }
02710                }
02711             } else { // Put after another record
02712                if ($sortRow)  {  // table is being sorted
02713                   $sortInfo = $this->getSortNumber($table,$uid,$destPid);
02714                   $destPid = $sortInfo['pid'];  // Setting the destPid to the new pid of the record.
02715                   if (is_array($sortInfo))   {  // If not an array, there was an error (which is already logged)
02716                      if ($mayInsertAccess)   {
02717                         if ($table!='pages' || $this->destNotInsideSelf($destPid,$uid))   {
02718                            $this->clear_cache($table,$uid); // clear cache before moving
02719 
02720                               // We now update the pid and sortnumber
02721                            $updateFields['pid'] = $destPid;
02722                            $updateFields[$sortRow] = $sortInfo['sortNumber'];
02723                            $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields);
02724 
02725                               // Logging...
02726                            if ($table=='pages') {
02727                               $thePositionID = $this->getInterfacePagePositionID($uid);
02728                            } else {
02729                               $thePositionID = 0;
02730                            }
02731                            $this->log($table,$uid,4,$thePositionID,0,'');
02732 
02733                               // Logging...
02734                            $newPropArr = $this->getRecordProperties($table,$uid);
02735                            $oldpagePropArr = $this->getRecordProperties('pages',$propArr['pid']);
02736                            if ($destPid!=$propArr['pid'])   {
02737                               $newpagePropArr = $this->getRecordProperties('pages',$destPid);
02738                               $this->log($table,$uid,4,$thePositionID,0,"Moved record '%s' (%s) to page '%s' (%s)",2,array($propArr['header'],$table.':'.$uid, $newpagePropArr['header'], $newPropArr['pid']),$propArr['pid']);  // Logged to old page
02739                               $this->log($table,$uid,4,$thePositionID,0,"Moved record '%s' (%s) from page '%s' (%s)",3,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid); // Logged to new page
02740                            } else {
02741                               $this->log($table,$uid,4,$thePositionID,0,"Moved record '%s' (%s) on page '%s' (%s)",4,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid);   // Logged to new page
02742                            }
02743 
02744                               // clear cache after moving
02745                            $this->clear_cache($table,$uid);
02746 
02747                               // fixUniqueInPid
02748                            $this->fixUniqueInPid($table,$uid);
02749 
02750                               // fixCopyAfterDuplFields
02751                            if ($origDestPid<0)  {$this->fixCopyAfterDuplFields($table,$uid,abs($origDestPid),1);}
02752                         } else {
02753                            $destPropArr = $this->getRecordProperties('pages',$destPid);
02754                            $this->log($table,$uid,4,0,1,"Attempt to move page '%s' (%s) to inside of its own rootline (at page '%s' (%s))",10,array($propArr['header'],$uid, $destPropArr['header'], $destPid),$propArr['pid']);
02755                         }
02756                      }
02757                   }
02758                } else {
02759                   $this->log($table,$uid,4,0,1,"Attempt to move record '%s' (%s) to after another record, although the table has no sorting row.",13,array($propArr['header'],$table.':'.$uid),$propArr['event_pid']);
02760                }
02761             }
02762          } else {
02763             $this->log($table,$uid,4,0,1,"Attempt to move record '%s' (%s) without having permissions to do so",14,array($propArr['header'],$table.':'.$uid),$propArr['event_pid']);
02764          }
02765       }
02766    }
02767 
02779    function copyRecord($table,$uid,$destPid,$first=0,$overrideValues=array(),$excludeFields='') {
02780       global $TCA;
02781 
02782       $uid = intval($uid);
02783       if ($TCA[$table] && $uid)  {
02784          t3lib_div::loadTCA($table);
02785          if ($this->doesRecordExist($table,$uid,'show')) {     // This checks if the record can be selected which is all that a copy action requires.
02786             $data = Array();
02787 
02788             $nonFields = array_unique(t3lib_div::trimExplode(',','uid,perms_userid,perms_groupid,perms_user,perms_group,perms_everybody,t3ver_oid,t3ver_id,t3ver_label,'.$excludeFields,1));
02789 
02790             $row = $this->recordInfo($table,$uid,'*');
02791             if (is_array($row))  {
02792 
02793                   // Initializing:
02794                $theNewID = uniqid('NEW');
02795                $enableField = isset($TCA[$table]['ctrl']['enablecolumns']) ? $TCA[$table]['ctrl']['enablecolumns']['disabled'] : '';
02796                $headerField = $TCA[$table]['ctrl']['label'];
02797 
02798                   // Getting default data:
02799                $defaultData = $this->newFieldArray($table);
02800 
02801                   // Getting "copy-after" fields if applicable:
02802                   // origDestPid is retrieve before it may possibly be converted to resolvePid if the table is not sorted anyway. In this way, copying records to after another records which are not sorted still lets you use this function in order to copy fields from the one before.
02803                $copyAfterFields = $destPid<0 ? $this->fixCopyAfterDuplFields($table,$uid,abs($destPid),0) : array();
02804 
02805                   // Page TSconfig related:
02806                $tscPID = t3lib_BEfunc::getTSconfig_pidValue($table,$uid,$destPid);  // NOT using t3lib_BEfunc::getTSCpid() because we need the real pid - not the id of a page, if the input is a page...
02807                $TSConfig = $this->getTCEMAIN_TSconfig($tscPID);
02808                $tE = $this->getTableEntries($table,$TSConfig);
02809 
02810                   // Traverse ALL fields of the selected record:
02811                foreach($row as $field => $value)   {
02812                   if (!in_array($field,$nonFields))   {
02813 
02814                         // Get TCA configuration for the field:
02815                      $conf = $TCA[$table]['columns'][$field]['config'];
02816 
02817                         // Preparation/Processing of the value:
02818                      if ($field=='pid')   {  // "pid" is hardcoded of course:
02819                         $value = $destPid;
02820                      } elseif (isset($overrideValues[$field])) {  // Override value...
02821                         $value = $overrideValues[$field];
02822                      } elseif (isset($copyAfterFields[$field]))   {  // Copy-after value if available:
02823                         $value = $copyAfterFields[$field];
02824                      } elseif ($TCA[$table]['ctrl']['setToDefaultOnCopy'] && t3lib_div::inList($TCA[$table]['ctrl']['setToDefaultOnCopy'],$field)) {  // Revert to default for some fields:
02825                         $value = $defaultData[$field];
02826                      } else {
02827                            // Hide at copy may override:
02828                         if ($first && $field==$enableField && $TCA[$table]['ctrl']['hideAtCopy'] && !$this->neverHideAtCopy && !$tE['disableHideAtCopy'])   {
02829                            $value=1;
02830                         }
02831                            // Prepend label on copy:
02832                         if ($first && $field==$headerField && $TCA[$table]['ctrl']['prependAtCopy'] && !$tE['disablePrependAtCopy'])   {
02833                            $value = $this->getCopyHeader($table,$this->resolvePid($table,$destPid),$field,$this->clearPrefixFromValue($table,$value),0);
02834                         }
02835                            // Processing based on the TCA config field type (files, references, flexforms...)
02836                         $value = $this->copyRecord_procBasedOnFieldType($table,$uid,$field,$value,$row,$conf);
02837                      }
02838 
02839                         // Add value to array.
02840                      $data[$table][$theNewID][$field] = $value;
02841                   }
02842 
02843                      // Overriding values:
02844                   if ($TCA[$table]['ctrl']['editlock'])  {
02845                      $data[$table][$theNewID][$TCA[$table]['ctrl']['editlock']] = 0;
02846                   }
02847                }
02848 
02849                   // Do the copy by simply submitting the array through TCEmain:
02850                $copyTCE = t3lib_div::makeInstance('t3lib_TCEmain');
02851                $copyTCE->stripslashes_values = 0;
02852                $copyTCE->copyTree = $this->copyTree;
02853                $copyTCE->cachedTSconfig = $this->cachedTSconfig;  // Copy forth the cached TSconfig
02854                $copyTCE->dontProcessTransformations=1;      // Transformations should NOT be carried out during copy
02855    //          $copyTCE->enableLogging = $table=='pages'?1:0;  // If enabled the list-view does not update...
02856 
02857                $copyTCE->start($data,'',$this->BE_USER);
02858                $copyTCE->process_datamap();
02859 
02860                   // Getting the new UID:
02861                $theNewSQLID = $copyTCE->substNEWwithIDs[$theNewID];
02862                if ($theNewSQLID) {
02863                   $this->copyMappingArray[$table][$uid] = $theNewSQLID;
02864                }
02865 
02866                   // Copy back the cached TSconfig
02867                $this->cachedTSconfig = $copyTCE->cachedTSconfig;
02868                unset($copyTCE);
02869             } else $this->log($table,$uid,3,0,1,'Attempt to copy record that did not exist!');
02870          } else $this->log($table,$uid,3,0,1,'Attempt to copy record without permission');
02871       }
02872    }
02873 
02888    function copyRecord_raw($table,$uid,$pid,$overrideArray=array())  {
02889       global $TCA;
02890 
02891       $uid = intval($uid);
02892       if ($TCA[$table] && $uid)  {
02893          t3lib_div::loadTCA($table);
02894          if ($this->doesRecordExist($table,$uid,'show')) {
02895 
02896                // Set up fields which should not be processed. They are still written - just passed through no-questions-asked!
02897             $nonFields = array('uid','pid','t3ver_id','t3ver_oid','t3ver_label','perms_userid','perms_groupid','perms_user','perms_group','perms_everybody');
02898 
02899                // Select main record:
02900             $row = $this->recordInfo($table,$uid,'*');
02901             if (is_array($row))  {
02902 
02903                   // Merge in override array.
02904                $row = array_merge($row,$overrideArray);
02905 
02906                   // Traverse ALL fields of the selected record:
02907                foreach($row as $field => $value)   {
02908                   if (!in_array($field,$nonFields))   {
02909 
02910                         // Get TCA configuration for the field:
02911                      $conf = $TCA[$table]['columns'][$field]['config'];
02912                      if (is_array($conf)) {
02913                            // Processing based on the TCA config field type (files, references, flexforms...)
02914                         $value = $this->copyRecord_procBasedOnFieldType($table,$uid,$field,$value,$row,$conf);
02915                      }
02916 
02917                         // Add value to array.
02918                      $row[$field] = $value;
02919                   }
02920                }
02921 
02922                   // Force versioning related fields:
02923                $row['pid'] = $pid;
02924 
02925                   // Do the copy by internal function
02926                $theNewSQLID = $this->insertNewCopyVersion($table,$row,$pid);
02927                if ($theNewSQLID) {
02928                   return $this->copyMappingArray[$table][$uid] = $theNewSQLID;
02929                }
02930             } else $this->log($table,$uid,3,0,1,'Attempt to rawcopy/versionize record that did not exist!');
02931          } else $this->log($table,$uid,3,0,1,'Attempt to rawcopy/versionize record without copy permission');
02932       }
02933    }
02934 
02944    function insertNewCopyVersion($table,$fieldArray,$realPid)  {
02945       global $TCA;
02946 
02947       $id = uniqid('NEW');
02948 
02949          // $fieldArray is set as current record.
02950          // 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...
02951       $this->checkValue_currentRecord = $fieldArray;
02952 
02953          // Traverse record and input-process each value:
02954       foreach($fieldArray as $field => $fieldValue)   {
02955          if (isset($TCA[$table]['columns'][$field]))  {
02956                // Evaluating the value.
02957             $res = $this->checkValue($table,$field,$fieldValue,$id,'new',$realPid,0);
02958             if (isset($res['value']))  {
02959                $fieldArray[$field] = $res['value'];
02960             }
02961          }
02962       }
02963 
02964          // System fields being set:
02965       if ($TCA[$table]['ctrl']['crdate']) {
02966          $fieldArray[$TCA[$table]['ctrl']['crdate']]=time();
02967       }
02968       if ($TCA[$table]['ctrl']['cruser_id']) {
02969          $fieldArray[$TCA[$table]['ctrl']['cruser_id']]=$this->userid;
02970       }
02971       if ($TCA[$table]['ctrl']['tstamp']) {
02972          $fieldArray[$TCA[$table]['ctrl']['tstamp']]=time();
02973       }
02974 
02975          // Finally, insert record:
02976       $this->insertDB($table,$id,$fieldArray, TRUE);
02977 
02978          // Return new id:
02979       return $this->substNEWwithIDs[$id];
02980    }
02981 
02995    function copyRecord_procBasedOnFieldType($table,$uid,$field,$value,$row,$conf)   {
02996       global $TCA;
02997 
02998          // Process references and files, currently that means only the files, prepending absolute paths (so the TCEmain engine will detect the file as new and one that should be made into a copy)
02999       $value = $this->copyRecord_procFilesRefs($conf, $uid, $value);
03000 
03001 
03002          // Register if there are references to take care of (no change to value):
03003       if ($this->isReferenceField($conf)) {
03004          $allowedTables = $conf['type']=='group' ? $conf['allowed'] : $conf['foreign_table'].','.$conf['neg_foreign_table'];
03005          $prependName = $conf['type']=='group' ? $conf['prepend_tname'] : $conf['neg_foreign_table'];
03006          if ($conf['MM'])  {
03007             $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
03008             $dbAnalysis->start('',$allowedTables,$conf['MM'],$uid);
03009             $value = implode(',',$dbAnalysis->getValueArray($prependName));
03010          }
03011          if ($value) {  // Setting the value in this array will notify the remapListedDBRecords() function that this field MAY need references to be corrected
03012             $this->registerDBList[$table][$uid][$field] = $value;
03013          }
03014       }
03015 
03016          // For "flex" fieldtypes we need to traverse the structure for two reasons: If there are file references they have to be prepended with absolute paths and if there are database reference they MIGHT need to be remapped (still done in remapListedDBRecords())
03017       if ($conf['type']=='flex') {
03018 
03019             // Get current value array:
03020          $dataStructArray = t3lib_BEfunc::getFlexFormDS($conf, $row, $table);
03021          $currentValueArray = t3lib_div::xml2array($value);
03022 
03023             // Traversing the XML structure, processing files:
03024          if (is_array($currentValueArray))   {
03025             $currentValueArray['data'] = $this->checkValue_flex_procInData(
03026                      $currentValueArray['data'],
03027                      array(), // Not used.
03028                      array(), // Not used.
03029                      $dataStructArray,
03030                      array($table,$uid,$field), // Parameters.
03031                      'copyRecord_flexFormCallBack'
03032                   );
03033             $value = $currentValueArray;  // Setting value as an array! -> which means the input will be processed according to the 'flex' type when the new copy is created.
03034          }
03035       }
03036 
03037       return $value;
03038    }
03039 
03048    function copyRecord_localize($table,$uid,$language)   {
03049       global $TCA;
03050 
03051       $uid = intval($uid);
03052 
03053       if ($TCA[$table] && $uid)  {
03054          t3lib_div::loadTCA($table);
03055 
03056          if ($TCA[$table]['ctrl']['languageField'] && $TCA[$table]['ctrl']['transOrigPointerField'])  {
03057             if ($langRec = t3lib_BEfunc::getRecord('sys_language',intval($language),'uid,title'))  {
03058                if ($this->doesRecordExist($table,$uid,'show')) {
03059 
03060                   $row = $this->recordInfo($table,$uid,'*');
03061                   if (is_array($row))  {
03062                      if ($row[$TCA[$table]['ctrl']['languageField']] <= 0) {
03063                         if ($row[$TCA[$table]['ctrl']['transOrigPointerField']] == 0)  {
03064                            if (!t3lib_BEfunc::getRecordsByField($table,$TCA[$table]['ctrl']['transOrigPointerField'],$uid,'AND pid='.intval($row['pid']).' AND '.$TCA[$table]['ctrl']['languageField'].'='.$langRec['uid']))  {
03065 
03066                                  // Initialize:
03067                               $overrideValues = array();
03068                               $excludeFields = array();
03069 
03070                                  // Set override values:
03071                               $overrideValues[$TCA[$table]['ctrl']['languageField']] = $langRec['uid'];
03072                               $overrideValues[$TCA[$table]['ctrl']['transOrigPointerField']] = $uid;
03073 
03074                                  // Set exclude Fields:
03075                               foreach($TCA[$table]['columns'] as $fN => $fCfg)   {
03076                                  if ($fCfg['l10n_mode']=='prefixLangTitle')   {  // Check if we are just prefixing:
03077                                     if ($fCfg['config']['type']=='text' || $fCfg['config']['type']=='input')   {
03078                                        $overrideValues[$fN] = '[Translate to '.$langRec['title'].':] '.$row[$fN];
03079                                     }
03080                                  } elseif (t3lib_div::inList('exclude,noCopy,mergeIfNotBlank',$fCfg['l10n_mode']) && $fN!=$TCA[$table]['ctrl']['languageField'] && $fN!=$TCA[$table]['ctrl']['transOrigPointerField']) {    // Otherwise, do not copy field (unless it is the language field or pointer to the original language)
03081                                     $excludeFields[] = $fN;
03082                                  }
03083                               }
03084                                  // Execute the copy:
03085                               $this->copyRecord($table,$uid,-$uid,1,$overrideValues,implode(',',$excludeFields));
03086                            } else $this->log($table,$uid,3,0,1,'Localization failed; There already was a localization for this language of the record!');
03087                         } else $this->log($table,$uid,3,0,1,'Localization failed; Source record contained a reference to an original default record (which is strange)!');
03088                      } else $this->log($table,$uid,3,0,1,'Localization failed; Source record had another language than "Default" or "All" defined!');
03089                   } else $this->log($table,$uid,3,0,1,'Attempt to localize record that did not exist!');
03090                } else $this->log($table,$uid,3,0,1,'Attempt to localize record without permission');
03091             } else $this->log($table,$uid,3,0,1,'Sys language UID "'.$language.'" not found valid!');
03092          } else $this->log($table,$uid,3,0,1,'Localization failed; "languageField" and "transOrigPointerField" must be defined for the table!');
03093       }
03094    }
03095 
03107    function copyRecord_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2) {
03108 
03109          // Extract parameters:
03110       list($table, $uid, $field) = $pParams;
03111 
03112          // Process references and files, currently that means only the files, prepending absolute paths:
03113       $dataValue = $this->copyRecord_procFilesRefs($dsConf, $uid, $dataValue);
03114 
03115          // If references are set for this field, set flag so they can be corrected later (in ->remapListedDBRecords())
03116       if ($this->isReferenceField($dsConf) && strlen($dataValue)) {
03117          $this->registerDBList[$table][$uid][$field] = 'FlexForm_reference';
03118       }
03119 
03120          // Return
03121       return array('value' => $dataValue);
03122    }
03123 
03135    function copyRecord_procFilesRefs($conf, $uid, $value)   {
03136 
03137          // Prepend absolute paths to files:
03138       if ($conf['type']=='group' && $conf['internal_type']=='file')  {
03139 
03140             // Get an array with files as values:
03141          if ($conf['MM'])  {
03142             $theFileValues = array();
03143 
03144             $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
03145             $dbAnalysis->start('', 'files', $conf['MM'], $uid);
03146 
03147             foreach($dbAnalysis->itemArray as $somekey => $someval)  {
03148                if ($someval['id'])  {
03149                   $theFileValues[] = $someval['id'];
03150                }
03151             }
03152          } else {
03153             $theFileValues = t3lib_div::trimExplode(',',$value,1);
03154          }
03155 
03156             // Traverse this array of files:
03157          $uploadFolder = $conf['uploadfolder'];
03158          $dest = $this->destPathFromUploadFolder($uploadFolder);
03159          $newValue = array();
03160 
03161          foreach($theFileValues as $file) {
03162             if (trim($file))  {
03163                $realFile = $dest.'/'.trim($file);
03164                if (@is_file($realFile))   {
03165                   $newValue[] = $realFile;
03166                }
03167             }
03168          }
03169 
03170             // Implode the new filelist into the new value (all files have absolute paths now which means they will get copied when entering TCEmain as new values...)
03171          $value = implode(',',$newValue);
03172       }
03173 
03174          // Return the new value:
03175       return $value;
03176    }
03177 
03186    function copyPages($uid,$destPid)   {
03187 
03188          // Initialize:
03189       $uid = intval($uid);
03190       $destPid = intval($destPid);
03191 
03192          // Finding list of tables to copy.
03193       $copyTablesArray = $this->admin ? $this->compileAdminTables() : explode(',',$this->BE_USER->groupData['tables_modify']);   // These are the tables, the user may modify
03194       if (!strstr($this->copyWhichTables,'*'))  {     // If not all tables are allowed then make a list of allowed tables: That is the tables that figure in both allowed tables AND the copyTable-list
03195          foreach($copyTablesArray as $k => $table) {
03196             if (!$table || !t3lib_div::inList($this->copyWhichTables.',pages',$table)) {  // pages are always going...
03197                unset($copyTablesArray[$k]);
03198             }
03199          }
03200       }
03201       $copyTablesArray = array_unique($copyTablesArray);
03202 
03203          // Begin to copy pages if we're allowed to:
03204       if ($this->admin || in_array('pages',$copyTablesArray))  {
03205 
03206             // Copy this page we're on. And set first-flag (this will trigger that the record is hidden if that is configured)!
03207          $this->copySpecificPage($uid,$destPid,$copyTablesArray,1);
03208          $theNewRootID = $this->copyMappingArray['pages'][$uid];     // This is the new ID of the rootpage of the copy-action. This ID is excluded when the list is gathered lateron
03209 
03210             // If we're going to copy recursively...:
03211          if ($theNewRootID && $this->copyTree)  {
03212 
03213                // Get ALL subpages to copy:
03214             $CPtable = $this->int_pageTreeInfo(Array(), $uid, intval($this->copyTree), $theNewRootID);
03215 
03216                // Now copying the subpages:
03217             foreach($CPtable as $thePageUid => $thePagePid) {
03218                $newPid = $this->copyMappingArray['pages'][$thePagePid];
03219                if (isset($newPid))  {
03220                   $this->copySpecificPage($thePageUid,$newPid,$copyTablesArray);
03221                } else {
03222                   $this->log('pages',$uid,5,0,1,'Something went wrong during copying branch');
03223                   break;
03224                }
03225             }
03226          }  // else the page was not copied. Too bad...
03227       } else {
03228          $this->log('pages',$uid,5,0,1,'Attempt to copy page without permission to this table');
03229       }
03230    }
03231 
03241    function copySpecificPage($uid,$destPid,$copyTablesArray,$first=0)   {
03242       global $TCA;
03243 
03244          // Copy the page itself:
03245       $this->copyRecord('pages',$uid,$destPid,$first);
03246       $theNewRootID = $this->copyMappingArray['pages'][$uid];  // The new uid
03247 
03248          // If a new page was created upon the copy operation we will proceed with all the tables ON that page:
03249       if ($theNewRootID)   {
03250          foreach($copyTablesArray as $table) {
03251             if ($table && is_array($TCA[$table]) && $table!='pages') {  // all records under the page is copied.
03252                $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, 'pid='.intval($uid).$this->deleteClause($table), '', ($TCA[$table]['ctrl']['sortby'] ? $TCA[$table]['ctrl']['sortby'].' DESC' : ''));
03253                while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) {
03254                   $this->copyRecord($table,$row['uid'], $theNewRootID); // Copying each of the underlying records...
03255                }
03256             }
03257          }
03258       }
03259    }
03260 
03271    function versionizeRecord($table,$id,$label) {
03272       global $TCA;
03273 
03274       $id = intval($id);
03275 
03276       if ($TCA[$table] && $TCA[$table]['ctrl']['versioning'] && $id>0)  {
03277          if ($this->doesRecordExist($table,$id,'show') && $this->doesRecordExist($table,$id,'edit'))  {
03278 
03279                // Select main record:
03280             $row = $this->recordInfo($table,$id,'pid,t3ver_id');
03281             if (is_array($row))  {
03282                if ($row['pid']>=0)  {
03283 
03284                      // Look for next version number:
03285                   $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
03286                      't3ver_id',
03287                      $table,
03288                      '(t3ver_oid='.$id.' || uid='.$id.')'.$this->deleteClause($table),
03289                      '',
03290                      't3ver_id DESC',
03291                      '1'
03292                   );
03293                   list($highestVerNumber) = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
03294 
03295                      // Look for version number of the current:
03296                   $subVer = $row['t3ver_id'].'.'.($highestVerNumber+1);
03297 
03298                      // Set up the values to override when making a raw-copy:
03299                   $overrideArray = array(
03300                      't3ver_id' => $highestVerNumber+1,
03301                      't3ver_oid' => $id,
03302                      't3ver_label' => ($label ? $label : $subVer.' / '.date('d-m-Y H:m:s'))
03303                   );
03304                   if ($TCA[$table]['ctrl']['editlock'])  {
03305                      $overrideArray[$TCA[$table]['ctrl']['editlock']] = 0;
03306                   }
03307 
03308                      // Create raw-copy and return result:
03309                   return $this->copyRecord_raw($table,$id,-1,$overrideArray);
03310                } else $this->log($table,$id,0,0,1,'Record you wanted to versionize was already a version in archive (pid=-1)!');
03311             } else $this->log($table,$id,0,0,1,'Record you wanted to versionize didnt exist!');
03312          } else $this->log($table,$id,0,0,1,'You didnt have correct permissions to make a new version (copy) of this record "'.$table.'" / '.$id);
03313       } else $this->log($table,$id,0,0,1,'Versioning is not supported for this table "'.$table.'" / '.$id);
03314    }
03315 
03324    function versionizePages($uid,$label)  {
03325       global $TCA;
03326 
03327       $uid = intval($uid);
03328 
03329          // Finding list of tables ALLOWED to be copied
03330       $allowedTablesArray = $this->admin ? $this->compileAdminTables() : explode(',',$this->BE_USER->groupData['tables_modify']);   // These are the tables, the user may modify
03331 
03332          // Make list of tables that should come along with a new version of the page:
03333       $verTablesArray = array();
03334       $allTables = array_keys($TCA);
03335       foreach($allTables as $tN) {
03336          if ($tN!='pages' && $TCA[$tN]['ctrl']['versioning_followPages'] && ($this->admin || in_array($tN, $allowedTablesArray)))   {
03337             $verTablesArray[] = $tN;
03338          }
03339       }
03340 
03341          // Begin to copy pages if we're allowed to:
03342       if ($this->admin || in_array('pages',$allowedTablesArray))  {
03343 
03344             // Versionize this page:
03345          $theNewRootID = $this->versionizeRecord('pages',$uid,$label);
03346          $this->rawCopyPageContent($uid,$theNewRootID,$verTablesArray);
03347 
03348             // If we're going to copy recursively...:
03349          if ($theNewRootID && $this->versionizeTree > 0) {
03350 
03351                // Get ALL subpages to copy:
03352             $CPtable = $this->int_pageTreeInfo(Array(), $uid, intval($this->versionizeTree), $theNewRootID);
03353 
03354                // Now copying the subpages:
03355             foreach($CPtable as $thePageUid => $thePagePid) {
03356                $newPid = $this->copyMappingArray['pages'][$thePagePid];
03357                if (isset($newPid))  {
03358                   $theNewRootID = $this->copyRecord_raw('pages',$thePageUid,$newPid);
03359                   $this->rawCopyPageContent($thePageUid,$theNewRootID,$verTablesArray);
03360                } else {
03361                   $this->log('pages',$uid,0,0,1,'Something went wrong during copying branch (for versioning)');
03362                   break;
03363                }
03364             }
03365          }  // else the page was not copied. Too bad...
03366       } else {
03367          $this->log('pages',$uid,0,0,1,'Attempt to versionize page without permission to this table');
03368       }
03369    }
03370 
03381    function rawCopyPageContent($old_pid,$new_pid,$copyTablesArray)   {
03382       global $TCA;
03383 
03384       if ($new_pid)  {
03385          foreach($copyTablesArray as $table) {
03386             if ($table && is_array($TCA[$table]) && $table!='pages') {  // all records under the page is copied.
03387                $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, 'pid='.intval($old_pid).$this->deleteClause($table));
03388                while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) {
03389                   $this->copyRecord_raw($table,$row['uid'],$new_pid);   // Copying each of the underlying records (method RAW)
03390                }
03391             }
03392          }
03393       }
03394    }
03395 
03406    function version_swap($table,$id,$swapWith,$swapContent) {
03407       global $TCA;
03408 
03409       /*
03410       Version ID swapping principles:
03411         - Version from archive (future/past, called "swap version") will get the uid of the "t3ver_oid", the official element with uid = "t3ver_oid" will get the new versions old uid. PIDs are swapped also
03412 
03413          uid      pid         uid      t3ver_oid   pid
03414       1: 13    123    -->  -13      247         123      (Original has negated UID, and sets t3ver_oid to the final UID (which is nice to know for recovery). PID is unchanged at this point)
03415       2: 247      -1  -->  13    13       123      (Swap version gets original UID, correct t3ver_oid (not required for online version) and is moved to the final PID (123))
03416       3: -13      123    -->  247      13       -1    (Original gets the swap versions old UID, has t3ver_oid set correctly (important) and the ver. repository PID set right.)
03417 
03418          13 is online UID,
03419          247 is specific versions UID
03420          123 is the PID of the original record
03421          -1 is the versioning repository PID
03422 
03423          Recovery Process:
03424             Search for negative UID (here "-13"):
03425                YES: Step 1 completed, but at least step 3 didn't.
03426                   Search for the negativ UIDs positive (here: "13")
03427                      YES: Step 2 completed: Rollback: "t3ver_oid" of the -uid record shows the original UID of the swap record. Use that to change back UID and pid to -1. After that, proceed with recovery for step 1 (see below)
03428                      NO: Only Step 1 completed! Rollback: Just change uid "-13" to "13" and "t3ver_oid" to "13" (not important)
03429                NO: No problems.
03430       */
03431 
03432          // First, check if we may actually edit this record:
03433       if ($this->checkRecordUpdateAccess($table,$id)) {
03434 
03435             // Find fields to select:
03436          $keepFields = array();  // Keep-fields can be used for other fields than "sortby" if needed in the future...
03437          $selectFields = array('uid','pid','t3ver_oid');
03438          if ($TCA[$table]['ctrl']['sortby']) {
03439             $selectFields[] = $keepFields[] = $TCA[$table]['ctrl']['sortby'];
03440          }
03441          $selectFields = array_unique($selectFields);
03442 
03443             // Select the two versions:
03444          $curVersion = t3lib_BEfunc::getRecord($table,$id,implode(',',$selectFields));
03445          $swapVersion = t3lib_BEfunc::getRecord($table,$swapWith,implode(',',$selectFields));
03446 
03447          if (is_array($curVersion) && is_array($swapVersion))  {
03448             if (!is_array(t3lib_BEfunc::getRecord($table,-$id,'uid')))  {
03449 
03450                   // Add "keepfields"
03451                $swapVerBaseArray = array();
03452                foreach($keepFields as $fN)   {
03453                   $swapVerBaseArray[$fN] = $curVersion[$fN];
03454                }
03455 #debug($swapVerBaseArray);
03456                   // Check if the swapWith record really IS a version of the original!
03457                if ($swapVersion['pid']==-1 && $swapVersion['t3ver_oid']==$id) {
03458 #debug($curVersion,'$curVersion');
03459 #debug($swapVersion,'$swapVersion');
03460                   $sqlErrors=array();
03461 
03462                      // Step 1:
03463                   $sArray = array();
03464                   $sArray['uid'] = -intval($id);
03465                   $sArray['t3ver_oid'] = intval($swapWith);
03466                   $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table,'uid='.intval($id),$sArray);
03467                   if ($GLOBALS['TYPO3_DB']->sql_error()) $sqlErrors[]=$GLOBALS['TYPO3_DB']->sql_error();
03468 
03469                      // Step 2:
03470                   $sArray = $swapVerBaseArray;
03471                   $sArray['uid'] = intval($id);
03472                   $sArray['t3ver_oid'] = intval($id);
03473                   $sArray['pid'] = intval($curVersion['pid']);
03474                   $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table,'uid='.intval($swapWith),$sArray);
03475                   if ($GLOBALS['TYPO3_DB']->sql_error()) $sqlErrors[]=$GLOBALS['TYPO3_DB']->sql_error();
03476 
03477                      // Step 3:
03478                   $sArray = array();
03479                   $sArray['uid'] = intval($swapWith);
03480                   $sArray['t3ver_oid'] = intval($id);
03481                   $sArray['pid'] = -1;
03482                   $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table,'uid=-'.intval($id),$sArray);
03483                   if ($GLOBALS['TYPO3_DB']->sql_error()) $sqlErrors[]=$GLOBALS['TYPO3_DB']->sql_error();
03484 
03485                   if (!count($sqlErrors)) {
03486                      $this->log($table,$id,0,0,0,'Swapping successful for table "'.$table.'" uid '.$id.'=>'.$swapWith);
03487 
03488                         // SWAPPING pids for subrecords:
03489                      if ($table=='pages' && $swapContent)   {
03490 
03491                         // Collect table names that should be copied along with the tables:
03492                         foreach($TCA as $tN => $tCfg) {
03493                            if ($TCA[$tN]['ctrl']['versioning_followPages'] || ($tN=='pages' && $swapContent==='ALL'))   {     // THIS produces the problem that some records might be left inside a versionized branch. Question is; Should ALL records swap pids, not only the versioning_followPages ones?
03494                               $temporaryPid = -($id+1000000);
03495 
03496                               $GLOBALS['TYPO3_DB']->exec_UPDATEquery($tN,'pid='.intval($id),array('pid'=>$temporaryPid));
03497                               if ($GLOBALS['TYPO3_DB']->sql_error()) $sqlErrors[]=$GLOBALS['TYPO3_DB']->sql_error();
03498 
03499                               $GLOBALS['TYPO3_DB']->exec_UPDATEquery($tN,'pid='.intval($swapWith),array('pid'=>$id));
03500                               if ($GLOBALS['TYPO3_DB']->sql_error()) $sqlErrors[]=$GLOBALS['TYPO3_DB']->sql_error();
03501 
03502                               $GLOBALS['TYPO3_DB']->exec_UPDATEquery($tN,'pid='.intval($temporaryPid),array('pid'=>$swapWith));
03503                               if ($GLOBALS['TYPO3_DB']->sql_error()) $sqlErrors[]=$GLOBALS['TYPO3_DB']->sql_error();
03504 
03505                               if (count($sqlErrors))  {
03506                                  $this->log($table,$id,0,0,1,'During Swapping: SQL errors happend: '.implode('; ',$sqlErrors));
03507                               }
03508                            }
03509                         }
03510                      }
03511                         // Clear cache:
03512                      $this->clear_cache($table,$id);
03513 
03514                   } else $this->log($table,$id,0,0,1,'During Swapping: SQL errors happend: '.implode('; ',$sqlErrors));
03515                } else $this->log($table,$id,0,0,1,'In swap version, either pid was not -1 or the t3ver_oid didn\'t match the id of the online version as it must!');
03516             } else $this->log($table,$id,0,0,1,'Error: A record with a negative UID existed - that indicates some inconsistency in the database from prior versioning actions!');
03517          } else $this->log($table,$id,0,0,1,'Error: Either online or swap version could not be selected!');
03518       } else $this->log($table,$id,0,0,1,'Error: You cannot swap versions for a record you do not have access to edit!');
03519    }
03520 
03530    function int_pageTreeInfo($CPtable,$pid,$counter, $rootID)  {
03531       if ($counter)  {
03532          $addW =  !$this->admin ? ' AND '.$this->BE_USER->getPagePermsClause($this->pMap['show']) : '';
03533          $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'pid='.intval($pid).$this->deleteClause('pages').$addW, '', 'sorting DESC');
03534          while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres))  {
03535             if ($row['uid']!=$rootID)  {
03536                $CPtable[$row['uid']] = $pid;
03537                if ($counter-1)   {  // If the uid is NOT the rootID of the copyaction and if we are supposed to walk further down
03538                   $CPtable = $this->int_pageTreeInfo($CPtable,$row['uid'],$counter-1, $rootID);
03539                }
03540             }
03541          }
03542       }
03543       return $CPtable;
03544    }
03545 
03551    function compileAdminTables() {
03552       global $TCA;
03553       reset ($TCA);
03554       $listArr = array();
03555       while (list($table)=each($TCA))  {
03556          $listArr[]=$table;
03557       }
03558       return $listArr;
03559    }
03560 
03568    function fixUniqueInPid($table,$uid)   {
03569       global $TCA;
03570       if ($TCA[$table]) {
03571          t3lib_div::loadTCA($table);
03572          reset ($TCA[$table]['columns']);
03573          $curData=$this->recordInfo($table,$uid,'*');
03574          $newData=array();
03575          while (list($field,$conf)=each($TCA[$table]['columns'])) {
03576             if ($conf['config']['type']=='input')  {
03577                $evalCodesArray = t3lib_div::trimExplode(',',$conf['config']['eval'],1);
03578                if (in_array('uniqueInPid',$evalCodesArray)) {
03579                   $newV = $this->getUnique($table,$field,$curData[$field],$uid,$curData['pid']);
03580                   if (strcmp($newV,$curData[$field])) {
03581                      $newData[$field]=$newV;
03582                   }
03583                }
03584             }
03585          }
03586             // IF there are changed fields, then update the database
03587          if (count($newData)) {
03588             $this->updateDB($table,$uid,$newData);
03589          }
03590       }
03591    }
03592 
03604    function fixCopyAfterDuplFields($table,$uid,$prevUid,$update, $newData=array())  {
03605       global $TCA;
03606       if ($TCA[$table] && $TCA[$table]['ctrl']['copyAfterDuplFields'])  {
03607          t3lib_div::loadTCA($table);
03608          $prevData=$this->recordInfo($table,$prevUid,'*');
03609          $theFields = t3lib_div::trimExplode(',',$TCA[$table]['ctrl']['copyAfterDuplFields'],1);
03610          reset($theFields);
03611          while(list(,$field)=each($theFields))  {
03612             if ($TCA[$table]['columns'][$field] && ($update || !isset($newData[$field]))) {
03613                $newData[$field]=$prevData[$field];
03614             }
03615          }
03616          if ($update && count($newData))  {
03617             $this->updateDB($table,$uid,$newData);
03618          }
03619       }
03620       return $newData;
03621    }
03622 
03629    function extFileFields ($table)  {
03630       global $TCA;
03631       $listArr=array();
03632       t3lib_div::loadTCA($table);
03633       if ($TCA[$table]['columns'])  {
03634          reset($TCA[$table]['columns']);
03635          while (list($field,$configArr)=each($TCA[$table]['columns']))  {
03636             if ($configArr['config']['type']=='group' && $configArr['config']['internal_type']=='file')  {
03637                $listArr[]=$field;
03638             }
03639          }
03640       }
03641       return $listArr;
03642    }
03643 
03655    function getCopyHeader($table,$pid,$field,$value,$count,$prevTitle='')  {
03656       global $TCA;
03657 
03658          // Set title value to check for:
03659       if ($count) {
03660          $checkTitle = $value.rtrim(' '.sprintf($this->prependLabel($table),$count));
03661       }  else {
03662          $checkTitle = $value;
03663       }
03664 
03665          // Do check:
03666       if ($prevTitle != $checkTitle || $count<100) {
03667          $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, 'pid='.intval($pid).' AND '.$field.'="'.$GLOBALS['TYPO3_DB']->quoteStr($checkTitle, $table).'"'.$this->deleteClause($table), '', '', '1');
03668          if ($GLOBALS['TYPO3_DB']->sql_num_rows($res))   {
03669             return $this->getCopyHeader($table,$pid,$field,$value,$count+1,$checkTitle);
03670          }
03671       }
03672 
03673          // Default is to just return the current input title if no other was returned before:
03674       return $checkTitle;
03675    }
03676 
03684    function prependLabel($table) {
03685       global $TCA;
03686       if (is_object($GLOBALS['LANG'])) {
03687          $label = $GLOBALS['LANG']->sL($TCA[$table]['ctrl']['prependAtCopy']);
03688       } else {
03689          list($label) = explode('|',$TCA[$table]['ctrl']['prependAtCopy']);
03690       }
03691       return $label;
03692    }
03693 
03701    function resolvePid($table,$pid) {
03702       global $TCA;
03703       $pid=intval($pid);
03704       if ($pid < 0)  {
03705          $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('pid', $table, 'uid='.abs($pid));
03706          $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
03707          $pid = intval($row['pid']);
03708       }
03709       return $pid;
03710    }
03711 
03719    function clearPrefixFromValue($table,$value) {
03720       global $TCA;
03721       $regex = sprintf(quotemeta($this->prependLabel($table)),'[0-9]*').'$';
03722       return @ereg_replace($regex,'',$value);
03723    }
03724 
03730    function remapListedDBRecords()  {
03731       global $TCA;
03732 #debug($this->registerDBList);
03733 #debug($this->copyMappingArray_merged);
03734       if (count($this->registerDBList))   {
03735          reset($this->registerDBList);
03736          while(list($table,$records)=each($this->registerDBList)) {
03737             t3lib_div::loadTCA($table);
03738             reset($records);
03739             while(list($uid,$fields)=each($records))  {
03740                $newData = array();
03741                $theUidToUpdate = $this->copyMappingArray_merged[$table][$uid];
03742 
03743                foreach($fields as $fieldName => $value)  {
03744                   $conf = $TCA[$table]['columns'][$fieldName]['config'];
03745 
03746                   switch($conf['type'])   {
03747                      case 'group':
03748                      case 'select':
03749                         $vArray = $this->remapListedDBRecords_procDBRefs($conf, $value, $theUidToUpdate);
03750                         if (is_array($vArray))  {
03751                            $newData[$fieldName] = implode(',',$vArray);
03752                         }
03753                      break;
03754                      case 'flex':
03755                         if ($value=='FlexForm_reference')   {
03756                            $origRecordRow = $this->recordInfo($table,$theUidToUpdate,'*');   // This will fetch the new row for the element
03757 
03758                            if (is_array($origRecordRow)) {
03759 
03760                                  // Get current data structure and value array:
03761                               $dataStructArray = t3lib_BEfunc::getFlexFormDS($conf, $origRecordRow, $table);
03762                               $currentValueArray = t3lib_div::xml2array($origRecordRow[$fieldName]);
03763 #debug($dataStructArray);
03764 #debug($currentValueArray);
03765 #debug($origRecordRow);
03766 #debug($currentValueArray['data']);
03767                                  // Do recursive processing of the XML data:
03768                               $currentValueArray['data'] = $this->checkValue_flex_procInData(
03769                                        $currentValueArray['data'],
03770                                        array(), // Not used.
03771                                        array(), // Not used.
03772                                        $dataStructArray,
03773                                        array($table,$theUidToUpdate,$fieldName), // Parameters.
03774                                        'remapListedDBRecords_flexFormCallBack'
03775                                     );
03776 #debug($currentValueArray['data']);
03777                                  // The return value should be compiled back into XML, ready to insert directly in the field (as we call updateDB() directly later):
03778                               if (is_array($currentValueArray['data'])) {
03779                                  $newData[$fieldName] =
03780                                     '<?xml version="1.0" encoding="'.$GLOBALS['LANG']->charSet.'" standalone="yes" ?>'.chr(10).
03781                                     $this->checkValue_flexArray2Xml($currentValueArray);
03782                               }
03783                            }
03784                         }
03785                      break;
03786                      default:
03787                         debug('Field type should not appear here: '. $conf['type']);
03788                      break;
03789                   }
03790                }
03791 
03792                if (count($newData)) {  // If any fields were changed, those fields are updated!
03793                   $this->updateDB($table,$theUidToUpdate,$newData);
03794 #debug($this->recordInfo($table,$theUidToUpdate,'*'),'Stored result:');
03795    //             debug($newData);
03796                }
03797             }
03798          }
03799       }
03800    }
03801 
03813    function remapListedDBRecords_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2)   {
03814 
03815          // Extract parameters:
03816       list($table,$uid,$field)   = $pParams;
03817 
03818          // If references are set for this field, set flag so they can be corrected later:
03819       if ($this->isReferenceField($dsConf) && strlen($dataValue)) {
03820          $vArray = $this->remapListedDBRecords_procDBRefs($dsConf, $dataValue, $uid);
03821          if (is_array($vArray))  {
03822             $dataValue = implode(',',$vArray);
03823          }
03824       }
03825 
03826          // Return
03827       return array('value' => $dataValue);
03828    }
03829 
03839    function remapListedDBRecords_procDBRefs($conf, $value, $MM_localUid)   {
03840 
03841          // Initialize variables
03842       $set = FALSE;  // Will be set true if an upgrade should be done...
03843       $allowedTables = $conf['type']=='group' ? $conf['allowed'] : $conf['foreign_table'].','.$conf['neg_foreign_table'];     // Allowed tables for references.
03844       $prependName = $conf['type']=='group' ? $conf['prepend_tname'] : ''; // Table name to prepend the UID
03845       $dontRemapTables = t3lib_div::trimExplode(',',$conf['dontRemapTablesOnCopy'],1); // Which tables that should possibly not be remapped
03846 
03847          // Convert value to list of references:
03848       $dbAnalysis = t3lib_div::makeInstance('t3lib_loadDBGroup');
03849       $dbAnalysis->registerNonTableValues = ($conf['type']=='select' && $conf['allowNonIdValues']) ? 1 : 0;
03850       $dbAnalysis->start($value, $allowedTables, $conf['MM'], $MM_localUid);
03851 
03852          // Traverse those references and map IDs:
03853       foreach($dbAnalysis->itemArray as $k => $v)  {
03854          $mapID = $this->copyMappingArray_merged[$v['table']][$v['id']];
03855          if ($mapID && !in_array($v['table'],$dontRemapTables))   {
03856             $dbAnalysis->itemArray[$k]['id'] = $mapID;
03857             $set = TRUE;
03858          }
03859       }
03860 
03861          // If a change has been done, set the new value(s)
03862       if ($set)   {
03863          if ($conf['MM'])  {
03864             $dbAnalysis->writeMM($conf['MM'], $theUidToUpdate, $prependName);
03865          } else {
03866             $vArray = $dbAnalysis->getValueArray($prependName);
03867             if ($conf['type']=='select')  {
03868                $vArray = $dbAnalysis->convertPosNeg($vArray, $conf['foreign_table'], $conf['neg_foreign_table']);
03869             }
03870             return $vArray;
03871          }
03872       }
03873    }
03874 
03884    function extFileFunctions($table,$field,$filelist,$func) {
03885       global $TCA;
03886       t3lib_div::loadTCA($table);
03887       $uploadFolder = $TCA[$table]['columns'][$field]['config']['uploadfolder'];
03888       if ($uploadFolder && trim($filelist))  {
03889          $uploadPath = $this->destPathFromUploadFolder($uploadFolder);
03890          $fileArray = explode(',',$filelist);
03891          while (list(,$theFile)=each($fileArray))  {
03892             $theFile=trim($theFile);
03893             if ($theFile)  {
03894                switch($func)  {
03895                   case 'deleteAll':
03896                      if (@is_file($uploadPath.'/'.$theFile))   {
03897                         unlink ($uploadPath.'/'.$theFile);
03898                      } else {
03899                         $this->log($table,0,3,0,100,"Delete: Referenced file that was supposed to be deleted together with it's record didn't exist");
03900                      }
03901                   break;
03902                }
03903             }
03904          }
03905       }
03906    }
03907 
03916    function deleteRecord($table,$uid, $noRecordCheck) {
03917          // This function may not be used to delete pages-records unless the underlying records are already deleted
03918          // If $noRecordCheck is set, then the function does not check permissions
03919       global $TCA;
03920       $uid = intval($uid);
03921       if ($TCA[$table] && $uid)  {
03922          $deleteRow = $TCA[$table]['ctrl']['delete'];
03923          if ($noRecordCheck || $this->doesRecordExist($table,$uid,'delete'))  {
03924             if ($deleteRow)   {
03925                $updateFields = array(
03926                   $deleteRow => 1
03927                );
03928 
03929                   // If the table is sorted, then the sorting number is set very high
03930                if ($TCA[$table]['ctrl']['sortby']) {
03931                   $updateFields[$TCA[$table]['ctrl']['sortby']] = 1000000000;
03932                }
03933 
03934                $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields);
03935             } else {
03936 
03937                   // Fetches all fields that holds references to files
03938                $fileFieldArr = $this->extFileFields($table);
03939                if (count($fileFieldArr))  {
03940                   $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(implode(',',$fileFieldArr), $table, 'uid='.intval($uid));
03941                   if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) {
03942                      $fArray = $fileFieldArr;
03943 
03944                      foreach($fArray as $theField) {  // MISSING: Support for MM file relations!
03945                         $this->extFileFunctions($table,$theField,$row[$theField],'deleteAll');     // This deletes files that belonged to this record.
03946                      }
03947                   } else {
03948                      $this->log($table,$uid,3,0,100,'Delete: Zero rows in result when trying to read filenames from record which should be deleted');
03949                   }
03950                }
03951 
03952                $GLOBALS['TYPO3_DB']->exec_DELETEquery($table, 'uid='.intval($uid));
03953             }
03954 
03955             if (!$GLOBALS['TYPO3_DB']->sql_error())   {
03956                $this->log($table,$uid,3,0,0,'');
03957             } else {
03958                $this->log($table,$uid,3,0,100,$GLOBALS['TYPO3_DB']->sql_error());
03959             }
03960 
03961             $this->clear_cache($table,$uid); // clear cache
03962          } else {
03963             $this->log($table,$uid,3,0,1,'Attempt to delete record without delete-permissions');
03964          }
03965       }
03966    }
03967 
03974    function deletePages($uid) {
03975       if ($this->doesRecordExist('pages',$uid,'delete')) {  // If we may at all delete this page
03976          if ($this->deleteTree)  {
03977             $brExist = $this->doesBranchExist('',$uid,$this->pMap['delete'],1);  // returns the branch
03978             if ($brExist != -1)  {  // Checks if we had permissions
03979                if ($this->noRecordsFromUnallowedTables($brExist.$uid))  {
03980                   $uidArray = explode(',',$brExist);
03981                   while (list(,$listUid)=each($uidArray))   {
03982                      if (trim($listUid))  {
03983                         $this->deleteSpecificPage($listUid);
03984                      }
03985                   }
03986                   $this->deleteSpecificPage($uid);
03987                } else {
03988                   $this->log('pages',$uid,3,0,1,'Attempt to delete records from disallowed tables');
03989                }
03990             } else {
03991                $this->log('pages',$uid,3,0,1,'Attempt to delete pages in branch without permissions');
03992             }
03993          } else {
03994             $brExist = $this->doesBranchExist('',$uid,$this->pMap['delete'],1);  // returns the branch
03995             if ($brExist == '')  {  // Checks if branch exists
03996                if ($this->noRecordsFromUnallowedTables($uid))  {
03997                   $this->deleteSpecificPage($uid);
03998                } else {
03999                   $this->log('pages',$uid,3,0,1,'Attempt to delete records from disallowed tables');
04000                }
04001             } else {
04002                $this->log('pages',$uid,3,0,1,'Attempt to delete page which has subpages');
04003             }
04004          }
04005       } else {
04006          $this->log('pages',$uid,3,0,1,'Attempt to delete page without permissions');
04007       }
04008    }
04009 
04016    function deleteSpecificPage($uid)   {
04017       // internal function !!
04018       global $TCA;
04019       reset ($TCA);
04020       $uid = intval($uid);
04021       if ($uid)   {
04022          while (list($table)=each($TCA))  {
04023             if ($table!='pages') {
04024                $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, 'pid='.intval($uid).$this->deleteClause($table));
04025                while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres)) {
04026                   $this->deleteRecord($table,$row['uid'], 1);
04027                }
04028             }
04029          }
04030          $this->deleteRecord('pages',$uid, 1);
04031       }
04032    }
04033 
04040    function noRecordsFromUnallowedTables($inList)  {
04041       // used by the deleteFunctions to check if there are records from disallowed tables under the pages to be deleted. Return true, if permission granted
04042       global $TCA;
04043       reset ($TCA);
04044       $inList = trim($this->rmComma(trim($inList)));
04045       if ($inList && !$this->admin) {
04046          while (list($table) = each($TCA))   {
04047             $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $table, 'pid IN ('.$inList.')');
04048             $count = $GLOBALS['TYPO3_DB']->sql_fetch_row($mres);
04049             if ($count[0] && ($this->tableReadOnly($table) || !$this->checkModifyAccessList($table))) {
04050                return false;
04051             }
04052          }
04053       }
04054       return true;
04055    }
04056 
04057 
04058 
04059 
04060 
04061 
04062 
04063 
04064 
04065 
04066 
04067 
04068 
04069 
04070 
04071 
04072 
04073 
04074 
04075 
04076 
04077 
04078 
04079 
04080 
04081 
04082    /*********************************************
04083     *
04084     * MISC FUNCTIONS
04085     *
04086     ********************************************/
04087 
04102    function getSortNumber($table,$uid,$pid)  {
04103       global $TCA;
04104       if ($TCA[$table] && $TCA[$table]['ctrl']['sortby'])   {
04105          $sortRow = $TCA[$table]['ctrl']['sortby'];
04106          if ($pid>=0)   {  // Sorting number is in the top
04107             $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($sortRow.',pid,uid', $table, 'pid='.intval($pid).$this->deleteClause($table), '', $sortRow.' ASC', '1');      // Fetches the first record under this pid
04108             if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))  {  // There was a page
04109                if ($row['uid']==$uid)  {  // The top record was the record it self, so we return its current sortnumber
04110                   return $row[$sortRow];
04111                }
04112                if ($row[$sortRow] < 1) {  // If the pages sortingnumber < 1 we must resort the records under this pid
04113                   $this->resorting($table,$pid,$sortRow,0);
04114                   return $this->sortIntervals;
04115                } else {
04116                   return floor($row[$sortRow]/2);
04117                }
04118             } else { // No pages, so we choose the default value as sorting-number
04119                return $this->sortIntervals;
04120             }
04121          } else { // Sorting number is inside the list
04122             $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($sortRow.',pid,uid', $table, 'uid='.abs($pid).$this->deleteClause($table));     // Fetches the record which is supposed to be the prev record
04123             if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))  {  // There was a record
04124                if ($row['uid']==$uid)  {  // If the record happends to be it self
04125                   $sortNumber = $row[$sortRow];
04126                } else {
04127                   $subres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
04128                               $sortRow.',pid,uid',
04129                               $table,
04130                               'pid='.intval($row['pid']).' AND '.$sortRow.'>='.intval($row[$sortRow]).$this->deleteClause($table),
04131                               '',
04132                               $sortRow.' ASC',
04133                               '2'
04134                            );    // Fetches the next record in order to calculate the in between sortNumber
04135                   if ($GLOBALS['TYPO3_DB']->sql_num_rows($subres)==2)   {  // There was a record afterwards
04136                      $GLOBALS['TYPO3_DB']->sql_fetch_assoc($subres);          // Forward to the second result...
04137                      $subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($subres);   // There was a record afterwards
04138                      $sortNumber = $row[$sortRow]+ floor(($subrow[$sortRow]-$row[$sortRow])/2); // The sortNumber is found in between these values
04139                      if ($sortNumber<=$row[$sortRow] || $sortNumber>=$subrow[$sortRow])   {  // The sortNumber happend NOT to be between the two surrounding numbers, so we'll have to resort the list
04140                         $sortNumber = $this->resorting($table,$row['pid'],$sortRow,  $row['uid']); // By this special param, resorting reserves and returns the sortnumber after the uid
04141                      }
04142                   } else { // If after the last record in the list, we just add the sortInterval to the last sortvalue
04143                      $sortNumber = $row[$sortRow]+$this->sortIntervals;
04144                   }
04145                }
04146                return Array('pid' => $row['pid'], 'sortNumber' => $sortNumber);
04147             } else {
04148                $propArr = $this->getRecordProperties($table,$uid);
04149                $this->log($table,$uid,4,0,1,"Attempt to move record '%s' (%s) to after a non-existing record (uid=%s)",1,array($propArr['header'],$table.':'.$uid,abs($pid)),$propArr['pid']);  // OK, dont insert $propArr['event_pid'] here...
04150                return false;  // There MUST be a page or else this cannot work
04151             }
04152          }
04153       }
04154    }
04155 
04167    function resorting($table,$pid,$sortRow, $return_SortNumber_After_This_Uid) {
04168       global $TCA;
04169       if ($TCA[$table] && $sortRow && $TCA[$table]['ctrl']['sortby']==$sortRow)  {
04170          $returnVal = 0;
04171          $intervals = $this->sortIntervals;
04172          $i = $intervals*2;
04173 
04174          $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, 'pid='.intval($pid).$this->deleteClause($table), '', $sortRow.' ASC');
04175          while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
04176             $uid=intval($row['uid']);
04177             if ($uid)   {
04178                $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), array($sortRow=>$i));
04179                if ($uid==$return_SortNumber_After_This_Uid) {     // This is used to return a sortingValue if the list is resorted because of inserting records inside the list and not in the top
04180                   $i = $i+$intervals;
04181                   $returnVal=$i;
04182                }
04183             } else {die ('Fatal ERROR!! No Uid at resorting.');}
04184             $i = $i+$intervals;
04185          }
04186          return $returnVal;
04187       }
04188    }
04189 
04196    function rmComma ($input)  {
04197       return ereg_replace(',$','',$input);
04198    }
04199 
04206    function convNumEntityToByteValue($input) {
04207       $token = md5(microtime());
04208       $parts = explode($token,ereg_replace('(&#([0-9]+);)',$token.'\2'.$token,$input));
04209 
04210       foreach($parts as $k => $v)   {
04211          if ($k%2)   {
04212             $v = intval($v);
04213             if ($v > 32)   {  // Just to make sure that control bytes are not converted.
04214                $parts[$k] =chr(intval($v));
04215             }
04216          }
04217       }
04218 
04219       return implode('',$parts);
04220    }
04221 
04228    function destPathFromUploadFolder ($folder)  {
04229       return PATH_site.$folder;
04230    }
04231 
04239    function destNotInsideSelf ($dest,$id) {
04240       $loopCheck = 100;
04241       $dest = intval($dest);
04242       $id = intval($id);
04243       if ($dest==$id)   {
04244          return false;
04245       }
04246       while ($dest!=0 && $loopCheck>0) {
04247          $loopCheck--;
04248          $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('pid, uid', 'pages', 'uid='.intval($dest).$this->deleteClause('pages'));
04249          if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))  {
04250             if ($row['pid']==$id)   {
04251                return false;
04252             }
04253          } else {
04254             return false;
04255          }
04256       }
04257       return true;
04258    }
04259 
04265    function getExcludeListArray()   {
04266       global $TCA;
04267       $list = array();
04268       reset($TCA);
04269       while (list($table)=each($TCA))  {
04270          t3lib_div::loadTCA($table);
04271          while (list($field,$config)=each($TCA[$table]['columns']))  {
04272             if ($config['exclude'] && !t3lib_div::inList($this->BE_USER->groupData['non_exclude_fields'],$table.':'.$field))  {
04273                $list[]=$table.'-'.$field;
04274             }
04275          }
04276       }
04277       return $list;
04278    }
04279 
04289    function doesPageHaveUnallowedTables($page_uid,$doktype) {
04290       global $TCA, $PAGES_TYPES;
04291       $page_uid = intval($page_uid);
04292       if (!$page_uid)   {
04293          return FALSE;  // Not a number. Probably a new page
04294       }
04295 
04296       $allowedTableList = isset($PAGES_TYPES[$doktype]['allowedTables']) ? $PAGES_TYPES[$doktype]['allowedTables'] : $PAGES_TYPES['default']['allowedTables'];
04297       $allowedArray = t3lib_div::trimExplode(',',$allowedTableList,1);
04298       if (strstr($allowedTableList,'*'))  {  // If all tables is OK the return true
04299          return FALSE;  // OK...
04300       }
04301 
04302       reset ($TCA);
04303       $tableList = array();
04304       while (list($table)=each($TCA))  {
04305          if (!in_array($table,$allowedArray))   {  // If the table is not in the allowed list, check if there are records...
04306             $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $table, 'pid='.intval($page_uid));
04307             $count = $GLOBALS['TYPO3_DB']->sql_fetch_row($mres);
04308             if ($count[0]) {
04309                $tableList[]=$table;
04310             }
04311          }
04312       }
04313       return implode(',',$tableList);
04314    }
04315 
04322    function deleteClause($table) {
04323          // Returns the proper delete-clause if any for a table from TCA
04324       global $TCA;
04325       if ($TCA[$table]['ctrl']['delete']) {
04326          return ' AND NOT '.$table.'.'.$TCA[$table]['ctrl']['delete'];
04327       } else {
04328          return '';
04329       }
04330    }
04331 
04338    function tableReadOnly($table)   {
04339          // returns true if table is readonly
04340       global $TCA;
04341       return ($TCA[$table]['ctrl']['readOnly'] ? 1 : 0);
04342    }
04343 
04350    function tableAdminOnly($table)  {
04351          // returns true if table is admin-only
04352       global $TCA;
04353       return ($TCA[$table]['ctrl']['adminOnly'] ? 1 : 0);
04354    }
04355 
04364    function getInterfacePagePositionID($uid) {
04365       global $TCA;
04366       $perms_clause = $this->BE_USER->getPagePermsClause(1);
04367       $deleted = $TCA['pages']['ctrl']['delete'] ? 'AND NOT A.'.$TCA['pages']['ctrl']['delete'].' AND NOT pages.'.$TCA['pages']['ctrl']['delete'].' ' : '';
04368 
04369          // This fetches a list of 1 or 2 pages, where - if 2 - the 2nd is the page BEFORE this ($uid). If 1 then the page ($uid) is at the top itself
04370       $subres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
04371                'pages.uid, pages.pid',
04372                'pages AS A, pages',
04373                'A.pid=pages.pid AND A.uid="'.$uid.'"
04374                   '.$deleted.'
04375                   AND pages.sorting<=A.sorting
04376                   AND '.$perms_clause,
04377                '',
04378                'pages.sorting DESC',
04379                '2'
04380             );
04381       if ($GLOBALS['TYPO3_DB']->sql_num_rows($subres)==2)   {  // There was a record before
04382          $GLOBALS['TYPO3_DB']->sql_fetch_assoc($subres);    // forwards to the second result
04383          $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($subres);
04384          return -$row['uid'];
04385       } else {
04386          $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($subres);
04387          return $row['pid'];
04388       }
04389    }
04390 
04397    function isReferenceField($conf) {
04398       return ($conf['type']=='group' && $conf['internal_type']=='db') ||   ($conf['type']=='select' && $conf['foreign_table']);
04399    }
04400 
04407    function getTCEMAIN_TSconfig($tscPID)  {
04408       if (!isset($this->cachedTSconfig[$tscPID]))  {
04409          $this->cachedTSconfig[$tscPID] = $this->BE_USER->getTSConfig('TCEMAIN',t3lib_BEfunc::getPagesTSconfig($tscPID));
04410       }
04411       return $this->cachedTSconfig[$tscPID]['properties'];
04412    }
04413 
04421    function getTableEntries($table,$TSconfig)   {
04422       $tA = is_array($TSconfig['table.'][$table.'.']) ? $TSconfig['table.'][$table.'.'] : array();;
04423       $dA = is_array($TSconfig['default.']) ? $TSconfig['default.'] : array();
04424       return t3lib_div::array_merge_recursive_overrule($dA,$tA);
04425    }
04426 
04435    function setHistory($table,$id,$logId)    {
04436       if (isset($this->historyRecords[$table.':'.$id]))  {
04437 
04438          list($tscPID) = t3lib_BEfunc::getTSCpid($table,$id,'');
04439          $TSConfig = $this->getTCEMAIN_TSconfig($tscPID);
04440 
04441          $tE = $this->getTableEntries($table,$TSConfig);
04442          $keepEntries = strcmp($tE['history.']['keepEntries'],'') ? t3lib_div::intInRange($tE['history.']['keepEntries'],0,200) : 10;
04443          $maxAgeSeconds = 60*60*24*(strcmp($tE['history.']['maxAgeDays'],'') ? t3lib_div::intInRange($tE['history.']['maxAgeDays'],0,200) : 7); // one week
04444          $this->clearHistory($table,$id,t3lib_div::intInRange($keepEntries-1,0),$maxAgeSeconds);
04445 
04446          if ($keepEntries) {
04447             $fields_values = array();
04448             $fields_values['history_data'] = serialize($this->historyRecords[$table.':'.$id]);
04449             $fields_values['fieldlist'] = implode(',',array_keys($this->historyRecords[$table.':'.$id]['newRecord']));
04450             $fields_values['tstamp'] = time();
04451             $fields_values['tablename'] = $table;
04452             $fields_values['recuid'] = $id;
04453             $fields_values['sys_log_uid'] = $logId;
04454 
04455             $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_history', $fields_values);
04456          }
04457       }
04458    }
04459 
04472    function clearHistory($table,$id,$keepEntries=10,$maxAgeSeconds=604800)    {
04473       $tstampLimit = $maxAgeSeconds ? time()-$maxAgeSeconds : 0;
04474 
04475       $where = '
04476          tablename="'.$GLOBALS['TYPO3_DB']->quoteStr($table, 'sys_history').'"
04477          AND recuid='.intval($id).'
04478          AND snapshot=0';
04479 
04480       $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,tstamp', 'sys_history', $where, '', 'uid DESC', intval($keepEntries).',1');
04481       $resRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
04482       if ($tstampLimit && intval($resRow['tstamp'])<$tstampLimit) {
04483          $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,tstamp', 'sys_history', $where.' AND tstamp<'.intval($tstampLimit), '', 'uid DESC', '1');
04484          $resRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
04485 
04486          $GLOBALS['TYPO3_DB']->exec_DELETEquery('sys_history', $where.' AND uid<='.intval($resRow['uid']));
04487       } elseif (is_array($resRow)) {
04488          $GLOBALS['TYPO3_DB']->exec_DELETEquery('sys_history', $where.' AND uid<='.intval($resRow['uid']));
04489       }
04490    }
04491 
04520    function log($table,$recuid,$action,$recpid,$error,$details,$details_nr=0,$data=array(),$event_pid=-1,$NEWid='') {
04521       if ($this->enableLogging)  {
04522          $type=1; // Type value for tce_db.php
04523          if (!$this->storeLogMessages) {$details='';}
04524          return $this->BE_USER->writelog($type,$action,$error,$details_nr,$details,$data,$table,$recuid,$recpid,$event_pid,$NEWid);
04525       }
04526    }
04527 
04534    function printLogErrorMessages($redirect) {
04535       $res_log = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
04536                '*',
04537                'sys_log',
04538                'type=1 AND userid='.intval($this->BE_USER->user['uid']).' AND tstamp='.intval($GLOBALS['EXEC_TIME']).'  AND error!=0'
04539             );
04540       $errorJS = array();
04541       while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res_log)) {
04542          $log_data = unserialize($row['log_data']);
04543          $errorJS[] = $row[error].': '.sprintf($row['details'], $log_data[0],$log_data[1],$log_data[2],$log_data[3],$log_data[4]);
04544       }
04545 
04546       if (count($errorJS)) {
04547          $error_doc = t3lib_div::makeInstance('template');
04548          $error_doc->backPath = '';
04549 
04550          $content.= $error_doc->startPage('tce_db.php Error output');
04551 
04552          $lines[] = '
04553                <tr class="bgColor5">
04554                   <td colspan="2" align="center"><strong>Errors:</strong></td>
04555                </tr>';
04556 
04557          foreach($errorJS as $line) {
04558             $lines[] = '
04559                <tr class="bgColor4">
04560                   <td valign="top"><img'.t3lib_iconWorks::skinImg('','gfx/icon_fatalerror.gif','width="18" height="16"').' alt="" /></td>
04561                   <td>'.htmlspecialchars($line).'</td>
04562                </tr>';
04563          }
04564 
04565          $lines[] = '
04566                <tr>
04567                   <td colspan="2" align="center"><br />'.
04568                   '<form action=""><input type="submit" value="Continue" onclick="'.htmlspecialchars('document.location=\''.$redirect.'\';return false;').'"></form>'.
04569                   '</td>
04570                </tr>';
04571 
04572          $content.= '
04573             <br/><br/>
04574             <table border="0" cellpadding="1" cellspacing="1" width="300" align="center">
04575                '.implode('',$lines).'
04576             </table>';
04577 
04578          $content.= $error_doc->endPage();
04579          echo $content;
04580          exit;
04581       }
04582    }
04583 
04596    function clear_cacheCmd($cacheCmd)  {
04597       global $TYPO3_CONF_VARS;
04598 
04599          // Clear cache for either ALL pages or ALL tables!
04600       switch($cacheCmd) {
04601          case 'pages':
04602             if ($this->admin || $this->BE_USER->getTSConfigVal('options.clearCache.pages'))  {
04603                if (t3lib_extMgm::isLoaded('cms'))  {
04604                   $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages','');
04605                }
04606             }
04607          break;
04608          case 'all':
04609             if ($this->admin || $this->BE_USER->getTSConfigVal('options.clearCache.all')) {
04610                if (t3lib_extMgm::isLoaded('cms'))  {
04611                   $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages','');
04612                   $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pagesection','');
04613                }
04614                $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_hash','');
04615 
04616                   // Clearing additional cache tables:
04617                if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearAllCache_additionalTables']))  {
04618                   foreach($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearAllCache_additionalTables'] as $tableName)   {
04619                      if (!ereg('[^[:alnum:]_]',$tableName) && substr($tableName,-5)=='cache')   {
04620                         $GLOBALS['TYPO3_DB']->exec_DELETEquery($tableName,'');
04621                      } else {
04622                         die('Fatal Error: Trying to flush table "'.$tableName.'" with "Clear All Cache"');
04623                      }
04624                   }
04625                }
04626             }
04627          break;
04628          case 'temp_CACHED':
04629             if ($this->admin && $TYPO3_CONF_VARS['EXT']['extCache']) {
04630                $this->removeCacheFiles();
04631             }
04632          break;
04633       }
04634 
04635          // Clear cache for a page ID!
04636       if (t3lib_div::testInt($cacheCmd))  {
04637          if (t3lib_extMgm::isLoaded('cms'))  {
04638             $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages', 'page_id='.intval($cacheCmd));
04639          }
04640       }
04641 
04642          // Call post processing function for clear-cache:
04643       if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc']))  {
04644          $_params = array('cacheCmd'=>$cacheCmd);
04645          foreach($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc'] as $_funcRef) {
04646             t3lib_div::callUserFunction($_funcRef,$_params,$this);
04647          }
04648       }
04649    }
04650 
04656    function removeCacheFiles()   {
04657       $cacheFiles=t3lib_extMgm::currentCacheFiles();
04658       $out=0;
04659       if (is_array($cacheFiles)) {
04660          reset($cacheFiles);
04661          while(list(,$cfile)=each($cacheFiles)) {
04662             @unlink($cfile);
04663             clearstatcache();
04664             $out++;
04665          }
04666       }
04667 
04668       return $out;
04669    }
04670 }
04671 
04672 
04673 
04674 
04675 /*
04676 Log messages:
04677 [action]-[details_nr.]
04678 
04679 REMEMBER to UPDATE the real messages set in tools/log/localconf_log.php
04680 
04681 0-1:  Referer host '%s' and server host '%s' did not match!
04682 1-11: Attempt to insert record on page '%s' (%s) where this table, %s, is not allowed
04683 1-12: Attempt to insert a record on page '%s' (%s) from table '%s' without permissions. Or non-existing page.
04684 2-1:  Attempt to modify table '%s' without permission
04685 2-2:  Attempt to modify record '%s' (%s) without permission. Or non-existing page.
04686 2-10: Record '%s' (%s) was updated.
04687 2-12: SQL error: '%s' (%s)
04688 2-13: Write-file error: '%s'
04689 4-1:  Attempt to move record '%s' (%s) to after a non-existing record (uid=%s)
04690 4-2:  Moved record '%s' (%s) to page '%s' (%s)
04691 4-3:  Moved record '%s' (%s) from page '%s' (%s)
04692 4-4:  Moved record '%s' (%s) on page '%s' (%s)
04693 4-10: Attempt to move page '%s' (%s) to inside of its own rootline (at page '%s' (%s))
04694 4-11: Attempt to insert record on page '%s' (%s) where this table, %s, is not allowed
04695 4-12: Attempt to insert a record on page '%s' (%s) from table '%s' without permissions. Or non-existing page.
04696 4-13: Attempt to move record '%s' (%s) to after another record, although the table has no sorting row.
04697 4-14: Attempt to move record '%s' (%s) without having permissions to do so
04698 5-1:  You cannot change the 'doktype' of page '%s' to the desired value.
04699 5-2:  'doktype' of page '%s' could not be changed because the page contains records from disallowed tables; %s
04700 5-3:  Too few items in the list of values. (%s)
04701 5-10: Could not delete file '%s' (does not exist). (%s)
04702 5-11: Copying file '%s' failed!: No destination file (%s) possible!. (%s)
04703 5-12: Fileextension '%' not allowed. (%s)
04704 5-13: Filesize (%s) of file '%s' exceeds limit (%s). (%s)
04705 5-14: The destination (%s) or the source file (%s) does not exist. (%s)
04706 5-15: Copying to file '%s' failed! (%s)
04707 5-16: Copying file '%s' failed!: The destination path (%s) may be write protected. Please make it write enabled!. (%s)
04708 
04709 */
04710 
04711 
04712 
04713 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tcemain.php']) {
04714    include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tcemain.php']);
04715 }
04716 ?>

Generated on Sun Oct 3 01:05:51 2004 for TYPO3core 3.7.0 dev by  doxygen 1.3.8-20040913