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