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