Project

General

Profile

Bug #16500 ยป fe_adminLib.inc

Administrator Admin, 2006-08-29 11:02

 
<?php
/***************************************************************
* Copyright notice
*
* (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* FE admin lib
*
* $Id: fe_adminLib.inc,v 1.19 2005/04/01 14:37:14 typo3 Exp $
* Revised for TYPO3 3.6 June/2003 by Kasper Skaarhoj
*
* @author Kasper Skaarhoj <kasperYYYY@typo3.com>
*/
/**
* [CLASS/FUNCTION INDEX of SCRIPT]
*
*
*
* 132: class user_feAdmin
* 179: function init($content,$conf)
*
* SECTION: Data processing
* 408: function parseValues()
* 503: function processFiles($cmdParts,$theField)
* 609: function overrideValues()
* 625: function defaultValues()
* 644: function evalValues()
* 766: function userProcess($mConfKey,$passVar)
* 784: function userProcess_alt($confVal,$confArr,$passVar)
*
* SECTION: Database manipulation functions
* 826: function save()
* 884: function deleteRecord()
* 914: function deleteFilesFromRecord($uid)
*
* SECTION: Command "display" functions
* 971: function displayDeleteScreen()
* 999: function displayCreateScreen()
* 1022: function displayEditScreen()
* 1073: function displayEditForm($origArr)
* 1101: function procesSetFixed()
*
* SECTION: Template processing functions
* 1190: function removeRequired($templateCode,$failure)
* 1208: function getPlainTemplate($key,$r='')
* 1225: function modifyDataArrForFormUpdate($inputArr)
* 1294: function setCObjects($templateCode,$currentArr=array(),$markerArray='',$specialPrefix='')
*
* SECTION: Emailing
* 1356: function sendInfoMail()
* 1404: function compileMail($key, $DBrows, $recipient, $setFixedConfig=array())
* 1450: function sendMail($recipient, $admin, $content='', $adminContent='')
* 1495: function isHTMLContent($c)
* 1516: function sendHTMLMail($content,$recipient,$dummy,$fromEmail,$fromName,$replyTo='')
*
* SECTION: Various helper functions
* 1600: function aCAuth($r)
* 1614: function authCode($r,$extra='')
* 1640: function setfixed($markerArray, $setfixed, $r)
* 1678: function setfixedHash($recCopy,$fields='')
* 1699: function isPreview()
* 1708: function createFileFuncObj()
* 1719: function clearCacheIfSet()
* 1734: function getFailure($theField, $theCmd, $label)
*
* TOTAL FUNCTIONS: 33
* (This index is automatically created/updated by the extension "extdeveval")
*
*/

require_once (PATH_t3lib.'class.t3lib_basicfilefunc.php'); // For use with images.



























