aa409f5dea54d002212b70d512f1b83bc6f4f64f
[Packages/TYPO3.CMS.git] / typo3 / sysext / cms / tslib / media / scripts / fe_adminLib.inc
1 <?php
2 /***************************************************************
3 *  Copyright notice
4 *
5 *  (c) 1999-2009 Kasper Skårhøj (kasperYYYY@typo3.com)
6 *  All rights reserved
7 *
8 *  This script is part of the TYPO3 project. The TYPO3 project is
9 *  free software; you can redistribute it and/or modify
10 *  it under the terms of the GNU General Public License as published by
11 *  the Free Software Foundation; either version 2 of the License, or
12 *  (at your option) any later version.
13 *
14 *  The GNU General Public License can be found at
15 *  http://www.gnu.org/copyleft/gpl.html.
16 *  A copy is found in the textfile GPL.txt and important notices to the license
17 *  from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 *  This script is distributed in the hope that it will be useful,
21 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 *  GNU General Public License for more details.
24 *
25 *  This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28  * FE admin lib
29  *
30  * Revised for TYPO3 3.6 June/2003 by Kasper Skårhøj
31  *
32  * @author Kasper Skårhøj <kasperYYYY@typo3.com>
33  */
34
35 /**
36  * This library provides a HTML-template file based framework for Front End creating/editing/deleting records authenticated by email or fe_user login.
37  * It is used in the extensions "direct_mail_subscription" and "feuser_admin" (and the deprecated(!) static template "plugin.feadmin.dmailsubscription" and "plugin.feadmin.fe_users" which are the old versions of these two extensions)
38  * 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.
39  * 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.
40  * Suggestions for improvement and streamlining is welcome so this powerful class could be used more and effectively.
41  *
42  * @author Kasper Skårhøj <kasperYYYY@typo3.com>
43  * @package TYPO3
44  * @subpackage tslib
45  */
46 class user_feAdmin      {
47
48                 // External, static:
49                 // If TRUE, values from the record put into markers going out into HTML will be passed through htmlspecialchars()!
50         var $recInMarkersHSC = TRUE;
51
52         var $dataArr = array();
53         var $failureMsg = array();
54         var $theTable = '';
55         var $thePid = 0;
56         var $markerArray = array();
57         var $templateCode='';
58         var $cObj;
59
60         var $cmd;
61         var $preview;
62         var $backURL;
63         var $recUid;
64                 // is set if data did not have the required fields set.
65         var $failure = 0;
66         var $error = '';
67                 // is set if data is saved
68         var $saved = 0;
69         var $requiredArr;
70         var $currentArr = array();
71         var $previewLabel = '';
72                 // '&no_cache=1' if you want that parameter sent.
73         var $nc = '';
74         var $additionalUpdateFields='';
75         var $emailMarkPrefix = 'EMAIL_TEMPLATE_';
76         var $codeLength;
77         var $cmdKey;
78                 // Set to a basic_filefunc object
79         var $fileFunc = '';
80                 // This array will hold the names of files transferred to the uploads/* folder if any.
81                 // If the records are NOT saved, these files should be deleted!! Currently this is not working!
82         var $filesStoredInUploadFolders = array();
83
84                 // Internal vars, dynamic:
85                 // Is loaded with all temporary filenames used for upload which should be deleted before exit...
86         var $unlinkTempFiles = array();
87
88         /**
89          * Main function. Called from TypoScript.
90          * This
91          * - initializes internal variables,
92          * - fills in the markerArray with default substitution string
93          * - saves/emails if such commands are sent
94          * - calls functions for display of the screen for editing/creation/deletion etc.
95          *
96          * @param string Empty string, ignore.
97          * @param array TypoScript properties following the USER_INT object which uses this library
98          * @return string HTML content
99          */
100         function init($content, $conf) {
101                 $this->conf = $conf;
102
103                         // template file is fetched.
104                 $this->templateCode = $this->conf['templateContent'] ? $this->conf['templateContent'] : $this->cObj->fileResource($this->conf['templateFile']);
105
106                         // Getting the cmd var
107                 $this->cmd = (string)t3lib_div::_GP('cmd');
108                         // Getting the preview var
109                 $this->preview = (string)t3lib_div::_GP('preview');
110                         // backURL is a given URL to return to when login is performed
111                 $this->backURL = t3lib_div::_GP('backURL');
112                 if (strstr($this->backURL, '"') || strstr($this->backURL, "'") || preg_match('/(javascript|vbscript):/i', $this->backURL) || stristr($this->backURL, "fromcharcode") || strstr($this->backURL, "<") || strstr($this->backURL, ">")) {
113                                 // Clear backURL if it seems to contain XSS code - only URLs are allowed
114                         $this->backURL = '';
115                 }
116                         // Remove host from URL: Make sure that $this->backURL maps to the current site
117                 $this->backURL = preg_replace('|[A-Za-z]+://[^/]+|', '', $this->backURL);
118                         // Uid to edit:
119                 $this->recUid = t3lib_div::_GP('rU');
120                         // Authentication code:
121                 $this->authCode = t3lib_div::_GP('aC');
122                         // Get table
123                 $this->theTable = $this->conf['table'];
124                         // Link configuration
125                 $linkConf = is_array($this->conf['formurl.']) ? $this->conf['formurl.'] : array();
126                         // pid
127                 $this->thePid = intval($this->conf['pid']) ? intval($this->conf['pid']) : $GLOBALS['TSFE']->id;
128
129                 $this->codeLength = intval($this->conf['authcodeFields.']['codeLength']) ? intval($this->conf['authcodeFields.']['codeLength']) : 8;
130
131                         // Setting the hardcoded lists of fields allowed for editing and creation.
132                 $this->fieldList=implode(',', t3lib_div::trimExplode(',', $GLOBALS['TCA'][$this->theTable]['feInterface']['fe_admin_fieldList'], 1));
133
134                         // Globally substituted markers, fonts and colors.
135                 $splitMark = md5(microtime());
136                 list($this->markerArray['###GW1B###'], $this->markerArray['###GW1E###']) = explode($splitMark, $this->cObj->stdWrap($splitMark, $this->conf['wrap1.']));
137                 list($this->markerArray['###GW2B###'], $this->markerArray['###GW2E###']) = explode($splitMark, $this->cObj->stdWrap($splitMark, $this->conf['wrap2.']));
138                 $this->markerArray['###GC1###'] = $this->cObj->stdWrap($this->conf['color1'], $this->conf['color1.']);
139                 $this->markerArray['###GC2###'] = $this->cObj->stdWrap($this->conf['color2'], $this->conf['color2.']);
140                 $this->markerArray['###GC3###'] = $this->cObj->stdWrap($this->conf['color3'], $this->conf['color3.']);
141
142                         // needed for backwards compatibility
143                 if (intval($this->conf['no_cache']) && !isset($linkConf['no_cache'])) {
144                         $linkConf['no_cache'] = 1;
145                 }
146                 if (!$linkConf['parameter']) {
147                         $linkConf['parameter'] = $GLOBALS['TSFE']->id;
148                 }
149                         // needed for backwards compatibility
150                 if (!$linkConf['additionalParams']) {
151                         $linkConf['additionalParams'] = $this->conf['addParams'];
152                 }
153
154                 $formURL = $this->cObj->typoLink_URL($linkConf);
155                 if (!strstr($formURL, '?')) {
156                         $formURL .= '?';
157                 }
158
159                         // Initialize markerArray, setting FORM_URL and HIDDENFIELDS
160                 $this->markerArray['###FORM_URL###'] = $formURL;
161                 $this->markerArray['###FORM_URL_ENC###'] = rawurlencode($this->markerArray['###FORM_URL###']);
162                 $this->markerArray['###FORM_URL_HSC###'] = htmlspecialchars($this->markerArray['###FORM_URL###']);
163
164                 $this->markerArray['###BACK_URL###'] = $this->backURL;
165                 $this->markerArray['###BACK_URL_ENC###'] = rawurlencode($this->markerArray['###BACK_URL###']);
166                 $this->markerArray['###BACK_URL_HSC###'] = htmlspecialchars($this->markerArray['###BACK_URL###']);
167
168                 $this->markerArray['###THE_PID###'] = $this->thePid;
169                 $this->markerArray['###REC_UID###'] = $this->recUid;
170                 $this->markerArray['###AUTH_CODE###'] = $this->authCode;
171                 $this->markerArray['###THIS_ID###'] = $GLOBALS['TSFE']->id;
172                 $this->markerArray['###THIS_URL###'] = htmlspecialchars(t3lib_div::getIndpEnv('TYPO3_REQUEST_DIR'));
173                 $this->markerArray['###HIDDENFIELDS###'] =
174                         ($this->cmd?'<input type="hidden" name="cmd" value="'.htmlspecialchars($this->cmd).'" />':'').
175                         ($this->authCode?'<input type="hidden" name="aC" value="'.htmlspecialchars($this->authCode).'" />':'').
176                         ($this->backURL?'<input type="hidden" name="backURL" value="'.htmlspecialchars($this->backURL).'" />':'');
177
178
179                         // Setting cmdKey which is either 'edit' or 'create'
180                 switch($this->cmd) {
181                         case 'edit':
182                                 $this->cmdKey='edit';
183                         break;
184                         default:
185                                 $this->cmdKey='create';
186                         break;
187                 }
188                         // Setting requiredArr to the fields in 'required' intersected field the total field list in order to remove invalid fields.
189                 $this->requiredArr = array_intersect(
190                         t3lib_div::trimExplode(',', $this->conf[$this->cmdKey.'.']['required'], 1),
191                         t3lib_div::trimExplode(',', $this->conf[$this->cmdKey.'.']['fields'], 1)
192                 );
193
194                         // Setting incoming data. Non-stripped
195                 $fe = t3lib_div::_GP('FE');
196                         // Incoming data.
197                 $this->dataArr = $fe[$this->theTable];
198
199                         // Checking template file and table value
200                 if (!$this->templateCode) {
201                         $content = 'No template file found: '.$this->conf['templateFile'];
202                         return $content;
203                 }
204
205                 if (!$this->theTable || !$this->fieldList) {
206                         $content = 'Wrong table: '.$this->theTable;
207                                 // Not listed or editable table!
208                         return $content;
209                 }
210
211                         // If data is submitted, we take care of it here.
212                         // Delete record if delete command is sent + the preview flag is NOT set.
213                 if ($this->cmd=='delete' && !$this->preview && !t3lib_div::_GP('doNotSave')) {
214                         $this->deleteRecord();
215                 }
216                         // If incoming data is seen...
217                 if (is_array($this->dataArr)) {
218                                 // Evaluation of data:
219                         $this->parseValues();
220                         $this->overrideValues();
221                         $this->evalValues();
222                         if ($this->conf['evalFunc']) {
223                                 $this->dataArr = $this->userProcess('evalFunc', $this->dataArr);
224                         }
225
226                                 // If not preview and no failures, then set data...
227                                 // doNotSave is a global var (eg a 'Cancel' submit button) that prevents the data from being processed
228                         if (!$this->failure && !$this->preview && !t3lib_div::_GP('doNotSave')) {
229                                 $this->save();
230                         } else {
231                                 if ($this->conf['debug']) {
232                                         debug($this->failure);
233                                 }
234                         }
235                 } else {
236                                 // If no incoming data, this will set the default values.
237                         $this->defaultValues();
238                                 // No preview if data is not received
239                         $this->preview = 0;
240                 }
241                 if ($this->failure) {
242                                 // No preview flag if a evaluation failure has occured
243                         $this->preview = 0;
244                 }
245                         // Setting preview label prefix.
246                 $this->previewLabel = $this->preview ? '_PREVIEW' : '';
247
248                         // DISPLAY FORMS:
249                 if ($this->saved) {
250                                 // Clear page cache
251                         $this->clearCacheIfSet();
252
253                                 // Displaying the page here that says, the record has been saved.
254                                 // You're able to include the saved values by markers.
255                         switch($this->cmd) {
256                                 case 'delete':
257                                         $key='DELETE';
258                                 break;
259                                 case 'edit':
260                                         $key='EDIT';
261                                 break;
262                                 default:
263                                         $key='CREATE';
264                                 break;
265                         }
266                                 // Output message
267                         $templateCode = $this->cObj->getSubpart($this->templateCode, '###TEMPLATE_'.$key.'_SAVED###');
268                         $this->setCObjects($templateCode, $this->currentArr);
269                         $markerArray = $this->cObj->fillInMarkerArray($this->markerArray, $this->currentArr, '', TRUE, 'FIELD_', $this->recInMarkersHSC);
270                         $content = $this->cObj->substituteMarkerArray($templateCode, $markerArray);
271
272                                 // Email message:
273                         $this->compileMail(
274                                 $key.'_SAVED',
275                                 array($this->currentArr),
276                                 $this->currentArr[$this->conf['email.']['field']],
277                                 $this->conf['setfixed.']
278                         );
279
280                 } elseif ($this->error) {       // If there was an error, we return the template-subpart with the error message
281                         $templateCode = $this->cObj->getSubpart($this->templateCode, $this->error);
282                         $this->setCObjects($templateCode);
283                         $content = $this->cObj->substituteMarkerArray($templateCode, $this->markerArray);
284                 } else {
285                                 // Finally, if there has been no attempt to save.
286                                 // That is either preview or just displaying and empty or not correctly filled form:
287                         if (!$this->cmd) {
288                                 $this->cmd=$this->conf['defaultCmd'];
289                         }
290                         if ($this->conf['debug']) {
291                                 debug('Display form: '.$this->cmd, 1);
292                         }
293                         switch($this->cmd) {
294                                 case 'setfixed':
295                                         $content = $this->procesSetFixed();
296                                 break;
297                                 case 'infomail':
298                                         $content = $this->sendInfoMail();
299                                 break;
300                                 case 'delete':
301                                         $content = $this->displayDeleteScreen();
302                                 break;
303                                 case 'edit':
304                                         $content = $this->displayEditScreen();
305                                 break;
306                                 case 'create':
307                                         $content = $this->displayCreateScreen();
308                                 break;
309                         }
310                 }
311
312                         // Delete temp files:
313                 foreach($this->unlinkTempFiles as $tempFileName) {
314                         t3lib_div::unlink_tempfile($tempFileName);
315                 }
316
317                         // Return content:
318                 return $content;
319         }
320
321         /*****************************************
322          *
323          * Data processing
324          *
325          *****************************************/
326
327         /**
328          * Performs processing on the values found in the input data array, $this->dataArr.
329          * The processing is done according to configuration found in TypoScript
330          * 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.
331          * Called from init() if the $this->dataArr is found to be an array
332          *
333          * @return void
334          * @see init()
335          */
336         function parseValues() {
337                 if (is_array($this->conf['parseValues.'])) {
338                         foreach ($this->conf['parseValues.'] as $theField => $theValue) {
339                                 $listOfCommands = t3lib_div::trimExplode(',', $theValue, 1);
340                                 foreach ($listOfCommands as $cmd) {
341                                                 // Point is to enable parameters after each command enclosed in brackets [..].
342                                                 // These will be in position 1 in the array.
343                                         $cmdParts = preg_split('/\[|\]/', $cmd);
344                                         $theCmd=trim($cmdParts[0]);
345                                         switch($theCmd) {
346                                                 case 'int':
347                                                         $this->dataArr[$theField]=intval($this->dataArr[$theField]);
348                                                 break;
349                                                 case 'lower':
350                                                 case 'upper':
351                                                         $this->dataArr[$theField] = $this->cObj->caseshift($this->dataArr[$theField], $theCmd);
352                                                 break;
353                                                 case 'nospace':
354                                                         $this->dataArr[$theField] = str_replace(' ', '', $this->dataArr[$theField]);
355                                                 break;
356                                                 case 'alpha':
357                                                         $this->dataArr[$theField] = preg_replace('/[^a-zA-Z]/', '', $this->dataArr[$theField]);
358                                                 break;
359                                                 case 'num':
360                                                         $this->dataArr[$theField] = preg_replace('/[^0-9]/', '', $this->dataArr[$theField]);
361                                                 break;
362                                                 case 'alphanum':
363                                                         $this->dataArr[$theField] = preg_replace('/[^a-zA-Z0-9]/', '', $this->dataArr[$theField]);
364                                                 break;
365                                                 case 'alphanum_x':
366                                                         $this->dataArr[$theField] = preg_replace('/[^a-zA-Z0-9_-]/', '', $this->dataArr[$theField]);
367                                                 break;
368                                                 case 'trim':
369                                                         $this->dataArr[$theField] = trim($this->dataArr[$theField]);
370                                                 break;
371                                                 case 'random':
372                                                         $this->dataArr[$theField] = substr(md5(uniqid(microtime(), 1)), 0, intval($cmdParts[1]));
373                                                 break;
374                                                 case 'files':
375                                                         if ($this->cmdKey=='create' && !t3lib_div::_GP('doNotSave')) {
376                                                                 $this->processFiles($cmdParts, $theField);
377
378                                                         } else {
379                                                                         // Fields with files cannot be edited - only created.
380                                                                 unset($this->dataArr[$theField]);
381                                                         }
382                                                 break;
383                                                 case 'setEmptyIfAbsent':
384                                                         if (!isset($this->dataArr[$theField])) {
385                                                                 $this->dataArr[$theField]='';
386                                                         }
387                                                 break;
388                                                 case 'multiple':
389                                                         if (is_array($this->dataArr[$theField])) {
390                                                                 $this->dataArr[$theField] = implode(',', $this->dataArr[$theField]);
391                                                         }
392                                                 break;
393                                                 case 'checkArray':
394                                                         if (is_array($this->dataArr[$theField])) {
395                                                                 $val = 0;
396                                                                 foreach ($this->dataArr[$theField] as $kk => $vv) {
397                                                                         $kk = t3lib_utility_Math::forceIntegerInRange($kk, 0);
398                                                                         if ($kk<=30) {
399                                                                                 if ($vv) {
400                                                                                         $val|=pow(2, $kk);
401                                                                                 }
402                                                                         }
403                                                                 }
404                                                                 $this->dataArr[$theField] = $val;
405                                                         } else {$this->dataArr[$theField]=0;}
406                                                 break;
407                                                 case 'uniqueHashInt':
408                                                         $otherFields = t3lib_div::trimExplode(';', $cmdParts[1], 1);
409                                                         $hashArray=array();
410                                                         foreach ($otherFields as $fN) {
411                                                                 $vv = $this->dataArr[$fN];
412                                                                 $vv = preg_replace('/[[:space:]]/', '', $vv);
413                                                                 $vv = preg_replace('/[^[:alnum:]]/', '', $vv);
414                                                                 $vv = strtolower($vv);
415                                                                 $hashArray[]=$vv;
416                                                         }
417                                                         $this->dataArr[$theField]=hexdec(substr(md5(serialize($hashArray)), 0, 8));
418                                                 break;
419                                         }
420                                 }
421                         }
422                 }
423         }
424
425         /**
426          * Processing of files.
427          * NOTICE: for now files can be handled only on creation of records. But a more advanced feature is that PREVIEW of files is handled.
428          *
429          * @param array $cmdParts Array with cmd-parts (from parseValues()). This will for example contain information about allowed file extensions and max size of uploaded files.
430          * @param string $theField The fieldname with the files.
431          * @return void
432          * @access private
433          * @see parseValues()
434          */
435         function processFiles($cmdParts, $theField) {
436                         // First, make an array with the filename and file reference, whether the file is just uploaded or a preview
437                 $filesArr = array();
438                         // Files from preview.
439                 if (is_string($this->dataArr[$theField])) {
440                         $tmpArr = explode(',', $this->dataArr[$theField]);
441                         foreach ($tmpArr as $val) {
442                                 $valParts = explode('|', $val);
443                                 $filesArr[] = array (
444                                         'name'=>$valParts[1],
445                                         'tmp_name'=>PATH_site.'typo3temp/'.$valParts[0]
446                                 );
447                         }
448                 } elseif (is_array($_FILES['FE'][$this->theTable][$theField]['name'])) {        // Files from upload
449                         foreach ($_FILES['FE'][$this->theTable][$theField]['name'] as $kk => $vv) {
450                                 if ($vv) {
451                                         $tmpFile = t3lib_div::upload_to_tempfile($_FILES['FE'][$this->theTable][$theField]['tmp_name'][$kk]);
452                                         if ($tmpFile) {
453                                                 $this->unlinkTempFiles[]=$tmpFile;
454                                                 $filesArr[] = array (
455                                                         'name'=>$vv,
456                                                         'tmp_name'=>$tmpFile
457                                                 );
458                                         }
459                                 }
460                         }
461                 } elseif (is_array($_FILES['FE']['name'][$this->theTable][$theField])) {        // Files from upload
462                         foreach ($_FILES['FE']['name'][$this->theTable][$theField] as $kk => $vv) {
463                                 if ($vv) {
464                                         $tmpFile = t3lib_div::upload_to_tempfile($_FILES['FE']['tmp_name'][$this->theTable][$theField][$kk]);
465                                         if ($tmpFile) {
466                                                 $this->unlinkTempFiles[]=$tmpFile;
467                                                 $filesArr[] = array (
468                                                         'name'=>$vv,
469                                                         'tmp_name'=>$tmpFile
470                                                 );
471                                         }
472                                 }
473                         }
474                 }
475
476                         // Then verify the files in that array; check existence, extension and size
477                 $this->dataArr[$theField] = '';
478                 $finalFilesArr = array();
479                 if (count($filesArr)) {
480                         $extArray = t3lib_div::trimExplode(';', strtolower($cmdParts[1]), 1);
481                         $maxSize = intval($cmdParts[3]);
482                         foreach ($filesArr as $infoArr) {
483                                 $fI = pathinfo($infoArr['name']);
484                                 if (t3lib_div::verifyFilenameAgainstDenyPattern($fI['name'])) {
485                                         if (!count($extArray) || in_array(strtolower($fI['extension']), $extArray)) {
486                                                 $tmpFile = $infoArr['tmp_name'];
487                                                 if (@is_file($tmpFile)) {
488                                                         if (!$maxSize || filesize($tmpFile)<$maxSize*1024) {
489                                                                 $finalFilesArr[]=$infoArr;
490                                                         } elseif ($this->conf['debug']) {debug('Size is beyond '.$maxSize.' kb ('.filesize($tmpFile).' bytes) and the file cannot be saved.');}
491                                                 } elseif ($this->conf['debug']) {debug('Surprisingly there was no file for '.$vv.' in '.$tmpFile);}
492                                         } elseif ($this->conf['debug']) {debug('Extension "'.$fI['extension'].'" not allowed');}
493                                 } elseif ($this->conf['debug']) {debug('Filename matched illegal pattern.');}
494                         }
495                 }
496                         // Copy the files in the resulting array to the proper positions based on preview/non-preview.
497                 $fileNameList = array();
498                 foreach ($finalFilesArr as $infoArr) {
499                                 // If the form is a preview form (and data is therefore not going into the database...) do this.
500                         if ($this->isPreview()) {
501                                 $this->createFileFuncObj();
502                                 $fI = pathinfo($infoArr['name']);
503                                 $tmpFilename = $this->theTable.'_'.t3lib_div::shortmd5(uniqid($infoArr['name'])).'.'.$fI['extension'];
504                                 $theDestFile = $this->fileFunc->getUniqueName($this->fileFunc->cleanFileName($tmpFilename), PATH_site.'typo3temp/');
505                                 t3lib_div::upload_copy_move($infoArr['tmp_name'], $theDestFile);
506                                         // Setting the filename in the list
507                                 $fI2 = pathinfo($theDestFile);
508                                 $fileNameList[] = $fI2['basename'].'|'.$infoArr['name'];
509                         } else {
510                                 $this->createFileFuncObj();
511                                 $GLOBALS['TSFE']->includeTCA();
512                                 t3lib_div::loadTCA($this->theTable);
513                                 if (is_array($GLOBALS['TCA'][$this->theTable]['columns'][$theField])) {
514                                         $uploadPath = $GLOBALS['TCA'][$this->theTable]['columns'][$theField]['config']['uploadfolder'];
515                                 }
516                                 if ($uploadPath) {
517                                         $theDestFile = $this->fileFunc->getUniqueName($this->fileFunc->cleanFileName($infoArr['name']), PATH_site.$uploadPath);
518                                         t3lib_div::upload_copy_move($infoArr['tmp_name'], $theDestFile);
519                                                 // Setting the filename in the list
520                                         $fI2 = pathinfo($theDestFile);
521                                         $fileNameList[] = $fI2['basename'];
522                                         $this->filesStoredInUploadFolders[]=$theDestFile;
523                                 }
524                         }
525                                 // Implode the list of filenames
526                         $this->dataArr[$theField] = implode(',', $fileNameList);
527                 }
528         }
529
530         /**
531          * Overriding values in $this->dataArr if configured for that in TypoScript ([edit/create].overrideValues)
532          *
533          * @return void
534          * @see init()
535          */
536         function overrideValues() {
537                         // Addition of overriding values
538                 if (is_array($this->conf[$this->cmdKey.'.']['overrideValues.'])) {
539                         foreach ($this->conf[$this->cmdKey.'.']['overrideValues.'] as $theField => $theValue) {
540                                 $this->dataArr[$theField] = $theValue;
541                         }
542                 }
543         }
544
545         /**
546          * Called if there is no input array in $this->dataArr. Then this function sets the default values configured in TypoScript
547          *
548          * @return void
549          * @see init()
550          */
551         function defaultValues() {
552                         // Addition of default values
553                 if (is_array($this->conf[$this->cmdKey.'.']['defaultValues.'])) {
554                         foreach ($this->conf[$this->cmdKey.'.']['defaultValues.'] as $theField => $theValue) {
555                                 $this->dataArr[$theField] = $theValue;
556                         }
557                 }
558         }
559
560         /**
561          * This will evaluate the input values from $this->dataArr to see if they conforms with the requirements configured in TypoScript per field.
562          * For example this could be checking if a field contains a valid email address, a unique value, a value within a certain range etc.
563          * 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())
564          * Works based on configuration in TypoScript key [create/edit].evalValues
565          *
566          * @return void
567          * @see init(), parseValues()
568          */
569         function evalValues() {
570                         // Check required, set failure if not ok.
571                 $tempArr = array();
572                 foreach ($this->requiredArr as $theField) {
573                         if (!trim($this->dataArr[$theField])) {
574                                 $tempArr[]=$theField;
575                         }
576                 }
577
578                         // 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!
579                 $recExist = 0;
580                 if (is_array($this->conf[$this->cmdKey.'.']['evalValues.'])) {
581                         switch($this->cmd) {
582                                 case 'edit':
583                                                 // This may be tricked if the input has the pid-field set but the edit-field list does NOT
584                                                 // allow the pid to be edited. Then the pid may be false.
585                                         if (isset($this->dataArr['pid'])) {
586                                                 $recordTestPid = intval($this->dataArr['pid']);
587                                         } else {
588                                                 $tempRecArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable, $this->dataArr['uid']);
589                                                 $recordTestPid = intval($tempRecArr['pid']);
590                                         }
591                                         $recExist = 1;
592                                 break;
593                                 default:
594                                         $recordTestPid = $this->thePid ? $this->thePid : t3lib_utility_Math::convertToPositiveInteger($this->dataArr['pid']);
595                                 break;
596                         }
597
598                         foreach ($this->conf[$this->cmdKey.'.']['evalValues.'] as $theField => $theValue) {
599                                 $listOfCommands = t3lib_div::trimExplode(',', $theValue, 1);
600                                 foreach ($listOfCommands as $cmd) {
601                                         $cmdParts = preg_split('/\[|\]/', $cmd);        // Point is to enable parameters after each command enclosed in brackets [..]. These will be in position 1 in the array.
602                                         $theCmd = trim($cmdParts[0]);
603                                         switch($theCmd) {
604                                                 case 'uniqueGlobal':
605                                                         if ($DBrows = $GLOBALS['TSFE']->sys_page->getRecordsByField($this->theTable, $theField, $this->dataArr[$theField], '', '', '', '1')) {
606                                                                         // 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.
607                                                                 if (!$recExist || $DBrows[0]['uid']!=$this->dataArr['uid']) {
608                                                                         $tempArr[]=$theField;
609                                                                         $this->failureMsg[$theField][] = $this->getFailure($theField, $theCmd, 'The value existed already. Enter a new value.');
610                                                                 }
611                                                         }
612                                                 break;
613                                                 case 'uniqueLocal':
614                                                         if ($DBrows = $GLOBALS['TSFE']->sys_page->getRecordsByField($this->theTable, $theField, $this->dataArr[$theField], 'AND pid IN ('.$recordTestPid.')', '', '', '1')) {
615                                                                         // 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.
616                                                                 if (!$recExist || $DBrows[0]['uid']!=$this->dataArr['uid']) {
617                                                                         $tempArr[]=$theField;
618                                                                         $this->failureMsg[$theField][] = $this->getFailure($theField, $theCmd, 'The value existed already. Enter a new value.');
619                                                                 }
620                                                         }
621                                                 break;
622                                                 case 'twice':
623                                                         if (strcmp($this->dataArr[$theField], $this->dataArr[$theField.'_again'])) {
624                                                                 $tempArr[]=$theField;
625                                                                 $this->failureMsg[$theField][] = $this->getFailure($theField, $theCmd, 'You must enter the same value twice');
626                                                         }
627                                                 break;
628                                                 case 'email':
629                                                         if (!t3lib_div::validEmail($this->dataArr[$theField])) {
630                                                                 $tempArr[]=$theField;
631                                                                 $this->failureMsg[$theField][] = $this->getFailure($theField, $theCmd, 'You must enter a valid email address');
632                                                         }
633                                                 break;
634                                                 case 'required':
635                                                         if (!trim($this->dataArr[$theField])) {
636                                                                 $tempArr[]=$theField;
637                                                                 $this->failureMsg[$theField][] = $this->getFailure($theField, $theCmd, 'You must enter a value!');
638                                                         }
639                                                 break;
640                                                 case 'atLeast':
641                                                         $chars=intval($cmdParts[1]);
642                                                         if (strlen($this->dataArr[$theField])<$chars) {
643                                                                 $tempArr[]=$theField;
644                                                                 $this->failureMsg[$theField][] = sprintf($this->getFailure($theField, $theCmd, 'You must enter at least %s characters!'), $chars);
645                                                         }
646                                                 break;
647                                                 case 'atMost':
648                                                         $chars=intval($cmdParts[1]);
649                                                         if (strlen($this->dataArr[$theField])>$chars) {
650                                                                 $tempArr[]=$theField;
651                                                                 $this->failureMsg[$theField][] = sprintf($this->getFailure($theField, $theCmd, 'You must enter at most %s characters!'), $chars);
652                                                         }
653                                                 break;
654                                                 case 'inBranch':
655                                                         $pars = explode(';', $cmdParts[1]);
656                                                         if (intval($pars[0])) {
657                                                                 $pid_list = $this->cObj->getTreeList(
658                                                                         intval($pars[0]),
659                                                                         intval($pars[1]) ? intval($pars[1]) : 999,
660                                                                         intval($pars[2])
661                                                                 );
662                                                                 if (!$pid_list || !t3lib_div::inList($pid_list, $this->dataArr[$theField])) {
663                                                                         $tempArr[]=$theField;
664                                                                         $this->failureMsg[$theField][] = sprintf($this->getFailure($theField, $theCmd, 'The value was not a valid valud from this list: %s'), $pid_list);
665                                                                 }
666                                                         }
667                                                 break;
668                                                 case 'unsetEmpty':
669                                                         if (!$this->dataArr[$theField]) {
670                                                                 $hash = array_flip($tempArr);
671                                                                 unset($hash[$theField]);
672                                                                 $tempArr = array_keys($hash);
673                                                                 unset($this->failureMsg[$theField]);
674                                                                         // This should prevent the field from entering the database.
675                                                                 unset($this->dataArr[$theField]);
676                                                         }
677                                                 break;
678                                         }
679                                 }
680                                 $this->markerArray['###EVAL_ERROR_FIELD_' . $theField . '###'] = is_array($this->failureMsg[$theField]) ? implode('<br />', $this->failureMsg[$theField]) : '';
681                         }
682                 }
683                         // $failure will show which fields were not OK
684                 $this->failure = implode(',', $tempArr);
685         }
686
687         /**
688          * Preforms user processing of input array - triggered right after the function call to evalValues() IF TypoScript property "evalFunc" was set.
689          *
690          * @param string $mConfKey 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.
691          * @param array $passVar The $this->dataArr passed for processing
692          * @return array The processed $passVar ($this->dataArr)
693          * @see init(), evalValues()
694          */
695         function userProcess($mConfKey, $passVar) {
696                 if ($this->conf[$mConfKey]) {
697                         $funcConf = $this->conf[$mConfKey.'.'];
698                         $funcConf['parentObj'] = $this;
699                         $passVar = $GLOBALS['TSFE']->cObj->callUserFunction($this->conf[$mConfKey], $funcConf, $passVar);
700                 }
701                 return $passVar;
702         }
703
704         /**
705          * User processing of contnet
706          *
707          * @param string $confVal Value of the TypoScript object triggering the processing.
708          * @param array $confArr 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.
709          * @param mixed $passVar Input variable to process
710          * @return mixed Processed input variable, $passVar
711          * @see userProcess(), save(), modifyDataArrForFormUpdate()
712          */
713         function userProcess_alt($confVal, $confArr, $passVar) {
714                 if ($confVal) {
715                         $funcConf = $confArr;
716                         $funcConf['parentObj'] = $this;
717                         $passVar = $GLOBALS['TSFE']->cObj->callUserFunction($confVal, $funcConf, $passVar);
718                 }
719                 return $passVar;
720         }
721
722         /*****************************************
723          *
724          * Database manipulation functions
725          *
726          *****************************************/
727
728         /**
729          * Performs the saving of records, either edited or created.
730          *
731          * @return void
732          * @see init()
733          */
734         function save() {
735                 switch($this->cmd) {
736                         case 'edit':
737                                 $theUid = $this->dataArr['uid'];
738                                         // Fetches the original record to check permissions
739                                 $origArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable, $theUid);
740                                         // Must be logged in in order to edit  (OR be validated by email)
741                                 if ($this->conf['edit'] && ($GLOBALS['TSFE']->loginUser || $this->aCAuth($origArr))) {
742                                         $newFieldList = implode(',', array_intersect(explode(',', $this->fieldList), t3lib_div::trimExplode(',', $this->conf['edit.']['fields'], 1)));
743                                         if ($this->aCAuth($origArr) || $this->cObj->DBmayFEUserEdit($this->theTable, $origArr, $GLOBALS['TSFE']->fe_user->user, $this->conf['allowedGroups'], $this->conf['fe_userEditSelf'])) {
744                                                 $this->cObj->DBgetUpdate($this->theTable, $theUid, $this->dataArr, $newFieldList, TRUE);
745                                                 $this->currentArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable, $theUid);
746                                                 $this->userProcess_alt($this->conf['edit.']['userFunc_afterSave'], $this->conf['edit.']['userFunc_afterSave.'], array('rec'=>$this->currentArr, 'origRec'=>$origArr));
747                                                 $this->saved=1;
748                                         } else {
749                                                 $this->error='###TEMPLATE_NO_PERMISSIONS###';
750                                         }
751                                 }
752                         break;
753                         default:
754                                 if ($this->conf['create']) {
755                                         $newFieldList = implode(',', array_intersect(explode(',', $this->fieldList), t3lib_div::trimExplode(',', $this->conf['create.']['fields'], 1)));
756                                         $this->cObj->DBgetInsert($this->theTable, $this->thePid, $this->dataArr, $newFieldList, TRUE);
757                                         $newId = $GLOBALS['TYPO3_DB']->sql_insert_id();
758
759                                                 // enables users, creating logins, to own them self.
760                                         if ($this->theTable == 'fe_users' && $this->conf['fe_userOwnSelf']) {
761                                                 $extraList = '';
762                                                 $dataArr = array();
763                                                 if ($GLOBALS['TCA'][$this->theTable]['ctrl']['fe_cruser_id'])           {
764                                                         $field = $GLOBALS['TCA'][$this->theTable]['ctrl']['fe_cruser_id'];
765                                                         $dataArr[$field] = $newId;
766                                                         $extraList .= ','.$field;
767                                                 }
768                                                 if ($GLOBALS['TCA'][$this->theTable]['ctrl']['fe_crgroup_id']) {
769                                                         $field = $GLOBALS['TCA'][$this->theTable]['ctrl']['fe_crgroup_id'];
770                                                         list($dataArr[$field]) = explode(',', $this->dataArr['usergroup']);
771                                                         $dataArr[$field] = intval($dataArr[$field]);
772                                                         $extraList .= ','.$field;
773                                                 }
774                                                 if (count($dataArr)) {
775                                                         $this->cObj->DBgetUpdate($this->theTable, $newId, $dataArr, $extraList, TRUE);
776                                                 }
777                                         }
778
779                                         $this->currentArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable, $newId);
780                                         $this->userProcess_alt($this->conf['create.']['userFunc_afterSave'], $this->conf['create.']['userFunc_afterSave.'], array('rec'=>$this->currentArr));
781                                         $this->saved = 1;
782                                 }
783                         break;
784                 }
785         }
786
787         /**
788          * Deletes the record from table/uid, $this->theTable/$this->recUid, IF the fe-user has permission to do so.
789          * If the deleted flag should just be set, then it is done so. Otherwise the record truely is deleted along with any attached files.
790          * Called from init() if "cmd" was set to "delete" (and some other conditions)
791          *
792          * @return string void
793          * @see init()
794          */
795         function deleteRecord() {
796                         // If deleting is enabled
797                 if ($this->conf['delete']) {
798                         $origArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable, $this->recUid);
799                                 // Must be logged in OR be authenticated by the aC code in order to delete
800                         if ($GLOBALS['TSFE']->loginUser || $this->aCAuth($origArr)) {
801                                         // If the recUid selects a record.... (no check here)
802                                 if (is_array($origArr)) {
803                                                 // Display the form, if access granted.
804                                         if ($this->aCAuth($origArr) || $this->cObj->DBmayFEUserEdit($this->theTable, $origArr, $GLOBALS['TSFE']->fe_user->user, $this->conf['allowedGroups'], $this->conf['fe_userEditSelf'])) {
805                                                         // If the record is fully deleted... then remove the image (or any file) attached.
806                                                 if (!$GLOBALS['TCA'][$this->theTable]['ctrl']['delete']) {
807                                                         $this->deleteFilesFromRecord($this->recUid);
808                                                 }
809                                                 $this->cObj->DBgetDelete($this->theTable, $this->recUid, TRUE);
810                                                 $this->currentArr = $origArr;
811                                                 $this->saved = 1;
812                                         } else {
813                                                 $this->error = '###TEMPLATE_NO_PERMISSIONS###';
814                                         }
815                                 }
816                         }
817                 }
818         }
819
820         /**
821          * Deletes the files attached to a record and updates the record.
822          * Table/uid is $this->theTable/$uid
823          *
824          * @param integer $uid Uid number of the record to delete from $this->theTable
825          * @return void
826          * @access private
827          * @see deleteRecord()
828          */
829         function deleteFilesFromRecord($uid) {
830                 $table = $this->theTable;
831                 $rec = $GLOBALS['TSFE']->sys_page->getRawRecord($table, $uid);
832
833                 $GLOBALS['TSFE']->includeTCA();
834                 t3lib_div::loadTCA($table);
835                 $iFields = array();
836                 foreach ($GLOBALS['TCA'][$table]['columns'] as $field => $conf) {
837                         if ($conf['config']['type'] == 'group' && $conf['config']['internal_type']=='file') {
838
839                                 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), array($field => ''));
840
841                                 $delFileArr = explode(',', $rec[$field]);
842                                 foreach ($delFileArr as $n) {
843                                         if ($n) {
844                                                 $fpath = $conf['config']['uploadfolder'].'/'.$n;
845                                                 unlink($fpath);
846                                         }
847                                 }
848                         }
849                 }
850         }
851
852         /*****************************************
853          *
854          * Command "display" functions
855          *
856          *****************************************/
857
858         /**
859          * Creates the preview display of delete actions
860          *
861          * @return string HTML content
862          * @see init()
863          */
864         function displayDeleteScreen() {
865                         // If deleting is enabled
866                 if ($this->conf['delete']) {
867                         $origArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable, $this->recUid);
868                                 // Must be logged in OR be authenticated by the aC code in order to delete
869                         if ($GLOBALS['TSFE']->loginUser || $this->aCAuth($origArr)) {
870                                         // If the recUid selects a record.... (no check here)
871                                 if (is_array($origArr)) {
872                                                 // Display the form, if access granted.
873                                         if ($this->aCAuth($origArr) || $this->cObj->DBmayFEUserEdit($this->theTable, $origArr, $GLOBALS['TSFE']->fe_user->user, $this->conf['allowedGroups'], $this->conf['fe_userEditSelf'])) {
874                                                 $this->markerArray['###HIDDENFIELDS###'].= '<input type="hidden" name="rU" value="'.$this->recUid.'" />';
875                                                 $content = $this->getPlainTemplate('###TEMPLATE_DELETE_PREVIEW###', $origArr);
876                                         } else {        // Else display error, that you could not edit that particular record...
877                                                 $content = $this->getPlainTemplate('###TEMPLATE_NO_PERMISSIONS###');
878                                         }
879                                 }
880                         } 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.
881                                 $content = $this->getPlainTemplate('###TEMPLATE_AUTH###');
882                         }
883                 } else {
884                         $content.='Delete-option is not set in TypoScript';
885                 }
886                 return $content;
887         }
888
889         /**
890          * Creates the "create" screen for records
891          *
892          * @return string HTML content
893          * @see init()
894          */
895         function displayCreateScreen() {
896                 if ($this->conf['create']) {
897                         $templateCode = $this->cObj->getSubpart($this->templateCode, ((!$GLOBALS['TSFE']->loginUser || $this->conf['create.']['noSpecialLoginForm'])?'###TEMPLATE_CREATE'.$this->previewLabel.'###':'###TEMPLATE_CREATE_LOGIN'.$this->previewLabel.'###'));
898                         $failure = t3lib_div::_GP('noWarnings')?'':$this->failure;
899                         if (!$failure)  $templateCode = $this->cObj->substituteSubpart($templateCode, '###SUB_REQUIRED_FIELDS_WARNING###', '');
900
901                         $templateCode = $this->removeRequired($templateCode, $failure);
902                         $this->setCObjects($templateCode);
903
904                         if (!is_array($this->dataArr)) {
905                                 $this->dataArr = array();
906                         }
907
908                         $markerArray = $this->cObj->fillInMarkerArray($this->markerArray, $this->dataArr, '', TRUE, 'FIELD_', $this->recInMarkersHSC);
909                         if ($this->conf['create.']['preview'] && !$this->previewLabel)  {$markerArray['###HIDDENFIELDS###'].= '<input type="hidden" name="preview" value="1" />';}
910                         $content = $this->cObj->substituteMarkerArray($templateCode, $markerArray);
911                         $content .= $this->cObj->getUpdateJS($this->modifyDataArrForFormUpdate($this->dataArr), $this->theTable.'_form', 'FE['.$this->theTable.']', $this->fieldList.$this->additionalUpdateFields);
912                 }
913                 return $content;
914         }
915
916         /**
917          * Creates the edit-screen for records
918          *
919          * @return string HTML content
920          * @see init()
921          */
922         function displayEditScreen() {
923                         // If editing is enabled
924                 if ($this->conf['edit']) {
925                         $origArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable, $this->dataArr['uid']?$this->dataArr['uid']:$this->recUid);
926                                 // Must be logged in OR be authenticated by the aC code in order to edit
927                         if ($GLOBALS['TSFE']->loginUser || $this->aCAuth($origArr)) {
928                                         // If the recUid selects a record.... (no check here)
929                                 if (is_array($origArr)) {
930                                         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.
931                                                 $content=$this->displayEditForm($origArr);
932                                         } else {        // Else display error, that you could not edit that particular record...
933                                                 $content = $this->getPlainTemplate('###TEMPLATE_NO_PERMISSIONS###');
934                                         }
935                                 } elseif ($GLOBALS['TSFE']->loginUser) {        // If the recUid did not select a record, we display a menu of records. (eg. if no recUid)
936                                         $lockPid = $this->conf['edit.']['menuLockPid'] ? ' AND pid='.intval($this->thePid) : '';
937
938                                         $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));
939
940                                                 // If there are menu-items ...
941                                         if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
942                                                 $templateCode = $this->getPlainTemplate('###TEMPLATE_EDITMENU###');
943                                                 $out = '';
944                                                 $itemCode = $this->cObj->getSubpart($templateCode, '###ITEM###');
945                                                 while ($menuRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
946                                                         $markerArray = $this->cObj->fillInMarkerArray(array(), $menuRow, '', TRUE, 'FIELD_', $this->recInMarkersHSC);
947                                                         $markerArray = $this->setCObjects($itemCode, $menuRow, $markerArray, 'ITEM_');
948                                                         $out.= $this->cObj->substituteMarkerArray($itemCode, $markerArray);
949                                                 }
950                                                 $content=$this->cObj->substituteSubpart($templateCode, '###ALLITEMS###', $out);
951                                         } else {        // If there are not menu items....
952                                                 $content = $this->getPlainTemplate('###TEMPLATE_EDITMENU_NOITEMS###');
953                                         }
954                                 } else {
955                                         $content = $this->getPlainTemplate('###TEMPLATE_AUTH###');
956                                 }
957                         } 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.
958                                 $content = $this->getPlainTemplate('###TEMPLATE_AUTH###');
959                         }
960                 } else {
961                         $content.='Edit-option is not set in TypoScript';
962                 }
963                 return $content;
964         }
965
966         /**
967          * Subfunction for displayEditScreen(); Takes a record and creates an edit form based on the template code for it.
968          * This function is called if the user is editing a record and permitted to do so. Checked in displayEditScreen()
969          *
970          * @param array $origArr The array with the record to edit
971          * @return string HTML content
972          * @access private
973          * @see displayEditScreen()
974          */
975         function displayEditForm($origArr) {
976                 $currentArr = is_array($this->dataArr) ? $this->dataArr+$origArr : $origArr;
977
978                 if ($this->conf['debug']) {
979                         debug('displayEditForm(): ###TEMPLATE_EDIT' . $this->previewLabel . '###', 1);
980                 }
981                 $templateCode = $this->cObj->getSubpart($this->templateCode, '###TEMPLATE_EDIT'.$this->previewLabel.'###');
982                 $failure = t3lib_div::_GP('noWarnings')?'':$this->failure;
983                 if (!$failure)  {$templateCode = $this->cObj->substituteSubpart($templateCode, '###SUB_REQUIRED_FIELDS_WARNING###', '');}
984
985                 $templateCode = $this->removeRequired($templateCode, $failure);
986
987                 $this->setCObjects($templateCode, $currentArr);
988
989                 $markerArray = $this->cObj->fillInMarkerArray($this->markerArray, $currentArr, '', TRUE, 'FIELD_', $this->recInMarkersHSC);
990
991                 $markerArray['###HIDDENFIELDS###'].= '<input type="hidden" name="FE['.$this->theTable.'][uid]" value="'.$currentArr['uid'].'" />';
992                 if ($this->conf['edit.']['preview'] && !$this->previewLabel) {
993                         $markerArray['###HIDDENFIELDS###'].= '<input type="hidden" name="preview" value="1" />';
994                 }
995                 $content = $this->cObj->substituteMarkerArray($templateCode, $markerArray);
996                 $content .= $this->cObj->getUpdateJS($this->modifyDataArrForFormUpdate($currentArr), $this->theTable.'_form', 'FE['.$this->theTable.']', $this->fieldList.$this->additionalUpdateFields);
997
998                 return $content;
999         }
1000
1001         /**
1002          * 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.
1003          * The idea is that only some allowed actions like this is allowed depending on the configured TypoScript.
1004          *
1005          * @return string HTML content displaying the status of the action
1006          */
1007         function procesSetFixed() {
1008                 if ($this->conf['setfixed']) {
1009                         $theUid = intval($this->recUid);
1010                         $origArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable, $theUid);
1011                         $fD = t3lib_div::_GP('fD');
1012                         $sFK = t3lib_div::_GP('sFK');
1013
1014                         $fieldArr=array();
1015                         if (is_array($fD) || $sFK == 'DELETE') {
1016                                 if (is_array($fD)) {
1017                                         foreach ($fD as $field => $value) {
1018                                                 $origArr[$field]=$value;
1019                                                 $fieldArr[]=$field;
1020                                         }
1021                                 }
1022                                 $theCode = $this->setfixedHash($origArr, $origArr['_FIELDLIST']);
1023                                 if (!strcmp($this->authCode, $theCode)) {
1024                                         if ($sFK == 'DELETE') {
1025                                                 $this->cObj->DBgetDelete($this->theTable, $theUid, TRUE);
1026                                         } else {
1027                                                 $newFieldList = implode(',', array_intersect(t3lib_div::trimExplode(',', $this->fieldList), t3lib_div::trimExplode(',', implode($fieldArr, ','), 1)));
1028                                                 $this->cObj->DBgetUpdate($this->theTable, $theUid, $fD, $newFieldList, TRUE);
1029                                                 $this->currentArr = $GLOBALS['TSFE']->sys_page->getRawRecord($this->theTable, $theUid);
1030                                                 $this->userProcess_alt($this->conf['setfixed.']['userFunc_afterSave'], $this->conf['setfixed.']['userFunc_afterSave.'], array('rec'=>$this->currentArr, 'origRec'=>$origArr));
1031                                         }
1032
1033                                                 // Outputting template
1034                                         $this->markerArray = $this->cObj->fillInMarkerArray($this->markerArray, $origArr, '', TRUE, 'FIELD_', $this->recInMarkersHSC);
1035                                         $content = $this->getPlainTemplate('###TEMPLATE_SETFIXED_OK_'.$sFK.'###');
1036                                         if (!$content)  {$content = $this->getPlainTemplate('###TEMPLATE_SETFIXED_OK###');}
1037
1038                                                 // Compiling email
1039                                         $this->compileMail(
1040                                                 'SETFIXED_'.$sFK,
1041                                                 array($origArr),
1042                                                 $origArr[$this->conf['email.']['field']],
1043                                                 $this->conf['setfixed.']
1044                                         );
1045                                                 // Clearing cache if set:
1046                                         $this->clearCacheIfSet();
1047                                 } else $content = $this->getPlainTemplate('###TEMPLATE_SETFIXED_FAILED###');
1048                         } else $content = $this->getPlainTemplate('###TEMPLATE_SETFIXED_FAILED###');
1049                 }
1050                 return $content;
1051         }
1052
1053         /*****************************************
1054          *
1055          * Template processing functions
1056          *
1057          *****************************************/
1058
1059         /**
1060          * Remove required parts from template code string
1061          *       Works like this:
1062          *               - 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.
1063          *               - These subparts are all removed, except if the field is listed in $failure string!
1064          *
1065          *              Only fields that are found in $this->requiredArr is processed.
1066          *
1067          * @param string $templateCode The template HTML code
1068          * @param string $failure Comma list of fields which has errors (and therefore should not be removed)
1069          * @return string The processed template HTML code
1070          */
1071         function removeRequired($templateCode, $failure) {
1072                 foreach ($this->requiredArr as $theField) {
1073                         if (!t3lib_div::inList($failure, $theField)) {
1074                                 $templateCode = $this->cObj->substituteSubpart($templateCode, '###SUB_REQUIRED_FIELD_'.$theField.'###', '');
1075                         }
1076                 }
1077                 return $templateCode;
1078         }
1079
1080         /**
1081          * Returns template subpart HTML code for the key given
1082          *
1083          * @param string $key Subpart marker to return subpart for.
1084          * @param array $r Optional data record array. If set, then all fields herein will also be substituted if found as markers in the template
1085          * @return string The subpart with all markers found in current $this->markerArray substituted.
1086          * @see tslib_cObj::fillInMarkerArray()
1087          */
1088         function getPlainTemplate($key, $r = '') {
1089                 if ($this->conf['debug']) {
1090                         debug('getPlainTemplate(): ' . $key, 1);
1091                 }
1092                 $templateCode = $this->cObj->getSubpart($this->templateCode, $key);
1093                 $this->setCObjects($templateCode, is_array($r) ? $r : array());
1094                 return $this->cObj->substituteMarkerArray(
1095                                 $templateCode,
1096                                 is_array($r) ? $this->cObj->fillInMarkerArray($this->markerArray, $r, '', TRUE, 'FIELD_', $this->recInMarkersHSC) : $this->markerArray
1097                         );
1098         }
1099
1100         /**
1101          * Modifies input array for passing on to tslib_cObj::getUpdateJS() which produces some JavaScript for form evaluation or the like.
1102          *
1103          * @param array $inputArr The data array
1104          * @return array The processed input array
1105          * @see displayCreateScreen(), displayEditForm(), tslib_cObj::getUpdateJS()
1106          */
1107         function modifyDataArrForFormUpdate($inputArr) {
1108                 if (is_array($this->conf[$this->cmdKey.'.']['evalValues.'])) {
1109                         foreach ($this->conf[$this->cmdKey.'.']['evalValues.'] as $theField => $theValue) {
1110                                 $listOfCommands = t3lib_div::trimExplode(',', $theValue, 1);
1111                                 foreach ($listOfCommands as $cmd) {
1112                                                 // Point is to enable parameters after each command enclosed in brackets [..]. These will be in position 1 in the array.
1113                                         $cmdParts = preg_split('/\[|\]/', $cmd);
1114                                         $theCmd = trim($cmdParts[0]);
1115                                         switch($theCmd) {
1116                                                 case 'twice':
1117                                                         if (isset($inputArr[$theField])) {
1118                                                                 if (!isset($inputArr[$theField.'_again'])) {
1119                                                                         $inputArr[$theField.'_again'] = $inputArr[$theField];
1120                                                                 }
1121                                                                 $this->additionalUpdateFields .= ','.$theField.'_again';
1122                                                         }
1123                                                 break;
1124                                         }
1125                                 }
1126                         }
1127                 }
1128                 if (is_array($this->conf['parseValues.'])) {
1129                         foreach ($this->conf['parseValues.'] as $theField => $theValue) {
1130                                 $listOfCommands = t3lib_div::trimExplode(',', $theValue, 1);
1131                                 foreach ($listOfCommands as $cmd) {
1132                                                 // Point is to enable parameters after each command enclosed in brackets [..]. These will be in position 1 in the array.
1133                                         $cmdParts = preg_split('/\[|\]/', $cmd);
1134                                         $theCmd = trim($cmdParts[0]);
1135                                         switch($theCmd) {
1136                                                 case 'multiple':
1137                                                         if (isset($inputArr[$theField]) && !$this->isPreview()) {
1138                                                                 $inputArr[$theField] = explode(',', $inputArr[$theField]);
1139                                                         }
1140                                                 break;
1141                                                 case 'checkArray':
1142                                                         if ($inputArr[$theField] && !$this->isPreview()) {
1143                                                                 for($a=0;$a<=30;$a++) {
1144                                                                         if ($inputArr[$theField] & pow(2, $a)) {
1145                                                                                 $alt_theField = $theField.']['.$a;
1146                                                                                 $inputArr[$alt_theField] = 1;
1147                                                                                 $this->additionalUpdateFields.=','.$alt_theField;
1148                                                                         }
1149                                                                 }
1150                                                         }
1151                                                 break;
1152                                         }
1153                                 }
1154                         }
1155                 }
1156
1157                 $inputArr = $this->userProcess_alt(
1158                         $this->conf['userFunc_updateArray'],
1159                         $this->conf['userFunc_updateArray.'],
1160                         $inputArr
1161                 );
1162
1163                 return $this->escapeHTML($inputArr);
1164         }
1165
1166         /**
1167          * 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.
1168          *
1169          * @param string $templateCode The current template code string. Is used to check if the marker string is found and if not, the content object is not rendered!
1170          * @param array $currentArr An alternative data record array (if empty then $this->dataArr is used)
1171          * @param mixed $markerArray 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.
1172          * @param string $specialPrefix Optional prefix to set for the marker strings.
1173          * @return array The processed $markerArray (if given).
1174          */
1175         function setCObjects($templateCode, $currentArr = array(), $markerArray = '', $specialPrefix = '') {
1176                 if (is_array($this->conf['cObjects.'])) {
1177
1178                         foreach ($this->conf['cObjects.'] as $theKey => $theConf) {
1179                                 if (!strstr($theKey, '.')) {
1180                                         if (strstr($templateCode, '###' . $specialPrefix . 'CE_' . $theKey . '###')) {
1181                                                 $cObjCode = $this->cObj->cObjGetSingle($this->conf['cObjects.'][$theKey], $this->conf['cObjects.'][$theKey.'.'], 'cObjects.'.$theKey);
1182
1183                                                 if (!is_array($markerArray)) {
1184                                                         $this->markerArray['###'.$specialPrefix.'CE_'.$theKey.'###'] = $cObjCode;
1185                                                 } else {
1186                                                         $markerArray['###'.$specialPrefix.'CE_'.$theKey.'###'] = $cObjCode;
1187                                                 }
1188                                         }
1189                                         if (strstr($templateCode, '###' . $specialPrefix . 'PCE_' . $theKey . '###')) {
1190                                                 $local_cObj =t3lib_div::makeInstance('tslib_cObj');
1191                                                 $local_cObj->start(count($currentArr) ? $currentArr : $this->dataArr, $this->theTable);
1192                                                 $cObjCode = $local_cObj->cObjGetSingle($this->conf['cObjects.'][$theKey], $this->conf['cObjects.'][$theKey.'.'], 'cObjects.'.$theKey);
1193
1194                                                 if (!is_array($markerArray)) {
1195                                                         $this->markerArray['###'.$specialPrefix.'PCE_'.$theKey.'###'] = $cObjCode;
1196                                                 } else {
1197                                                         $markerArray['###'.$specialPrefix.'PCE_'.$theKey.'###'] = $cObjCode;
1198                                                 }
1199                                         }
1200                                 }
1201                         }
1202                 }
1203                 return $markerArray;
1204         }
1205
1206         /*****************************************
1207          *
1208          * Emailing
1209          *
1210          *****************************************/
1211
1212         /**
1213          * Sends info mail to user
1214          *
1215          * @return string HTML content message
1216          * @see init(), compileMail(), sendMail()
1217          */
1218         function sendInfoMail() {
1219                 if ($this->conf['infomail'] && $this->conf['email.']['field']) {
1220                         $fetch = t3lib_div::_GP('fetch');
1221                         if ($fetch) {
1222                                         // Getting infomail config.
1223                                 $key = trim(t3lib_div::_GP('key'));
1224                                 if (is_array($this->conf['infomail.'][$key.'.'])) {
1225                                         $config = $this->conf['infomail.'][$key.'.'];
1226                                 } else {
1227                                         $config = $this->conf['infomail.']['default.'];
1228                                 }
1229                                 $pidLock = '';
1230                                 if (!$config['dontLockPid']) {
1231                                         $pidLock='AND pid IN ('.$this->thePid.') ';
1232                                 }
1233
1234                                         // Getting records
1235                                 if (t3lib_utility_Math::canBeInterpretedAsInteger($fetch)) {
1236                                         $DBrows = $GLOBALS['TSFE']->sys_page->getRecordsByField($this->theTable, 'uid', $fetch, $pidLock, '', '', '1');
1237                                 } elseif ($fetch) {     // $this->conf['email.']['field'] must be a valid field in the table!
1238                                         $DBrows = $GLOBALS['TSFE']->sys_page->getRecordsByField($this->theTable, $this->conf['email.']['field'], $fetch, $pidLock, '', '', '100');
1239                                 }
1240
1241                                         // Processing records
1242                                 if (is_array($DBrows)) {
1243                                         $recipient = $DBrows[0][$this->conf['email.']['field']];
1244                                         $this->compileMail($config['label'], $DBrows, $recipient, $this->conf['setfixed.']);
1245                                 } elseif (t3lib_div::validEmail($fetch)) {
1246                                         $this->sendMail($fetch, '', trim($this->cObj->getSubpart($this->templateCode, '###'.$this->emailMarkPrefix.'NORECORD###')));
1247                                 }
1248
1249                                 $content = $this->getPlainTemplate('###TEMPLATE_INFOMAIL_SENT###');
1250                         } else {
1251                                 $content = $this->getPlainTemplate('###TEMPLATE_INFOMAIL###');
1252                         }
1253                 } else $content='Error: infomail option is not available or emailField is not setup in TypoScript';
1254                 return $content;
1255         }
1256
1257         /**
1258          * 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.
1259          *
1260          * @param string $key A key which together with $this->emailMarkPrefix will identify the part from the template code to use for the email.
1261          * @param array $DBrows An array of records which fields are substituted in the templates
1262          * @param mixed $recipient 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.
1263          * @param array $setFixedConfig Additional fields to set in the markerArray used in the substitution process
1264          * @return void
1265          */
1266         function compileMail($key, $DBrows, $recipient, $setFixedConfig = array()) {
1267                 $GLOBALS['TT']->push('compileMail');
1268                 $mailContent = '';
1269                 $key = $this->emailMarkPrefix.$key;
1270
1271                 $userContent['all'] = trim($this->cObj->getSubpart($this->templateCode, '###'.$key.'###'));
1272                 $adminContent['all'] = trim($this->cObj->getSubpart($this->templateCode, '###'.$key.'-ADMIN###'));
1273                 $userContent['rec'] = $this->cObj->getSubpart($userContent['all'], '###SUB_RECORD###');
1274                 $adminContent['rec'] = $this->cObj->getSubpart($adminContent['all'], '###SUB_RECORD###');
1275
1276                 foreach ($DBrows as $r) {
1277                         $markerArray = $this->cObj->fillInMarkerArray($this->markerArray, $r, '', 0);
1278                         $markerArray = $this->setCObjects($userContent['rec'] . $adminContent['rec'], $r, $markerArray, 'ITEM_');
1279                         $markerArray['###SYS_AUTHCODE###'] = $this->authCode($r);
1280                         $markerArray = $this->setfixed($markerArray, $setFixedConfig, $r);
1281
1282                         if ($userContent['rec'])        $userContent['accum'] .=$this->cObj->substituteMarkerArray($userContent['rec'], $markerArray);
1283                         if ($adminContent['rec'])       $adminContent['accum'].=$this->cObj->substituteMarkerArray($adminContent['rec'], $markerArray);
1284                 }
1285
1286                 if ($userContent['all'])        $userContent['final'] .=$this->cObj->substituteSubpart($userContent['all'], '###SUB_RECORD###', $userContent['accum']);
1287                 if ($adminContent['all'])       $adminContent['final'].=$this->cObj->substituteSubpart($adminContent['all'], '###SUB_RECORD###', $adminContent['accum']);
1288
1289                 if (t3lib_utility_Math::canBeInterpretedAsInteger($recipient)) {
1290                         $fe_userRec = $GLOBALS['TSFE']->sys_page->getRawRecord('fe_users', $recipient);
1291                         $recipient=$fe_userRec['email'];
1292                 }
1293
1294                 $GLOBALS['TT']->setTSlogMessage('Template key: ###'.$key.'###, userContentLength: '.strlen($userContent['final']).', adminContentLength: '.strlen($adminContent['final']));
1295
1296                 $this->sendMail($recipient, $this->conf['email.']['admin'], $userContent['final'], $adminContent['final']);
1297                 $GLOBALS['TT']->pull();
1298         }
1299
1300         /**
1301          * Actually sends the requested mails (through $this->cObj->sendNotifyEmail or through $this->sendHTMLMail).
1302          * As of TYPO3 v4.3 with autoloader, a check for $GLOBALS['TSFE']->config['config']['incT3Lib_htmlmail'] has been included for backwards compatibility.
1303          *
1304          * @param string $recipient Recipient email address (or list)
1305          * @param string $recipient Possible "admin" email address. Will enable sending of admin emails if also $adminContent is provided
1306          * @param string $content Content for the regular email to user
1307          * @param string $adminContent Content for the admin email to administrator
1308          * @return void
1309          * @access private
1310          * @see compileMail(), sendInfoMail()
1311          */
1312         function sendMail($recipient, $admin, $content = '', $adminContent = '') {
1313                         // Admin mail:
1314                 if ($admin && $adminContent) {
1315                         if (!$this->isHTMLContent($adminContent) || !$GLOBALS['TSFE']->config['config']['incT3Lib_htmlmail']) {
1316                                 $admMail = $this->cObj->sendNotifyEmail(
1317                                                                         strip_tags($adminContent),
1318                                                                         $admin,
1319                                                                         '',
1320                                                                         $this->conf['email.']['from'],
1321                                                                         $this->conf['email.']['fromName'],
1322                                                                         $recipient
1323                                                         );
1324                         } else {
1325                                 $this->sendHTMLMail($adminContent,
1326                                                                         $admin,
1327                                                                         '',
1328                                                                         $this->conf['email.']['from'],
1329                                                                         $this->conf['email.']['fromName'],
1330                                                                         $recipient
1331                                                         );
1332                         }
1333                 }
1334                         // user mail:
1335                 if (!$this->isHTMLContent($content) || !$GLOBALS['TSFE']->config['config']['incT3Lib_htmlmail']) {
1336                         $this->cObj->sendNotifyEmail(
1337                                                                 strip_tags($content),
1338                                                                 $recipient,
1339                                                                 '',
1340                                                                 $this->conf['email.']['from'],
1341                                                                 $this->conf['email.']['fromName']
1342                                                 );
1343                 } else {
1344                         $this->sendHTMLMail($content,
1345                                                                 $recipient,
1346                                                                 '',
1347                                                                 $this->conf['email.']['from'],
1348                                                                 $this->conf['email.']['fromName']
1349                                                 );
1350                 }
1351         }
1352
1353         /**
1354          * Detects if content is HTML (looking for <html> tag as first and last in string)
1355          *
1356          * @param string $c Content string to test
1357          * @return boolean Returns TRUE if the content begins and ends with <html></html>-tags
1358          */
1359         function isHTMLContent($c) {
1360                 $c = trim($c);
1361                 $first = strtolower(substr($c, 0, 6));
1362                 $last = strtolower(substr($c, -7));
1363                 if ($first . $last == '<html></html>') {
1364                         return 1;
1365                 }
1366         }
1367
1368         /**
1369          * Sending HTML email, using same parameters as tslib_cObj::sendNotifyEmail()
1370          *
1371          * @param string $content The message content. If blank, no email is sent.
1372          * @param string $recipient Comma list of recipient email addresses
1373          * @param string $dummy IGNORE this parameter
1374          * @param string $fromEmail "From" email address
1375          * @param string $fromName Optional "From" name
1376          * @param string $replyTo Optional "Reply-To" header email address.
1377          * @return void
1378          * @access private
1379          * @see sendMail(), tslib_cObj::sendNotifyEmail()
1380          */
1381         function sendHTMLMail($content, $recipient, $dummy, $fromEmail, $fromName, $replyTo = '') {
1382                 if (trim($recipient) && trim($content)) {
1383                         $parts = preg_split('/<title>|<\/title>/i', $content, 3);
1384                         $subject = trim($parts[1]) ? trim($parts[1]) : 'TYPO3 FE Admin message';
1385
1386                         $Typo3_htmlmail = t3lib_div::makeInstance('t3lib_htmlmail');
1387                         $Typo3_htmlmail->start();
1388                         $Typo3_htmlmail->useBase64();
1389
1390                         $Typo3_htmlmail->subject = $subject;
1391                         $Typo3_htmlmail->from_email = $fromEmail;
1392                         $Typo3_htmlmail->from_name = $fromName;
1393                         $Typo3_htmlmail->replyto_email = $replyTo ? $replyTo : $fromEmail;
1394                         $Typo3_htmlmail->replyto_name = $replyTo ? '' : $fromName;
1395                         $Typo3_htmlmail->organisation = '';
1396                         $Typo3_htmlmail->priority = 3;
1397
1398                                 // HTML
1399                                 // Fetches the content of the page
1400                         $Typo3_htmlmail->theParts['html']['content'] = $content;
1401                         $Typo3_htmlmail->theParts['html']['path'] = '';
1402                         $Typo3_htmlmail->extractMediaLinks();
1403                         $Typo3_htmlmail->extractHyperLinks();
1404                         $Typo3_htmlmail->fetchHTMLMedia();
1405                                 // 0 = relative
1406                         $Typo3_htmlmail->substMediaNamesInHTML(0);
1407                         $Typo3_htmlmail->substHREFsInHTML();
1408                         $Typo3_htmlmail->setHTML($Typo3_htmlmail->encodeMsg($Typo3_htmlmail->theParts['html']['content']));
1409
1410                                 // PLAIN
1411                         $Typo3_htmlmail->addPlain('');
1412
1413                                 // SET Headers and Content
1414                         $Typo3_htmlmail->setHeaders();
1415                         $Typo3_htmlmail->setContent();
1416                         $Typo3_htmlmail->setRecipient($recipient);
1417
1418                         $Typo3_htmlmail->sendtheMail();
1419                 }
1420         }
1421
1422         /*****************************************
1423          *
1424          * Various helper functions
1425          *
1426          *****************************************/
1427
1428         /**
1429          * 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.
1430          * This allows to authenticate editing without having a fe_users login
1431          * Uses $this->authCode which is set in init() by "t3lib_div::_GP('aC');"
1432          *
1433          * @param array $r The data array for which to evaluate authentication
1434          * @return boolean TRUE if authenticated OK
1435          * @see authCode(), init()
1436          */
1437         function aCAuth($r) {
1438                 if ($this->authCode && !strcmp($this->authCode, $this->authCode($r))) {
1439                         return TRUE;
1440                 }
1441         }
1442
1443         /**
1444          * Creating authentication hash string based on input record and the fields listed in TypoScript property "authcodeFields"
1445          *
1446          * @param array $r The data record
1447          * @param string $extra Additional string to include in the hash
1448          * @return string Hash string of $this->codeLength (if TypoScript "authcodeFields" was set)
1449          * @see aCAuth()
1450          */
1451         function authCode($r, $extra = '') {
1452                 $l = $this->codeLength;
1453                 if ($this->conf['authcodeFields']) {
1454                         $fieldArr = t3lib_div::trimExplode(',', $this->conf['authcodeFields'], 1);
1455                         $value = '';
1456                         foreach ($fieldArr as $field) {
1457                                 $value .= $r[$field].'|';
1458                         }
1459                         $value .= $extra.'|'.$this->conf['authcodeFields.']['addKey'];
1460                         if ($this->conf['authcodeFields.']['addDate']) {
1461                                 $value .= '|'.date($this->conf['authcodeFields.']['addDate']);
1462                         }
1463                         $value .= $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'];
1464                         return substr(md5($value), 0, $l);
1465                 }
1466         }
1467
1468         /**
1469          * Adding keys to the marker array with "setfixed" GET parameters
1470          *
1471          * @param array $markerArray Marker-array to modify/add a key to.
1472          * @param array $setfixed TypoScript properties configuring "setfixed" for the plugin. Basically this is $this->conf['setfixed.'] passed along.
1473          * @param array $r The data record
1474          * @return array Processed $markerArray
1475          * @see compileMail()
1476          */
1477         function setfixed($markerArray, $setfixed, $r) {
1478                 if (is_array($setfixed)) {
1479                         foreach ($setfixed as $theKey => $data) {
1480                                 if (!strcmp($theKey, 'DELETE')) {
1481                                         $recCopy = $r;
1482                                         $string = '&cmd=setfixed&sFK='.rawurlencode($theKey).'&rU='.$r['uid'];
1483                                         $string .= '&aC='.$this->setfixedHash($recCopy, $data['_FIELDLIST']);
1484                                         $markerArray['###SYS_SETFIXED_DELETE###'] = $string;
1485                                         $markerArray['###SYS_SETFIXED_HSC_DELETE###'] = htmlspecialchars($string);
1486                                 } elseif (strstr($theKey, '.')) {
1487                                         $theKey = substr($theKey, 0, -1);
1488                                         if (is_array($data)) {
1489                                                 $recCopy = $r;
1490                                                 $string = '&cmd=setfixed&sFK='.rawurlencode($theKey).'&rU='.$r['uid'];
1491                                                 foreach ($data as $fieldName => $fieldValue) {
1492                                                         $string .= '&fD%5B'.$fieldName.'%5D='.rawurlencode($fieldValue);
1493                                                         $recCopy[$fieldName]=$fieldValue;
1494                                                 }
1495                                                 $string .= '&aC='.$this->setfixedHash($recCopy, $data['_FIELDLIST']);
1496                                                 $markerArray['###SYS_SETFIXED_'.$theKey.'###'] = $string;
1497                                                 $markerArray['###SYS_SETFIXED_HSC_'.$theKey.'###'] = htmlspecialchars($string);
1498                                         }
1499                                 }
1500                         }
1501                 }
1502                 return $markerArray;
1503         }
1504
1505         /**
1506          * Creating hash string for setFixed. Much similar to authCode()
1507          *
1508          * @param array $recCopy The data record
1509          * @param string $fields List of fields to use
1510          * @return string Hash string of $this->codeLength (if TypoScript "authcodeFields" was set)
1511          * @see setfixed(), authCode()
1512          */
1513         function setfixedHash($recCopy, $fields = '') {
1514                 if ($fields) {
1515                         $fieldArr = t3lib_div::trimExplode(',', $fields, 1);
1516                         foreach ($fieldArr as $k => $v) {
1517                                 $recCopy_temp[$k]=$recCopy[$v];
1518                         }
1519                 } else {
1520                         $recCopy_temp = $recCopy;
1521                 }
1522                 $encStr = implode('|', $recCopy_temp) . '|' . $this->conf['authcodeFields.']['addKey'] . '|' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'];
1523                 $hash = substr(md5($encStr), 0, $this->codeLength);
1524                 return $hash;
1525         }
1526
1527         /**
1528          * Returns TRUE if preview display is on.
1529          *
1530          * @return boolean
1531          */
1532         function isPreview() {
1533                 return ($this->conf[$this->cmdKey.'.']['preview'] && $this->preview);
1534         }
1535
1536         /**
1537          * Creates an instance of class "t3lib_basicFileFunctions" in $this->fileFunc (if not already done)
1538          *
1539          * @return void
1540          */
1541         function createFileFuncObj() {
1542                 if (!$this->fileFunc) {
1543                         $this->fileFunc = t3lib_div::makeInstance('t3lib_basicFileFunctions');
1544                 }
1545         }
1546
1547         /**
1548          * If TypoScript property clearCacheOfPages is set then all page ids in this value will have their cache cleared
1549          *
1550          * @return void
1551          */
1552         function clearCacheIfSet() {
1553                 if ($this->conf['clearCacheOfPages']) {
1554                         $cc_pidList = $GLOBALS['TYPO3_DB']->cleanIntList($this->conf['clearCacheOfPages']);
1555                         $GLOBALS['TSFE']->clearPageCacheContent_pidList($cc_pidList);
1556                 }
1557         }
1558
1559         /**
1560          * 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
1561          *
1562          * @param string $theField Field name
1563          * @param string $theCmd Command identifier string
1564          * @param string $label Alternative label, shown if no other error string was found
1565          * @return string The error message string
1566          */
1567         function getFailure($theField, $theCmd, $label) {
1568                 return isset($this->conf['evalErrors.'][$theField.'.'][$theCmd]) ? $this->conf['evalErrors.'][$theField.'.'][$theCmd] : $label;
1569         }
1570
1571         /**
1572          * Will escape HTML-tags
1573          *
1574          * @param mixed $var The unescaped data
1575          * @return mixed The processed input data
1576          */
1577         function escapeHTML($var) {
1578                 if (is_array($var)) {
1579                         foreach ($var as $k => $value) {
1580                                 $var[$k] = $this->escapeHTML($var[$k]);
1581                         }
1582                 } else {
1583                         $var = htmlspecialchars($var, ENT_NOQUOTES);
1584                 }
1585                 return $var;
1586         }
1587 }
1588
1589
1590 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['media/scripts/fe_adminLib.inc'])) {
1591         include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['media/scripts/fe_adminLib.inc']);
1592 }
1593 ?>