Documentation TYPO3 par Ameos

class.t3lib_tcemain.php

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 ?>


Gnr par L'expert TYPO3 avec  doxygen 1.4.6