/**
* This library provides a HTML-template file based framework for Front End creating/editing/deleting records authenticated by email or fe_user login.
* It is used in the extensions "direct_mail_subscription" and "feuser_admin" (and the depreciated(!) static template "plugin.feadmin.dmailsubscription" and "plugin.feadmin.fe_users" which are the old versions of these two extensions)
* Further the extensions "t3consultancies" and "t3references" also uses this library but contrary to the "direct_mail_subscription" and "feuser_admin" extensions which relies on external HTML templates which must be adapted these two extensions delivers the HTML template code from inside.
* Generally the fe_adminLib appears to be hard to use. Personally I feel turned off by all the template-file work involved and since it is very feature rich (and for that sake pretty stable!) there are lots of things that can go wrong - you feel. Therefore I like the concept used by "t3consultancies"/"t3references" since those extensions uses the library by supplying the HTML-template code automatically.
* Suggestions for improvement and streamlining is welcome so this powerful class could be used more and effectively.
*
* @author Kasper Skaarhoj <kasperYYYY@typo3.com>
* @package TYPO3
* @subpackage tslib
* @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=396&cHash=d267c36546
*/
class user_feAdmin {

// External, static:
var $recInMarkersHSC = TRUE; // If true, values from the record put into markers going out into HTML will be passed through htmlspecialchars()!

var $dataArr = array();
var $failureMsg = array();
var $theTable = '';
var $thePid = 0;
var $markerArray = array();
var $templateCode='';
var $cObj;

var $cmd;
var $preview;
var $backURL;
var $recUid;
var $failure=0; // is set if data did not have the required fields set.
var $error='';
var $saved=0; // is set if data is saved
var $requiredArr;
var $currentArr = array();
var $previewLabel='';
var $nc = ''; // '&no_cache=1' if you want that parameter sent.
var $additionalUpdateFields='';
var $emailMarkPrefix = 'EMAIL_TEMPLATE_';
var $codeLength;
var $cmdKey;
var $fileFunc=''; // Set to a basic_filefunc object
var $filesStoredInUploadFolders=array(); // This array will hold the names of files transferred to the uploads/* folder if any. If the records are NOT saved, these files should be deleted!! Currently this is not working!

// Internal vars, dynamic:
var $unlinkTempFiles = array(); // Is loaded with all temporary filenames used for upload which should be deleted before exit...

/**
* Main function. Called from TypoScript.
* This
* - initializes internal variables,
* - fills in the markerArray with default substitution string
* - saves/emails if such commands are sent
* - calls functions for display of the screen for editing/creation/deletion etc.
*
* @param string Empty string, ignore.
* @param array TypoScript properties following the USER_INT object which uses this library
* @return string HTML content
* @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=396&cHash=d267c36546
*/
function init($content,$conf) {
$this->conf = $conf;

// template file is fetched.
$this->templateCode = $this->conf['templateContent'] ? $this->conf['templateContent'] : $this->cObj->fileResource($this->conf['templateFile']);

// Getting the cmd var
$this->cmd = (string)t3lib_div::_GP('cmd');
// Getting the preview var
$this->preview = (string)t3lib_div::_GP('preview');
// backURL is a given URL to return to when login is performed
$this->backURL = t3lib_div::_GP('backURL');
// Uid to edit:
$this->recUid = t3lib_div::_GP('rU');
// Authentication code:
$this->authCode = t3lib_div::_GP('aC');
// get table
$this->theTable = $this->conf['table'];

$this->nc = $this->conf['no_cache'] ? '&no_cache=1' : $this->nc;
// pid
$this->thePid = intval($this->conf['pid']) ? intval($this->conf['pid']) : $GLOBALS['TSFE']->id;
//
$this->codeLength = intval($this->conf['authcodeFields.']['codeLength']) ? intval($this->conf['authcodeFields.']['codeLength']) : 8;

// Setting the hardcoded lists of fields allowed for editing and creation.
$this->fieldList=implode(',',t3lib_div::trimExplode(',',$GLOBALS['TCA'][$this->theTable]['feInterface']['fe_admin_fieldList'],1));

// globally substituted markers, fonts and colors.
$splitMark = md5(microtime());
list($this->markerArray['###GW1B###'],$this->markerArray['###GW1E###']) = explode($splitMark,$this->cObj->stdWrap($splitMark,$this->conf['wrap1.']));
list($this->markerArray['###GW2B###'],$this->markerArray['###GW2E###']) = explode($splitMark,$this->cObj->stdWrap($splitMark,$this->conf['wrap2.']));
$this->markerArray['###GC1###'] = $this->cObj->stdWrap($this->conf['color1'],$this->conf['color1.']);
$this->markerArray['###GC2###'] = $this->cObj->stdWrap($this->conf['color2'],$this->conf['color2.']);
$this->markerArray['###GC3###'] = $this->cObj->stdWrap($this->conf['color3'],$this->conf['color3.']);

// Initialize markerArray, setting FORM_URL and HIDDENFIELDS
$this->markerArray['###FORM_URL###'] = 'index.php?id='.$GLOBALS['TSFE']->id.'&amp;type='.$GLOBALS['TSFE']->type.$this->nc.$this->conf['addParams'];
$this->markerArray['###FORM_URL_ENC###'] = rawurlencode($this->markerArray['###FORM_URL###']);
$this->markerArray['###FORM_URL_HSC###'] = htmlspecialchars($this->markerArray['###FORM_URL###']);

$this->markerArray['###BACK_URL###'] = $this->backURL;
$this->markerArray['###BACK_URL_ENC###'] = rawurlencode($this->markerArray['###BACK_URL###']);
$this->markerArray['###BACK_URL_HSC###'] = htmlspecialchars($this->markerArray['###BACK_URL###']);

$this->markerArray['###THE_PID###'] = $this->thePid;
$this->markerArray['###REC_UID###'] = $this->recUid;
$this->markerArray['###AUTH_CODE###'] = $this->authCode;
$this->markerArray['###THIS_ID###'] = $GLOBALS['TSFE']->id;
$this->markerArray['###THIS_URL###'] = htmlspecialchars(t3lib_div::getIndpEnv('TYPO3_REQUEST_DIR'));
$this->markerArray['###HIDDENFIELDS###'] =
($this->cmd?'<input type="hidden" name="cmd" value="'.htmlspecialchars($this->cmd).'" />':'').
($this->authCode?'<input type="hidden" name="aC" value="'.htmlspecialchars($this->authCode).'" />':'').
($this->backURL?'<input type="hidden" name="backURL" value="'.htmlspecialchars($this->backURL).'" />':'');


// Setting cmdKey which is either 'edit' or 'create'
switch($this->cmd) {
case 'edit':
$this->cmdKey='edit';
break;
default:
$this->cmdKey='create';
break;
}
// Setting requiredArr to the fields in 'required' intersected field the total field list in order to remove invalid fields.
$this->requiredArr = array_intersect(
t3lib_div::trimExplode(',',$this->conf[$this->cmdKey.'.']['required'],1),
t3lib_div::trimExplode(',',$this->conf[$this->cmdKey.'.']['fields'],1)
);

// Setting incoming data. Non-stripped
$fe=t3lib_div::_GP('FE');
$this->dataArr = $fe[$this->theTable]; // Incoming data.

// Checking template file and table value
if (!$this->templateCode) {
$content = 'No template file found: '.$this->conf['templateFile'];
return $content;
}

if (!$this->theTable || !$this->fieldList) {
$content = 'Wrong table: '.$this->theTable;
return $content; // Not listed or editable table!
}

// *****************
// If data is submitted, we take care of it here.
// *******************
if ($this->cmd=='delete' && !$this->preview && !t3lib_div::_GP('doNotSave')) { // Delete record if delete command is sent + the preview flag is NOT set.
$this->deleteRecord();
}
// If incoming data is seen...
if (is_array($this->dataArr)) {
// Evaluation of data:
$this->parseValues();
$this->overrideValues();
$this->evalValues();
if ($this->conf['evalFunc']) {
$this->dataArr = $this->userProcess('evalFunc',$this->dataArr);
}

/*
debug($this->dataArr);
debug($this->failure);
debug($this->preview);
*/
// if not preview and no failures, then set data...
if (!$this->failure && !$this->preview && !t3lib_div::_GP('doNotSave')) { // doNotSave is a global var (eg a 'Cancel' submit button) that prevents the data from being processed
$this->save();
} else {
if ($this->conf['debug']) debug($this->failure);
}
} else {
$this->defaultValues(); // If no incoming data, this will set the default values.
$this->preview = 0; // No preview if data is not received
}
if ($this->failure) {$this->preview=0;} // No preview flag if a evaluation failure has occured
$this->previewLabel = $this->preview ? '_PREVIEW' : ''; // Setting preview label prefix.


// *********************
// DISPLAY FORMS:
// ***********************
if ($this->saved) {
// Clear page cache
$this->clearCacheIfSet();

// Displaying the page here that says, the record has been saved. You're able to include the saved values by markers.
switch($this->cmd) {
case 'delete':
$key='DELETE';
break;
case 'edit':
$key='EDIT';
break;
default:
$key='CREATE';
break;
}
// Output message
$templateCode = $this->cObj->getSubpart($this->templateCode, '###TEMPLATE_'.$key.'_SAVED###');
$this->setCObjects($templateCode,$this->currentArr);
$markerArray = $this->cObj->fillInMarkerArray($this->markerArray, $this->currentArr, '', TRUE, 'FIELD_', $this->recInMarkersHSC);
$content = $this->cObj->substituteMarkerArray($templateCode, $markerArray);

// email message:
$this->compileMail(
$key.'_SAVED',
array($this->currentArr),
$this->currentArr[$this->conf['email.']['field']],
$this->conf['setfixed.']
);

} elseif ($this->error) { // If there was an error, we return the template-subpart with the error message
$templateCode = $this->cObj->getSubpart($this->templateCode, $this->error);
$this->setCObjects($templateCode);
$content = $this->cObj->substituteMarkerArray($templateCode, $this->markerArray);
} else {
// Finally, if there has been no attempt to save. That is either preview or just displaying and empty or not correctly filled form:
if (!$this->cmd) {
$this->cmd=$this->conf['defaultCmd'];
}
if ($this->conf['debug']) debug('Display form: '.$this->cmd,1);
switch($this->cmd) {
case 'setfixed':
$content = $this->procesSetFixed();
break;
case 'infomail':
$content = $this->sendInfoMail();
break;
case 'delete':
$content = $this->displayDeleteScreen();
break;
case 'edit':
$content = $this->displayEditScreen();
break;
case 'create':
$content = $this->displayCreateScreen();
break;
}
}

// Delete temp files:
foreach($this->unlinkTempFiles as $tempFileName) {
t3lib_div::unlink_tempfile($tempFileName);
}

// Return content:
return $content;
}























/*****************************************
*
* Data processing
*
*****************************************/

/**
* Performs processing on the values found in the input data array, $this->dataArr.
* The processing is done according to configuration found in TypoScript
* Examples of this could be to force a value to an integer, remove all non-alphanumeric characters, trimming a value, upper/lowercase it, or process it due to special types like files submitted etc.
* Called from init() if the $this->dataArr is found to be an array
*
* @return void
* @see init()
*/
function parseValues() {
if (is_array($this->conf['parseValues.'])) {
reset($this->conf['parseValues.']);
while(list($theField,$theValue)=each($this->conf['parseValues.'])) {
$listOfCommands = t3lib_div::trimExplode(',',$theValue,1);
while(list(,$cmd)=each($listOfCommands)) {
$cmdParts = split('\[|\]',$cmd); // Point is to enable parameters after each command enclosed in brackets [..]. These will be in position 1 in the array.
$theCmd=trim($cmdParts[0]);
switch($theCmd) {
case 'int':
$this->dataArr[$theField]=intval($this->dataArr[$theField]);
break;
case 'lower':
case 'upper':
$this->dataArr[$theField] = $this->cObj->caseshift($this->dataArr[$theField],$theCmd);
break;
case 'nospace':
$this->dataArr[$theField] = str_replace(' ', '', $this->dataArr[$theField]);
break;
case 'alpha':
$this->dataArr[$theField] = ereg_replace('[^a-zA-Z]','',$this->dataArr[$theField]);
break;
case 'num':
$this->dataArr[$theField] = ereg_replace('[^0-9]','',$this->dataArr[$theField]);
break;
case 'alphanum':
$this->dataArr[$theField] = ereg_replace('[^a-zA-Z0-9]','',$this->dataArr[$theField]);
break;
case 'alphanum_x':
$this->dataArr[$theField] = ereg_replace('[^a-zA-Z0-9_-]','',$this->dataArr[$theField]);
break;
case 'trim':
$this->dataArr[$theField] = trim($this->dataArr[$theField]);
break;
case 'random':
$this->dataArr[$theField] = substr(md5(uniqid(microtime(),1)),0,intval($cmdParts[1]));
break;
case 'files':
if ($this->cmdKey=='create' && !t3lib_div::_GP('doNotSave')) {
$this->processFiles($cmdParts,$theField);
} else unset($this->dataArr[$theField]); // Fields with files cannot be edited - only created.
break;
case 'setEmptyIfAbsent':
if (!isset($this->dataArr[$theField])) {
$this->dataArr[$theField]='';
}
break;
case 'multiple':
if (is_array($this->dataArr[$theField])) {
$this->dataArr[$theField] = implode(',',$this->dataArr[$theField]);
}
break;
case 'checkArray':
if (is_array($this->dataArr[$theField])) {
reset($this->dataArr[$theField]);
$val = 0;
while(list($kk,$vv)=each($this->dataArr[$theField])) {
$kk = t3lib_div::intInRange($kk,0);
if ($kk<=30) {
if ($vv) {
$val|=pow(2,$kk);
}
}
}
$this->dataArr[$theField] = $val;
} else {$this->dataArr[$theField]=0;}
break;
case 'uniqueHashInt':
$otherFields = t3lib_div::trimExplode(';',$cmdParts[1],1);
$hashArray=array();
while(list(,$fN)=each($otherFields)) {
$vv = $this->dataArr[$fN];
$vv = ereg_replace('[[:space:]]','',$vv);
$vv = ereg_replace('[^[:alnum:]]','',$vv);
$vv = strtolower($vv);
$hashArray[]=$vv;
}
$this->dataArr[$theField]=hexdec(substr(md5(serialize($hashArray)),0,8));
break;
}
}
}
}
}

/**
* Processing of files.
* NOTICE: for now files can be handled only on creation of records. But a more advanced feature is that PREVIEW of files is handled.
*
* @param array Array with cmd-parts (from parseValues()). This will for example contain information about allowed file extensions and max size of uploaded files.
* @param string The fieldname with the files.
* @return void
* @access private
* @see parseValues()
*/
function processFiles($cmdParts,$theField) {
//debug($_FILES);
// First, make an array with the filename and file reference, whether the file is just uploaded or a preview
$filesArr = array();

if (is_string($this->dataArr[$theField])) { // files from preview.
$tmpArr = explode(',',$this->dataArr[$theField]);
reset($tmpArr);
while(list(,$val)=each($tmpArr)) {
$valParts = explode('|',$val);
$filesArr[] = array (
'name'=>$valParts[1],
'tmp_name'=>PATH_site.'typo3temp/'.$valParts[0]
);
}
} elseif (is_array($_FILES['FE'][$this->theTable][$theField]['name'])) { // Files from upload
reset($_FILES['FE'][$this->theTable][$theField]['name']);
while(list($kk,$vv)=each($_FILES['FE'][$this->theTable][$theField]['name'])) {
if ($vv) {
$tmpFile = t3lib_div::upload_to_tempfile($_FILES['FE'][$this->theTable][$theField]['tmp_name'][$kk]);
if ($tmpFile) {
$this->unlinkTempFiles[]=$tmpFile;
$filesArr[] = array (
'name'=>$vv,
'tmp_name'=>$tmpFile
);
}
}
}
} elseif (is_array($_FILES['FE']['name'][$this->theTable][$theField])) { // Files from upload
reset($_FILES['FE']['name'][$this->theTable][$theField]);
while(list($kk,$vv)=each($_FILES['FE']['name'][$this->theTable][$theField])) {
if ($vv) {
$tmpFile = t3lib_div::upload_to_tempfile($_FILES['FE']['tmp_name'][$this->theTable][$theField][$kk]);
if ($tmpFile) {
$this->unlinkTempFiles[]=$tmpFile;
$filesArr[] = array (
'name'=>$vv,
'tmp_name'=>$tmpFile
);
}
}
}
}

// Then verify the files in that array; check existence, extension and size
$this->dataArr[$theField]='';
$finalFilesArr=array();
if (count($filesArr)) {
$extArray = t3lib_div::trimExplode(';',strtolower($cmdParts[1]),1);
$maxSize = intval($cmdParts[3]);
reset($filesArr);
while(list(,$infoArr)=each($filesArr)) {
$fI = pathinfo($infoArr['name']);
if (t3lib_div::verifyFilenameAgainstDenyPattern($fI['name'])) {
if (!count($extArray) || in_array(strtolower($fI['extension']), $extArray)) {
$tmpFile = $infoArr['tmp_name'];
if (@is_file($tmpFile)) {
if (!$maxSize || filesize($tmpFile)<$maxSize*1024) {
$finalFilesArr[]=$infoArr;
} elseif ($this->conf['debug']) {debug('Size is beyond '.$maxSize.' kb ('.filesize($tmpFile).' bytes) and the file cannot be saved.');}
} elseif ($this->conf['debug']) {debug('Surprisingly there was no file for '.$vv.' in '.$tmpFile);}
} elseif ($this->conf['debug']) {debug('Extension "'.$fI['extension'].'" not allowed');}
} elseif ($this->conf['debug']) {debug('Filename matched illegal pattern.');}
}
}
// Copy the files in the resulting array to the proper positions based on preview/non-preview.
reset($finalFilesArr);
$fileNameList=array();
while(list(,$infoArr)=each($finalFilesArr)) {
if ($this->isPreview()) { // If the form is a preview form (and data is therefore not going into the database...) do this.
$this->createFileFuncObj();
$fI = pathinfo($infoArr['name']);
$tmpFilename = $this->theTable.'_'.t3lib_div::shortmd5(uniqid($infoArr['name'])).'.'.$fI['extension'];
$theDestFile = $this->fileFunc->getUniqueName($this->fileFunc->cleanFileName($tmpFilename), PATH_site.'typo3temp/');
t3lib_div::upload_copy_move($infoArr['tmp_name'],$theDestFile);
// Setting the filename in the list
$fI2 = pathinfo($theDestFile);
$fileNameList[] = $fI2['basename'].'|'.$infoArr['name'];
} else {
$this->createFileFuncObj();
$GLOBALS['TSFE']->includeTCA();
t3lib_div::loadTCA($this->theTable);
if (is_array($GLOBALS['TCA'][$this->theTable]['columns'][$theField])) {
$uploadPath = $GLOBALS['TCA'][$this->theTable]['columns'][$theField]['config']['uploadfolder'];
}
if ($uploadPath) {
$theDestFile = $this->fileFunc->getUniqueName($this->fileFunc->cleanFileName($infoArr['name']), PATH_site.$uploadPath);
t3lib_div::upload_copy_move($infoArr['tmp_name'],$theDestFile);
// Setting the filename in the list
$fI2 = pathinfo($theDestFile);
$fileNameList[] = $fI2['basename'];
$this->filesStoredInUploadFolders[]=$theDestFile;
}
}
// Implode the list of filenames
$this->dataArr[$theField] = implode(',',$fileNameList);
}
}

/**
* Overriding values in $this->dataArr if configured for that in TypoScript ([edit/create].overrideValues)
*
* @return void
* @see init()
*/
function overrideValues() {
// Addition of overriding values
if (is_array($this->conf[$this->cmdKey.'.']['overrideValues.'])) {
reset($this->conf[$this->cmdKey.'.']['overrideValues.']);
while(list($theField,$theValue)=each($this->conf[$this->cmdKey.'.']['overrideValues.'])) {
$this->dataArr[$theField] = $theValue;
}
}
}

/**
* Called if there is no input array in $this->dataArr. Then this function sets the default values configured in TypoScript
*
* @return void
* @see init()
*/
function defaultValues() {
// Addition of default values
if (is_array($this->conf[$this->cmdKey.'.']['defaultValues.'])) {
reset($this->conf[$this->cmdKey.'.']['defaultValues.']);
while(list($theField,$theValue)=each($this->conf[$this->cmdKey.'.']['defaultValues.'])) {
$this->dataArr[$theField] = $theValue;
}
}
}

/**
* This will evaluate the input values from $this->dataArr to see if they conforms with the requirements configured in TypoScript per field.
* For example this could be checking if a field contains a valid email address, a unique value, a value within a certain range etc.
* It will populate arrays like $this->failure and $this->failureMsg with error messages (which can later be displayed in the template). Mostly it does NOT alter $this->dataArr (such parsing of values was done by parseValues())
* Works based on configuration in TypoScript key [create/edit].evalValues
*
* @return void
* @see init(), parseValues()
*/
function evalValues() {
// Check required, set failure if not ok.
reset($this->requiredArr);
$tempArr=array();
while(list(,$theField)=each($this->requiredArr)) {
if (!trim($this->dataArr[$theField])) {
$tempArr[]=$theField;
}
}

// Evaluate: This evaluates for more advanced things than 'required' does. But it returns the same error code, so you must let the required-message tell, if further evaluation has failed!
$recExist=0;
if (is_array($this->conf[$this->cmdKey.'.']['evalValues.'])) {
switch($this->cmd) {
case 'edit':
if (isset($this->dataArr['pid'])) { // This may be tricked if the input has the pid-field set but the edit-field list does NOT allow the pid to be edited. Then the pid may be false.
$recordTestPid = intval($this->dataArr['pid']);
} else {
$tempRecArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable,$this->dataArr['uid']);
$recordTestPid = intval($tempRecArr['pid']);
}
$recExist=1;
break;
default:
$recordTestPid = $this->thePid ? $this->thePid : t3lib_div::intval_positive($this->dataArr['pid']);
break;
}

reset($this->conf[$this->cmdKey.'.']['evalValues.']);
while(list($theField,$theValue)=each($this->conf[$this->cmdKey.'.']['evalValues.'])) {
$listOfCommands = t3lib_div::trimExplode(',',$theValue,1);
while(list(,$cmd)=each($listOfCommands)) {
$cmdParts = split('\[|\]',$cmd); // Point is to enable parameters after each command enclosed in brackets [..]. These will be in position 1 in the array.
$theCmd = trim($cmdParts[0]);
switch($theCmd) {
case 'uniqueGlobal':
if ($DBrows = $GLOBALS['TSFE']->sys_page->getRecordsByField($this->theTable,$theField,$this->dataArr[$theField],'','','','1')) {
if (!$recExist || $DBrows[0]['uid']!=$this->dataArr['uid']) { // Only issue an error if the record is not existing (if new...) and if the record with the false value selected was not our self.
$tempArr[]=$theField;
$this->failureMsg[$theField][] = $this->getFailure($theField, $theCmd, 'The value existed already. Enter a new value.');
}
}
break;
case 'uniqueLocal':
if ($DBrows = $GLOBALS['TSFE']->sys_page->getRecordsByField($this->theTable,$theField,$this->dataArr[$theField], 'AND pid IN ('.$recordTestPid.')','','','1')) {
if (!$recExist || $DBrows[0]['uid']!=$this->dataArr['uid']) { // Only issue an error if the record is not existing (if new...) and if the record with the false value selected was not our self.
$tempArr[]=$theField;
$this->failureMsg[$theField][] = $this->getFailure($theField, $theCmd, 'The value existed already. Enter a new value.');
}
}
break;
case 'twice':
if (strcmp($this->dataArr[$theField], $this->dataArr[$theField.'_again'])) {
$tempArr[]=$theField;
$this->failureMsg[$theField][] = $this->getFailure($theField, $theCmd, 'You must enter the same value twice');
}
break;
case 'email':
if (!$this->cObj->checkEmail($this->dataArr[$theField])) {
$tempArr[]=$theField;
$this->failureMsg[$theField][] = $this->getFailure($theField, $theCmd, 'You must enter a valid email address');
}
break;
case 'required':
if (!trim($this->dataArr[$theField])) {
$tempArr[]=$theField;
$this->failureMsg[$theField][] = $this->getFailure($theField, $theCmd, 'You must enter a value!');
}
break;
case 'atLeast':
$chars=intval($cmdParts[1]);
if (strlen($this->dataArr[$theField])<$chars) {
$tempArr[]=$theField;
$this->failureMsg[$theField][] = sprintf($this->getFailure($theField, $theCmd, 'You must enter at least %s characters!'), $chars);
}
break;
case 'atMost':
$chars=intval($cmdParts[1]);
if (strlen($this->dataArr[$theField])>$chars) {
$tempArr[]=$theField;
$this->failureMsg[$theField][] = sprintf($this->getFailure($theField, $theCmd, 'You must enter at most %s characters!'), $chars);
}
break;
case 'inBranch':
$pars = explode(';',$cmdParts[1]);
if (intval($pars[0])) {
$pid_list = $this->cObj->getTreeList(
intval($pars[0]),
intval($pars[1]) ? intval($pars[1]) : 999,
intval($pars[2])
);
if (!$pid_list || !t3lib_div::inList($pid_list,$this->dataArr[$theField])) {
$tempArr[]=$theField;
$this->failureMsg[$theField][] = sprintf($this->getFailure($theField, $theCmd, 'The value was not a valid valud from this list: %s'), $pid_list);
}
}
break;
case 'unsetEmpty':
if (!$this->dataArr[$theField]) {
$hash = array_flip($tempArr);
unset($hash[$theField]);
$tempArr = array_keys($hash);
unset($this->failureMsg[$theField]);
unset($this->dataArr[$theField]); // This should prevent the field from entering the database.
}
break;
}
}
$this->markerArray['###EVAL_ERROR_FIELD_'.$theField.'###'] = is_array($this->failureMsg[$theField]) ? implode('<br />',$this->failureMsg[$theField]) : '';
}
}
$this->failure=implode(',',$tempArr); //$failure will show which fields were not OK
}

