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