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