/**
* Preforms user processing of input array - triggered right after the function call to evalValues() IF TypoScript property "evalFunc" was set.
*
* @param string Key pointing to the property in TypoScript holding the configuration for this processing (here: "evalFunc.*"). Well: at least its safe to say that "parentObj" in this array passed to the function is a reference back to this object.
* @param array The $this->dataArr passed for processing
* @return array The processed $passVar ($this->dataArr)
* @see init(), evalValues()
*/
function userProcess($mConfKey,$passVar) {
if ($this->conf[$mConfKey]) {
$funcConf = $this->conf[$mConfKey.'.'];
$funcConf['parentObj']=&$this;
$passVar = $GLOBALS['TSFE']->cObj->callUserFunction($this->conf[$mConfKey], $funcConf, $passVar);
}
return $passVar;
}

/**
* User processing of contnet
*
* @param string Value of the TypoScript object triggering the processing.
* @param array Properties of the TypoScript object triggering the processing. The key "parentObj" in this array is passed to the function as a reference back to this object.
* @param mixed Input variable to process
* @return mixed Processed input variable, $passVar
* @see userProcess(), save(), modifyDataArrForFormUpdate()
*/
function userProcess_alt($confVal,$confArr,$passVar) {
if ($confVal) {
$funcConf = $confArr;
$funcConf['parentObj']=&$this;
$passVar = $GLOBALS['TSFE']->cObj->callUserFunction($confVal, $funcConf, $passVar);
}
return $passVar;
}






















