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