/*****************************************
*
* Database manipulation functions
*
*****************************************/

/**
* Performs the saving of records, either edited or created.
*
* @return void
* @see init()
*/
function save() {
switch($this->cmd) {
case 'edit':
$theUid = $this->dataArr['uid'];
$origArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable,$theUid); // Fetches the original record to check permissions
if ($this->conf['edit'] && ($GLOBALS['TSFE']->loginUser || $this->aCAuth($origArr))) { // Must be logged in in order to edit (OR be validated by email)
$newFieldList = implode(',',array_intersect(explode(',',$this->fieldList),t3lib_div::trimExplode(',',$this->conf['edit.']['fields'],1)));
if ($this->aCAuth($origArr) || $this->cObj->DBmayFEUserEdit($this->theTable,$origArr,$GLOBALS['TSFE']->fe_user->user,$this->conf['allowedGroups'],$this->conf['fe_userEditSelf'])) {
$this->cObj->DBgetUpdate($this->theTable, $theUid, $this->dataArr, $newFieldList, TRUE);
$this->currentArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable,$theUid);
$this->userProcess_alt($this->conf['edit.']['userFunc_afterSave'],$this->conf['edit.']['userFunc_afterSave.'],array('rec'=>$this->currentArr, 'origRec'=>$origArr));
$this->saved=1;
} else {
$this->error='###TEMPLATE_NO_PERMISSIONS###';
}
}
break;
default:
if ($this->conf['create']) {
$newFieldList = implode(',',array_intersect(explode(',',$this->fieldList),t3lib_div::trimExplode(',',$this->conf['create.']['fields'],1)));
$this->cObj->DBgetInsert($this->theTable, $this->thePid, $this->dataArr, $newFieldList, TRUE);
$newId = $GLOBALS['TYPO3_DB']->sql_insert_id();

if ($this->theTable=='fe_users' && $this->conf['fe_userOwnSelf']) { // enables users, creating logins, to own them self.
$extraList='';
$dataArr = array();
if ($GLOBALS['TCA'][$this->theTable]['ctrl']['fe_cruser_id']) {
$field=$GLOBALS['TCA'][$this->theTable]['ctrl']['fe_cruser_id'];
$dataArr[$field]=$newId;
$extraList.=','.$field;
}
if ($GLOBALS['TCA'][$this->theTable]['ctrl']['fe_crgroup_id']) {
$field=$GLOBALS['TCA'][$this->theTable]['ctrl']['fe_crgroup_id'];
list($dataArr[$field])=explode(',',$this->dataArr['usergroup']);
$dataArr[$field]=intval($dataArr[$field]);
$extraList.=','.$field;
}
if (count($dataArr)) {
$this->cObj->DBgetUpdate($this->theTable, $newId, $dataArr, $extraList, TRUE);
}
}

$this->currentArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable,$newId);
$this->userProcess_alt($this->conf['create.']['userFunc_afterSave'],$this->conf['create.']['userFunc_afterSave.'],array('rec'=>$this->currentArr));
$this->saved=1;
}
break;
}
}

/**
* Deletes the record from table/uid, $this->theTable/$this->recUid, IF the fe-user has permission to do so.
* If the deleted flag should just be set, then it is done so. Otherwise the record truely is deleted along with any attached files.
* Called from init() if "cmd" was set to "delete" (and some other conditions)
*
* @return string void
* @see init()
*/
function deleteRecord() {
if ($this->conf['delete']) { // If deleting is enabled
$origArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable, $this->recUid);
if ($GLOBALS['TSFE']->loginUser || $this->aCAuth($origArr)) { // Must be logged in OR be authenticated by the aC code in order to delete
// If the recUid selects a record.... (no check here)
if (is_array($origArr)) {
if ($this->aCAuth($origArr) || $this->cObj->DBmayFEUserEdit($this->theTable,$origArr, $GLOBALS['TSFE']->fe_user->user,$this->conf['allowedGroups'],$this->conf['fe_userEditSelf'])) { // Display the form, if access granted.
if (!$GLOBALS['TCA'][$this->theTable]['ctrl']['delete']) { // If the record is fully deleted... then remove the image (or any file) attached.
$this->deleteFilesFromRecord($this->recUid);
}
$this->cObj->DBgetDelete($this->theTable, $this->recUid, TRUE);
$this->currentArr = $origArr;
$this->saved = 1;
} else {
$this->error = '###TEMPLATE_NO_PERMISSIONS###';
}
}
}
}
}

/**
* Deletes the files attached to a record and updates the record.
* Table/uid is $this->theTable/$uid
*
* @param integer Uid number of the record to delete from $this->theTable
* @return void
* @access private
* @see deleteRecord()
*/
function deleteFilesFromRecord($uid) {
$table = $this->theTable;
$rec = $GLOBALS['TSFE']->sys_page->getRawRecord($table,$uid);

$GLOBALS['TSFE']->includeTCA();
t3lib_div::loadTCA($table);
reset($GLOBALS['TCA'][$table]['columns']);
$iFields=array();
while(list($field,$conf)=each($GLOBALS['TCA'][$table]['columns'])) {
if ($conf['config']['type']=='group' && $conf['config']['internal_type']=='file') {

$GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), array($field => ''));

$delFileArr = explode(',',$rec[$field]);
reset($delFileArr);
while(list(,$n)=each($delFileArr)) {
if ($n) {
$fpath = $conf['config']['uploadfolder'].'/'.$n;
unlink($fpath);
}
}
}
}
}





















/*****************************************
*
* Command "display" functions
*
*****************************************/

/**
* Creates the preview display of delete actions
*
* @return string HTML content
* @see init()
*/
function displayDeleteScreen() {
if ($this->conf['delete']) { // If deleting is enabled
$origArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable, $this->recUid);
if ($GLOBALS['TSFE']->loginUser || $this->aCAuth($origArr)) { // Must be logged in OR be authenticated by the aC code in order to delete
// If the recUid selects a record.... (no check here)
if (is_array($origArr)) {
if ($this->aCAuth($origArr) || $this->cObj->DBmayFEUserEdit($this->theTable,$origArr, $GLOBALS['TSFE']->fe_user->user,$this->conf['allowedGroups'],$this->conf['fe_userEditSelf'])) { // Display the form, if access granted.
$this->markerArray['###HIDDENFIELDS###'].= '<input type="hidden" name="rU" value="'.$this->recUid.'" />';
$content = $this->getPlainTemplate('###TEMPLATE_DELETE_PREVIEW###', $origArr);
} else { // Else display error, that you could not edit that particular record...
$content = $this->getPlainTemplate('###TEMPLATE_NO_PERMISSIONS###');
}
}
} else { // Finally this is if there is no login user. This must tell that you must login. Perhaps link to a page with create-user or login information.
$content = $this->getPlainTemplate('###TEMPLATE_AUTH###');
}
} else {
$content.='Delete-option is not set in TypoScript';
}
return $content;
}

/**
* Creates the "create" screen for records
*
* @return string HTML content
* @see init()
*/
function displayCreateScreen() {
if ($this->conf['create']) {
$templateCode = $this->cObj->getSubpart($this->templateCode, ((!$GLOBALS['TSFE']->loginUser||$this->conf['create.']['noSpecialLoginForm'])?'###TEMPLATE_CREATE'.$this->previewLabel.'###':'###TEMPLATE_CREATE_LOGIN'.$this->previewLabel.'###'));
$failure = t3lib_div::_GP('noWarnings')?'':$this->failure;
if (!$failure) $templateCode = $this->cObj->substituteSubpart($templateCode, '###SUB_REQUIRED_FIELDS_WARNING###', '');

$templateCode = $this->removeRequired($templateCode,$failure);
$this->setCObjects($templateCode);

$markerArray = $this->cObj->fillInMarkerArray($this->markerArray, $this->dataArr, '', TRUE, 'FIELD_', $this->recInMarkersHSC);
if ($this->conf['create.']['preview'] && !$this->previewLabel) {$markerArray['###HIDDENFIELDS###'].= '<input type="hidden" name="preview" value="1" />';}
$content = $this->cObj->substituteMarkerArray($templateCode, $markerArray);
$content.=$this->cObj->getUpdateJS($this->modifyDataArrForFormUpdate($this->dataArr), $this->theTable.'_form', 'FE['.$this->theTable.']', $this->fieldList.$this->additionalUpdateFields);
}
return $content;
}

/**
* Creates the edit-screen for records
*
* @return string HTML content
* @see init()
*/
function displayEditScreen() {
if ($this->conf['edit']) { // If editing is enabled
$origArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable, $this->dataArr['uid']?$this->dataArr['uid']:$this->recUid);

if ($GLOBALS['TSFE']->loginUser || $this->aCAuth($origArr)) { // Must be logged in OR be authenticated by the aC code in order to edit
// If the recUid selects a record.... (no check here)
if (is_array($origArr)) {
if ($this->aCAuth($origArr) || $this->cObj->DBmayFEUserEdit($this->theTable,$origArr, $GLOBALS['TSFE']->fe_user->user,$this->conf['allowedGroups'],$this->conf['fe_userEditSelf'])) { // Display the form, if access granted.
$content=$this->displayEditForm($origArr);
} else { // Else display error, that you could not edit that particular record...
$content = $this->getPlainTemplate('###TEMPLATE_NO_PERMISSIONS###');
}
} elseif ($GLOBALS['TSFE']->loginUser) { // If the recUid did not select a record, we display a menu of records. (eg. if no recUid)
$lockPid = $this->conf['edit.']['menuLockPid'] ? ' AND pid='.intval($this->thePid) : '';

$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $this->theTable, '1 '.$lockPid.$this->cObj->DBmayFEUserEditSelect($this->theTable,$GLOBALS['TSFE']->fe_user->user, $this->conf['allowedGroups'],$this->conf['fe_userEditSelf']).$GLOBALS['TSFE']->sys_page->deleteClause($this->theTable));

if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) { // If there are menu-items ...
$templateCode = $this->getPlainTemplate('###TEMPLATE_EDITMENU###');
$out='';
$itemCode = $this->cObj->getSubpart($templateCode, '###ITEM###');
while($menuRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
$markerArray = $this->cObj->fillInMarkerArray(array(), $menuRow, '', TRUE, 'FIELD_', $this->recInMarkersHSC);
$markerArray = $this->setCObjects($itemCode,$menuRow,$markerArray,'ITEM_');
$out.= $this->cObj->substituteMarkerArray($itemCode, $markerArray);
}
$content=$this->cObj->substituteSubpart($templateCode, '###ALLITEMS###', $out);
} else { // If there are not menu items....
$content = $this->getPlainTemplate('###TEMPLATE_EDITMENU_NOITEMS###');
}
} else {
$content = $this->getPlainTemplate('###TEMPLATE_AUTH###');
}
} else { // Finally this is if there is no login user. This must tell that you must login. Perhaps link to a page with create-user or login information.
$content = $this->getPlainTemplate('###TEMPLATE_AUTH###');
}
} else {
$content.='Edit-option is not set in TypoScript';
}
return $content;
}

/**
* Subfunction for displayEditScreen(); Takes a record and creates an edit form based on the template code for it.
* This function is called if the user is editing a record and permitted to do so. Checked in displayEditScreen()
*
* @param array The array with the record to edit
* @return string HTML content
* @access private
* @see displayEditScreen()
*/
function displayEditForm($origArr) {
$currentArr = is_array($this->dataArr) ? $this->dataArr+$origArr : $origArr;

if ($this->conf['debug']) debug('displayEditForm(): '.'###TEMPLATE_EDIT'.$this->previewLabel.'###',1);
$templateCode = $this->cObj->getSubpart($this->templateCode, '###TEMPLATE_EDIT'.$this->previewLabel.'###');
$failure = t3lib_div::_GP('noWarnings')?'':$this->failure;
if (!$failure) {$templateCode = $this->cObj->substituteSubpart($templateCode, '###SUB_REQUIRED_FIELDS_WARNING###', '');}

$templateCode = $this->removeRequired($templateCode,$failure);

$this->setCObjects($templateCode,$currentArr);

$markerArray = $this->cObj->fillInMarkerArray($this->markerArray, $currentArr, '', TRUE, 'FIELD_', $this->recInMarkersHSC);

$markerArray['###HIDDENFIELDS###'].= '<input type="hidden" name="FE['.$this->theTable.'][uid]" value="'.$currentArr['uid'].'" />';
if ($this->conf['edit.']['preview'] && !$this->previewLabel) {$markerArray['###HIDDENFIELDS###'].= '<input type="hidden" name="preview" value="1" />';}
$content = $this->cObj->substituteMarkerArray($templateCode, $markerArray);
$content.=$this->cObj->getUpdateJS($this->modifyDataArrForFormUpdate($currentArr), $this->theTable.'_form', 'FE['.$this->theTable.']', $this->fieldList.$this->additionalUpdateFields);

return $content;
}

/**
* Processes socalled "setfixed" commands. These are commands setting a certain field in a certain record to a certain value. Like a link you can click in an email which will unhide a record to enable something. Or likewise a link which can delete a record by a single click.
* The idea is that only some allowed actions like this is allowed depending on the configured TypoScript.
*
* @return string HTML content displaying the status of the action
*/
function procesSetFixed() {
if ($this->conf['setfixed.']) {
$theUid = intval($this->recUid);
$origArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable, $theUid);
$fD = t3lib_div::_GP('fD');
$sFK = t3lib_div::_GP('sFK');

$fieldArr=array();
if (is_array($fD) || $sFK=='DELETE') {
if (is_array($fD)) {
reset($fD);
while(list($field,$value)=each($fD)) {
$origArr[$field]=$value;
$fieldArr[]=$field;
}
}
$theCode = $this->setfixedHash($origArr,$origArr['_FIELDLIST']);
if (!strcmp($this->authCode,$theCode)) {
if ($sFK=='DELETE') {
$this->cObj->DBgetDelete($this->theTable, $theUid, TRUE);
} else {
$newFieldList = implode(',',array_intersect(t3lib_div::trimExplode(',',$this->fieldList),t3lib_div::trimExplode(',',implode($fieldArr,','),1)));
$this->cObj->DBgetUpdate($this->theTable, $theUid, $fD, $newFieldList, TRUE);
$this->currentArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable,$theUid);
$this->userProcess_alt($this->conf['setfixed.']['userFunc_afterSave'],$this->conf['setfixed.']['userFunc_afterSave.'],array('rec'=>$this->currentArr, 'origRec'=>$origArr));
}

// Outputting template
$this->markerArray = $this->cObj->fillInMarkerArray($this->markerArray, $origArr, '', TRUE, 'FIELD_', $this->recInMarkersHSC);
$content = $this->getPlainTemplate('###TEMPLATE_SETFIXED_OK_'.$sFK.'###');
if (!$content) {$content = $this->getPlainTemplate('###TEMPLATE_SETFIXED_OK###');}

// Compiling email
$this->compileMail(
'SETFIXED_'.$sFK,
array($origArr),
$origArr[$this->conf['email.']['field']],
$this->conf['setfixed.']
);
// Clearing cache if set:
$this->clearCacheIfSet();
} else $content = $this->getPlainTemplate('###TEMPLATE_SETFIXED_FAILED###');
} else $content = $this->getPlainTemplate('###TEMPLATE_SETFIXED_FAILED###');
}
return $content;
}























/*****************************************
*
* Template processing functions
*
*****************************************/



/**
* Remove required parts from template code string
* Works like this:
* - You insert subparts like this ###SUB_REQUIRED_FIELD_'.$theField.'### in the template that tells what is required for the field, if it's not correct filled in.
* - These subparts are all removed, except if the field is listed in $failure string!
*
* Only fields that are found in $this->requiredArr is processed.
*
* @param string The template HTML code
* @param string Comma list of fields which has errors (and therefore should not be removed)
* @return string The processed template HTML code
*/
function removeRequired($templateCode,$failure) {
reset($this->requiredArr);
while(list(,$theField)=each($this->requiredArr)) {
if (!t3lib_div::inList($failure,$theField)) {
$templateCode = $this->cObj->substituteSubpart($templateCode, '###SUB_REQUIRED_FIELD_'.$theField.'###', '');
}
}
return $templateCode;
}

/**
* Returns template subpart HTML code for the key given
*
* @param string Subpart marker to return subpart for.
* @param array Optional data record array. If set, then all fields herein will also be substituted if found as markers in the template
* @return string The subpart with all markers found in current $this->markerArray substituted.
* @see tslib_cObj::fillInMarkerArray()
*/
function getPlainTemplate($key,$r='') {
if ($this->conf['debug']) debug('getPlainTemplate(): '.$key,1);
$templateCode = $this->cObj->getSubpart($this->templateCode, $key);
$this->setCObjects($templateCode,is_array($r)?$r:array());
return $this->cObj->substituteMarkerArray(
$templateCode,
is_array($r) ? $this->cObj->fillInMarkerArray($this->markerArray, $r, '', TRUE, 'FIELD_', $this->recInMarkersHSC) : $this->markerArray
);
}

/**
* Modifies input array for passing on to tslib_cObj::getUpdateJS() which produces some JavaScript for form evaluation or the like.
*
* @param array The data array
* @return array The processed input array
* @see displayCreateScreen(), displayEditForm(), tslib_cObj::getUpdateJS()
*/
function modifyDataArrForFormUpdate($inputArr) {
if (is_array($this->conf[$this->cmdKey.'.']['evalValues.'])) {
reset($this->conf[$this->cmdKey.'.']['evalValues.']);
while(list($theField,$theValue)=each($this->conf[$this->cmdKey.'.']['evalValues.'])) {
$listOfCommands = t3lib_div::trimExplode(',',$theValue,1);
while(list(,$cmd)=each($listOfCommands)) {
$cmdParts = split('\[|\]',$cmd); // Point is to enable parameters after each command enclosed in brackets [..]. These will be in position 1 in the array.
$theCmd = trim($cmdParts[0]);
switch($theCmd) {
case 'twice':
if (isset($inputArr[$theField])) {
if (!isset($inputArr[$theField.'_again'])) {
$inputArr[$theField.'_again'] = $inputArr[$theField];
}
$this->additionalUpdateFields.=','.$theField.'_again';
}
break;
}
}
}
}
if (is_array($this->conf['parseValues.'])) {
reset($this->conf['parseValues.']);
while(list($theField,$theValue)=each($this->conf['parseValues.'])) {
$listOfCommands = t3lib_div::trimExplode(',',$theValue,1);
while(list(,$cmd)=each($listOfCommands)) {
$cmdParts = split('\[|\]',$cmd); // Point is to enable parameters after each command enclosed in brackets [..]. These will be in position 1 in the array.
$theCmd = trim($cmdParts[0]);
switch($theCmd) {
case 'multiple':
if (isset($inputArr[$theField]) && !$this->isPreview()) {
$inputArr[$theField] = explode(',',$inputArr[$theField]);
}
break;
case 'checkArray':
if ($inputArr[$theField] && !$this->isPreview()) {
for($a=0;$a<=30;$a++) {
if ($inputArr[$theField] & pow(2,$a)) {
$alt_theField = $theField.']['.$a;
$inputArr[$alt_theField] = 1;
$this->additionalUpdateFields.=','.$alt_theField;
}
}
}
break;
}
}
}
}


$inputArr = $this->userProcess_alt(
$this->conf['userFunc_updateArray'],
$this->conf['userFunc_updateArray.'],
$inputArr
);

return $inputArr;
}

/**
* Will render TypoScript cObjects (configured in $this->conf['cObjects.']) and add their content to keys in a markerArray, either the array passed to the function or the internal one ($this->markerArray) if the input $markerArray is not set.
*
* @param string The current template code string. Is used to check if the marker string is found and if not, the content object is not rendered!
* @param array An alternative data record array (if empty then $this->dataArr is used)
* @param mixed An alternative markerArray to fill in (instead of $this->markerArray). If you want to set the cobjects in the internal $this->markerArray, then just set this to non-array value.
* @param string Optional prefix to set for the marker strings.
* @return array The processed $markerArray (if given).
*/
function setCObjects($templateCode,$currentArr=array(),$markerArray='',$specialPrefix='') {
if (is_array($this->conf['cObjects.'])) {
reset($this->conf['cObjects.']);

while(list($theKey,$theConf)=each($this->conf['cObjects.'])) {
if (!strstr($theKey,'.')) {
if (strstr($templateCode,'###'.$specialPrefix.'CE_'.$theKey.'###')) {
$cObjCode = $this->cObj->cObjGetSingle($this->conf['cObjects.'][$theKey], $this->conf['cObjects.'][$theKey.'.'], 'cObjects.'.$theKey);

if (!is_array($markerArray)) {
$this->markerArray['###'.$specialPrefix.'CE_'.$theKey.'###'] = $cObjCode;
} else {
$markerArray['###'.$specialPrefix.'CE_'.$theKey.'###'] = $cObjCode;
}
}
if (strstr($templateCode,'###'.$specialPrefix.'PCE_'.$theKey.'###')) {
$local_cObj =t3lib_div::makeInstance('tslib_cObj');
$local_cObj->start(count($currentArr)?$currentArr:$this->dataArr,$this->theTable);
$cObjCode = $local_cObj->cObjGetSingle($this->conf['cObjects.'][$theKey], $this->conf['cObjects.'][$theKey.'.'], 'cObjects.'.$theKey);

if (!is_array($markerArray)) {
$this->markerArray['###'.$specialPrefix.'PCE_'.$theKey.'###'] = $cObjCode;
} else {
$markerArray['###'.$specialPrefix.'PCE_'.$theKey.'###'] = $cObjCode;
}
}
}
}
}
return $markerArray;
}



















/*****************************************
*
* Emailing
*
*****************************************/

/**
* Sends info mail to user
*
* @return string HTML content message
* @see init(),compileMail(), sendMail()
*/
function sendInfoMail() {
if ($this->conf['infomail'] && $this->conf['email.']['field']) {
$fetch = t3lib_div::_GP('fetch');
if ($fetch) {
// Getting infomail config.
$key= trim(t3lib_div::_GP('key'));
if (is_array($this->conf['infomail.'][$key.'.'])) {
$config = $this->conf['infomail.'][$key.'.'];
} else {
$config = $this->conf['infomail.']['default.'];
}
$pidLock='';
if (!$config['dontLockPid']) {
$pidLock='AND pid IN ('.$this->thePid.') ';
}

// Getting records
if (t3lib_div::testInt($fetch)) {
$DBrows = $GLOBALS['TSFE']->sys_page->getRecordsByField($this->theTable,'uid',$fetch,$pidLock,'','','1');
} elseif ($fetch) { // $this->conf['email.']['field'] must be a valid field in the table!
$DBrows = $GLOBALS['TSFE']->sys_page->getRecordsByField($this->theTable,$this->conf['email.']['field'],$fetch,$pidLock,'','','100');
}

// Processing records
if (is_array($DBrows)) {
$recipient = $DBrows[0][$this->conf['email.']['field']];
$this->compileMail($config['label'], $DBrows, $recipient, $this->conf['setfixed.']);
} elseif ($this->cObj->checkEmail($fetch)) {
$this->sendMail($fetch, '', trim($this->cObj->getSubpart($this->templateCode, '###'.$this->emailMarkPrefix.'NORECORD###')));
}

$content = $this->getPlainTemplate('###TEMPLATE_INFOMAIL_SENT###');
} else {
$content = $this->getPlainTemplate('###TEMPLATE_INFOMAIL###');
}
} else $content='Error: infomail option is not available or emailField is not setup in TypoScript';
return $content;
}

/**
* Compiles and sends a mail based on input values + template parts. Looks for a normal and an "-admin" template and may send both kinds of emails. See documentation in TSref.
*
* @param string A key which together with $this->emailMarkPrefix will identify the part from the template code to use for the email.
* @param array An array of records which fields are substituted in the templates
* @param mixed Mail recipient. If string then its supposed to be an email address. If integer then its a uid of a fe_users record which is looked up and the email address from here is used for sending the mail.
* @param array Additional fields to set in the markerArray used in the substitution process
* @return void
*/
function compileMail($key, $DBrows, $recipient, $setFixedConfig=array()) {
$GLOBALS['TT']->push('compileMail');
$mailContent='';
$key = $this->emailMarkPrefix.$key;

$userContent['all'] = trim($this->cObj->getSubpart($this->templateCode, '###'.$key.'###'));
$adminContent['all'] = trim($this->cObj->getSubpart($this->templateCode, '###'.$key.'-ADMIN###'));
$userContent['rec'] = $this->cObj->getSubpart($userContent['all'], '###SUB_RECORD###');
$adminContent['rec'] = $this->cObj->getSubpart($adminContent['all'], '###SUB_RECORD###');

reset($DBrows);
while(list(,$r)=each($DBrows)) {
$markerArray = $this->cObj->fillInMarkerArray($this->markerArray, $r,'',0);
$markerArray = $this->setCObjects($userContent['rec'].$adminContent['rec'],$r,$markerArray,'ITEM_');
$markerArray['###SYS_AUTHCODE###'] = $this->authCode($r);
$markerArray = $this->setfixed($markerArray, $setFixedConfig, $r);

if ($userContent['rec']) $userContent['accum'] .=$this->cObj->substituteMarkerArray($userContent['rec'], $markerArray);
if ($adminContent['rec']) $adminContent['accum'].=$this->cObj->substituteMarkerArray($adminContent['rec'], $markerArray);
}

if ($userContent['all']) $userContent['final'] .=$this->cObj->substituteSubpart($userContent['all'], '###SUB_RECORD###', $userContent['accum']);
if ($adminContent['all']) $adminContent['final'].=$this->cObj->substituteSubpart($adminContent['all'], '###SUB_RECORD###', $adminContent['accum']);

if (t3lib_div::testInt($recipient)) {
$fe_userRec = $GLOBALS['TSFE']->sys_page->getRawRecord('fe_users',$recipient);
$recipient=$fe_userRec['email'];
}

$GLOBALS['TT']->setTSlogMessage('Template key: ###'.$key.'###, userContentLength: '.strlen($userContent['final']).', adminContentLength: '.strlen($adminContent['final']));

$this->sendMail($recipient, $this->conf['email.']['admin'], $userContent['final'], $adminContent['final']);
$GLOBALS['TT']->pull();
}

/**
* Actually sends the requested mails (through $this->cObj->sendNotifyEmail)
*
* @param string Recipient email address (or list)
* @param string Possible "admin" email address. Will enable sending of admin emails if also $adminContent is provided
* @param string Content for the regular email to user
* @param string Content for the admin email to administrator
* @return void
* @access private
* @see compileMail(), sendInfoMail()
*/
function sendMail($recipient, $admin, $content='', $adminContent='') {
// Admin mail:
if ($admin && $adminContent) {
if (!$this->isHTMLContent($adminContent)) {
$admMail = $this->cObj->sendNotifyEmail($adminContent,
$admin,
'',
$this->conf['email.']['from'],
$this->conf['email.']['fromName'],
$recipient
);
} else {
$this->sendHTMLMail($adminContent,
$admin,
'',
$this->conf['email.']['from'],
$this->conf['email.']['fromName'],
$recipient
);
}
}
// user mail:
if (!$this->isHTMLContent($content)) {
$this->cObj->sendNotifyEmail($content,
$recipient,
'', // ($admMail ? '' : $admin), // If the special administration mail was not found and send, the regular is...
$this->conf['email.']['from'],
$this->conf['email.']['fromName']
);
} else {
$this->sendHTMLMail($content,
$recipient,
'', // ($admMail ? '' : $admin), // If the special administration mail was not found and send, the regular is...
$this->conf['email.']['from'],
$this->conf['email.']['fromName']
);
}
}

/**
* Detects if content is HTML (looking for <html> tag as first and last in string)
*
* @param string Content string to test
* @return boolean Returns true if the content begins and ends with <html></html>-tags
*/
function isHTMLContent($c) {
$c = trim($c);
$first = strtolower(substr($c,0,6));
$last = strtolower(substr($c,-7));
if ($first.$last=='<html></html>') return 1;
}

/**
* Sending HTML email, using same parameters as tslib_cObj::sendNotifyEmail()
* NOTICE: "t3lib_htmlmail" library must be included for this to work, otherwise an error message is outputted.
*
* @param string The message content. If blank, no email is sent.
* @param string Comma list of recipient email addresses
* @param string IGNORE this parameter
* @param string "From" email address
* @param string Optional "From" name
* @param string Optional "Reply-To" header email address.
* @return void
* @access private
* @see sendMail(), tslib_cObj::sendNotifyEmail()
*/
function sendHTMLMail($content,$recipient,$dummy,$fromEmail,$fromName,$replyTo='') {
if (trim($recipient) && trim($content)) {
$cls=t3lib_div::makeInstanceClassName('t3lib_htmlmail');
if (class_exists($cls)) { // If htmlmail lib is included, then generate a nice HTML-email
$parts = spliti('<title>|</title>',$content,3);
$subject = trim($parts[1]) ? trim($parts[1]) : 'TYPO3 FE Admin message';

$Typo3_htmlmail = t3lib_div::makeInstance('t3lib_htmlmail');
$Typo3_htmlmail->start();
$Typo3_htmlmail->useBase64();

$Typo3_htmlmail->subject = $subject;
$Typo3_htmlmail->from_email = $fromEmail;
$Typo3_htmlmail->from_name = $fromName;
$Typo3_htmlmail->replyto_email = $replyTo ? $replyTo : $fromEmail;
$Typo3_htmlmail->replyto_name = $replyTo ? '' : $fromName;
$Typo3_htmlmail->organisation = '';
$Typo3_htmlmail->priority = 3;

// HTML
$Typo3_htmlmail->theParts['html']['content'] = $content; // Fetches the content of the page
$Typo3_htmlmail->theParts['html']['path'] = '';
$Typo3_htmlmail->extractMediaLinks();
$Typo3_htmlmail->extractHyperLinks();
$Typo3_htmlmail->fetchHTMLMedia();
$Typo3_htmlmail->substMediaNamesInHTML(0); // 0 = relative
$Typo3_htmlmail->substHREFsInHTML();
$Typo3_htmlmail->setHTML($Typo3_htmlmail->encodeMsg($Typo3_htmlmail->theParts['html']['content']));

// PLAIN
$Typo3_htmlmail->addPlain('');

// SET Headers and Content
$Typo3_htmlmail->setHeaders();
$Typo3_htmlmail->setContent();
$Typo3_htmlmail->setRecipient($recipient);

// debug($Typo3_htmlmail->theParts);
$Typo3_htmlmail->sendtheMail();
} else {
debug('SYSTEM ERROR: No HTML-mail library loaded. Set "page.config.incT3Lib_htmlmail = 1" is your TypoScript template.');
}
}
}
























/*****************************************
*
* Various helper functions
*
*****************************************/


/**
* Returns true if authentication is OK based on the "aC" code which is a GET parameter set from outside with a hash string which must match some internal hash string.
* This allows to authenticate editing without having a fe_users login
* Uses $this->authCode which is set in init() by "t3lib_div::_GP('aC');"
*
* @param array The data array for which to evaluate authentication
* @return boolean True if authenticated OK
* @see authCode(), init()
*/
function aCAuth($r) {
if ($this->authCode && !strcmp($this->authCode,$this->authCode($r))) {
return true;
}
}

/**
* Creating authentication hash string based on input record and the fields listed in TypoScript property "authcodeFields"
*
* @param array The data record
* @param string Additional string to include in the hash
* @return string Hash string of $this->codeLength (if TypoScript "authcodeFields" was set)
* @see aCAuth()
*/
function authCode($r,$extra='') {
$l=$this->codeLength;
if ($this->conf['authcodeFields']) {
$fieldArr = t3lib_div::trimExplode(',', $this->conf['authcodeFields'], 1);
$value='';
while(list(,$field)=each($fieldArr)) {
$value.=$r[$field].'|';
}
$value.=$extra.'|'.$this->conf['authcodeFields.']['addKey'];
if ($this->conf['authcodeFields.']['addDate']) {
$value.='|'.date($this->conf['authcodeFields.']['addDate']);
}
$value.=$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'];
return substr(md5($value), 0,$l);
}
}

/**
* Adding keys to the marker array with "setfixed" GET parameters
*
* @param array Marker-array to modify/add a key to.
* @param array TypoScript properties configuring "setfixed" for the plugin. Basically this is $this->conf['setfixed.'] passed along.
* @param array The data record
* @return array Processed $markerArray
* @see compileMail()
*/
function setfixed($markerArray, $setfixed, $r) {
if (is_array($setfixed)) {
reset($setfixed);
while(list($theKey,$data)=each($setfixed)) {
if (!strcmp($theKey,'DELETE')) {
$recCopy = $r;
$string='&cmd=setfixed&sFK='.rawurlencode($theKey).'&rU='.$r['uid'];
$string.='&aC='.$this->setfixedHash($recCopy,$data['_FIELDLIST']);
$markerArray['###SYS_SETFIXED_DELETE###'] = $string;
$markerArray['###SYS_SETFIXED_HSC_DELETE###'] = htmlspecialchars($string);
} elseif (strstr($theKey,'.')) {
$theKey = substr($theKey,0,-1);
if (is_array($data)) {
reset($data);
$recCopy = $r;
$string='&cmd=setfixed&sFK='.rawurlencode($theKey).'&rU='.$r['uid'];
while(list($fieldName,$fieldValue)=each($data)) {
$string.='&fD['.$fieldName.']='.rawurlencode($fieldValue);
$recCopy[$fieldName]=$fieldValue;
}
$string.='&aC='.$this->setfixedHash($recCopy,$data['_FIELDLIST']);
$markerArray['###SYS_SETFIXED_'.$theKey.'###'] = $string;
$markerArray['###SYS_SETFIXED_HSC_'.$theKey.'###'] = htmlspecialchars($string);
}
}
}
}
return $markerArray;
}

/**
* Creating hash string for setFixed. Much similar to authCode()
*
* @param array The data record
* @param string List of fields to use
* @return string Hash string of $this->codeLength (if TypoScript "authcodeFields" was set)
* @see setfixed(),authCode()
*/
function setfixedHash($recCopy,$fields='') {
if ($fields) {
$fieldArr = t3lib_div::trimExplode(',',$fields,1);
reset($fieldArr);
while(list($k,$v)=each($fieldArr)) {
$recCopy_temp[$k]=$recCopy[$v];
}
} else {
$recCopy_temp=$recCopy;
}
$encStr = implode('|',$recCopy_temp).'|'.$this->conf['authcodeFields.']['addKey'].'|'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'];
$hash = substr(md5($encStr),0,$this->codeLength);
return $hash;
}


/**
* Returns true if preview display is on.
*
* @return boolean
*/
function isPreview() {
return ($this->conf[$this->cmdKey.'.']['preview'] && $this->preview);
}

/**
* Creates an instance of class "t3lib_basicFileFunctions" in $this->fileFunc (if not already done)
*
* @return void
*/
function createFileFuncObj() {
if (!$this->fileFunc) {
$this->fileFunc = t3lib_div::makeInstance('t3lib_basicFileFunctions');
}
}

/**
* If TypoScript property clearCacheOfPages is set then all page ids in this value will have their cache cleared
*
* @return void
*/
function clearCacheIfSet() {
if ($this->conf['clearCacheOfPages']) {
$cc_pidList = $GLOBALS['TYPO3_DB']->cleanIntList($this->conf['clearCacheOfPages']);
$GLOBALS['TSFE']->clearPageCacheContent_pidList($cc_pidList);
}
}

/**
* Returns an error message for the field/command combination inputted. The error message is looked up in the TypoScript properties (evalErrors.[fieldname].[command]) and if empty then the $label value is returned
*
* @param string Field name
* @param string Command identifier string
* @param string Alternative label, shown if no other error string was found
* @return string The error message string
*/
function getFailure($theField, $theCmd, $label) {
return isset($this->conf['evalErrors.'][$theField.'.'][$theCmd]) ? $this->conf['evalErrors.'][$theField.'.'][$theCmd] : $label;
}
}


if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['media/scripts/fe_adminLib.inc']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['media/scripts/fe_adminLib.inc']);
}
?>
    (1-1/1)