TYPO3 API  SVNRelease
class.tslib_content.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003  * Copyright notice
00004  *
00005  * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
00006  * All rights reserved
00007  *
00008  * This script is part of the TYPO3 project. The TYPO3 project is
00009  * free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * The GNU General Public License can be found at
00015  * http://www.gnu.org/copyleft/gpl.html.
00016  * A copy is found in the textfile GPL.txt and important notices to the license
00017  * from the author is found in LICENSE.txt distributed with these scripts.
00018  *
00019  *
00020  * This script is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * This copyright notice MUST APPEAR in all copies of the script!
00026  ***************************************************************/
00027 /**
00028  * Contains classes for Content Rendering based on TypoScript Template configuration
00029  *
00030  * $Id: class.tslib_content.php 10547 2011-02-22 20:03:57Z lolli $
00031  * Revised for TYPO3 3.6 June/2003 by Kasper Skårhøj
00032  * XHTML compliant
00033  *
00034  * class tslib_cObj         :       All main TypoScript features, rendering of content objects (cObjects). This class is the backbone of TypoScript Template rendering.
00035  * class tslib_controlTable     :       Makes a table CTABLE (TS cObject)
00036  * class tslib_tableOffset      :       Makes a table-offset (TS)
00037  * class tslib_frameset         :       Generates framesets (TS)
00038  *
00039  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00040  */
00041 /**
00042  * [CLASS/FUNCTION INDEX of SCRIPT]
00043  *
00044  *
00045  *
00046  * 256: class tslib_cObj
00047  * 353:     function start($data,$table='')
00048  * 387:     function setParent($data,$currentRecord)
00049  *
00050  * SECTION: CONTENT_OBJ:
00051  * 412:     function getCurrentVal()
00052  * 423:     function setCurrentVal($value)
00053  * 436:     function cObjGet($setup,$addKey='')
00054  * 460:     function cObjGetSingle($name,$conf,$TSkey='__')
00055  *
00056  * SECTION: Functions rendering content objects (cObjects)
00057  * 629:     function HTML($conf)
00058  * 640:     function TEXT($conf)
00059  * 651:     function CLEARGIF($conf)
00060  * 670:     function COBJ_ARRAY($conf,$ext='')
00061  * 706:     function USER($conf,$ext='')
00062  * 733:     function FILE($conf)
00063  * 749:     function IMAGE($conf)
00064  * 768:     function IMG_RESOURCE($conf)
00065  * 780:     function IMGTEXT($conf)
00066  * 1203:     function CONTENT($conf)
00067  * 1290:     function RECORDS($conf)
00068  * 1370:     function HMENU($conf)
00069  * 1402:     function CTABLE ($conf)
00070  * 1440:     function OTABLE ($conf)
00071  * 1455:     function COLUMNS ($conf)
00072  * 1534:     function HRULER ($conf)
00073  * 1559:     function CASEFUNC ($conf)
00074  * 1584:     function LOAD_REGISTER($conf,$name)
00075  * 1624:     function FORM($conf,$formData='')
00076  * 2145:     function SEARCHRESULT($conf)
00077  * 2311:     function PHP_SCRIPT($conf,$ext='')
00078  * 2354:     function TEMPLATE($conf)
00079  * 2505:     function MULTIMEDIA($conf)
00080  *
00081  * SECTION: Various helper functions for content objects:
00082  * 2592:     function getSlidePids($pidList, $pidConf)
00083  * 2623:     function getFieldDefaultValue($noValueInsert, $fieldName, $defaultVal)
00084  * 2641:     function cImage($file,$conf)
00085  * 2669:     function getBorderAttr($borderAttr)
00086  * 2685:     function imageLinkWrap($string,$imageFile,$conf)
00087  * 2765:     function fileResource($fName, $addParams='alt="" title=""')
00088  * 2788:     function lastChanged($tstamp)
00089  * 2805:     function linkWrap($content,$wrap)
00090  * 2824:     function getAltParam($conf, $longDesc=TRUE)
00091  * 2859:     function cleanFormName($name)
00092  * 2875:     function getATagParams($conf, $addGlobal=1)
00093  *
00094  * SECTION: HTML template processing functions
00095  * 2922:     function getSubpart($content, $marker)
00096  * 2938:     function substituteSubpart($content,$marker,$subpartContent,$recursive=1)
00097  * 2951:     function substituteMarker($content,$marker,$markContent)
00098  * 2971:     function substituteMarkerArrayCached($content,$markContentArray=array(),$subpartContentArray=array(),$wrappedSubpartContentArray=array())
00099  * 3069:     function substituteMarkerArray($content,$markContentArray,$wrap='',$uppercase=0)
00100  * 3081:     function substituteMarkerInObject(&$tree, $markContentArray)
00101  * 3104:     function fillInMarkerArray($markContentArray, $row, $fieldList='', $nl2br=TRUE, $prefix='FIELD_', $HSC=FALSE)
00102  *
00103  * SECTION: "stdWrap" + sub functions
00104  * 3167:     function stdWrap($content,$conf)
00105  * 3364:     function numRows($conf)
00106  * 3388:     function listNum($content,$listNum,$char)
00107  * 3408:     function checkIf($conf)
00108  * 3471:     function filelist($data)
00109  * 3553:     function clean_directory($theDir)
00110  * 3571:     function HTMLparser_TSbridge($theValue, $conf)
00111  * 3585:     function dataWrap($content,$wrap)
00112  * 3598:     function insertData($str)
00113  * 3628:     function prefixComment($str,$conf,$content)
00114  * 3652:     function substring($content,$options)
00115  * 3670:     function crop($content,$options)
00116  * 3702:     function removeBadHTML($text, $conf)
00117  * 3746:     function textStyle($theValue, $conf)
00118  * 3813:     function tableStyle($theValue, $conf)
00119  * 3854:     function addParams($content,$conf)
00120  * 3895:     function filelink($theValue, $conf)
00121  * 3966:     function locDataJU($jumpUrl,$conf)
00122  * 3997:     function calc($val)
00123  * 4026:     function calcIntExplode($delim, $string)
00124  * 4046:     function splitObj($value, $conf)
00125  * 4108:     function parseFunc($theValue, $conf, $ref='')
00126  * 4218:     function _parseFunc ($theValue, $conf)
00127  * 4424:     function encaps_lineSplit($theValue, $conf)
00128  * 4507:     function http_makelinks($data,$conf)
00129  * 4574:     function mailto_makelinks($data,$conf)
00130  * 4617:     function getImgResource($file,$fileArray)
00131  *
00132  * SECTION: Data retrieval etc.
00133  * 4810:     function getFieldVal($field)
00134  * 4830:     function getData($string,$fieldArray)
00135  * 4975:     function rootLineValue($key,$field,$slideBack=0,$altRootLine='')
00136  * 4997:     function getGlobal($var, $source=NULL)
00137  * 5033:     function getKey($key,$arr)
00138  * 5056:     function TCAlookup($inputValue,$conf)
00139  *
00140  * SECTION: Link functions (typolink)
00141  * 5116:     function typoLink($linktxt, $conf)
00142  * 5481:     function typoLink_URL($conf)
00143  * 5499:     function getTypoLink($label,$params,$urlParameters=array(),$target='')
00144  * 5526:     function getTypoLink_URL($params,$urlParameters=array(),$target='')
00145  * 5538:     function typolinkWrap($conf)
00146  * 5551:     function currentPageUrl($urlParameters=array(),$id=0)
00147  * 5564:     function getClosestMPvalueForPage($pageId, $raw=FALSE)
00148  * 5619:     function getMailTo($mailAddress,$linktxt,$initP='?')
00149  * 5658:     function getQueryArguments($conf,$overruleQueryArgs=array(),$forceArgs=FALSE)
00150  *
00151  * SECTION: Miscellaneous functions, stand alone
00152  * 5754:     function wrap($content,$wrap,$char='|')
00153  * 5770:     function noTrimWrap($content,$wrap)
00154  * 5784:     function wrapSpace($content, $wrap)
00155  * 5810:     function callUserFunction($funcName,$conf,$content)
00156  * 5851:     function processParams($params)
00157  * 5869:     function keywords($content)
00158  * 5886:     function caseshift($theValue, $case)
00159  * 5911:     function HTMLcaseshift($theValue, $case)
00160  * 5940:     function bytes($sizeInBytes,$labels)
00161  * 5951:     function calcAge($seconds,$labels)
00162  * 5983:     function sendNotifyEmail($msg, $recipients, $cc, $email_from, $email_fromName='', $replyTo='')
00163  * 6010:     function URLqMark($url,$params)
00164  * 6026:     function checkEmail($email)
00165  * 6038:     function clearTSProperties($TSArr,$propList)
00166  * 6057:     function mergeTSRef($confArr,$prop)
00167  * 6080:     function joinTSarrays($conf,$old_conf)
00168  * 6103:     function gifBuilderTextBox($gifbuilderConf, $conf, $text)
00169  * 6159:     function linebreaks($string,$chars,$maxLines=0)
00170  * 6190:     function getUpdateJS($dataArray, $formName, $arrPrefix, $fieldList)
00171  *
00172  * SECTION: Database functions, making of queries
00173  * 6260:     function DBgetDelete($table, $uid, $doExec=FALSE)
00174  * 6292:     function DBgetUpdate($table, $uid, $dataArr, $fieldList, $doExec=FALSE)
00175  * 6334:     function DBgetInsert($table, $pid, $dataArr, $fieldList, $doExec=FALSE)
00176  * 6371:     function DBmayFEUserEdit($table,$row, $feUserRow, $allowedGroups='',$feEditSelf=0)
00177  * 6411:     function DBmayFEUserEditSelect($table,$feUserRow,$allowedGroups='',$feEditSelf=0)
00178  * 6451:     function enableFields($table,$show_hidden=0)
00179  * 6475:     function getTreeList($id,$depth,$begin=0,$dontCheckEnableFields=FALSE,$addSelectFields='',$moreWhereClauses='', $prevId_array=array(), $recursionLevel=0)
00180  * 6583:     function whereSelectFromList($field,$value)
00181  * 6601:     function exec_mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause='',$groupBy='',$orderBy='',$limit='')
00182  * 6628:     function exec_mm_query_uidList($select,$local_table_uidlist,$mm_table,$foreign_table='',$whereClause='',$groupBy='',$orderBy='',$limit='')
00183  * 6649:     function searchWhere($sw,$searchFieldList,$searchTable='')
00184  * 6685:     function exec_getQuery($table, $conf)
00185  * 6703:     function getQuery($table, $conf, $returnQueryArray=FALSE)
00186  * 6783:     function getWhere($table,$conf, $returnQueryArray=FALSE)
00187  * 6878:     function checkPidArray($listArr)
00188  * 6902:     function checkPid($uid)
00189  *
00190  * SECTION: Frontend editing functions
00191  * 6959:     function editPanel($content, $conf, $currentRecord='', $dataArr=array())
00192  * 7146:     function editIcons($content,$params, $conf=array(), $currentRecord='', $dataArr=array(),$addUrlParamStr='')
00193  * 7228:     function editPanelLinkWrap($string,$formName,$cmd,$currentRecord='',$confirm='',$nPid='')
00194  * 7270:     function editPanelLinkWrap_doWrap($string,$url,$currentRecord)
00195  * 7298:     function editPanelPreviewBorder($table,$row,$content,$thick,$conf=array())
00196  * 7320:     function isDisabled($table,$row)
00197  *
00198  *
00199  * 7351: class tslib_frameset
00200  * 7361:     function make($setup)
00201  * 7398:     function frameParams($setup, $typeNum)
00202  * 7426:     function framesetParams($setup)
00203  *
00204  *
00205  * 7459: class tslib_tableOffset
00206  * 7471:     function start($content,$offset)
00207  *
00208  *
00209  * 7549: class tslib_controlTable
00210  * 7584:     function start($offset,$cMargins)
00211  *
00212  * TOTAL FUNCTIONS: 135
00213  * (This index is automatically created/updated by the extension "extdeveval")
00214  *
00215  */
00216 
00217 
00218 
00219 /**
00220  * This class contains all main TypoScript features.
00221  * This includes the rendering of TypoScript content objects (cObjects).
00222  * Is the backbone of TypoScript Template rendering.
00223  *
00224  * There are lots of functions you can use from your include-scripts.
00225  * The class "tslib_cObj" is normally instantiated and referred to as "cObj".
00226  * When you call your own PHP-code typically through a USER or USER_INT cObject then it is this class that instantiates the object and calls the main method. Before it does so it will set (if you are using classes) a reference to itself in the internal variable "cObj" of the object. Thus you can access all functions and data from this class by $this->cObj->... from within you classes written to be USER or USER_INT content objects.
00227  *
00228  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00229  * @package TYPO3
00230  * @subpackage tslib
00231  */
00232 class tslib_cObj {
00233 
00234     var $align = array(
00235         'center',
00236         'right',
00237         'left'
00238     );
00239 
00240     /**
00241      * stdWrap functions in their correct order
00242      *
00243      * @see stdWrap()
00244      */
00245     var $stdWrapOrder = array(
00246         'stdWrapPreProcess' => 'hook', // this is a placeholder for the first Hook
00247         'setContentToCurrent' => 'boolean',
00248         'setContentToCurrent.' => 'array',
00249         'setCurrent' => 'string',
00250         'setCurrent.' => 'array',
00251         'lang.' => 'array',
00252         'data' => 'getText',
00253         'data.' => 'array',
00254         'field' => 'fieldName',
00255         'field.' => 'array',
00256         'current' => 'boolean',
00257         'current.' => 'array',
00258         'cObject' => 'cObject',
00259         'cObject.' => 'array',
00260         'numRows.' => 'array',
00261         'filelist' => 'dir',
00262         'filelist.' => 'array',
00263         'preUserFunc' => 'functionName',
00264         'stdWrapOverride' => 'hook', // this is a placeholder for the second Hook
00265         'override' => 'string',
00266         'override.' => 'array',
00267         'preIfEmptyListNum' => 'listNum',
00268         'preIfEmptyListNum.' => 'array',
00269         'ifEmpty' => 'string',
00270         'ifEmpty.' => 'array',
00271         'ifBlank' => 'string',
00272         'ifBlank.' => 'array',
00273         'listNum' => 'listNum',
00274         'listNum.' => 'array',
00275         'trim' => 'boolean',
00276         'trim.' => 'array',
00277         'stdWrap' => 'stdWrap',
00278         'stdWrap.' => 'array',
00279         'stdWrapProcess' => 'hook', // this is a placeholder for the third Hook
00280         'required' => 'boolean',
00281         'required.' => 'array',
00282         'if.' => 'array',
00283         'fieldRequired' => 'fieldName',
00284         'fieldRequired.' => 'array',
00285         'csConv' => 'string',
00286         'csConv.' => 'array',
00287         'parseFunc' => 'objectpath',
00288         'parseFunc.' => 'array',
00289         'HTMLparser' => 'boolean',
00290         'HTMLparser.' => 'array',
00291         'split.' => 'array',
00292         'prioriCalc' => 'boolean',
00293         'prioriCalc.' => 'array',
00294         'char' => 'integer',
00295         'char.' => 'array',
00296         'intval' => 'boolean',
00297         'intval.' => 'array',
00298         'numberFormat.' => 'array',
00299         'date' => 'dateconf',
00300         'date.' => 'array',
00301         'strftime' => 'strftimeconf',
00302         'strftime.' => 'array',
00303         'age' => 'boolean',
00304         'age.' => 'array',
00305         'case' => 'case',
00306         'case.' => 'array',
00307         'bytes' => 'boolean',
00308         'bytes.' => 'array',
00309         'substring' => 'parameters',
00310         'substring.' => 'array',
00311         'removeBadHTML' => 'boolean',
00312         'removeBadHTML.' => 'array',
00313         'cropHTML' => 'crop',
00314         'cropHTML.' => 'array',
00315         'stripHtml' => 'boolean',
00316         'stripHtml.' => 'array',
00317         'crop' => 'crop',
00318         'crop.' => 'array',
00319         'rawUrlEncode' => 'boolean',
00320         'rawUrlEncode.' => 'array',
00321         'htmlSpecialChars' => 'boolean',
00322         'htmlSpecialChars.' => 'array',
00323         'doubleBrTag' => 'string',
00324         'doubleBrTag.' => 'array',
00325         'br' => 'boolean',
00326         'br.' => 'array',
00327         'brTag' => 'string',
00328         'brTag.' => 'array',
00329         'encapsLines.' => 'array',
00330         'keywords' => 'boolean',
00331         'keywords.' => 'array',
00332         'innerWrap' => 'wrap',
00333         'innerWrap.' => 'array',
00334         'innerWrap2' => 'wrap',
00335         'innerWrap2.' => 'array',
00336         'fontTag' => 'wrap',
00337         'fontTag.' => 'array',
00338         'addParams.' => 'array',
00339         'textStyle.' => 'array',
00340         'tableStyle.' => 'array',
00341         'filelink.' => 'array',
00342         'preCObject' => 'cObject',
00343         'preCObject.' => 'array',
00344         'postCObject' => 'cObject',
00345         'postCObject.' => 'array',
00346         'wrapAlign' => 'align',
00347         'wrapAlign.' => 'array',
00348         'typolink.' => 'array',
00349         'TCAselectItem.' => 'array',
00350         'space' => 'space',
00351         'space.' => 'array',
00352         'spaceBefore' => 'int',
00353         'spaceBefore.' => 'array',
00354         'spaceAfter' => 'int',
00355         'spaceAfter.' => 'array',
00356         'wrap' => 'wrap',
00357         'wrap.' => 'array',
00358         'noTrimWrap' => 'wrap',
00359         'noTrimWrap.' => 'array',
00360         'wrap2' => 'wrap',
00361         'wrap2.' => 'array',
00362         'dataWrap' => 'dataWrap',
00363         'dataWrap.' => 'array',
00364         'prepend' => 'cObject',
00365         'prepend.' => 'array',
00366         'append' => 'cObject',
00367         'append.' => 'array',
00368         'wrap3' => 'wrap',
00369         'wrap3.' => 'array',
00370         'outerWrap' => 'wrap',
00371         'outerWrap.' => 'array',
00372         'insertData' => 'boolean',
00373         'insertData.' => 'array',
00374         'offsetWrap' => 'space',
00375         'offsetWrap.' => 'array',
00376         'postUserFunc' => 'functionName',
00377         'postUserFuncInt' => 'functionName',
00378         'prefixComment' => 'string',
00379         'prefixComment.' => 'array',
00380         'editIcons' => 'string',
00381         'editIcons.' => 'array',
00382         'editPanel' => 'boolean',
00383         'editPanel.' => 'array',
00384         'stdWrapPostProcess' => 'hook', // this is a placeholder for the last Hook
00385         'debug' => 'boolean',
00386         'debug.' => 'array',
00387         'debugFunc' => 'boolean',
00388         'debugFunc.' => 'array',
00389         'debugData' => 'boolean',
00390         'debugData.' => 'array'
00391     );
00392 
00393     /**
00394      * Holds ImageMagick parameters and extensions used for compression
00395      *
00396      * @see IMGTEXT()
00397      *
00398      * 0= Default
00399      * 1= Dont change! (removes all parameters for the image_object!!)
00400      * 1x = GIFs
00401      * 2x = JPGs
00402      */
00403     var $image_compression = array(
00404         10 => array(
00405             'params' => '', 'ext' => 'gif'
00406         ),
00407         11 => array(
00408             'params' => '-colors 128', 'ext' => 'gif'
00409         ),
00410         12 => array(
00411             'params' => '-colors 64', 'ext' => 'gif'
00412         ),
00413         13 => array(
00414             'params' => '-colors 32', 'ext' => 'gif'
00415         ),
00416         14 => array(
00417             'params' => '-colors 16', 'ext' => 'gif'
00418         ),
00419         15 => array(
00420             'params' => '-colors 8', 'ext' => 'gif'
00421         ),
00422 
00423         20 => array(
00424             'params' => '-quality 100', 'ext' => 'jpg'
00425         ),
00426         21 => array(
00427             'params' => '-quality 90', 'ext' => 'jpg'
00428         ),
00429         22 => array(
00430             'params' => '-quality 80', 'ext' => 'jpg'
00431         ),
00432         23 => array(
00433             'params' => '-quality 70', 'ext' => 'jpg'
00434         ),
00435         24 => array(
00436             'params' => '-quality 60', 'ext' => 'jpg'
00437         ),
00438         25 => array(
00439             'params' => '-quality 50', 'ext' => 'jpg'
00440         ),
00441         26 => array(
00442             'params' => '-quality 40', 'ext' => 'jpg'
00443         ),
00444         27 => array(
00445             'params' => '-quality 30', 'ext' => 'jpg'
00446         ),
00447         28 => array(
00448             'params' => '-quality 20', 'ext' => 'jpg'
00449         ),
00450 
00451         30 => array(
00452             'params' => '-colors 256', 'ext' => 'png'
00453         ),
00454         31 => array(
00455             'params' => '-colors 128', 'ext' => 'png'
00456         ),
00457         32 => array(
00458             'params' => '-colors 64', 'ext' => 'png'
00459         ),
00460         33 => array(
00461             'params' => '-colors 32', 'ext' => 'png'
00462         ),
00463         34 => array(
00464             'params' => '-colors 16', 'ext' => 'png'
00465         ),
00466         35 => array(
00467             'params' => '-colors 8', 'ext' => 'png'
00468         ),
00469         39 => array(
00470             'params' => '', 'ext' => 'png'
00471         ),
00472     );
00473 
00474     /**
00475      * ImageMagick parameters for image effects
00476      *
00477      * @see IMGTEXT()
00478      */
00479     var $image_effects = array(
00480         1 => '-rotate 90',
00481         2 => '-rotate 270',
00482         3 => '-rotate 180',
00483         10 => '-colorspace GRAY',
00484         11 => '-sharpen 70',
00485         20 => '-normalize',
00486         23 => '-contrast',
00487         25 => '-gamma 1.3',
00488         26 => '-gamma 0.8'
00489     );
00490 
00491     /**
00492      * Loaded with the current data-record.
00493      *
00494      * If the instance of this class is used to render records from the database those records are found in this array.
00495      * The function stdWrap has TypoScript properties that fetch field-data from this array.
00496      * @see init()
00497      */
00498     var $data = array();
00499     protected $table = '';
00500     var $oldData = array(); // Used for backup...
00501     var $alternativeData = ''; // If this is set with an array before stdWrap, it's used instead of $this->data in the data-property in stdWrap
00502     var $parameters = array(); // Used by the parseFunc function and is loaded with tag-parameters when parsing tags.
00503     var $currentValKey = 'currentValue_kidjls9dksoje';
00504     var $currentRecord = ''; // This is set to the [table]:[uid] of the record delivered in the $data-array, if the cObjects CONTENT or RECORD is in operation. Note that $GLOBALS['TSFE']->currentRecord is set to an equal value but always indicating the latest record rendered.
00505     var $currentRecordTotal = 0; // Set in cObj->RECORDS and cObj->CONTENT to the current number of records selected in a query.
00506     var $currentRecordNumber = 0; // Incremented in cObj->RECORDS and cObj->CONTENT before each record rendering.
00507     var $parentRecordNumber = 0; // Incremented in parent cObj->RECORDS and cObj->CONTENT before each record rendering.
00508     var $parentRecord = array(); // If the tslib_cObj was started from CONTENT, RECORD or SEARCHRESULT cObject's this array has two keys, 'data' and 'currentRecord' which indicates the record and data for the parent cObj.
00509     var $regObj; // This may be set as a reference to the calling object of eg. cObjGetSingle. Anyway, just use it as you like. It's used in productsLib.inc for example.
00510 
00511 
00512         // internal
00513     var $INT_include = 0; // Is set to 1 if the instance of this cObj is executed from a PHP_SCRIPT_INT -include script (see pagegen, bottom of document)
00514     var $checkPid_cache = array(); // This is used by checkPid, that checks if pages are accessible. The $checkPid_cache['page_uid'] is set TRUE or FALSE upon this check featuring a caching function for the next request.
00515     var $checkPid_badDoktypeList = '255';
00516     var $lastTypoLinkUrl = ''; // This will be set by typoLink() to the url of the most recent link created.
00517     var $lastTypoLinkTarget = ''; // DO. link target.
00518     var $lastTypoLinkLD = array();
00519     var $substMarkerCache = array(); // Caching substituteMarkerArrayCached function
00520     var $recordRegister = array(); // array that registers rendered content elements (or any table) to make sure they are not rendered recursively!
00521     var $cObjHookObjectsArr = array(); // Containig hooks for userdefined cObjects
00522     protected $stdWrapHookObjects = array(); // Containing hook objects for stdWrap
00523     protected $getImgResourceHookObjects; // Containing hook objects for getImgResource
00524 
00525     /**
00526      * @var array with members of tslib_content_abstract
00527      */
00528     protected $contentObjects = array();
00529 
00530     /**
00531      * Set to TRUE by doConvertToUserIntObject() if USER object wants to become USER_INT
00532      */
00533     public $doConvertToUserIntObject = FALSE;
00534 
00535     /**
00536      * Indicates current object type. Can hold one of OBJECTTYPE_ constants or FALSE.
00537      * The value is set and reset inside USER() function. Any time outside of
00538      * USER() it is FALSE.
00539      */
00540     protected $userObjectType = FALSE;
00541 
00542     /**
00543      * Indicates that object type is USER.
00544      *
00545      * @see tslib_cObjh::$userObjectType
00546      */
00547     const OBJECTTYPE_USER_INT = 1;
00548 
00549     /**
00550      * Indicates that object type is USER.
00551      *
00552      * @see tslib_cObjh::$userObjectType
00553      */
00554     const OBJECTTYPE_USER = 2;
00555 
00556     /**
00557      * Class constructor.
00558      * Well, it has to be called manually since it is not a real constructor function.
00559      * So after making an instance of the class, call this function and pass to it a database record and the tablename from where the record is from. That will then become the "current" record loaded into memory and accessed by the .fields property found in eg. stdWrap.
00560      *
00561      * @param   array       $data   the record data that is rendered.
00562      * @param   string      $table  the table that the data record is from.
00563      * @return  void
00564      */
00565     function start($data, $table = '') {
00566         global $TYPO3_CONF_VARS;
00567         $this->data = $data;
00568         $this->table = $table;
00569         $this->currentRecord = $table ? $table . ':' . $this->data['uid'] : '';
00570         $this->parameters = array();
00571         if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'])) {
00572             foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'] as $classArr) {
00573                 $this->cObjHookObjectsArr[$classArr[0]] = t3lib_div::getUserObj($classArr[1]);
00574             }
00575         }
00576 
00577         $this->stdWrapHookObjects = array();
00578         if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'])) {
00579             foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'] as $classData) {
00580                 $hookObject = t3lib_div::getUserObj($classData);
00581 
00582                 if (!($hookObject instanceof tslib_content_stdWrapHook)) {
00583                     throw new UnexpectedValueException(
00584                         $classData . ' must implement interface tslib_content_stdWrapHook',
00585                         1195043965
00586                     );
00587                 }
00588 
00589                 $this->stdWrapHookObjects[] = $hookObject;
00590             }
00591         }
00592 
00593         if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'])) {
00594             foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'] as $classData) {
00595                 $postInitializationProcessor = t3lib_div::getUserObj($classData);
00596 
00597                 if (!($postInitializationProcessor instanceof tslib_content_PostInitHook)) {
00598                     throw new UnexpectedValueException(
00599                         $classData . ' must implement interface tslib_content_PostInitHook',
00600                         1274563549
00601                     );
00602                 }
00603 
00604                 $postInitializationProcessor->postProcessContentObjectInitialization($this);
00605             }
00606         }
00607     }
00608 
00609     /**
00610      * Clone helper.
00611      *
00612      * Resets the references to the TypoScript Content Object implementation
00613      * objects of tslib_content_*. Otherwise they would still point to the
00614      * original tslib_cObj instance's tslib_content_* instances, they in return
00615      * would back-reference to the original tslib_cObj instance instead of the
00616      * newly cloned tslib_cObj instance.
00617      *
00618      * @see http://bugs.typo3.org/view.php?id=16568
00619      */
00620     public function __clone() {
00621         $this->contentObjects = array();
00622     }
00623 
00624     /**
00625      * Gets the 'getImgResource' hook objects.
00626      * The first call initializes the accordant objects.
00627      *
00628      * @return  array       The 'getImgResource' hook objects (if any)
00629      */
00630     protected function getGetImgResourceHookObjects() {
00631         if (!isset($this->getImgResourceHookObjects)) {
00632             $this->getImgResourceHookObjects = array();
00633 
00634             if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'])) {
00635                 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'] as $classData) {
00636                     $hookObject = t3lib_div::getUserObj($classData);
00637 
00638                     if (!($hookObject instanceof tslib_cObj_getImgResourceHook)) {
00639                         throw new UnexpectedValueException(
00640                             '$hookObject must implement interface tslib_cObj_getImgResourceHook',
00641                             1218636383
00642                         );
00643                     }
00644 
00645                     $this->getImgResourceHookObjects[] = $hookObject;
00646                 }
00647             }
00648         }
00649 
00650         return $this->getImgResourceHookObjects;
00651     }
00652 
00653     /**
00654      * Sets the internal variable parentRecord with information about current record.
00655      * If the tslib_cObj was started from CONTENT, RECORD or SEARCHRESULT cObject's this array has two keys, 'data' and 'currentRecord' which indicates the record and data for the parent cObj.
00656      *
00657      * @param   array       $data: The record array
00658      * @param   string      $currentRecord: This is set to the [table]:[uid] of the record delivered in the $data-array, if the cObjects CONTENT or RECORD is in operation. Note that $GLOBALS['TSFE']->currentRecord is set to an equal value but always indicating the latest record rendered.
00659      * @return  void
00660      * @access private
00661      */
00662     function setParent($data, $currentRecord) {
00663         $this->parentRecord = array(
00664             'data' => $data,
00665             'currentRecord' => $currentRecord
00666         );
00667     }
00668 
00669 
00670 
00671     /***********************************************
00672      *
00673      * CONTENT_OBJ:
00674      *
00675      ***********************************************/
00676 
00677     /**
00678      * Returns the "current" value.
00679      * The "current" value is just an internal variable that can be used by functions to pass a single value on to another function later in the TypoScript processing.
00680      * It's like "load accumulator" in the good old C64 days... basically a "register" you can use as you like.
00681      * The TSref will tell if functions are setting this value before calling some other object so that you know if it holds any special information.
00682      *
00683      * @return  mixed       The "current" value
00684      */
00685     function getCurrentVal() {
00686         return $this->data[$this->currentValKey];
00687     }
00688 
00689     /**
00690      * Sets the "current" value.
00691      *
00692      * @param   mixed       The variable that you want to set as "current"
00693      * @return  void
00694      * @see getCurrentVal()
00695      */
00696     function setCurrentVal($value) {
00697         $this->data[$this->currentValKey] = $value;
00698     }
00699 
00700     /**
00701      * Rendering of a "numerical array" of cObjects from TypoScript
00702      * Will call ->cObjGetSingle() for each cObject found and accumulate the output.
00703      *
00704      * @param   array       $setup: array with cObjects as values.
00705      * @param   string      $addKey: A prefix for the debugging information
00706      * @return  string      Rendered output from the cObjects in the array.
00707      * @see cObjGetSingle()
00708      */
00709     function cObjGet($setup, $addKey = '') {
00710         if (is_array($setup)) {
00711             $sKeyArray = t3lib_TStemplate::sortedKeyList($setup);
00712             $content = '';
00713             foreach ($sKeyArray as $theKey) {
00714                 $theValue = $setup[$theKey];
00715                 if (intval($theKey) && !strstr($theKey, '.')) {
00716                     $conf = $setup[$theKey . '.'];
00717                     $content .= $this->cObjGetSingle($theValue, $conf, $addKey . $theKey); // Get the contentObject
00718                 }
00719             }
00720             return $content;
00721         }
00722     }
00723 
00724     /**
00725      * Renders a content object
00726      *
00727      * @param   string      The content object name, eg. "TEXT" or "USER" or "IMAGE"
00728      * @param   array       The array with TypoScript properties for the content object
00729      * @param   string      A string label used for the internal debugging tracking.
00730      * @return  string      cObject output
00731      */
00732     function cObjGetSingle($name, $conf, $TSkey = '__') {
00733         global $TYPO3_CONF_VARS;
00734 
00735         $content = '';
00736             // Checking that the function is not called eternally. This is done by interrupting at a depth of 100
00737         $GLOBALS['TSFE']->cObjectDepthCounter--;
00738         if ($GLOBALS['TSFE']->cObjectDepthCounter > 0) {
00739             $name = trim($name);
00740             if ($GLOBALS['TT']->LR)
00741                 $GLOBALS['TT']->push($TSkey, $name);
00742 
00743                 // Checking if the COBJ is a reference to another object. (eg. name of 'blabla.blabla = < styles.something')
00744             if (substr($name, 0, 1) == '<') {
00745                 $key = trim(substr($name, 1));
00746                 $cF = t3lib_div::makeInstance('t3lib_TSparser');
00747                     // $name and $conf is loaded with the referenced values.
00748                 $old_conf = $conf;
00749                 list ($name, $conf) = $cF->getVal($key, $GLOBALS['TSFE']->tmpl->setup);
00750                 if (is_array($old_conf) && count($old_conf)) {
00751                     $conf = $this->joinTSarrays($conf, $old_conf);
00752                 }
00753                     // Getting the cObject
00754                 $GLOBALS['TT']->incStackPointer();
00755                 $content .= $this->cObjGetSingle($name, $conf, $key);
00756                 $GLOBALS['TT']->decStackPointer();
00757             } else {
00758 
00759                 $hooked = FALSE;
00760                     // Application defined cObjects
00761                 foreach ($this->cObjHookObjectsArr as $cObjName => $hookObj) {
00762                     if (($name === $cObjName) && method_exists($hookObj, 'cObjGetSingleExt')) {
00763                         $content .= $hookObj->cObjGetSingleExt($name, $conf, $TSkey, $this);
00764                         $hooked = TRUE;
00765                     }
00766                 }
00767                 if (!$hooked) {
00768                     $contentObject = $this->getContentObject($name);
00769                     if ($contentObject) {
00770                         $content .= $contentObject->render($conf);
00771                     } else {
00772                                 // call hook functions for extra processing
00773                             if ($name && is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'])) {
00774                                 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'] as $classData) {
00775                                     $hookObject = t3lib_div::getUserObj($classData);
00776 
00777                                     if (!($hookObject instanceof tslib_content_cObjGetSingleHook)) {
00778                                         throw new UnexpectedValueException(
00779                                             '$hookObject must implement interface tslib_content_cObjGetSingleHook',
00780                                             1195043731
00781                                         );
00782                                     }
00783                                     /* @var $hookObject tslib_content_cObjGetSingleHook */
00784                                     $content .= $hookObject->getSingleContentObject($name, (array) $conf, $TSkey, $this);
00785                                 }
00786                         } else {
00787                                 // log error in AdminPanel
00788                             $warning = sprintf('Content Object "%s" does not exist', $name);
00789                             $GLOBALS['TT']->setTSlogMessage($warning, 2);
00790                         }
00791                     }
00792                 }
00793             }
00794             if ($GLOBALS['TT']->LR)
00795                 $GLOBALS['TT']->pull($content);
00796         }
00797             // Increasing on exit...
00798         $GLOBALS['TSFE']->cObjectDepthCounter++;
00799         return $content;
00800     }
00801 
00802     /**
00803      * Returns a new content object of type $name.
00804      *
00805      * @param string $name
00806      * @return tslib_content_abstract
00807      */
00808     public function getContentObject($name) {
00809         $classMapping = array(
00810             'HTML' => 'Html',
00811             'TEXT' => 'Text',
00812             'CASE' => 'Case',
00813             'CLEARGIF' => 'ClearGif',
00814             'COBJ_ARRAY' => 'ContentObjectArray',
00815             'COA' => 'ContentObjectArray',
00816             'COA_INT' => 'ContentObjectArrayInternal',
00817             'USER' => 'User',
00818             'USER_INT' => 'UserInternal',
00819             'FILE' => 'File',
00820             'IMAGE' => 'Image',
00821             'IMG_RESOURCE' => 'ImageResource',
00822             'IMGTEXT' => 'ImageText',
00823             'CONTENT' => 'Content',
00824             'RECORDS' => 'Records',
00825             'HMENU' => 'HierarchicalMenu',
00826             'CTABLE' => 'ContentTable',
00827             'OTABLE' => 'OffsetTable',
00828             'COLUMNS' => 'Columns',
00829             'HRULER' => 'HorizontalRuler',
00830             'CASEFUNC' => 'Case',
00831             'LOAD_REGISTER' => 'LoadRegister',
00832             'RESTORE_REGISTER' => 'RestoreRegister',
00833             'FORM' => 'Form',
00834             'SEARCHRESULT' => 'SearchResult',
00835             'PHP_SCRIPT' => 'PhpScript',
00836             'PHP_SCRIPT_INT' => 'PhpScriptInternal',
00837             'PHP_SCRIPT_EXT' => 'PhpScriptExternal',
00838             'TEMPLATE' => 'Template',
00839             'FLUIDTEMPLATE' => 'FluidTemplate',
00840             'MULTIMEDIA' => 'Multimedia',
00841             'MEDIA' => 'Media',
00842             'SWFOBJECT' => 'ShockwaveFlashObject',
00843             'QTOBJECT' => 'QuicktimeObject',
00844             'SVG' => 'ScalableVectorGraphics',
00845             'EDITPANEL' => 'EditPanel',
00846         );
00847         $name = $classMapping[$name];
00848 
00849         if (!array_key_exists($name, $this->contentObjects)) {
00850             try {
00851                 $this->contentObjects[$name] = t3lib_div::makeInstance('tslib_content_' . $name, $this);
00852             } catch (ReflectionException $e) {
00853                 $this->contentObjects[$name] = NULL;
00854             }
00855         }
00856         return $this->contentObjects[$name];
00857     }
00858 
00859 
00860     /********************************************
00861      *
00862      * Functions rendering content objects (cObjects)
00863      *
00864      ********************************************/
00865 
00866     /**
00867      * Rendering the cObject, HTML
00868      *
00869      * @param   array       array of TypoScript properties
00870      * @return  string      Output
00871      */
00872     function HTML($conf) {
00873         return $this->getContentObject('HTML')->render($conf);
00874     }
00875 
00876     /**
00877      * Rendering the cObject, TEXT
00878      *
00879      * @param   array       array of TypoScript properties
00880      * @return  string      Output
00881      */
00882     function TEXT($conf) {
00883         return $this->getContentObject('TEXT')->render($conf);
00884     }
00885 
00886     /**
00887      * Rendering the cObject, CLEARGIF
00888      *
00889      * @param   array       array of TypoScript properties
00890      * @return  string      Output
00891      */
00892     function CLEARGIF($conf) {
00893         return $this->getContentObject('CLEARGIF')->render($conf);
00894     }
00895 
00896     /**
00897      * Rendering the cObject, COBJ_ARRAY / COA and COBJ_ARRAY_INT
00898      *
00899      * @param   array       array of TypoScript properties
00900      * @param   string      If "INT" then the cObject is a "COBJ_ARRAY_INT" (non-cached), otherwise just "COBJ_ARRAY" (cached)
00901      * @return  string      Output
00902      */
00903     function COBJ_ARRAY($conf, $ext = '') {
00904         if ($ext === 'INT') {
00905             return $this->getContentObject('COA_INT')->render($conf);
00906         } else {
00907             return $this->getContentObject('COA')->render($conf);
00908         }
00909     }
00910 
00911     /**
00912      * Rendering the cObject, USER and USER_INT
00913      *
00914      * @param   array       array of TypoScript properties
00915      * @param   string      If "INT" then the cObject is a "USER_INT" (non-cached), otherwise just "USER" (cached)
00916      * @return  string      Output
00917      */
00918     function USER($conf, $ext = '') {
00919         if ($ext === 'INT') {
00920             return $this->getContentObject('USER_INT')->render($conf);
00921         } else {
00922             return $this->getContentObject('USER')->render($conf);
00923         }
00924     }
00925 
00926     /**
00927      * Retrieves a type of object called as USER or USER_INT. Object can detect their
00928      * type by using this call. It returns OBJECTTYPE_USER_INT or OBJECTTYPE_USER depending on the
00929      * current object execution. In all other cases it will return FALSE to indicate
00930      * a call out of context.
00931      *
00932      * @return  mixed   One of OBJECTTYPE_ class constants or FALSE
00933      */
00934     public function getUserObjectType() {
00935         return $this->userObjectType;
00936     }
00937 
00938     /**
00939      * Sets the user object type
00940      *
00941      * @param mixed $userObjectType
00942      * @return void
00943      */
00944     public function setUserObjectType($userObjectType) {
00945         $this->userObjectType = $userObjectType;
00946     }
00947 
00948     /**
00949      * Requests the current USER object to be converted to USER_INT.
00950      *
00951      * @return  void
00952      */
00953     public function convertToUserIntObject() {
00954         if ($this->userObjectType !== self::OBJECTTYPE_USER) {
00955             $GLOBALS['TT']->setTSlogMessage('tslib_cObj::convertToUserIntObject() ' . 'is called in the wrong context or for the wrong object type', 2);
00956         } else {
00957             $this->doConvertToUserIntObject = TRUE;
00958         }
00959     }
00960 
00961     /**
00962      * Rendering the cObject, FILE
00963      *
00964      * @param   array       array of TypoScript properties
00965      * @return  string      Output
00966      */
00967     function FILE($conf) {
00968         return $this->getContentObject('FILE')->render($conf);
00969     }
00970 
00971     /**
00972      * Rendering the cObject, IMAGE
00973      *
00974      * @param   array       array of TypoScript properties
00975      * @return  string      Output
00976      * @see cImage()
00977      */
00978     function IMAGE($conf) {
00979         return $this->getContentObject('IMAGE')->render($conf);
00980     }
00981 
00982     /**
00983      * Rendering the cObject, IMG_RESOURCE
00984      *
00985      * @param   array       array of TypoScript properties
00986      * @return  string      Output
00987      * @see getImgResource()
00988      */
00989     function IMG_RESOURCE($conf) {
00990         return $this->getContentObject('IMG_RESOURCE')->render($conf);
00991     }
00992 
00993     /**
00994      * Rendering the cObject, IMGTEXT
00995      *
00996      * @param   array       array of TypoScript properties
00997      * @return  string      Output
00998      */
00999     function IMGTEXT($conf) {
01000         return $this->getContentObject('IMGTEXT')->render($conf);
01001     }
01002 
01003     /**
01004      * Rendering the cObject, CONTENT
01005      *
01006      * @param   array       array of TypoScript properties
01007      * @return  string      Output
01008      */
01009     function CONTENT($conf) {
01010         return $this->getContentObject('CONTENT')->render($conf);
01011     }
01012 
01013     /**
01014      * Rendering the cObject, RECORDS
01015      *
01016      * @param   array       array of TypoScript properties
01017      * @return  string      Output
01018      */
01019     function RECORDS($conf) {
01020         return $this->getContentObject('RECORDS')->render($conf);
01021     }
01022 
01023     /**
01024      * Rendering the cObject, HMENU
01025      *
01026      * @param   array       array of TypoScript properties
01027      * @return  string      Output
01028      */
01029     function HMENU($conf) {
01030         return $this->getContentObject('HMENU')->render($conf);
01031     }
01032 
01033     /**
01034      * Rendering the cObject, CTABLE
01035      *
01036      * @param   array       array of TypoScript properties
01037      * @return  string      Output
01038      */
01039     function CTABLE($conf) {
01040         return $this->getContentObject('CTABLE')->render($conf);
01041     }
01042 
01043     /**
01044      * Rendering the cObject, OTABLE
01045      *
01046      * @param   array       array of TypoScript properties
01047      * @return  string      Output
01048      */
01049     function OTABLE($conf) {
01050         return $this->getContentObject('OTABLE')->render($conf);
01051     }
01052 
01053     /**
01054      * Rendering the cObject, COLUMNS
01055      *
01056      * @param   array       array of TypoScript properties
01057      * @return  string      Output
01058      */
01059     function COLUMNS($conf) {
01060         return $this->getContentObject('COLUMNS')->render($conf);
01061     }
01062 
01063     /**
01064      * Rendering the cObject, HRULER
01065      *
01066      * @param   array       array of TypoScript properties
01067      * @return  string      Output
01068      */
01069     function HRULER($conf) {
01070         return $this->getContentObject('HRULER')->render($conf);
01071     }
01072 
01073     /**
01074      * Rendering the cObject, CASE
01075      *
01076      * @param   array       array of TypoScript properties
01077      * @return  string      Output
01078      */
01079     function CASEFUNC($conf) {
01080         return $this->getContentObject('CASE')->render($conf);
01081     }
01082 
01083     /**
01084      * Rendering the cObject, LOAD_REGISTER and RESTORE_REGISTER
01085      * NOTICE: This cObject does NOT return any content since it just sets internal data based on the TypoScript properties.
01086      *
01087      * @param   array       array of TypoScript properties
01088      * @param   string      If "RESTORE_REGISTER" then the cObject rendered is "RESTORE_REGISTER", otherwise "LOAD_REGISTER"
01089      * @return  string      Empty string (the cObject only sets internal data!)
01090      */
01091     function LOAD_REGISTER($conf, $name) {
01092         if ($name === 'RESTORE_REGISTER') {
01093             return $this->getContentObject('RESTORE_REGISTER')->render($conf);
01094         } else {
01095             return $this->getContentObject('LOAD_REGISTER')->render($conf);
01096         }
01097     }
01098 
01099     /**
01100      * Rendering the cObject, FORM
01101      *
01102      * @param   array       array of TypoScript properties
01103      * @param   array       Alternative formdata overriding whatever comes from TypoScript
01104      * @return  string      Output
01105      */
01106     function FORM($conf, $formData = '') {
01107         return $this->getContentObject('FORM')->render($conf, $formData);
01108     }
01109 
01110     /**
01111      * Rendering the cObject, SEARCHRESULT
01112      *
01113      * @param   array       array of TypoScript properties
01114      * @return  string      Output
01115      */
01116     function SEARCHRESULT($conf) {
01117         return $this->getContentObject('SEARCHRESULT')->render($conf);
01118     }
01119 
01120     /**
01121      * Rendering the cObject, PHP_SCRIPT, PHP_SCRIPT_INT and PHP_SCRIPT_EXT
01122      *
01123      * @param   array       array of TypoScript properties
01124      * @param   string      If "INT", then rendering "PHP_SCRIPT_INT"; If "EXT", then rendering "PHP_SCRIPT_EXT"; Default is rendering "PHP_SCRIPT" (cached)
01125      * @return  string      Output
01126      */
01127     function PHP_SCRIPT($conf, $ext = '') {
01128         if ($ext === 'INT' || $ext === 'EXT') {
01129             $conf['scriptSuffix'] = $ext;
01130             return $this->getContentObject('PHP_SCRIPT_INT')->render($conf);
01131         } else {
01132             return $this->getContentObject('PHP_SCRIPT')->render($conf);
01133         }
01134     }
01135 
01136     /**
01137      * Rendering the cObject, TEMPLATE
01138      *
01139      * @param   array       array of TypoScript properties
01140      * @return  string      Output
01141      * @see substituteMarkerArrayCached()
01142      */
01143     function TEMPLATE($conf) {
01144         return $this->getContentObject('TEMPLATE')->render($conf);
01145     }
01146 
01147     /**
01148      * Rendering the cObject, FLUIDTEMPLATE
01149      *
01150      * @param   array       array of TypoScript properties
01151      * @return  string      the HTML output
01152      * @author  Steffen Ritter  <info@steffen-ritter.net>
01153      * @author  Benjamin Mack   <benni@typo3.org>
01154      */
01155     protected function FLUIDTEMPLATE(array $conf) {
01156         return $this->getContentObject('FLUIDTEMPLATE')->render($conf);
01157     }
01158 
01159         /**
01160      * Rendering the cObject, MULTIMEDIA
01161      *
01162      * @param   array       array of TypoScript properties
01163      * @return  string      Output
01164      */
01165     function MULTIMEDIA($conf) {
01166         return $this->getContentObject('MULTIMEDIA')->render($conf);
01167     }
01168 
01169     /**
01170      * Rendering the cObject, MEDIA
01171      *
01172      * @param   array       array of TypoScript properties
01173      * @return  string      Output
01174      */
01175     public function MEDIA($conf) {
01176         return $this->getContentObject('MEDIA')->render($conf);
01177     }
01178 
01179     /**
01180      * Rendering the cObject, SWFOBJECT
01181      *
01182      * @param   array       array of TypoScript properties
01183      * @return  string      Output
01184      */
01185     public function SWFOBJECT($conf) {
01186         return $this->getContentObject('SWFOBJECT')->render($conf);
01187     }
01188 
01189     /**
01190      * Rendering the cObject, QTOBJECT
01191      *
01192      * @param   array       array of TypoScript properties
01193      * @return  string      Output
01194      */
01195     public function QTOBJECT($conf) {
01196         return $this->getContentObject('QTOBJECT')->render($conf);
01197     }
01198 
01199     /**
01200      * Rendering the cObject, SVG
01201      *
01202      * @param   array       array of TypoScript properties
01203      * @return  string      Output
01204      */
01205     public function SVG($conf) {
01206         return $this->getContentObject('SVG')->render($conf);
01207     }
01208 
01209     /************************************
01210      *
01211      * Various helper functions for content objects:
01212      *
01213      ************************************/
01214 
01215 
01216     /**
01217      * Converts a given config in Flexform to a conf-array
01218      * @param   string      Flexform data
01219      * @param   array       array to write the data into, by reference
01220      * @param   boolean     is set if called recursive. Don't call function with this parameter, it's used inside the function only
01221      * @access  public
01222      *
01223      */
01224     public function readFlexformIntoConf($flexData, &$conf, $recursive = FALSE) {
01225         if ($recursive === FALSE) {
01226             $flexData = t3lib_div::xml2array($flexData, 'T3');
01227         }
01228 
01229         if (is_array($flexData)) {
01230             if (isset($flexData['data']['sDEF']['lDEF'])) {
01231                 $flexData = $flexData['data']['sDEF']['lDEF'];
01232             }
01233 
01234             foreach ($flexData as $key => $value) {
01235                 if (is_array($value['el']) && count($value['el']) > 0) {
01236                     foreach ($value['el'] as $ekey => $element) {
01237                         if (isset($element['vDEF'])) {
01238                             $conf[$ekey] = $element['vDEF'];
01239                         } else {
01240                             if (is_array($element)) {
01241                                 $this->readFlexformIntoConf($element, $conf[$key][key($element)][$ekey], TRUE);
01242                             } else {
01243                                 $this->readFlexformIntoConf($element, $conf[$key][$ekey], TRUE);
01244                             }
01245                         }
01246                     }
01247                 } else {
01248                     $this->readFlexformIntoConf($value['el'], $conf[$key], TRUE);
01249                 }
01250                 if ($value['vDEF']) {
01251                     $conf[$key] = $value['vDEF'];
01252                 }
01253             }
01254         }
01255     }
01256 
01257 
01258     /**
01259      * Returns all parents of the given PID (Page UID) list
01260      *
01261      * @param   string      A list of page Content-Element PIDs (Page UIDs) / stdWrap
01262      * @param   array       stdWrap array for the list
01263      * @return  string      A list of PIDs
01264      * @access private
01265      */
01266     function getSlidePids($pidList, $pidConf) {
01267         $pidList = isset($pidConf)
01268             ? trim($this->stdWrap($pidList, $pidConf))
01269             : trim($pidList);
01270         if (!strcmp($pidList, '')) {
01271             $pidList = 'this';
01272         }
01273         if (trim($pidList)) {
01274             $listArr = t3lib_div::intExplode(',', str_replace('this', $GLOBALS['TSFE']->contentPid, $pidList));
01275             $listArr = $this->checkPidArray($listArr);
01276         }
01277         $pidList = array();
01278         if (is_array($listArr) && count($listArr)) {
01279             foreach ($listArr as $uid) {
01280                 $page = $GLOBALS['TSFE']->sys_page->getPage($uid);
01281                 if (!$page['is_siteroot']) {
01282                     $pidList[] = $page['pid'];
01283                 }
01284             }
01285         }
01286         return implode(',', $pidList);
01287     }
01288 
01289     /**
01290      * Returns a default value for a form field in the FORM cObject.
01291      * Page CANNOT be cached because that would include the inserted value for the current user.
01292      *
01293      * @param   boolean     If noValueInsert OR if the no_cache flag for this page is NOT set, the original default value is returned.
01294      * @param   string      $fieldName: The POST var name to get default value for
01295      * @param   string      $defaultVal: The current default value
01296      * @return  string      The default value, either from INPUT var or the current default, based on whether caching is enabled or not.
01297      * @access private
01298      */
01299     function getFieldDefaultValue($noValueInsert, $fieldName, $defaultVal) {
01300         if (!$GLOBALS['TSFE']->no_cache || (!isset($_POST[$fieldName]) && !isset($_GET[$fieldName])) || $noValueInsert) {
01301             return $defaultVal;
01302         } else {
01303             return t3lib_div::_GP($fieldName);
01304         }
01305     }
01306 
01307     /**
01308      * Returns a <img> tag with the image file defined by $file and processed according to the properties in the TypoScript array.
01309      * Mostly this function is a sub-function to the IMAGE function which renders the IMAGE cObject in TypoScript.
01310      * This function is called by "$this->cImage($conf['file'],$conf);" from IMAGE().
01311      *
01312      * @param   string      File TypoScript resource
01313      * @param   array       TypoScript configuration properties
01314      * @return  string      <img> tag, (possibly wrapped in links and other HTML) if any image found.
01315      * @access private
01316      * @see IMAGE()
01317      */
01318     function cImage($file, $conf) {
01319         $info = $this->getImgResource($file, $conf['file.']);
01320         $GLOBALS['TSFE']->lastImageInfo = $info;
01321         if (is_array($info)) {
01322             $info[3] = t3lib_div::png_to_gif_by_imagemagick($info[3]);
01323             $GLOBALS['TSFE']->imagesOnPage[] = $info[3]; // This array is used to collect the image-refs on the page...
01324 
01325 
01326                 // Backwards compatibility if altText is not set and alttext is set
01327                 // @deprecated since TYPO3 4.3, will be removed in TYPO3 4.6
01328             if (strlen($conf['alttext']) || is_array($conf['alttext.'])) {
01329                 $GLOBALS['TSFE']->logDeprecatedTyposcript(
01330                     'IMAGE.alttext',
01331                     'use IMAGE.altText instead - src: ' . $info[3] . ' - original image: ' . $info['origFile']
01332                 );
01333                 if (!strlen($conf['altText']) && !is_array($conf['altText.'])) {
01334                     $conf['altText'] = $conf['alttext'];
01335                     $conf['altText.'] = $conf['alttext.'];
01336                 }
01337             }
01338 
01339             $altParam = $this->getAltParam($conf);
01340             if($conf['params'] && !isset($conf['params.'])) {
01341                 $params = ' ' . $conf['params'];
01342             } else {
01343                 $params = isset($conf['params.'])
01344                     ? ' ' . $this->stdWrap($conf['params'], $conf['params.'])
01345                     : '';
01346             }
01347             $theValue = '<img src="' . htmlspecialchars($GLOBALS['TSFE']->absRefPrefix .
01348                 t3lib_div::rawUrlEncodeFP($info[3])) . '" width="' . $info[0] . '" height="' . $info[1] . '"' .
01349                 $this->getBorderAttr(' border="' . intval($conf['border']) . '"') .
01350                 $params .
01351                 ($altParam) . ' />';
01352             $linkWrap = isset($conf['linkWrap.'])
01353                 ? $this->stdWrap($conf['linkWrap'], $conf['linkWrap.'])
01354                 : $conf['linkWrap'];
01355             if ($linkWrap) {
01356                 $theValue = $this->linkWrap($theValue, $linkWrap);
01357             } elseif ($conf['imageLinkWrap']) {
01358                 $theValue = $this->imageLinkWrap($theValue, $info['origFile'], $conf['imageLinkWrap.']);
01359             }
01360             $wrap = isset($conf['wrap.'])
01361                 ? $this->stdWrap($conf['wrap'], $conf['wrap.'])
01362                 : $conf['wrap'];
01363             if($wrap) {
01364                 $theValue = $this->wrap($theValue, $conf['wrap']);
01365             }
01366             return $theValue;
01367         }
01368     }
01369 
01370     /**
01371      * Returns the 'border' attribute for an <img> tag only if the doctype is not xhtml_strict, xhtml_11, xhtml_2 or html5
01372      * or if the config parameter 'disableImgBorderAttr' is not set.
01373      *
01374      * @param   string      the border attribute
01375      * @return  string      the border attribute
01376      */
01377     function getBorderAttr($borderAttr) {
01378         if (! t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype) &&
01379                 $GLOBALS['TSFE']->config['config']['doctype'] != 'html5' &&
01380                 ! $GLOBALS['TSFE']->config['config']['disableImgBorderAttr']) {
01381             return $borderAttr;
01382         }
01383     }
01384 
01385     /**
01386      * Wraps the input string in link-tags that opens the image in a new window.
01387      *
01388      * @param   string      String to wrap, probably an <img> tag
01389      * @param   string      The original image file
01390      * @param   array       TypoScript properties for the "imageLinkWrap" function
01391      * @return  string      The input string, $string, wrapped as configured.
01392      * @see cImage()
01393      */
01394     function imageLinkWrap($string, $imageFile, $conf) {
01395         $a1 = '';
01396         $a2 = '';
01397         $content = $string;
01398         $enable = isset($conf['enable.'])
01399             ? $this->stdWrap($conf['enable'], $conf['enable.'])
01400             : $conf['enable'];
01401         if ($enable) {
01402             $content = $this->typolink($string, $conf['typolink.']);
01403             if(isset($conf['file.'])) {
01404                 $imageFile = $this->stdWrap($imageFile, $conf['file.']);
01405             }
01406 
01407                 // imageFileLink:
01408             if ($content == $string && @is_file($imageFile)) {
01409                 $parameterNames = array('width', 'height', 'effects', 'alternativeTempPath', 'bodyTag', 'title', 'wrap');
01410                 $parameters = array();
01411 
01412                 $sample = isset($conf['sample.'])
01413                     ? $this->stdWrap($conf['sample'], $conf['sample.'])
01414                     : $conf['sample'];
01415                 if ($sample) {
01416                     $parameters['sample'] = 1;
01417                 }
01418 
01419                 foreach ($parameterNames as $parameterName) {
01420                     if(isset($conf[$parameterName.'.'])) {
01421                         $conf[$parameterName] = $this->stdWrap($conf[$parameterName], $conf[$parameterName.'.']);
01422                     }
01423                     if (isset($conf[$parameterName]) && $conf[$parameterName]) {
01424                         $parameters[$parameterName] = $conf[$parameterName];
01425                     }
01426                 }
01427 
01428                 $parametersEncoded = base64_encode(serialize($parameters));
01429 
01430                 $md5_value = t3lib_div::hmac(
01431                     implode(
01432                         '|',
01433                         array($imageFile, $parametersEncoded)
01434                     )
01435                 );
01436 
01437                 $params = '&md5=' . $md5_value;
01438                 foreach (str_split($parametersEncoded, 64) as $index => $chunk) {
01439                     $params .= '&parameters[' . $index . ']=' . rawurlencode($chunk);
01440                 }
01441 
01442                 $url = $GLOBALS['TSFE']->absRefPrefix . 'index.php?eID=tx_cms_showpic&file=' . rawurlencode($imageFile) . $params;
01443 
01444                 $directImageLink = isset($conf['directImageLink.'])
01445                     ? $this->stdWrap($conf['directImageLink'], $conf['directImageLink.'])
01446                     : $conf['directImageLink'];
01447                 if ($directImageLink) {
01448                     $imgResourceConf = array(
01449                         'file' => $imageFile,
01450                         'file.' => $conf
01451                     );
01452                     $url = $this->IMG_RESOURCE($imgResourceConf);
01453                     if (!$url) {
01454                             // if no imagemagick / gm is available
01455                         $url = $imageFile;
01456                     }
01457                 }
01458 
01459                     // Create TARGET-attribute only if the right doctype is used
01460                 if (!t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype)) {
01461                     $target = isset($conf['target.'])
01462                         ? $this-stdWrap($conf['target'], $conf['target.'])
01463                         : $conf['target'];
01464                     if(!$target) {
01465                         $target = sprintf(' target="%s"', $target);
01466                     } else {
01467                         $target = ' target="thePicture"';
01468                     }
01469                 } else {
01470                     $target = '';
01471                 }
01472                 $conf['JSwindow'] = isset($conf['JSwindow.'])
01473                     ? $this->stdWrap($conf['JSwindow'], $conf['JSwindow.'])
01474                     : $conf['JSwindow'];
01475                 if ($conf['JSwindow']) {
01476                     if ($conf['JSwindow.']['altUrl'] || $conf['JSwindow.']['altUrl.']) {
01477                         $altUrl = isset($conf['JSwindow.']['altUrl.'])
01478                             ? $this->stdWrap($conf['JSwindow.']['altUrl'], $conf['JSwindow.']['altUrl.'])
01479                             : $conf['JSwindow.']['altUrl'];
01480                         if ($altUrl) {
01481                             $url = $altUrl .
01482                                 ($conf['JSwindow.']['altUrl_noDefaultParams'] ? '' : '?file=' .
01483                                 rawurlencode($imageFile) . $params);
01484                         }
01485                     }
01486                     $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
01487                     $gifCreator->init();
01488                     $gifCreator->mayScaleUp = 0;
01489 
01490                     $dims = $gifCreator->getImageScale($gifCreator->getImageDimensions($imageFile), $conf['width'], $conf['height'], '');
01491                     $JSwindowExpand = isset($conf['JSwindow.']['expand.'])
01492                         ? $this->stdWrap($conf['JSwindow.']['expand'], $conf['JSwindow.']['expand.'])
01493                         : $conf['JSwindow.']['expand'];
01494                     $offset = t3lib_div::intExplode(',', $JSwindowExpand . ',');
01495 
01496                     $newWindow = isset($conf['JSwindow.']['newWindow.'])
01497                         ? $this->stdWrap($conf['JSwindow.']['newWindow'], $conf['JSwindow.']['newWindow.'])
01498                         : $conf['JSwindow.']['newWindow'];
01499                     $a1 = '<a href="' . htmlspecialchars($url) . '" onclick="' .
01500                         htmlspecialchars('openPic(\'' . $GLOBALS['TSFE']->baseUrlWrap($url) . '\',\'' .
01501                         ($newWindow ? md5($url) : 'thePicture') . '\',\'width=' .
01502                         ($dims[0] + $offset[0]) . ',height=' . ($dims[1] + $offset[1]) .
01503                         ',status=0,menubar=0\'); return false;') . '"' .
01504                         $target . $GLOBALS['TSFE']->ATagParams . '>';
01505                     $a2 = '</a>';
01506                     $GLOBALS['TSFE']->setJS('openPic');
01507                 } else {
01508                     $conf['linkParams.']['parameter'] = $url;
01509                     $string = $this->typoLink($string, $conf['linkParams.']);
01510                 }
01511 
01512                 if(isset($conf['stdWrap.'])) {
01513                     $string = $this->stdWrap($string, $conf['stdWrap.']);
01514                 }
01515 
01516                 $content = $a1 . $string . $a2;
01517             }
01518         }
01519 
01520         return $content;
01521     }
01522 
01523     /**
01524      * Returns content of a file. If it's an image the content of the file is not returned but rather an image tag is.
01525      *
01526      * @param   string      The filename, being a TypoScript resource data type
01527      * @param   string      Additional parameters (attributes). Default is empty alt and title tags.
01528      * @return  string      If jpg,gif,jpeg,png: returns image_tag with picture in. If html,txt: returns content string
01529      * @see FILE()
01530      */
01531     function fileResource($fName, $addParams = 'alt="" title=""') {
01532         $incFile = $GLOBALS['TSFE']->tmpl->getFileName($fName);
01533         if ($incFile) {
01534             $fileinfo = t3lib_div::split_fileref($incFile);
01535             if (t3lib_div::inList('jpg,gif,jpeg,png', $fileinfo['fileext'])) {
01536                 $imgFile = $incFile;
01537                 $imgInfo = @getImageSize($imgFile);
01538                 return '<img src="' . $GLOBALS['TSFE']->absRefPrefix . $imgFile .
01539                     '" width="' . $imgInfo[0] . '" height="' . $imgInfo[1] . '"' .
01540                     $this->getBorderAttr(' border="0"') . ' ' . $addParams . ' />';
01541             } elseif (filesize($incFile) < 1024 * 1024) {
01542                 return $GLOBALS['TSFE']->tmpl->fileContent($incFile);
01543             }
01544         }
01545     }
01546 
01547     /**
01548      * Sets the SYS_LASTCHANGED timestamp if input timestamp is larger than current value.
01549      * The SYS_LASTCHANGED timestamp can be used by various caching/indexing applications to determine if the page has new content.
01550      * Therefore you should call this function with the last-changed timestamp of any element you display.
01551      *
01552      * @param   integer     Unix timestamp (number of seconds since 1970)
01553      * @return  void
01554      * @see tslib_fe::setSysLastChanged()
01555      */
01556     function lastChanged($tstamp) {
01557         $tstamp = intval($tstamp);
01558         if ($tstamp > intval($GLOBALS['TSFE']->register['SYS_LASTCHANGED'])) {
01559             $GLOBALS['TSFE']->register['SYS_LASTCHANGED'] = $tstamp;
01560         }
01561     }
01562 
01563     /**
01564      * Wraps the input string by the $wrap value and implements the "linkWrap" data type as well.
01565      * The "linkWrap" data type means that this function will find any integer encapsulated in {} (curly braces) in the first wrap part and substitute it with the corresponding page uid from the rootline where the found integer is pointing to the key in the rootline. See link below.
01566      *
01567      * @param   string      Input string
01568      * @param   string      A string where the first two parts separated by "|" (vertical line) will be wrapped around the input string
01569      * @return  string      Wrapped output string
01570      * @see wrap(), cImage(), FILE()
01571      */
01572     function linkWrap($content, $wrap) {
01573         $wrapArr = explode('|', $wrap);
01574         if (preg_match('/\{([0-9]*)\}/', $wrapArr[0], $reg)) {
01575             if ($uid = $GLOBALS['TSFE']->tmpl->rootLine[$reg[1]]['uid']) {
01576                 $wrapArr[0] = str_replace($reg[0], $uid, $wrapArr[0]);
01577             }
01578         }
01579         return trim($wrapArr[0]) . $content . trim($wrapArr[1]);
01580     }
01581 
01582     /**
01583      * An abstraction method which creates an alt or title parameter for an HTML img, applet, area or input element and the FILE content element.
01584      * From the $conf array it implements the properties "altText", "titleText" and "longdescURL"
01585      *
01586      * @param   array       TypoScript configuration properties
01587      * @param   boolean     If set, the longdesc attribute will be generated - must only be used for img elements!
01588      * @return  string      Parameter string containing alt and title parameters (if any)
01589      * @see IMGTEXT(), FILE(), FORM(), cImage(), filelink()
01590      */
01591     function getAltParam($conf, $longDesc = TRUE) {
01592         $altText = isset($conf['altText.'])
01593             ? trim($this->stdWrap($conf['altText'], $conf['altText.']))
01594             : trim($conf['altText']);
01595         $titleText = isset($conf['titleText.'])
01596             ? trim($this->stdWrap($conf['titleText'], $conf['titleText.']))
01597             : trim($conf['titleText']);
01598         $longDesc = isset($conf['longdescURL.'])
01599             ? trim($this->stdWrap($conf['longdescURL'], $conf['longdescURL.']))
01600             : trim($conf['longdescURL']);
01601 
01602             // "alt":
01603         $altParam = ' alt="' . htmlspecialchars($altText) . '"';
01604 
01605             // "title":
01606         $emptyTitleHandling = 'useAlt';
01607         $emptyTitleHandling = isset($conf['emptyTitleHandling.'])
01608             ? $this->stdWrap($conf['emptyTitleHandling'], $conf['emptyTitleHandling.'])
01609             : $conf['emptyTitleHandling'];
01610                 // choices: 'keepEmpty' | 'useAlt' | 'removeAttr'
01611         if ($titleText || $emptyTitleHandling == 'keepEmpty') {
01612             $altParam .= ' title="' . htmlspecialchars($titleText) . '"';
01613         } elseif (!$titleText && $emptyTitleHandling == 'useAlt') {
01614             $altParam .= ' title="' . htmlspecialchars($altText) . '"';
01615         }
01616 
01617             // "longDesc" URL
01618         if ($longDesc) {
01619             $altParam .= ' longdesc="' . htmlspecialchars(strip_tags($longDesc)) . '"';
01620         }
01621 
01622         return $altParam;
01623     }
01624 
01625     /**
01626      * Removes forbidden characters and spaces from name/id attributes in the form tag and formfields
01627      *
01628      * @param   string      Input string
01629      * @return  string      the cleaned string
01630      * @see FORM()
01631      */
01632     function cleanFormName($name) {
01633             // turn data[x][y] into data:x:y:
01634         $name = preg_replace('/\[|\]\[?/', ':', trim($name));
01635             // remove illegal chars like _
01636         return preg_replace('#[^:a-zA-Z0-9]#', '', $name);
01637     }
01638 
01639     /**
01640      * An abstraction method to add parameters to an A tag.
01641      * Uses the ATagParams property.
01642      *
01643      * @param   array       TypoScript configuration properties
01644      * @param   boolean     If set, will add the global config.ATagParams to the link
01645      * @return  string      String containing the parameters to the A tag (if non empty, with a leading space)
01646      * @see IMGTEXT(), filelink(), makelinks(), typolink()
01647      */
01648     function getATagParams($conf, $addGlobal = 1) {
01649         $aTagParams = '';
01650         if ($conf['ATagParams.']) {
01651             $aTagParams = ' ' . $this->stdWrap($conf['ATagParams'], $conf['ATagParams.']);
01652         } elseif ($conf['ATagParams']) {
01653             $aTagParams = ' ' . $conf['ATagParams'];
01654         }
01655         if ($addGlobal) {
01656             $aTagParams = ' ' . trim($GLOBALS['TSFE']->ATagParams . $aTagParams);
01657         }
01658         return $aTagParams;
01659     }
01660 
01661     /**
01662      * All extension links should ask this function for additional properties to their tags.
01663      * Designed to add for instance an "onclick" property for site tracking systems.
01664      *
01665      * @param   string  URL of the website
01666      * @return  string  the additional tag properties
01667      */
01668     function extLinkATagParams($URL, $TYPE) {
01669         $out = '';
01670 
01671         if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']) {
01672             $extLinkATagParamsHandler = t3lib_div::getUserObj(
01673                 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']
01674             );
01675 
01676             if (method_exists($extLinkATagParamsHandler, 'main')) {
01677                 $out .= trim($extLinkATagParamsHandler->main($URL, $TYPE, $this));
01678             }
01679         }
01680 
01681         return trim($out) ? ' ' . trim($out) : '';
01682     }
01683 
01684 
01685 
01686     /***********************************************
01687      *
01688      * HTML template processing functions
01689      *
01690      ***********************************************/
01691 
01692     /**
01693      * Returns a subpart from the input content stream.
01694      * A subpart is a part of the input stream which is encapsulated in a
01695      * string matching the input string, $marker. If this string is found
01696      * inside of HTML comment tags the start/end points of the content block
01697      * returned will be that right outside that comment block.
01698      * Example: The contennt string is
01699      * "Hello <!--###sub1### begin--> World. How are <!--###sub1### end--> you?"
01700      * If $marker is "###sub1###" then the content returned is
01701      * " World. How are ". The input content string could just as well have
01702      * been "Hello ###sub1### World. How are ###sub1### you?" and the result
01703      * would be the same
01704      * Wrapper for t3lib_parsehtml::getSubpart which behaves identical
01705      *
01706      * @param   string      The content stream, typically HTML template content.
01707      * @param   string      The marker string, typically on the form "###[the marker string]###"
01708      * @return  string      The subpart found, if found.
01709      * @see substituteSubpart(), t3lib_parsehtml::getSubpart()
01710      */
01711     public function getSubpart($content, $marker) {
01712         return t3lib_parsehtml::getSubpart($content, $marker);
01713     }
01714 
01715     /**
01716      * Substitute subpart in input template stream.
01717      * This function substitutes a subpart in $content with the content of
01718      * $subpartContent.
01719      * Wrapper for t3lib_parsehtml::substituteSubpart which behaves identical
01720      *
01721      * @param   string      The content stream, typically HTML template content.
01722      * @param   string      The marker string, typically on the form "###[the marker string]###"
01723      * @param   mixed       The content to insert instead of the subpart found. If a string, then just plain substitution happens (includes removing the HTML comments of the subpart if found). If $subpartContent happens to be an array, it's [0] and [1] elements are wrapped around the EXISTING content of the subpart (fetched by getSubpart()) thereby not removing the original content.
01724      * @param   boolean     If $recursive is set, the function calls itself with the content set to the remaining part of the content after the second marker. This means that proceding subparts are ALSO substituted!
01725      * @return  string      The processed HTML content string.
01726      * @see getSubpart(), t3lib_parsehtml::substituteSubpart()
01727      */
01728     public function substituteSubpart($content, $marker, $subpartContent, $recursive = 1) {
01729         return t3lib_parsehtml::substituteSubpart($content, $marker, $subpartContent, $recursive);
01730     }
01731 
01732     /**
01733      * Substitues multiple subparts at once
01734      *
01735      * @param   string      The content stream, typically HTML template content.
01736      * @param   array       The array of key/value pairs being subpart/content values used in the substitution. For each element in this array the function will substitute a subpart in the content stream with the content.
01737      * @return  string      The processed HTML content string.
01738      */
01739     public function substituteSubpartArray($content, array $subpartsContent) {
01740         return t3lib_parsehtml::substituteSubpartArray($content, $subpartsContent);
01741     }
01742 
01743     /**
01744      * Substitutes a marker string in the input content
01745      * (by a simple str_replace())
01746      *
01747      * @param   string      The content stream, typically HTML template content.
01748      * @param   string      The marker string, typically on the form "###[the marker string]###"
01749      * @param   mixed       The content to insert instead of the marker string found.
01750      * @return  string      The processed HTML content string.
01751      * @see substituteSubpart()
01752      */
01753     public function substituteMarker($content, $marker, $markContent) {
01754         return t3lib_parsehtml::substituteMarker($content, $marker, $markContent);
01755     }
01756 
01757     /**
01758      * Multi substitution function with caching.
01759      *
01760      * This function should be a one-stop substitution function for working
01761      * with HTML-template. It does not substitute by str_replace but by
01762      * splitting. This secures that the value inserted does not themselves
01763      * contain markers or subparts.
01764      *
01765      * Note that the "caching" won't cache the content of the substition,
01766      * but only the splitting of the template in various parts. So if you
01767      * want only one cache-entry per template, make sure you always pass the
01768      * exact same set of marker/subpart keys. Else you will be flooding the
01769      * users cache table.
01770      *
01771      * This function takes three kinds of substitutions in one:
01772      * $markContentArray is a regular marker-array where the 'keys' are
01773      * substituted in $content with their values
01774      *
01775      * $subpartContentArray works exactly like markContentArray only is whole
01776      * subparts substituted and not only a single marker.
01777      *
01778      * $wrappedSubpartContentArray is an array of arrays with 0/1 keys where
01779      * the subparts pointed to by the main key is wrapped with the 0/1 value
01780      * alternating.
01781      *
01782      * @param   string      The content stream, typically HTML template content.
01783      * @param   array       Regular marker-array where the 'keys' are substituted in $content with their values
01784      * @param   array       Exactly like markContentArray only is whole subparts substituted and not only a single marker.
01785      * @param   array       An array of arrays with 0/1 keys where the subparts pointed to by the main key is wrapped with the 0/1 value alternating.
01786      * @return  string      The output content stream
01787      * @see substituteSubpart(), substituteMarker(), substituteMarkerInObject(), TEMPLATE()
01788      */
01789     public function substituteMarkerArrayCached($content, array $markContentArray = NULL, array $subpartContentArray = NULL, array $wrappedSubpartContentArray = NULL) {
01790         $GLOBALS['TT']->push('substituteMarkerArrayCached');
01791 
01792             // If not arrays then set them
01793         if (is_null($markContentArray))
01794             $markContentArray = array(); // Plain markers
01795         if (is_null($subpartContentArray))
01796             $subpartContentArray = array(); // Subparts being directly substituted
01797         if (is_null($wrappedSubpartContentArray))
01798             $wrappedSubpartContentArray = array(); // Subparts being wrapped
01799             // Finding keys and check hash:
01800         $sPkeys = array_keys($subpartContentArray);
01801         $wPkeys = array_keys($wrappedSubpartContentArray);
01802         $aKeys = array_merge(array_keys($markContentArray), $sPkeys, $wPkeys);
01803         if (!count($aKeys)) {
01804             $GLOBALS['TT']->pull();
01805             return $content;
01806         }
01807         asort($aKeys);
01808         $storeKey = md5('substituteMarkerArrayCached_storeKey:' . serialize(array(
01809             $content, $aKeys
01810         )));
01811         if ($this->substMarkerCache[$storeKey]) {
01812             $storeArr = $this->substMarkerCache[$storeKey];
01813             $GLOBALS['TT']->setTSlogMessage('Cached', 0);
01814         } else {
01815             $storeArrDat = $GLOBALS['TSFE']->sys_page->getHash($storeKey);
01816             if (!isset($storeArrDat)) {
01817                     // Initialize storeArr
01818                 $storeArr = array();
01819 
01820                     // Finding subparts and substituting them with the subpart as a marker
01821                 foreach ($sPkeys as $sPK) {
01822                     $content = $this->substituteSubpart($content, $sPK, $sPK);
01823                 }
01824 
01825                     // Finding subparts and wrapping them with markers
01826                 foreach ($wPkeys as $wPK) {
01827                     $content = $this->substituteSubpart($content, $wPK, array(
01828                         $wPK, $wPK
01829                     ));
01830                 }
01831 
01832                     // traverse keys and quote them for reg ex.
01833                 foreach ($aKeys as $tK => $tV) {
01834                     $aKeys[$tK] = preg_quote($tV, '/');
01835                 }
01836                 $regex = '/' . implode('|', $aKeys) . '/';
01837                     // Doing regex's
01838                 $storeArr['c'] = preg_split($regex, $content);
01839                 preg_match_all($regex, $content, $keyList);
01840                 $storeArr['k'] = $keyList[0];
01841                     // Setting cache:
01842                 $this->substMarkerCache[$storeKey] = $storeArr;
01843 
01844                     // Storing the cached data:
01845                 $GLOBALS['TSFE']->sys_page->storeHash($storeKey, serialize($storeArr), 'substMarkArrayCached');
01846 
01847                 $GLOBALS['TT']->setTSlogMessage('Parsing', 0);
01848             } else {
01849                     // Unserializing
01850                 $storeArr = unserialize($storeArrDat);
01851                     // Setting cache:
01852                 $this->substMarkerCache[$storeKey] = $storeArr;
01853                 $GLOBALS['TT']->setTSlogMessage('Cached from DB', 0);
01854             }
01855         }
01856 
01857             // Substitution/Merging:
01858             // Merging content types together, resetting
01859         $valueArr = array_merge($markContentArray, $subpartContentArray, $wrappedSubpartContentArray);
01860 
01861         $wSCA_reg = array();
01862         $content = '';
01863             // traversing the keyList array and merging the static and dynamic content
01864         foreach ($storeArr['k'] as $n => $keyN) {
01865             $content .= $storeArr['c'][$n];
01866             if (!is_array($valueArr[$keyN])) {
01867                 $content .= $valueArr[$keyN];
01868             } else {
01869                 $content .= $valueArr[$keyN][(intval($wSCA_reg[$keyN]) % 2)];
01870                 $wSCA_reg[$keyN]++;
01871             }
01872         }
01873         $content .= $storeArr['c'][count($storeArr['k'])];
01874 
01875         $GLOBALS['TT']->pull();
01876         return $content;
01877     }
01878 
01879     /**
01880      * Traverses the input $markContentArray array and for each key the marker
01881      * by the same name (possibly wrapped and in upper case) will be
01882      * substituted with the keys value in the array.
01883      *
01884      * This is very useful if you have a data-record to substitute in some
01885      * content. In particular when you use the $wrap and $uppercase values to
01886      * pre-process the markers. Eg. a key name like "myfield" could effectively
01887      * be represented by the marker "###MYFIELD###" if the wrap value
01888      * was "###|###" and the $uppercase boolean TRUE.
01889      *
01890      * @param   string      The content stream, typically HTML template content.
01891      * @param   array       The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content stream with the content.
01892      * @param   string      A wrap value - [part 1] | [part 2] - for the markers before substitution
01893      * @param   boolean     If set, all marker string substitution is done with upper-case markers.
01894      * @param   boolean     If set, all unused marker are deleted.
01895      * @return  string      The processed output stream
01896      * @see substituteMarker(), substituteMarkerInObject(), TEMPLATE()
01897      */
01898     public function substituteMarkerArray($content, array $markContentArray, $wrap = '', $uppercase = FALSE, $deleteUnused = FALSE) {
01899         return t3lib_parsehtml::substituteMarkerArray($content, $markContentArray, $wrap, $uppercase, $deleteUnused);
01900     }
01901 
01902     /**
01903      * Substitute marker array in an array of values
01904      *
01905      * @param   mixed       If string, then it just calls substituteMarkerArray. If array(and even multi-dim) then for each key/value pair the marker array will be substituted (by calling this function recursively)
01906      * @param   array       The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content string/array values.
01907      * @return  mixed       The processed input variable.
01908      * @see substituteMarker()
01909      */
01910     public function substituteMarkerInObject(&$tree, array $markContentArray) {
01911         if (is_array($tree)) {
01912             foreach ($tree as $key => $value) {
01913                 $this->substituteMarkerInObject($tree[$key], $markContentArray);
01914             }
01915         } else {
01916             $tree = $this->substituteMarkerArray($tree, $markContentArray);
01917         }
01918 
01919         return $tree;
01920     }
01921 
01922     /**
01923      * Adds elements to the input $markContentArray based on the values from
01924      * the fields from $fieldList found in $row
01925      *
01926      * @param   array       array with key/values being marker-strings/substitution values.
01927      * @param   array       An array with keys found in the $fieldList (typically a record) which values should be moved to the $markContentArray
01928      * @param   string      A list of fields from the $row array to add to the $markContentArray array. If empty all fields from $row will be added (unless they are integers)
01929      * @param   boolean     If set, all values added to $markContentArray will be nl2br()'ed
01930      * @param   string      Prefix string to the fieldname before it is added as a key in the $markContentArray. Notice that the keys added to the $markContentArray always start and end with "###"
01931      * @param   boolean     If set, all values are passed through htmlspecialchars() - RECOMMENDED to avoid most obvious XSS and maintain XHTML compliance.
01932      * @return  array       The modified $markContentArray
01933      */
01934     public function fillInMarkerArray(array $markContentArray, array $row, $fieldList = '', $nl2br = TRUE, $prefix = 'FIELD_', $HSC = FALSE) {
01935         if ($fieldList) {
01936             $fArr = t3lib_div::trimExplode(',', $fieldList, 1);
01937             foreach ($fArr as $field) {
01938                 $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($row[$field]) : $row[$field];
01939             }
01940         } else {
01941             if (is_array($row)) {
01942                 foreach ($row as $field => $value) {
01943                     if (!t3lib_div::testInt($field)) {
01944                         if ($HSC) {
01945                             $value = htmlspecialchars($value);
01946                         }
01947 
01948                         $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($value) : $value;
01949                     }
01950                 }
01951             }
01952         }
01953 
01954         return $markContentArray;
01955     }
01956 
01957     /***********************************************
01958      *
01959      * "stdWrap" + sub functions
01960      *
01961      ***********************************************/
01962 
01963     /**
01964      * The "stdWrap" function. This is the implementation of what is known as "stdWrap properties" in TypoScript.
01965      * Basically "stdWrap" performs some processing of a value based on properties in the input $conf array(holding the TypoScript "stdWrap properties")
01966      * See the link below for a complete list of properties and what they do. The order of the table with properties found in TSref (the link) follows the actual order of implementation in this function.
01967      *
01968      * If $this->alternativeData is an array it's used instead of the $this->data array in ->getData
01969      *
01970      * @param   string      Input value undergoing processing in this function. Possibly substituted by other values fetched from another source.
01971      * @param   array       TypoScript "stdWrap properties".
01972      * @return  string      The processed input value
01973      */
01974     public function stdWrap($content = '', $conf = array()) {
01975         if (count($this->stdWrapHookObjects)) {
01976             foreach ($this->stdWrapHookObjects as $hookObject) {
01977                 if (is_callable(array($hookObject, 'stdWrapPreProcess'))) {
01978                     $conf['stdWrapPreProcess'] = 1;
01979                 }
01980                 ;
01981                 if (is_callable(array($hookObject, 'stdWrapOverride'))) {
01982                     $conf['stdWrapOverride'] = 1;
01983                 }
01984                 ;
01985                 if (is_callable(array($hookObject, 'stdWrapProcess'))) {
01986                     $conf['stdWrapProcess'] = 1;
01987                 }
01988                 ;
01989                 if (is_callable(array($hookObject, 'stdWrapPostProcess'))) {
01990                     $conf['stdWrapPostProcess'] = 1;
01991                 }
01992                 ;
01993             }
01994         }
01995         if (is_array($conf) && count($conf)) {
01996             // check, which of the available stdWrap functions is needed for the current conf Array
01997             // and keep only those but still in the same order
01998             $sortedConf = array_intersect_key($this->stdWrapOrder, $conf);
01999             // functions types that should not make use of nested stdWrap function calls to avoid conflicts with internal TypoScript used by these functions
02000             $stdWrapDisabledFunctionTypes = 'cObject,functionName,stdWrap';
02001             // additional Array to check whether a function has already been executed
02002             $isExecuted = array();
02003             // additional switch to make sure 'required', 'if' and 'fieldRequired'
02004             // will still stop rendering immediately in case they return false
02005 
02006             $this->stdWrapRecursionLevel++;
02007             $this->stopRendering[$this->stdWrapRecursionLevel] = false;
02008 
02009             // execute each funtion in the predefined order
02010             foreach ($sortedConf as $stdWrapName => $functionType) {
02011                 // eliminate the second key of a pair 'key'|'key.' to make sure functions get called only once and check if rendering has been stopped
02012                 if (!$isExecuted[$stdWrapName] &&
02013                         !$this->stopRendering[$this->stdWrapRecursionLevel]) {
02014                     $functionName = rtrim($stdWrapName, '.');
02015                     $functionProperties = $functionName . '.';
02016                     // if there is any code one the next level, check if it contains "official" stdWrap functions
02017                     // if yes, execute them first - will make each function stdWrap aware
02018                     // so additional stdWrap calls within the functions can be removed, since the result will be the same
02019                     // exception: the recursive stdWrap function and cObject will still be using their own stdWrap call, since it modifies the content and not a property
02020                     if (count($conf[$functionProperties]) &&
02021                             !t3lib_div::inList($stdWrapDisabledFunctionTypes, $functionType)) {
02022                         if (array_intersect_key($this->stdWrapOrder, $conf[$functionProperties])) {
02023                             $conf[$functionName] = $this->stdWrap($conf[$functionName], $conf[$functionProperties]);
02024                         }
02025                     }
02026                     // get just that part of $conf that is needed for the particular function
02027                     $singleConf = array(
02028                         $functionName => $conf[$functionName],
02029                         $functionProperties => $conf[$functionProperties]
02030                     );
02031 
02032                     // in this special case 'spaceBefore' and 'spaceAfter' need additional stuff from 'space.''
02033                     if ($functionName == 'spaceBefore' || $functionName == 'spaceAfter') {
02034                         $singleConf['space.'] = $conf['space.'];
02035                     }
02036 
02037                     // hand over the whole $conf array to the stdWrapHookObjects
02038                     if ($functionType === 'hook') {
02039                         $singleConf = $conf;
02040                     }
02041                     // check if key is still containing something, since it might have been changed by next level stdWrap before
02042                     if ((isset($conf[$functionName]) || $conf[$functionProperties]) &&
02043                             !($functionType == 'boolean' && $conf[$functionName] === '0')) {
02044                         //add both keys - with and without the dot - to the set of executed functions
02045                         $isExecuted[$functionName] = true;
02046                         $isExecuted[$functionProperties] = true;
02047                         // call the function with the prefix stdWrap_ to make sure nobody can execute functions just by adding their name to the TS Array
02048                         $functionName = 'stdWrap_' . $functionName;
02049                         $content = $this->$functionName(
02050                             $content,
02051                             $singleConf
02052                         );
02053                     }
02054                 }
02055             }
02056 
02057             unset($this->stopRendering[$this->stdWrapRecursionLevel]);
02058             $this->stdWrapRecursionLevel--;
02059 
02060         }
02061         return $content;
02062     }
02063 
02064     /**
02065      * stdWrap pre process hook
02066      * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
02067      * this hook will execute functions before any other stdWrap function can modify anything
02068      *
02069      * @param   string      Input value undergoing processing in these functions.
02070      * @param   array       All stdWrap properties, not just the ones for a particular function.
02071      * @return  string      The processed input value
02072      */
02073     public function stdWrap_stdWrapPreProcess($content = '', $conf = array()) {
02074         foreach ($this->stdWrapHookObjects as $hookObject) {
02075             $content = $hookObject->stdWrapPreProcess($content, $conf, $this);
02076         }
02077         return $content;
02078     }
02079 
02080     /**
02081      * setContentToCurrent
02082      * actually it just does the contrary: Sets the value of 'current' based on current content
02083      *
02084      * @param   string      Input value undergoing processing in this function.
02085      * @param   array       stdWrap properties for setContentToCurrent.
02086      * @return  string      The processed input value
02087      */
02088     public function stdWrap_setContentToCurrent($content = '', $conf = array()) {
02089         $this->data[$this->currentValKey] = $content;
02090         return $content;
02091     }
02092 
02093     /**
02094      * setCurrent
02095      * Sets the value of 'current' based on the outcome of stdWrap operations
02096      *
02097      * @param   string      Input value undergoing processing in this function.
02098      * @param   array       stdWrap properties for setCurrent.
02099      * @return  string      The processed input value
02100      */
02101     public function stdWrap_setCurrent($content = '', $conf = array()) {
02102         $this->data[$this->currentValKey] = $conf['setCurrent'];
02103         return $content;
02104     }
02105 
02106     /**
02107      * lang
02108      * Translates content based on the language currently used by the FE
02109      *
02110      * @param   string      Input value undergoing processing in this function.
02111      * @param   array       stdWrap properties for lang.
02112      * @return  string      The processed input value
02113      */
02114     public function stdWrap_lang($content = '', $conf = array()) {
02115         if (isset($conf['lang.']) && $GLOBALS['TSFE']->config['config']['language'] && isset($conf['lang.'][$GLOBALS['TSFE']->config['config']['language']])) {
02116             $content = $conf['lang.'][$GLOBALS['TSFE']->config['config']['language']];
02117         }
02118         return $content;
02119     }
02120 
02121     /**
02122      * data
02123      * Gets content from different sources based on getText functions, makes use of alternativeData, when set
02124      *
02125      * @param   string      Input value undergoing processing in this function.
02126      * @param   array       stdWrap properties for data.
02127      * @return  string      The processed input value
02128      */
02129     public function stdWrap_data($content = '', $conf = array()) {
02130         $content = $this->getData($conf['data'], is_array($this->alternativeData) ? $this->alternativeData : $this->data);
02131         $this->alternativeData = ''; // This must be unset directly after
02132         return $content;
02133     }
02134 
02135     /**
02136      * field
02137      * Gets content from a DB field
02138      *
02139      * @param   string      Input value undergoing processing in this function.
02140      * @param   array       stdWrap properties for field.
02141      * @return  string      The processed input value
02142      */
02143     public function stdWrap_field($content = '', $conf = array()) {
02144         $content = $this->getFieldVal($conf['field']);
02145         return $content;
02146     }
02147 
02148     /**
02149      * current
02150      * Gets content that has been perviously set as 'current'
02151      * Can be set via setContentToCurrent or setCurrent or will be set automatically i.e. inside the split function
02152      *
02153      * @param   string      Input value undergoing processing in this function.
02154      * @param   array       stdWrap properties for current.
02155      * @return  string      The processed input value
02156      */
02157     public function stdWrap_current($content = '', $conf = array()) {
02158         $content = $this->data[$this->currentValKey];
02159         return $content;
02160     }
02161 
02162     /**
02163      * cObject
02164      * Will replace the content with the value of a any official TypoScript cObject
02165      * like TEXT, COA, HMENU
02166      *
02167      * @param   string      Input value undergoing processing in this function.
02168      * @param   array       stdWrap properties for cObject.
02169      * @return  string      The processed input value
02170      */
02171     public function stdWrap_cObject($content = '', $conf = array()) {
02172         $content = $this->cObjGetSingle($conf['cObject'], $conf['cObject.'], '/stdWrap/.cObject');
02173         return $content;
02174     }
02175 
02176     /**
02177      * numRows
02178      * Counts the number of returned records of a DB operation
02179      * makes use of select internally
02180      *
02181      * @param   string      Input value undergoing processing in this function.
02182      * @param   array       stdWrap properties for numRows.
02183      * @return  string      The processed input value
02184      */
02185     public function stdWrap_numRows($content = '', $conf = array()) {
02186         $content = $this->numRows($conf['numRows.']);
02187         return $content;
02188     }
02189 
02190     /**
02191      * filelist
02192      * Will create a list of files based on some additional parameters
02193      *
02194      * @param   string      Input value undergoing processing in this function.
02195      * @param   array       stdWrap properties for filelist.
02196      * @return  string      The processed input value
02197      */
02198     public function stdWrap_filelist($content = '', $conf = array()) {
02199         $content = $this->filelist($conf['filelist']);
02200         return $content;
02201     }
02202 
02203     /**
02204      * preUserFunc
02205      * Will execute a user public function before the content will be modified by any other stdWrap function
02206      *
02207      * @param   string      Input value undergoing processing in this function.
02208      * @param   array       stdWrap properties for preUserFunc.
02209      * @return  string      The processed input value
02210      */
02211     public function stdWrap_preUserFunc($content = '', $conf = array()) {
02212         $content = $this->callUserFunction($conf['preUserFunc'], $conf['preUserFunc.'], $content);
02213         return $content;
02214     }
02215 
02216     /**
02217      * stdWrap override hook
02218      * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
02219      * this hook will execute functions on existing content but still before the content gets modified or replaced
02220      *
02221      * @param   string      Input value undergoing processing in these functions.
02222      * @param   array       All stdWrap properties, not just the ones for a particular function.
02223      * @return  string      The processed input value
02224      */
02225     public function stdWrap_stdWrapOverride($content = '', $conf = array()) {
02226         foreach ($this->stdWrapHookObjects as $hookObject) {
02227             $content = $hookObject->stdWrapOverride($content, $conf, $this);
02228         }
02229         return $content;
02230     }
02231 
02232     /**
02233      * override
02234      * Will override the current value of content with its own value'
02235      *
02236      * @param   string      Input value undergoing processing in this function.
02237      * @param   array       stdWrap properties for override.
02238      * @return  string      The processed input value
02239      */
02240     public function stdWrap_override($content = '', $conf = array()) {
02241         if (trim($conf['override'])) {
02242             $content = $conf['override'];
02243         }
02244         return $content;
02245     }
02246 
02247     /**
02248      * preIfEmptyListNum
02249      * Gets a value off a CSV list before the following ifEmpty check
02250      * Makes sure that the result of ifEmpty will be true in case the CSV does not contain a value at the position given by preIfEmptyListNum
02251      *
02252      * @param   string      Input value undergoing processing in this function.
02253      * @param   array       stdWrap properties for preIfEmptyListNum.
02254      * @return  string      The processed input value
02255      */
02256     public function stdWrap_preIfEmptyListNum($content = '', $conf = array()) {
02257         $content = $this->listNum($content, $conf['preIfEmptyListNum'], $conf['preIfEmptyListNum.']['splitChar']);
02258         return $content;
02259     }
02260 
02261     /**
02262      * ifEmpty
02263      * Will set content to a replacement value in case the trimmed value of content returns false
02264      * 0 (zero) will be replaced as well
02265      *
02266      * @param   string      Input value undergoing processing in this function.
02267      * @param   array       stdWrap properties for ifEmpty.
02268      * @return  string      The processed input value
02269      */
02270     public function stdWrap_ifEmpty($content = '', $conf = array()) {
02271         if (!trim($content)) {
02272             $content = $conf['ifEmpty'];
02273         }
02274         return $content;
02275     }
02276 
02277     /**
02278      * ifBlank
02279      * Will set content to a replacement value in case the trimmed value of content has no length
02280      * 0 (zero) will not be replaced
02281      *
02282      * @param   string      Input value undergoing processing in this function.
02283      * @param   array       stdWrap properties for ifBlank.
02284      * @return  string      The processed input value
02285      */
02286     public function stdWrap_ifBlank($content = '', $conf = array()) {
02287         if (!strlen(trim($content))) {
02288             $content = $conf['ifBlank'];
02289         }
02290         return $content;
02291     }
02292 
02293     /**
02294      * listNum
02295      * Gets a value off a CSV list after ifEmpty check
02296      * Might return an empty value in case the CSV does not contain a value at the position given by listNum
02297      * Use preIfEmptyListNum to avoid that behaviour
02298      *
02299      * @param   string      Input value undergoing processing in this function.
02300      * @param   array       stdWrap properties for listNum.
02301      * @return  string      The processed input value
02302      */
02303     public function stdWrap_listNum($content = '', $conf = array()) {
02304         $content = $this->listNum($content, $conf['listNum'], $conf['listNum.']['splitChar']);
02305         return $content;
02306     }
02307 
02308     /**
02309      * trim
02310      * Cuts off any whitespace at the beginning and the end of the content
02311      *
02312      * @param   string      Input value undergoing processing in this function.
02313      * @param   array       stdWrap properties for trim.
02314      * @return  string      The processed input value
02315      */
02316     public function stdWrap_trim($content = '', $conf = array()) {
02317         $content = trim($content);
02318         return $content;
02319     }
02320 
02321     /**
02322      * stdWrap
02323      * A recursive call of the stdWrap function set
02324      * This enables the user to execute stdWrap functions in another than the predefined order
02325      * It modifies the content, not the property
02326      * while the new feature of chained stdWrap functions modifies the property and not the content
02327      *
02328      * @param   string      Input value undergoing processing in this function.
02329      * @param   array       stdWrap properties for stdWrap.
02330      * @return  string      The processed input value
02331      */
02332     public function stdWrap_stdWrap($content = '', $conf = array()) {
02333         $content = $this->stdWrap($content, $conf['stdWrap.']);
02334         return $content;
02335     }
02336 
02337     /**
02338      * stdWrap process hook
02339      * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
02340      * this hook executes functions directly after the recursive stdWrap function call but still before the content gets modified
02341      *
02342      * @param   string      Input value undergoing processing in these functions.
02343      * @param   array       All stdWrap properties, not just the ones for a particular function.
02344      * @return  string      The processed input value
02345      */
02346     public function stdWrap_stdWrapProcess($content = '', $conf = array()) {
02347         foreach ($this->stdWrapHookObjects as $hookObject) {
02348             $content = $hookObject->stdWrapProcess($content, $conf, $this);
02349         }
02350         return $content;
02351     }
02352 
02353     /**
02354      * required
02355      * Will immediately stop rendering and return an empty value
02356      * when there is no content at this point
02357      *
02358      * @param   string      Input value undergoing processing in this function.
02359      * @param   array       stdWrap properties for required.
02360      * @return  string      The processed input value
02361      */
02362     public function stdWrap_required($content = '', $conf = array()) {
02363         if ((string) $content == '') {
02364             $content = '';
02365             $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
02366         }
02367         return $content;
02368     }
02369 
02370     /**
02371      * if
02372      * Will immediately stop rendering and return an empty value
02373      * when the result of the checks returns false
02374      *
02375      * @param   string      Input value undergoing processing in this function.
02376      * @param   array       stdWrap properties for if.
02377      * @return  string      The processed input value
02378      */
02379     public function stdWrap_if($content = '', $conf = array()) {
02380         if (!$this->checkIf($conf['if.'])) {
02381             $content = '';
02382             $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
02383         }
02384         return $content;
02385     }
02386 
02387     /**
02388      * fieldRequired
02389      * Will immediately stop rendering and return an empty value
02390      * when there is no content in the field given by fieldRequired
02391      *
02392      * @param   string      Input value undergoing processing in this function.
02393      * @param   array       stdWrap properties for fieldRequired.
02394      * @return  string      The processed input value
02395      */
02396     public function stdWrap_fieldRequired($content = '', $conf = array()) {
02397         if (!trim($this->data[$conf['fieldRequired']])) {
02398             $content = '';
02399             $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
02400         }
02401         return $content;
02402     }
02403 
02404     /**
02405      * csConv
02406      * Will convert the current chracter set of the content to the one given in csConv
02407      *
02408      * @param   string      Input value undergoing processing in this function.
02409      * @param   array       stdWrap properties for csConv.
02410      * @return  string      The processed input value
02411      */
02412     public function stdWrap_csConv($content = '', $conf = array()) {
02413         $content = $GLOBALS['TSFE']->csConv($content, $conf['csConv']);
02414         return $content;
02415     }
02416 
02417     /**
02418      * parseFunc
02419      * Will parse the content based on functions given as stdWrap properties
02420      * Heavily used together with RTE based content
02421      *
02422      * @param   string      Input value undergoing processing in this function.
02423      * @param   array       stdWrap properties for parseFunc.
02424      * @return  string      The processed input value
02425      */
02426     public function stdWrap_parseFunc($content = '', $conf = array()) {
02427         $content = $this->parseFunc($content, $conf['parseFunc.'], $conf['parseFunc']);
02428         return $content;
02429     }
02430 
02431     /**
02432      * HTMLparser
02433      * Will parse HTML content based on functions given as stdWrap properties
02434      * Heavily used together with RTE based content
02435      *
02436      * @param   string      Input value undergoing processing in this function.
02437      * @param   array       stdWrap properties for HTMLparser.
02438      * @return  string      The processed input value
02439      */
02440     public function stdWrap_HTMLparser($content = '', $conf = array()) {
02441         if (is_array($conf['HTMLparser.'])) {
02442             $content = $this->HTMLparser_TSbridge($content, $conf['HTMLparser.']);
02443         }
02444         return $content;
02445     }
02446 
02447     /**
02448      * split
02449      * Will split the content by a given token and treat the results separately
02450      * Automatically fills 'current' with a single result
02451      *
02452      * @param   string      Input value undergoing processing in this function.
02453      * @param   array       stdWrap properties for split.
02454      * @return  string      The processed input value
02455      */
02456     public function stdWrap_split($content = '', $conf = array()) {
02457         $content = $this->splitObj($content, $conf['split.']);
02458         return $content;
02459     }
02460 
02461     /**
02462      * prioriCalc
02463      * Will use the content as a mathematical term and calculate the result
02464      * Can be set to 1 to just get a calculated value or 'intval' to get the integer of the result
02465      *
02466      * @param   string      Input value undergoing processing in this function.
02467      * @param   array       stdWrap properties for prioriCalc.
02468      * @return  string      The processed input value
02469      */
02470     public function stdWrap_prioriCalc($content = '', $conf = array()) {
02471         $content = t3lib_div::calcParenthesis($content);
02472         if ($conf['prioriCalc'] == 'intval')
02473             $content = intval($content);
02474         return $content;
02475     }
02476 
02477     /**
02478      * char
02479      * Will return a character based on its position within the current character set
02480      *
02481      * @param   string      Input value undergoing processing in this function.
02482      * @param   array       stdWrap properties for char.
02483      * @return  string      The processed input value
02484      */
02485     public function stdWrap_char($content = '', $conf = array()) {
02486         $content = chr(intval($conf['char']));
02487         return $content;
02488     }
02489 
02490     /**
02491      * intval
02492      * Will return an integer value of the current content
02493      *
02494      * @param   string      Input value undergoing processing in this function.
02495      * @param   array       stdWrap properties for intval.
02496      * @return  string      The processed input value
02497      */
02498     public function stdWrap_intval($content = '', $conf = array()) {
02499         $content = intval($content);
02500         return $content;
02501     }
02502 
02503     /**
02504      * numberFormat
02505      * Will return a formatted number based on configuration given as stdWrap properties
02506      *
02507      * @param   string      Input value undergoing processing in this function.
02508      * @param   array       stdWrap properties for numberFormat.
02509      * @return  string      The processed input value
02510      */
02511     public function stdWrap_numberFormat($content = '', $conf = array()) {
02512         $content = $this->numberFormat($content, $conf['numberFormat.']);
02513         return $content;
02514     }
02515 
02516     /**
02517      * date
02518      * Will return a formatted date based on configuration given according to PHP date/gmdate properties
02519      * Will return gmdate when the property GMT returns true
02520      *
02521      * @param   string      Input value undergoing processing in this function.
02522      * @param   array       stdWrap properties for date.
02523      * @return  string      The processed input value
02524      */
02525     public function stdWrap_date($content = '', $conf = array()) {
02526         $content = ($conf['date.']['GMT'] ? gmdate($conf['date'], $content) : date($conf['date'], $content));
02527         return $content;
02528     }
02529 
02530     /**
02531      * strftime
02532      * Will return a formatted date based on configuration given according to PHP strftime/gmstrftime properties
02533      * Will return gmstrftime when the property GMT returns true
02534      *
02535      * @param   string      Input value undergoing processing in this function.
02536      * @param   array       stdWrap properties for strftime.
02537      * @return  string      The processed input value
02538      */
02539     public function stdWrap_strftime($content = '', $conf = array()) {
02540         $content = ($conf['strftime.']['GMT'] ? gmstrftime($conf['strftime'], $content) : strftime($conf['strftime'], $content));
02541         $tmp_charset = $conf['strftime.']['charset'] ? $conf['strftime.']['charset'] : $GLOBALS['TSFE']->localeCharset;
02542         if ($tmp_charset) {
02543             $content = $GLOBALS['TSFE']->csConv($content, $tmp_charset);
02544         }
02545         return $content;
02546     }
02547 
02548     /**
02549      * age
02550      * Will return the age of a given timestamp based on configuration given by stdWrap properties
02551      *
02552      * @param   string      Input value undergoing processing in this function.
02553      * @param   array       stdWrap properties for age.
02554      * @return  string      The processed input value
02555      */
02556     public function stdWrap_age($content = '', $conf = array()) {
02557         $content = $this->calcAge($GLOBALS['EXEC_TIME'] - $content, $conf['age']);
02558         return $content;
02559     }
02560 
02561     /**
02562      * case
02563      * Will transform the content to be upper or lower case only
02564      * Leaves HTML tags untouched
02565      *
02566      * @param   string      Input value undergoing processing in this function.
02567      * @param   array       stdWrap properties for case.
02568      * @return  string      The processed input value
02569      */
02570     public function stdWrap_case($content = '', $conf = array()) {
02571         $content = $this->HTMLcaseshift($content, $conf['case']);
02572         return $content;
02573     }
02574 
02575     /**
02576      * bytes
02577      * Will return the size of a given number in Bytes   *
02578      *
02579      * @param   string      Input value undergoing processing in this function.
02580      * @param   array       stdWrap properties for bytes.
02581      * @return  string      The processed input value
02582      */
02583     public function stdWrap_bytes($content = '', $conf = array()) {
02584         $content = t3lib_div::formatSize($content, $conf['bytes.']['labels']);
02585         return $content;
02586     }
02587 
02588     /**
02589      * substring
02590      * Will return a substring based on position information given by stdWrap properties
02591      *
02592      * @param   string      Input value undergoing processing in this function.
02593      * @param   array       stdWrap properties for substring.
02594      * @return  string      The processed input value
02595      */
02596     public function stdWrap_substring($content = '', $conf = array()) {
02597         $content = $this->substring($content, $conf['substring']);
02598         return $content;
02599     }
02600 
02601     /**
02602      * removeBadHTML
02603      * Removes HTML tags based on stdWrap properties
02604      *
02605      * @param   string      Input value undergoing processing in this function.
02606      * @param   array       stdWrap properties for removeBadHTML.
02607      * @return  string      The processed input value
02608      */
02609     public function stdWrap_removeBadHTML($content = '', $conf = array()) {
02610         $content = $this->removeBadHTML($content, $conf['removeBadHTML.']);
02611         return $content;
02612     }
02613 
02614     /**
02615      * cropHTML
02616      * Crops content to a given size while leaving HTML tags untouched
02617      *
02618      * @param   string      Input value undergoing processing in this function.
02619      * @param   array       stdWrap properties for cropHTML.
02620      * @return  string      The processed input value
02621      */
02622     public function stdWrap_cropHTML($content = '', $conf = array()) {
02623         $content = $this->cropHTML($content, $conf['cropHTML']);
02624         return $content;
02625     }
02626 
02627     /**
02628      * stripHtml
02629      * Copmletely removes HTML tags from content
02630      *
02631      * @param   string      Input value undergoing processing in this function.
02632      * @param   array       stdWrap properties for stripHtml.
02633      * @return  string      The processed input value
02634      */
02635     public function stdWrap_stripHtml($content = '', $conf = array()) {
02636         $content = strip_tags($content);
02637         return $content;
02638     }
02639 
02640     /**
02641      * cropHTML
02642      * Crops content to a given size without caring abhout HTML tags
02643      *
02644      * @param   string      Input value undergoing processing in this function.
02645      * @param   array       stdWrap properties for crop.
02646      * @return  string      The processed input value
02647      */
02648     public function stdWrap_crop($content = '', $conf = array()) {
02649         $content = $this->crop($content, $conf['crop']);
02650         return $content;
02651     }
02652 
02653     /**
02654      * rawUrlEncode
02655      * Encodes content to be used within URLs
02656      *
02657      * @param   string      Input value undergoing processing in this function.
02658      * @param   array       stdWrap properties for rawUrlEncode.
02659      * @return  string      The processed input value
02660      */
02661     public function stdWrap_rawUrlEncode($content = '', $conf = array()) {
02662         $content = rawurlencode($content);
02663         return $content;
02664     }
02665 
02666     /**
02667      * htmlSpecialChars
02668      * Transforms HTML tags to readable text by replacing special characters with their HTML entity
02669      * When preserveEntities returns true, existing entities will be left untouched
02670      *
02671      * @param   string      Input value undergoing processing in this function.
02672      * @param   array       stdWrap properties for htmlSpecalChars.
02673      * @return  string      The processed input value
02674      */
02675     public function stdWrap_htmlSpecialChars($content = '', $conf = array()) {
02676         $content = htmlSpecialChars($content);
02677         if ($conf['htmlSpecialChars.']['preserveEntities'])
02678             $content = t3lib_div::deHSCentities($content);
02679         return $content;
02680     }
02681 
02682     /**
02683      * doubleBrTag
02684      * Searches for double line breaks and replaces them with the given value
02685      *
02686      * @param   string      Input value undergoing processing in this function.
02687      * @param   array       stdWrap properties for doubleBrTag.
02688      * @return  string      The processed input value
02689      */
02690     public function stdWrap_doubleBrTag($content = '', $conf = array()) {
02691         $content = preg_replace("/\r?\n[\t ]*\r?\n/", $conf['doubleBrTag'], $content);
02692         return $content;
02693     }
02694 
02695     /**
02696      * br
02697      * Searches for single line breaks and replaces them with a <br /> tag
02698      *
02699      * @param   string      Input value undergoing processing in this function.
02700      * @param   array       stdWrap properties for br.
02701      * @return  string      The processed input value
02702      */
02703     public function stdWrap_br($content = '', $conf = array()) {
02704         $content = nl2br($content);
02705         return $content;
02706     }
02707 
02708     /**
02709      * brTag
02710      * Searches for single line feeds and replaces them with the given value
02711      *
02712      * @param   string      Input value undergoing processing in this function.
02713      * @param   array       stdWrap properties for brTag.
02714      * @return  string      The processed input value
02715      */
02716     public function stdWrap_brTag($content = '', $conf = array()) {
02717         $content = str_replace(LF, $conf['brTag'], $content);
02718         return $content;
02719     }
02720 
02721     /**
02722      * encapsLines
02723      * Modifies text blocks by searching for lines which are not surrounded by HTML tags yet
02724      * and wrapping them with values given by stdWrap properties
02725      *
02726      * @param   string      Input value undergoing processing in this function.
02727      * @param   array       stdWrap properties for erncapsLines.
02728      * @return  string      The processed input value
02729      */
02730     public function stdWrap_encapsLines($content = '', $conf = array()) {
02731         $content = $this->encaps_lineSplit($content, $conf['encapsLines.']);
02732         return $content;
02733     }
02734 
02735     /**
02736      * keywords
02737      * Transforms content into a CSV list to be used i.e. as keywords within a meta tag
02738      *
02739      * @param   string      Input value undergoing processing in this function.
02740      * @param   array       stdWrap properties for keywords.
02741      * @return  string      The processed input value
02742      */
02743     public function stdWrap_keywords($content = '', $conf = array()) {
02744         $content = $this->keywords($content);
02745         return $content;
02746     }
02747 
02748     /**
02749      * innerWrap
02750      * First of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
02751      * See wrap
02752      *
02753      * @param   string      Input value undergoing processing in this function.
02754      * @param   array       stdWrap properties for innerWrap.
02755      * @return  string      The processed input value
02756      */
02757     public function stdWrap_innerWrap($content = '', $conf = array()) {
02758         $content = $this->wrap($content, $conf['innerWrap']);
02759         return $content;
02760     }
02761 
02762     /**
02763      * innerWrap2
02764      * Second of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
02765      * See wrap
02766      *
02767      * @param   string      Input value undergoing processing in this function.
02768      * @param   array       stdWrap properties for innerWrap2.
02769      * @return  string      The processed input value
02770      */
02771     public function stdWrap_innerWrap2($content = '', $conf = array()) {
02772         $content = $this->wrap($content, $conf['innerWrap2']);
02773         return $content;
02774     }
02775 
02776     /**
02777      * fontTag
02778      * A wrap formerly used to apply font tags to format the content
02779      * Still used by lib.stdheader although real font tags are not state of the art anymore
02780      * See wrap
02781      *
02782      * @param   string      Input value undergoing processing in this function.
02783      * @param   array       stdWrap properties for fontTag.
02784      * @return  string      The processed input value
02785      */
02786     public function stdWrap_fontTag($content = '', $conf = array()) {
02787         $content = $this->wrap($content, $conf['fontTag']);
02788         return $content;
02789     }
02790 
02791     /**
02792      * addParams
02793      * Adds tag attributes to any content that is a tag
02794      *
02795      * @param   string      Input value undergoing processing in this function.
02796      * @param   array       stdWrap properties for addParams.
02797      * @return  string      The processed input value
02798      */
02799     public function stdWrap_addParams($content = '', $conf = array()) {
02800         $content = $this->addParams($content, $conf['addParams.']);
02801         return $content;
02802     }
02803 
02804     /**
02805      * textStyle
02806      * Wraps content in font tags
02807      * See wrap
02808      *
02809      * @param   string      Input value undergoing processing in this function.
02810      * @param   array       stdWrap properties for textStyle.
02811      * @return  string      The processed input value
02812      */
02813     public function stdWrap_textStyle($content = '', $conf = array()) {
02814         $content = $this->textStyle($content, $conf['textStyle.']);
02815         return $content;
02816     }
02817 
02818     /**
02819      * tableStyle
02820      * Wraps content with table tags
02821      * See wrap
02822      *
02823      * @param   string      Input value undergoing processing in this function.
02824      * @param   array       stdWrap properties for tableStyle.
02825      * @return  string      The processed input value
02826      */
02827     public function stdWrap_tableStyle($content = '', $conf = array()) {
02828         $content = $this->tableStyle($content, $conf['tableStyle.']);
02829         return $content;
02830     }
02831 
02832     /**
02833      * filelink
02834      * Used to make lists of links to files
02835      * See wrap
02836      *
02837      * @param   string      Input value undergoing processing in this function.
02838      * @param   array       stdWrap properties for filelink.
02839      * @return  string      The processed input value
02840      */
02841     public function stdWrap_filelink($content = '', $conf = array()) {
02842         $content = $this->filelink($content, $conf['filelink.']);
02843         return $content;
02844     }
02845 
02846     /**
02847      * preCObject
02848      * A content object that is prepended to the current content but between the innerWraps and the rest of the wraps
02849      *
02850      * @param   string      Input value undergoing processing in this function.
02851      * @param   array       stdWrap properties for preCObject.
02852      * @return  string      The processed input value
02853      */
02854     public function stdWrap_preCObject($content = '', $conf = array()) {
02855         $content = $this->cObjGetSingle($conf['preCObject'], $conf['preCObject.'], '/stdWrap/.preCObject') . $content;
02856         return $content;
02857     }
02858 
02859     /**
02860      * postCObject
02861      * A content object that is appended to the current content but between the innerWraps and the rest of the wraps
02862      *
02863      * @param   string      Input value undergoing processing in this function.
02864      * @param   array       stdWrap properties for postCObject.
02865      * @return  string      The processed input value
02866      */
02867     public function stdWrap_postCObject($content = '', $conf = array()) {
02868         $content .= $this->cObjGetSingle($conf['postCObject'], $conf['postCObject.'], '/stdWrap/.postCObject');
02869         return $content;
02870     }
02871 
02872     /**
02873      * wrapAlign
02874      * Wraps content with a div container having the style attribute text-align set to the given value
02875      * See wrap
02876      *
02877      * @param   string      Input value undergoing processing in this function.
02878      * @param   array       stdWrap properties for wrapAlign.
02879      * @return  string      The processed input value
02880      */
02881     public function stdWrap_wrapAlign($content = '', $conf = array()) {
02882         $wrapAlign = trim($conf['wrapAlign']);
02883         if ($wrapAlign) {
02884             $content = $this->wrap($content, '<div style="text-align:' . $wrapAlign . ';">|</div>');
02885         }
02886         return $content;
02887     }
02888 
02889     /**
02890      * typolink
02891      * Wraps the content with a link tag
02892      * URLs and other attributes are created automatically by the values given in the stdWrap properties
02893      * See wrap
02894      *
02895      * @param   string      Input value undergoing processing in this function.
02896      * @param   array       stdWrap properties for typolink.
02897      * @return  string      The processed input value
02898      */
02899     public function stdWrap_typolink($content = '', $conf = array()) {
02900         $content = $this->typolink($content, $conf['typolink.']);
02901         return $content;
02902     }
02903 
02904     /**
02905      * TCAselectItem
02906      * Returns a list of options available for a given field in the DB which has to be of the type select
02907      *
02908      * @param   string      Input value undergoing processing in this function.
02909      * @param   array       stdWrap properties for TCAselectItem.
02910      * @return  string      The processed input value
02911      */
02912     public function stdWrap_TCAselectItem($content = '', $conf = array()) {
02913         if (is_array($conf['TCAselectItem.'])) {
02914             $content = $this->TCAlookup($content, $conf['TCAselectItem.']);
02915         }
02916         return $content;
02917     }
02918 
02919     /**
02920      * spaceBefore
02921      * Will add space before the current content
02922      * By default this is done with a clear.gif but it can be done with CSS margins by setting the property space.useDiv to true
02923      *
02924      * @param   string      Input value undergoing processing in this function.
02925      * @param   array       stdWrap properties for spaceBefore and space.
02926      * @return  string      The processed input value
02927      */
02928     public function stdWrap_spaceBefore($content = '', $conf = array()) {
02929         $content = $this->wrapSpace($content, trim($conf['spaceBefore']) . '|', $conf['space.']);
02930         return $content;
02931     }
02932 
02933     /**
02934      * spaceAfter
02935      * Will add space after the current content
02936      * By default this is done with a clear.gif but it can be done with CSS margins by setting the property space.useDiv to true
02937      *
02938      * @param   string      Input value undergoing processing in this function.
02939      * @param   array       stdWrap properties for spaceAfter and space.
02940      * @return  string      The processed input value
02941      */
02942     public function stdWrap_spaceAfter($content = '', $conf = array()) {
02943         $content = $this->wrapSpace($content, '|' . trim($conf['spaceAfter']), $conf['space.']);
02944         return $content;
02945     }
02946 
02947     /**
02948      * space
02949      * Will add space before or after the current content
02950      * By default this is done with a clear.gif but it can be done with CSS margins by setting the property space.useDiv to true
02951      * See wrap
02952      *
02953      * @param   string      Input value undergoing processing in this function.
02954      * @param   array       stdWrap properties for space.
02955      * @return  string      The processed input value
02956      */
02957     public function stdWrap_space($content = '', $conf = array()) {
02958         $content = $this->wrapSpace($content, trim($conf['space']), $conf['space.']);
02959         return $content;
02960     }
02961 
02962     /**
02963      * wrap
02964      * This is the "mother" of all wraps
02965      * Third of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
02966      * Basically it will put additional content before and after the current content using a split character as a placeholder for the current content
02967      * The default split character is | but it can be replaced with other characters by the property splitChar
02968      * Any other wrap that does not have own splitChar settings will be using the default split char though
02969      *
02970      * @param   string      Input value undergoing processing in this function.
02971      * @param   array       stdWrap properties for wrap.
02972      * @return  string      The processed input value
02973      */
02974     public function stdWrap_wrap($content = '', $conf = array()) {
02975         $content = $this->wrap($content, $conf['wrap'], ($conf['wrap.']['splitChar'] ? $conf['wrap.']['splitChar'] : '|'));
02976         return $content;
02977     }
02978 
02979     /**
02980      * noTrimWrap
02981      * Fourth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
02982      * The major difference to any other wrap is, that this one can make use of whitespace without trimming  *
02983      *
02984      * @param   string      Input value undergoing processing in this function.
02985      * @param   array       stdWrap properties for noTrimWrap.
02986      * @return  string      The processed input value
02987      */
02988     public function stdWrap_noTrimWrap($content = '', $conf = array()) {
02989         $content = $this->noTrimWrap($content, $conf['noTrimWrap']);
02990         return $content;
02991     }
02992 
02993     /**
02994      * wrap2
02995      * Fifth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
02996      * The default split character is | but it can be replaced with other characters by the property splitChar
02997      *
02998      * @param   string      Input value undergoing processing in this function.
02999      * @param   array       stdWrap properties for wrap2.
03000      * @return  string      The processed input value
03001      */
03002     public function stdWrap_wrap2($content = '', $conf = array()) {
03003         $content = $this->wrap($content, $conf['wrap2'], ($conf['wrap2.']['splitChar'] ? $conf['wrap2.']['splitChar'] : '|'));
03004         return $content;
03005     }
03006 
03007     /**
03008      * dataWrap
03009      * Sixth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
03010      * Can fetch additional content the same way data does (i.e. {field:whatever}) and apply it to the wrap before that is applied to the content
03011      *
03012      * @param   string      Input value undergoing processing in this function.
03013      * @param   array       stdWrap properties for dataWrap.
03014      * @return  string      The processed input value
03015      */
03016     public function stdWrap_dataWrap($content = '', $conf = array()) {
03017         $content = $this->dataWrap($content, $conf['dataWrap']);
03018         return $content;
03019     }
03020 
03021     /**
03022      * prepend
03023      * A content object that will be prepended to the current content after most of the wraps have already been applied
03024      *
03025      * @param   string      Input value undergoing processing in this function.
03026      * @param   array       stdWrap properties for prepend.
03027      * @return  string      The processed input value
03028      */
03029     public function stdWrap_prepend($content = '', $conf = array()) {
03030         $content = $this->cObjGetSingle($conf['prepend'], $conf['prepend.'], '/stdWrap/.prepend') . $content;
03031         return $content;
03032     }
03033 
03034     /**
03035      * append
03036      * A content object that will be appended to the current content after most of the wraps have already been applied
03037      *
03038      * @param   string      Input value undergoing processing in this function.
03039      * @param   array       stdWrap properties for append.
03040      * @return  string      The processed input value
03041      */
03042     public function stdWrap_append($content = '', $conf = array()) {
03043         $content .= $this->cObjGetSingle($conf['append'], $conf['append.'], '/stdWrap/.append');
03044         return $content;
03045     }
03046 
03047     /**
03048      * wrap3
03049      * Seventh of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
03050      * The default split character is | but it can be replaced with other characters by the property splitChar
03051      *
03052      * @param   string      Input value undergoing processing in this function.
03053      * @param   array       stdWrap properties for wrap3.
03054      * @return  string      The processed input value
03055      */
03056     public function stdWrap_wrap3($content = '', $conf = array()) {
03057         $content = $this->wrap($content, $conf['wrap3'], ($conf['wrap3.']['splitChar'] ? $conf['wrap3.']['splitChar'] : '|'));
03058         return $content;
03059     }
03060 
03061     /**
03062      * outerWrap
03063      * Eighth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
03064      *
03065      * @param   string      Input value undergoing processing in this function.
03066      * @param   array       stdWrap properties for outerWrap.
03067      * @return  string      The processed input value
03068      */
03069     public function stdWrap_outerWrap($content = '', $conf = array()) {
03070         $content = $this->wrap($content, $conf['outerWrap']);
03071         return $content;
03072     }
03073 
03074     /**
03075      * inserData
03076      * Can fetch additional content the same way data does and replaces any occurence of {field:whatever} with this content
03077      *
03078      * @param   string      Input value undergoing processing in this function.
03079      * @param   array       stdWrap properties for insertData.
03080      * @return  string      The processed input value
03081      */
03082     public function stdWrap_insertData($content = '', $conf = array()) {
03083         $content = $this->insertData($content);
03084         return $content;
03085     }
03086 
03087     /**
03088      * offsetWrap
03089      * Creates a so called offset table around the content
03090      * Still here for historical reasons even not used too much nowadays
03091      *
03092      * @param   string      Input value undergoing processing in this function.
03093      * @param   array       stdWrap properties for offsetWrap.
03094      * @return  string      The processed input value
03095      */
03096     public function stdWrap_offsetWrap($content = '', $conf = array()) {
03097         $controlTable = t3lib_div::makeInstance('tslib_tableOffset');
03098         if ($conf['offsetWrap.']['tableParams'] || $conf['offsetWrap.']['tableParams.']) {
03099             $controlTable->tableParams = isset($conf['offsetWrap.']['tableParams.'])
03100                 ? $this->stdWrap($conf['offsetWrap.']['tableParams'], $conf['offsetWrap.']['tableParams.'])
03101                 : $conf['offsetWrap.']['tableParams'];
03102         }
03103         if ($conf['offsetWrap.']['tdParams'] || $conf['offsetWrap.']['tdParams.']) {
03104             $controlTable->tdParams = ' ' . isset($conf['offsetWrap.']['tdParams.'])
03105                 ? $this->stdWrap($conf['offsetWrap.']['tdParams'], $conf['offsetWrap.']['tdParams.'])
03106                 : $conf['offsetWrap.']['tdParams'];
03107         }
03108         $content = $controlTable->start($content, $conf['offsetWrap']);
03109         if ($conf['offsetWrap.']['stdWrap.']) {
03110             $content = $this->stdWrap($content, $conf['offsetWrap.']['stdWrap.']);
03111         }
03112         return $content;
03113     }
03114 
03115     /**
03116      * postUserFunc
03117      * Will execute a user function after the content has been modified by any other stdWrap function
03118      *
03119      * @param   string      Input value undergoing processing in this function.
03120      * @param   array       stdWrap properties for postUserFunc.
03121      * @return  string      The processed input value
03122      */
03123     public function stdWrap_postUserFunc($content = '', $conf = array()) {
03124         $content = $this->callUserFunction($conf['postUserFunc'], $conf['postUserFunc.'], $content);
03125         return $content;
03126     }
03127 
03128     /**
03129      * postUserFuncInt
03130      * Will execute a user function after the content has been created and each time it is fetched from Cache
03131      * The result of this function itself will not be cached
03132      *
03133      * @param   string      Input value undergoing processing in this function.
03134      * @param   array       stdWrap properties for postUserFuncInt.
03135      * @return  string      The processed input value
03136      */
03137     public function stdWrap_postUserFuncInt($content = '', $conf = array()) {
03138         $substKey = 'INT_SCRIPT.' . $GLOBALS['TSFE']->uniqueHash();
03139         $GLOBALS['TSFE']->config['INTincScript'][$substKey] = array(
03140             'content' => $content, 'postUserFunc' => $conf['postUserFuncInt'], 'conf' => $conf['postUserFuncInt.'], 'type' => 'POSTUSERFUNC', 'cObj' => serialize($this)
03141         );
03142         $content = '<!--' . $substKey . '-->';
03143         return $content;
03144     }
03145 
03146     /**
03147      * prefixComment
03148      * Will add HTML comments to the content to make it easier to identify certain content elements within the HTML output later on
03149      *
03150      * @param   string      Input value undergoing processing in this function.
03151      * @param   array       stdWrap properties for prefixComment.
03152      * @return  string      The processed input value
03153      */
03154     public function stdWrap_prefixComment($content = '', $conf = array()) {
03155         if (!$GLOBALS['TSFE']->config['config']['disablePrefixComment']) {
03156             $content = $this->prefixComment($conf['prefixComment'], $conf['prefixComment.'], $content);
03157         }
03158         return $content;
03159     }
03160 
03161     /**
03162      * editIcons
03163      * Will render icons for frontend editing as long as there is a BE user logged in
03164      *
03165      * @param   string      Input value undergoing processing in this function.
03166      * @param   array       stdWrap properties for editIcons.
03167      * @return  string      The processed input value
03168      */
03169     public function stdWrap_editIcons($content = '', $conf = array()) {
03170         if ($GLOBALS['TSFE']->beUserLogin && $conf['editIcons']) {
03171             if(!is_array($conf['editIcons.'])) {
03172                 $conf['editIcons.'] = array();
03173             }
03174             $content = $this->editIcons($content, $conf['editIcons'], $conf['editIcons.']);
03175         }
03176         return $content;
03177     }
03178 
03179     /**
03180      * editPanel
03181      * Will render the edit panel for frontend editing as long as there is a BE user logged in
03182      *
03183      * @param   string      Input value undergoing processing in this function.
03184      * @param   array       stdWrap properties for editPanel.
03185      * @return  string      The processed input value
03186      */
03187     public function stdWrap_editPanel($content = '', $conf = array()) {
03188         if ($GLOBALS['TSFE']->beUserLogin) {
03189             $content = $this->editPanel($content, $conf['editPanel.']);
03190         }
03191         return $content;
03192     }
03193 
03194     /**
03195      * stdWrap post process hook
03196      * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
03197      * this hook executes functions at after the content has been modified by the rest of the stdWrap functions but still before debugging
03198      *
03199      * @param   string      Input value undergoing processing in these functions.
03200      * @param   array       All stdWrap properties, not just the ones for a particular function.
03201      * @return  string      The processed input value
03202      */
03203     public function stdWrap_stdWrapPostProcess($content = '', $conf = array()) {
03204         foreach ($this->stdWrapHookObjects as $hookObject) {
03205             $content = $hookObject->stdWrapPostProcess($content, $conf, $this);
03206         }
03207         return $content;
03208     }
03209 
03210     /**
03211      * debug
03212      * Will output the content as readable HTML code
03213      *
03214      * @param   string      Input value undergoing processing in this function.
03215      * @param   array       stdWrap properties for debug.
03216      * @return  string      The processed input value
03217      */
03218     public function stdWrap_debug($content = '', $conf = array()) {
03219         $content = '<pre>' . htmlspecialchars($content) . '</pre>';
03220         return $content;
03221     }
03222 
03223     /**
03224      * debugFunc
03225      * Will output the content in a debug table
03226      *
03227      * @param   string      Input value undergoing processing in this function.
03228      * @param   array       stdWrap properties for debugFunc.
03229      * @return  string      The processed input value
03230      */
03231     public function stdWrap_debugFunc($content = '', $conf = array()) {
03232         debug($conf['debugFunc'] == 2 ? array(
03233             $content
03234         ) : $content);
03235         return $content;
03236     }
03237 
03238     /**
03239      * debugData
03240      * Will output the data used by the current record in a debug table
03241      *
03242      * @param   string      Input value undergoing processing in this function.
03243      * @param   array       stdWrap properties for debugData.
03244      * @return  string      The processed input value
03245      */
03246     public function stdWrap_debugData($content = '', $conf = array()) {
03247         debug($this->data, '$cObj->data:');
03248         if (is_array($this->alternativeData)) {
03249             debug($this->alternativeData, '$this->alternativeData');
03250         }
03251         return $content;
03252     }
03253 
03254     /**
03255      * Returns number of rows selected by the query made by the properties set.
03256      * Implements the stdWrap "numRows" property
03257      *
03258      * @param   array       TypoScript properties for the property (see link to "numRows")
03259      * @return  integer     The number of rows found by the select (FALSE on error)
03260      * @access private
03261      * @see stdWrap()
03262      */
03263     function numRows($conf) {
03264         $result = FALSE;
03265         $conf['select.']['selectFields'] = 'count(*)';
03266 
03267         $res = $this->exec_getQuery($conf['table'], $conf['select.']);
03268 
03269         if ($error = $GLOBALS['TYPO3_DB']->sql_error()) {
03270             $GLOBALS['TT']->setTSlogMessage($error, 3);
03271         } else {
03272             $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
03273             $result = intval($row[0]);
03274         }
03275         $GLOBALS['TYPO3_DB']->sql_free_result($res);
03276         return $result;
03277     }
03278 
03279     /**
03280      * Exploding a string by the $char value (if integer its an ASCII value) and returning index $listNum
03281      *
03282      * @param   string      String to explode
03283      * @param   string      Index-number. You can place the word "last" in it and it will be substituted with the pointer to the last value. You can use math operators like "+-/*" (passed to calc())
03284      * @param   string      Either a string used to explode the content string or an integer value which will then be changed into a character, eg. "10" for a linebreak char.
03285      * @return  string
03286      */
03287     function listNum($content, $listNum, $char) {
03288         $char = $char ? $char : ',';
03289         if (t3lib_div::testInt($char)) {
03290             $char = chr($char);
03291         }
03292         $temp = explode($char, $content);
03293         $last = '' . (count($temp) - 1);
03294         $index = $this->calc(str_ireplace('last', $last, $listNum));
03295         return $temp[$index];
03296     }
03297 
03298     /**
03299      * Compares values together based on the settings in the input TypoScript array and returns TRUE or FALSE based on the comparison result.
03300      * Implements the "if" function in TYPO3 TypoScript
03301      *
03302      * @param   array       TypoScript properties defining what to compare
03303      * @return  boolean
03304      * @see HMENU(), CASEFUNC(), IMAGE(), COLUMN(), stdWrap(), _parseFunc()
03305      */
03306     function checkIf($conf) {
03307         if (!is_array($conf)) {
03308             return TRUE;
03309         }
03310         if (isset($conf['directReturn'])) {
03311             return $conf['directReturn'] ? 1 : 0;
03312         }
03313         $flag = TRUE;
03314         if (isset($conf['isTrue']) || isset($conf['isTrue.'])) {
03315             $isTrue = isset($conf['isTrue.'])
03316                 ? trim($this->stdWrap($conf['isTrue'], $conf['isTrue.']))
03317                 : trim($conf['isTrue']);
03318             if (!$isTrue) {
03319                 $flag = 0;
03320             }
03321         }
03322         if (isset($conf['isFalse']) || isset($conf['isFalse.'])) {
03323             $isFalse = isset($conf['isFalse.'])
03324                 ? trim($this->stdWrap($conf['isFalse'], $conf['isFalse.']))
03325                 : trim($conf['isFalse']);
03326             if ($isFalse) {
03327                 $flag = 0;
03328             }
03329         }
03330         if (isset($conf['isPositive']) || isset($conf['isPositive.'])) {
03331             $number = isset($conf['isPositive.'])
03332                 ? $this->calc($this->stdWrap($conf['isPositive'], $conf['isPositive.']))
03333                 : $this->calc($conf['isPositive']);
03334             if ($number < 1) {
03335                 $flag = 0;
03336             }
03337         }
03338         if ($flag) {
03339             $value = isset($conf['value.'])
03340                 ? trim($this->stdWrap($conf['value'], $conf['value.']))
03341                 : trim($conf['value']);
03342 
03343             if (isset($conf['isGreaterThan']) || isset($conf['isGreaterThan.'])) {
03344                 $number = isset($conf['isGreaterThan.'])
03345                     ? trim($this->stdWrap($conf['isGreaterThan'], $conf['isGreaterThan.']))
03346                     : trim($conf['isGreaterThan']);
03347                 if ($number <= $value) {
03348                     $flag = 0;
03349                 }
03350             }
03351             if (isset($conf['isLessThan']) || isset($conf['isLessThan.'])) {
03352                 $number = isset($conf['isLessThan.'])
03353                     ? trim($this->stdWrap($conf['isLessThan'], $conf['isLessThan.']))
03354                     : trim($conf['isLessThan']);
03355                 if ($number >= $value) {
03356                     $flag = 0;
03357                 }
03358             }
03359             if (isset($conf['equals']) || isset($conf['equals.'])) {
03360                 $number = isset($conf['equals.'])
03361                     ? trim($this->stdWrap($conf['equals'], $conf['equals.']))
03362                     : trim($conf['equals']);
03363                 if ($number != $value) {
03364                     $flag = 0;
03365                 }
03366             }
03367             if (isset($conf['isInList']) || isset($conf['isInList.'])) {
03368                 $number = isset($conf['isInList.'])
03369                     ? trim($this->stdWrap($conf['isInList'], $conf['isInList.']))
03370                     : trim($conf['isInList']);
03371                 if (!t3lib_div::inList($value, $number)) {
03372                     $flag = 0;
03373                 }
03374             }
03375         }
03376         if ($conf['negate']) {
03377             $flag = $flag ? 0 : 1;
03378         }
03379         return $flag;
03380     }
03381 
03382     /**
03383      * Reads a directory for files and returns the filepaths in a string list separated by comma.
03384      * Implements the stdWrap property "filelist"
03385      *
03386      * @param   string      The command which contains information about what files/directory listing to return. See the "filelist" property of stdWrap for details.
03387      * @return  string      Comma list of files.
03388      * @access private
03389      * @see stdWrap()
03390      */
03391     function filelist($data) {
03392         $data = trim($data);
03393         if ($data) {
03394             $data_arr = explode('|', $data);
03395                 // read directory:
03396             if ($GLOBALS['TSFE']->lockFilePath) { // MUST exist!
03397                 $path = $this->clean_directory($data_arr[0]); // Cleaning name..., only relative paths accepted.
03398                     // see if path starts with lockFilePath, the additional '/' is needed because clean_directory gets rid of it
03399                 $path = (t3lib_div::isFirstPartOfStr($path . '/', $GLOBALS['TSFE']->lockFilePath) ? $path : '');
03400             }
03401             if ($path) {
03402                 $items = array(
03403                     'files' => array(),
03404                     'sorting' => array()
03405                 );
03406                 $ext_list = strtolower(t3lib_div::uniqueList($data_arr[1]));
03407                 $sorting = trim($data_arr[2]);
03408                     // read dir:
03409                 $d = @dir($path);
03410                 $tempArray = array();
03411                 if (is_object($d)) {
03412                     $count = 0;
03413                     while ($entry = $d->read()) {
03414                         if ($entry != '.' && $entry != '..') {
03415                             $wholePath = $path . '/' . $entry; // Because of odd PHP-error where  <br />-tag is sometimes placed after a filename!!
03416                             if (file_exists($wholePath) && filetype($wholePath) == 'file') {
03417                                 $info = t3lib_div::split_fileref($wholePath);
03418                                 if (!$ext_list || t3lib_div::inList($ext_list, $info['fileext'])) {
03419                                     $items['files'][] = $info['file'];
03420                                     switch ($sorting) {
03421                                         case 'name' :
03422                                             $items['sorting'][] = strtolower($info['file']);
03423                                         break;
03424                                         case 'size' :
03425                                             $items['sorting'][] = filesize($wholePath);
03426                                         break;
03427                                         case 'ext' :
03428                                             $items['sorting'][] = $info['fileext'];
03429                                         break;
03430                                         case 'date' :
03431                                             $items['sorting'][] = filectime($wholePath);
03432                                         break;
03433                                         case 'mdate' :
03434                                             $items['sorting'][] = filemtime($wholePath);
03435                                         break;
03436                                         default :
03437                                             $items['sorting'][] = $count;
03438                                         break;
03439                                     }
03440                                     $count++;
03441                                 }
03442                             }
03443                         }
03444                     }
03445                     $d->close();
03446                 }
03447                     // Sort if required
03448                 if (count($items['sorting'])) {
03449                     if (strtolower(trim($data_arr[3])) != 'r') {
03450                         asort($items['sorting']);
03451                     } else {
03452                         arsort($items['sorting']);
03453                     }
03454                 }
03455                 if (count($items['files'])) {
03456                         // make list
03457                     reset($items['sorting']);
03458                     $fullPath = trim($data_arr[4]);
03459                     $list_arr = array();
03460                     foreach ($items['sorting'] as $key => $v) {
03461                         $list_arr[] = $fullPath ? $path . '/' . $items['files'][$key] : $items['files'][$key];
03462                     }
03463                     return implode(',', $list_arr);
03464                 }
03465             }
03466         }
03467     }
03468 
03469     /**
03470      * Cleans $theDir for slashes in the end of the string and returns the new path, if it exists on the server.
03471      *
03472      * @param   string      Absolute path to directory
03473      * @return  string      The directory path if it existed as was valid to access.
03474      * @access private
03475      * @see filelist()
03476      */
03477     function clean_directory($theDir) {
03478         if (t3lib_div::validPathStr($theDir)) { // proceeds if no '//', '..' or '\' is in the $theFile
03479             $theDir = preg_replace('/[\/\. ]*$/', '', $theDir); // Removes all dots, slashes and spaces after a path...
03480             if (!t3lib_div::isAbsPath($theDir) && @is_dir($theDir)) {
03481                 return $theDir;
03482             }
03483         }
03484     }
03485 
03486     /**
03487      * Passes the input value, $theValue, to an instance of "t3lib_parsehtml" together with the TypoScript options which are first converted from a TS style array to a set of arrays with options for the t3lib_parsehtml class.
03488      *
03489      * @param   string      The value to parse by the class "t3lib_parsehtml"
03490      * @param   array       TypoScript properties for the parser. See link.
03491      * @return  string      Return value.
03492      * @see stdWrap(), t3lib_parsehtml::HTMLparserConfig(), t3lib_parsehtml::HTMLcleaner()
03493      */
03494     function HTMLparser_TSbridge($theValue, $conf) {
03495         $htmlParser = t3lib_div::makeInstance('t3lib_parsehtml');
03496         $htmlParserCfg = $htmlParser->HTMLparserConfig($conf);
03497         return $htmlParser->HTMLcleaner($theValue, $htmlParserCfg[0], $htmlParserCfg[1], $htmlParserCfg[2], $htmlParserCfg[3]);
03498     }
03499 
03500     /**
03501      * Wrapping input value in a regular "wrap" but parses the wrapping value first for "insertData" codes.
03502      *
03503      * @param   string      Input string being wrapped
03504      * @param   string      The wrap string, eg. "<strong></strong>" or more likely here '<a href="index.php?id={TSFE:id}"> | </a>' which will wrap the input string in a <a> tag linking to the current page.
03505      * @return  string      Output string wrapped in the wrapping value.
03506      * @see insertData(), stdWrap()
03507      */
03508     function dataWrap($content, $wrap) {
03509         return $this->wrap($content, $this->insertData($wrap));
03510     }
03511 
03512     /**
03513      * Implements the "insertData" property of stdWrap meaning that if strings matching {...} is found in the input string they will be substituted with the return value from getData (datatype) which is passed the content of the curly braces.
03514      * Example: If input string is "This is the page title: {page:title}" then the part, '{page:title}', will be substituted with the current pages title field value.
03515      *
03516      * @param   string      Input value
03517      * @return  string      Processed input value
03518      * @see getData(), stdWrap(), dataWrap()
03519      */
03520     function insertData($str) {
03521         $inside = 0;
03522         $newVal = '';
03523         $pointer = 0;
03524         $totalLen = strlen($str);
03525         do {
03526             if (!$inside) {
03527                 $len = strcspn(substr($str, $pointer), '{');
03528                 $newVal .= substr($str, $pointer, $len);
03529                 $inside = 1;
03530             } else {
03531                 $len = strcspn(substr($str, $pointer), '}') + 1;
03532                 $newVal .= $this->getData(substr($str, $pointer + 1, $len - 2), $this->data);
03533                 $inside = 0;
03534             }
03535             $pointer += $len;
03536         } while ($pointer < $totalLen);
03537         return $newVal;
03538     }
03539 
03540     /**
03541      * Returns a HTML comment with the second part of input string (divided by "|") where first part is an integer telling how many trailing tabs to put before the comment on a new line.
03542      * Notice; this function (used by stdWrap) can be disabled by a "config.disablePrefixComment" setting in TypoScript.
03543      *
03544      * @param   string      Input value
03545      * @param   array       TypoScript Configuration (not used at this point.)
03546      * @param   string      The content to wrap the comment around.
03547      * @return  string      Processed input value
03548      * @see stdWrap()
03549      */
03550     function prefixComment($str, $conf, $content) {
03551         $parts = explode('|', $str);
03552 
03553         $output = LF . str_pad('', $parts[0], TAB) .
03554             '<!-- ' . htmlspecialchars($this->insertData($parts[1])) . ' [begin] -->' . LF .
03555             str_pad('', $parts[0] + 1, TAB) .
03556             $content . LF .
03557             str_pad('', $parts[0], TAB) .
03558             '<!-- ' . htmlspecialchars($this->insertData($parts[1])) . ' [end] -->' . LF .
03559             str_pad('', $parts[0] + 1, TAB);
03560 
03561         return $output;
03562     }
03563 
03564     /**
03565      * Implements the stdWrap property "substring" which is basically a TypoScript implementation of the PHP function, substr()
03566      *
03567      * @param   string      The string to perform the operation on
03568      * @param   string      The parameters to substring, given as a comma list of integers where the first and second number is passed as arg 1 and 2 to substr().
03569      * @return  string      The processed input value.
03570      * @access private
03571      * @see stdWrap()
03572      */
03573     function substring($content, $options) {
03574         $options = t3lib_div::intExplode(',', $options . ',');
03575         if ($options[1]) {
03576             return $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, $options[0], $options[1]);
03577         } else {
03578             return $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, $options[0]);
03579         }
03580     }
03581 
03582     /**
03583      * Implements the stdWrap property "crop" which is a modified "substr" function allowing to limit a string lenght to a certain number of chars (from either start or end of string) and having a pre/postfix applied if the string really was cropped.
03584      *
03585      * @param   string      The string to perform the operation on
03586      * @param   string      The parameters splitted by "|": First parameter is the max number of chars of the string. Negative value means cropping from end of string. Second parameter is the pre/postfix string to apply if cropping occurs. Third parameter is a boolean value. If set then crop will be applied at nearest space.
03587      * @return  string      The processed input value.
03588      * @access private
03589      * @see stdWrap()
03590      */
03591     function crop($content, $options) {
03592         $options = explode('|', $options);
03593         $chars = intval($options[0]);
03594         $afterstring = trim($options[1]);
03595         $crop2space = trim($options[2]);
03596         if ($chars) {
03597             if ($GLOBALS['TSFE']->csConvObj->strlen($GLOBALS['TSFE']->renderCharset, $content) > abs($chars)) {
03598                 $truncatePosition = FALSE;
03599                 if ($chars < 0) {
03600                     $content = $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, $chars);
03601                     if ($crop2space) {
03602                         $truncatePosition = strpos($content, ' ');
03603                     }
03604                     $content = ($truncatePosition) ? $afterstring . substr($content, $truncatePosition) : $afterstring . $content;
03605                 } else {
03606                     $content = $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, 0, $chars);
03607                     if ($crop2space) {
03608                         $truncatePosition = strrpos($content, ' ');
03609                     }
03610                     $content = ($truncatePosition) ? substr($content, 0, $truncatePosition) . $afterstring : $content . $afterstring;
03611                 }
03612             }
03613         }
03614         return $content;
03615     }
03616 
03617     /**
03618      * Implements the stdWrap property "cropHTML" which is a modified "substr" function allowing to limit a string length
03619      * to a certain number of chars (from either start or end of string) and having a pre/postfix applied if the string
03620      * really was cropped.
03621      *
03622      * Compared to stdWrap.crop it respects HTML tags and entities.
03623      *
03624      * @param   string      The string to perform the operation on
03625      * @param   string      The parameters splitted by "|": First parameter is the max number of chars of the string. Negative value means cropping from end of string. Second parameter is the pre/postfix string to apply if cropping occurs. Third parameter is a boolean value. If set then crop will be applied at nearest space.
03626      * @return  string      The processed input value.
03627      * @access private
03628      * @see stdWrap()
03629      */
03630     function cropHTML($content, $options) {
03631         $options = explode('|', $options);
03632         $chars = intval($options[0]);
03633         $absChars = abs($chars);
03634         $replacementForEllipsis = trim($options[1]);
03635         $crop2space = trim($options[2]) === '1' ? TRUE : FALSE;
03636 
03637             // Split $content into an array(even items in the array are outside the tags, odd numbers are tag-blocks).
03638         $tags = 'a|b|blockquote|body|div|em|font|form|h1|h2|h3|h4|h5|h6|i|li|map|ol|option|p|pre|sub|sup|select|span|strong|table|thead|tbody|tfoot|td|textarea|tr|u|ul|br|hr|img|input|area|link';
03639             // TODO We should not crop inside <script> tags.
03640         $tagsRegEx = "
03641             (
03642                 (?:
03643                     <!--.*?-->                  # a comment
03644                 )
03645                 |
03646                 </?(?:" . $tags . ")+           # opening tag ('<tag') or closing tag ('</tag')
03647                 (?:
03648                     (?:
03649                         \s+\w+                  # EITHER spaces, followed by word characters (attribute names)
03650                         (?:
03651                             \s*=?\s*            # equals
03652                             (?>
03653                                 \".*?\"         # attribute values in double-quotes
03654                                 |
03655                                 '.*?'           # attribute values in single-quotes
03656                                 |
03657                                 [^'\">\s]+      # plain attribute values
03658                             )
03659                         )?
03660                     )+\s*
03661                     |                           # OR only spaces
03662                     \s*
03663                 )
03664                 /?>                             # closing the tag with '>' or '/>'
03665             )";
03666         $splittedContent = preg_split('%' . $tagsRegEx . '%xs', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
03667 
03668             // Reverse array if we are cropping from right.
03669         if ($chars < 0) {
03670             $splittedContent = array_reverse($splittedContent);
03671         }
03672 
03673             // Crop the text (chars of tag-blocks are not counted).
03674         $strLen = 0;
03675         $croppedOffset = NULL; // This is the offset of the content item which was cropped.
03676         $countSplittedContent = count($splittedContent);
03677         for ($offset = 0; $offset < $countSplittedContent; $offset++) {
03678             if ($offset % 2 === 0) {
03679                 $tempContent = $GLOBALS['TSFE']->csConvObj->utf8_encode($splittedContent[$offset], $GLOBALS['TSFE']->renderCharset);
03680                 $thisStrLen = $GLOBALS['TSFE']->csConvObj->strlen('utf-8', html_entity_decode($tempContent, ENT_COMPAT, 'UTF-8'));
03681                 if (($strLen + $thisStrLen > $absChars)) {
03682                     $croppedOffset = $offset;
03683                     $cropPosition = $absChars - $strLen;
03684                         // The snippet "&[^&\s;]{2,8};" in the RegEx below represents entities.
03685                     $patternMatchEntityAsSingleChar = '(&[^&\s;]{2,8};|.)';
03686                     if ($crop2space) {
03687                         $cropRegEx = $chars < 0
03688                             ? '#(?<=\s)' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}$#ui'
03689                             : '#^' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}(?=\s)#ui';
03690                     } else {
03691                         $cropRegEx = $chars < 0
03692                             ? '#' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}$#ui'
03693                             : '#^' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}#ui';
03694                     }
03695                     if (preg_match($cropRegEx, $tempContent, $croppedMatch)) {
03696                         $tempContent = $croppedMatch[0];
03697                     }
03698                     $splittedContent[$offset] = $GLOBALS['TSFE']->csConvObj->utf8_decode($tempContent, $GLOBALS['TSFE']->renderCharset);
03699                     break;
03700                 } else {
03701                     $strLen += $thisStrLen;
03702                 }
03703             }
03704         }
03705 
03706             // Close cropped tags.
03707         $closingTags = array();
03708         if ($croppedOffset !== NULL) {
03709             $tagName = '';
03710             $openingTagRegEx = '#^<(\w+)(?:\s|>)#';
03711             $closingTagRegEx = '#^</(\w+)(?:\s|>)#';
03712             for ($offset = $croppedOffset - 1; $offset >= 0; $offset = $offset - 2) {
03713                 if (substr($splittedContent[$offset], -2) === '/>') {
03714                         // Ignore empty element tags (e.g. <br />).
03715                     continue;
03716                 }
03717                 preg_match($chars < 0 ? $closingTagRegEx : $openingTagRegEx, $splittedContent[$offset], $matches);
03718                 $tagName = isset($matches[1]) ? $matches[1] : NULL;
03719                 if ($tagName !== NULL) {
03720                         // Seek for the closing (or opening) tag.
03721                     $seekingTagName = '';
03722                     $countSplittedContent = count($splittedContent);
03723                     for ($seekingOffset = $offset + 2; $seekingOffset < $countSplittedContent; $seekingOffset = $seekingOffset + 2) {
03724                         preg_match($chars < 0 ? $openingTagRegEx : $closingTagRegEx, $splittedContent[$seekingOffset], $matches);
03725                         $seekingTagName = isset($matches[1]) ? $matches[1] : NULL;
03726                         if ($tagName === $seekingTagName) { // We found a matching tag.
03727                                 // Add closing tag only if it occurs after the cropped content item.
03728                             if ($seekingOffset > $croppedOffset) {
03729                                 $closingTags[] = $splittedContent[$seekingOffset];
03730                             }
03731                             break;
03732                         }
03733                     }
03734                 }
03735             }
03736                 // Drop the cropped items of the content array. The $closingTags will be added later on again.
03737             array_splice($splittedContent, $croppedOffset + 1);
03738         }
03739         $splittedContent = array_merge($splittedContent, array(
03740             $croppedOffset !== NULL ? $replacementForEllipsis : ''
03741         ), $closingTags);
03742 
03743             // Reverse array once again if we are cropping from the end.
03744         if ($chars < 0) {
03745             $splittedContent = array_reverse($splittedContent);
03746         }
03747 
03748         return implode('', $splittedContent);
03749     }
03750 
03751     /**
03752      * Function for removing malicious HTML code when you want to provide some HTML code user-editable.
03753      * The purpose is to avoid XSS attacks and the code will be continously modified to remove such code.
03754      * For a complete reference with javascript-on-events, see http://www.wdvl.com/Authoring/JavaScript/Events/events_target.html
03755      *
03756      * @param   string      Input string to be cleaned.
03757      * @param   array       TypoScript configuration.
03758      * @return  string      Return string
03759      * @author  Thomas Bley (all from moregroupware cvs code / readmessage.inc.php, published under gpl by Thomas)
03760      * @author  Kasper Sk�rh�j
03761      */
03762     function removeBadHTML($text, $conf) {
03763 
03764             // Copyright 2002-2003 Thomas Bley
03765         $text = preg_replace(
03766             array(
03767                 "'<script[^>]*?>.*?</script[^>]*?>'si", "'<applet[^>]*?>.*?</applet[^>]*?>'si", "'<object[^>]*?>.*?</object[^>]*?>'si", "'<iframe[^>]*?>.*?</iframe[^>]*?>'si", "'<frameset[^>]*?>.*?</frameset[^>]*?>'si", "'<style[^>]*?>.*?</style[^>]*?>'si", "'<marquee[^>]*?>.*?</marquee[^>]*?>'si", "'<script[^>]*?>'si", "'<meta[^>]*?>'si", "'<base[^>]*?>'si", "'<applet[^>]*?>'si", "'<object[^>]*?>'si", "'<link[^>]*?>'si", "'<iframe[^>]*?>'si", "'<frame[^>]*?>'si", "'<frameset[^>]*?>'si", "'<input[^>]*?>'si", "'<form[^>]*?>'si", "'<embed[^>]*?>'si", "'background-image:url'si", "'<\w+.*?(onabort|onbeforeunload|onblur|onchange|onclick|ondblclick|ondragdrop|onerror|onfilterchange|onfocus|onhelp|onkeydown|onkeypress|onkeyup|onload|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onmove|onreadystatechange|onreset|onresize|onscroll|onselect|onselectstart|onsubmit|onunload).*?>'si"
03768             ),
03769             '',
03770             $text
03771         );
03772 
03773         $text = preg_replace(
03774             '/<a[^>]*href[[:space:]]*=[[:space:]]*["\']?[[:space:]]*javascript[^>]*/i',
03775             '',
03776             $text
03777         );
03778 
03779             // Return clean content
03780         return $text;
03781     }
03782 
03783     /**
03784      * Implements the stdWrap property "textStyle"; This generates a <font>-tag (and a <div>-tag for align-attributes) which is wrapped around the input value.
03785      *
03786      * @param   string      The input value
03787      * @param   array       TypoScript properties for the "TypoScript function" '->textStyle'
03788      * @return  string      The processed output value
03789      * @access private
03790      * @see stdWrap()
03791      */
03792     function textStyle($theValue, $conf) {
03793         $conf['face.'][1] = 'Times New Roman';
03794         $conf['face.'][2] = 'Verdana,Arial,Helvetica,Sans serif';
03795         $conf['face.'][3] = 'Arial,Helvetica,Sans serif';
03796 
03797         $conf['size.'][1] = 1;
03798         $conf['size.'][2] = 2;
03799         $conf['size.'][3] = 3;
03800         $conf['size.'][4] = 4;
03801         $conf['size.'][5] = 5;
03802         $conf['size.'][10] = '+1';
03803         $conf['size.'][11] = '-1';
03804 
03805         $conf['color.'][240] = 'black';
03806         $conf['color.'][241] = 'white';
03807         $conf['color.'][242] = '#333333';
03808         $conf['color.'][243] = 'gray';
03809         $conf['color.'][244] = 'silver';
03810         $conf['color.'][245] = 'red';
03811         $conf['color.'][246] = 'navy';
03812         $conf['color.'][247] = 'yellow';
03813         $conf['color.'][248] = 'green';
03814         $conf['color.'][249] = 'olive';
03815         $conf['color.'][250] = 'maroon';
03816 
03817         $face = $this->data[$conf['face.']['field']];
03818         $size = $this->data[$conf['size.']['field']];
03819         $color = $this->data[$conf['color.']['field']];
03820         $align = $this->data[$conf['align.']['field']];
03821         $properties = $this->data[$conf['properties.']['field']];
03822         if (!$properties) {
03823             $properties = isset($conf['properties.']['default.'])
03824                 ? $this->stdWrap($conf['properties.']['default'], $conf['properties.']['default.'])
03825                 : $conf['properties.']['default'];
03826         }
03827 
03828             // properties
03829         if (($properties & 8)) {
03830             $theValue = $this->HTMLcaseshift($theValue, 'upper');
03831         }
03832         if (($properties & 1)) {
03833             $theValue = '<strong>' . $theValue . '</strong>';
03834         }
03835         if (($properties & 2)) {
03836             $theValue = '<i>' . $theValue . '</i>';
03837         }
03838         if (($properties & 4)) {
03839             $theValue = '<u>' . $theValue . '</u>';
03840         }
03841 
03842             // Fonttag
03843         $theFace = $conf['face.'][$face];
03844         if(!$theFace) {
03845             $theFace = isset($conf['face.']['default.'])
03846                 ? $this->stdWrap($conf['face.']['default'], $conf['face.']['default.'])
03847                 : $conf['face.']['default'];
03848         }
03849 
03850         $theSize = $conf['size.'][$size];
03851         if(!$theSize) {
03852             $theSize = isset($conf['size.']['default.'])
03853                 ? $this->stdWrap($conf['size.']['default'], $conf['size.']['default.'])
03854                 : $conf['size.']['default'];
03855         }
03856 
03857         $theColor = $conf['color.'][$color];
03858         if(!$theColor) {
03859             $theColor = isset($conf['color.']['default.'])
03860                 ? $this->stdWrap($conf['color.']['default'], $conf['color.']['default.'])
03861                 : $conf['color.']['default.'];
03862         }
03863 
03864         if ($conf['altWrap']) {
03865             $theValue = $this->wrap($theValue, $conf['altWrap']);
03866         } elseif ($theFace || $theSize || $theColor) {
03867             $fontWrap = '<font' . ($theFace ? ' face="' . $theFace . '"' : '') .
03868                 ($theSize ? ' size="' . $theSize . '"' : '') .
03869                 ($theColor ? ' color="' . $theColor . '"' : '') .
03870                 '>|</font>';
03871             $theValue = $this->wrap($theValue, $fontWrap);
03872         }
03873             // align
03874         if ($align) {
03875             $theValue = $this->wrap($theValue, '<div style="text-align:' . $align . ';">|</div>');
03876         }
03877             // return
03878         return $theValue;
03879     }
03880 
03881     /**
03882      * Implements the stdWrap property "tableStyle"; Basically this generates a <table>-tag with properties which is wrapped around the input value.
03883      *
03884      * @param   string      The input value
03885      * @param   array       TypoScript properties for the "TypoScript function" '->textStyle'
03886      * @return  string      The processed output value
03887      * @access private
03888      * @see stdWrap()
03889      */
03890     function tableStyle($theValue, $conf) {
03891         $conf['color.'][240] = 'black';
03892         $conf['color.'][241] = 'white';
03893         $conf['color.'][242] = '#333333';
03894         $conf['color.'][243] = 'gray';
03895         $conf['color.'][244] = 'silver';
03896 
03897         $align = isset($conf['align.'])
03898             ? $this->stdWrap($conf['align'], $conf['align.'])
03899             : $conf['align'];
03900         $border = isset($conf['border.'])
03901             ? intval($this->stdWrap($conf['border'], $conf['border.']))
03902             : intval($conf['border']);
03903         $cellspacing = isset($conf['cellspacing.'])
03904             ? intval($this->stdWrap($conf['cellspacing'], $conf['cellspacing.']))
03905             : intval($conf['cellspacing']);
03906         $cellpadding = isset($conf['cellpadding.'])
03907             ? intval($this->stdWrap($conf['cellpadding'], $conf['cellpadding.']))
03908             : intval($conf['cellpadding']);
03909 
03910         $color = $this->data[$conf['color.']['field']];
03911         $theColor = $conf['color.'][$color] ? $conf['color.'][$color] : $conf['color.']['default'];
03912             // Assembling the table tag
03913         $tableTagArray = array(
03914             '<table'
03915         );
03916         $tableTagArray[] = 'border="' . $border . '"';
03917         $tableTagArray[] = 'cellspacing="' . $cellspacing . '"';
03918         $tableTagArray[] = 'cellpadding="' . $cellpadding . '"';
03919         if ($align) {
03920             $tableTagArray[] = 'align="' . $align . '"';
03921         }
03922         if ($theColor) {
03923             $tableTagArray[] = 'bgcolor="' . $theColor . '"';
03924         }
03925 
03926         if ($conf['params']) {
03927             $tableTagArray[] = $conf['params'];
03928         }
03929 
03930         $tableWrap = implode(' ', $tableTagArray) . '> | </table>';
03931         $theValue = $this->wrap($theValue, $tableWrap);
03932         // return
03933         return $theValue;
03934     }
03935 
03936     /**
03937      * Implements the TypoScript function "addParams"
03938      *
03939      * @param   string      The string with the HTML tag.
03940      * @param   array       The TypoScript configuration properties
03941      * @return  string      The modified string
03942      * @todo    Make it XHTML compatible. Will not present "/>" endings of tags right now. Further getting the tagname might fail if it is not separated by a normal space from the attributes.
03943      */
03944     function addParams($content, $conf) {
03945         $lowerCaseAttributes = TRUE; // For XHTML compliance.
03946 
03947 
03948         if (!is_array($conf)) {
03949             return $content;
03950         }
03951 
03952         $key = 1;
03953         $parts = explode('<', $content);
03954         if (intval($conf['_offset']))
03955             $key = intval($conf['_offset']) < 0 ? count($parts) + intval($conf['_offset']) : intval($conf['_offset']);
03956         $subparts = explode('>', $parts[$key]);
03957         if (trim($subparts[0])) {
03958                 // Get attributes and name
03959             $attribs = t3lib_div::get_tag_attributes('<' . $subparts[0] . '>');
03960             list ($tagName) = explode(' ', $subparts[0], 2);
03961                 // adds/overrides attributes
03962             foreach ($conf as $pkey => $val) {
03963                 if (substr($pkey, -1) != '.' && substr($pkey, 0, 1) != '_') {
03964                     $tmpVal = isset($conf[$pkey . '.'])
03965                         ? $this->stdWrap($conf[$pkey], $conf[$pkey . '.'])
03966                         : $conf[$pkey];
03967                     if ($lowerCaseAttributes) {
03968                         $pkey = strtolower($pkey);
03969                     }
03970                     if (strcmp($tmpVal, '')) {
03971                         $attribs[$pkey] = $tmpVal;
03972                     }
03973                 }
03974             }
03975 
03976                 // Re-assembles the tag and content
03977             $subparts[0] = trim($tagName . ' ' . t3lib_div::implodeAttributes($attribs));
03978             $parts[$key] = implode('>', $subparts);
03979             $content = implode('<', $parts);
03980         }
03981         return $content;
03982     }
03983 
03984     /**
03985      * Creates a list of links to files.
03986      * Implements the stdWrap property "filelink"
03987      *
03988      * @param   string      The filename to link to, possibly prefixed with $conf[path]
03989      * @param   array       TypoScript parameters for the TypoScript function ->filelink
03990      * @return  string      The link to the file possibly with icons, thumbnails, size in bytes shown etc.
03991      * @access private
03992      * @see stdWrap()
03993      */
03994     function filelink($theValue, $conf) {
03995         $conf['path'] = isset($conf['path.'])
03996             ? $this->stdWrap($conf['path'], $conf['path.'])
03997             : $conf['path'];
03998         $theFile = trim($conf['path']) . $theValue;
03999         if (@is_file($theFile)) {
04000             $theFileEnc = str_replace('%2F', '/', rawurlencode($theFile));
04001 
04002                 // the jumpURL feature will be taken care of by typoLink, only "jumpurl.secure = 1" is applyable needed for special link creation
04003             if ($conf['jumpurl.']['secure']) {
04004                 $alternativeJumpUrlParameter = isset($conf['jumpurl.']['parameter.'])
04005                     ? $this->stdWrap($conf['jumpurl.']['parameter'], $conf['jumpurl.']['parameter.'])
04006                     : $conf['jumpurl.']['parameter'];
04007                 $typoLinkConf = array(
04008                     'parameter' => ($alternativeJumpUrlParameter ? $alternativeJumpUrlParameter : ($GLOBALS['TSFE']->id . ',' . $GLOBALS['TSFE']->type)),
04009                     'fileTarget' => $conf['target'],
04010                     'ATagParams' => $this->getATagParams($conf),
04011                     'additionalParams' => '&jumpurl=' . rawurlencode($theFileEnc) . $this->locDataJU($theFileEnc, $conf['jumpurl.']['secure.']) . $GLOBALS['TSFE']->getMethodUrlIdToken
04012                 );
04013             } else {
04014                 $typoLinkConf = array(
04015                     'parameter' => $theFileEnc,
04016                     'fileTarget' => $conf['target'],
04017                     'ATagParams' => $this->getATagParams($conf)
04018                 );
04019             }
04020 
04021                 // if the global jumpURL feature is activated, but is disabled for this
04022                 // filelink, the global parameter needs to be disabled as well for this link creation
04023             $globalJumpUrlEnabled = $GLOBALS['TSFE']->config['config']['jumpurl_enable'];
04024             if ($globalJumpUrlEnabled && isset($conf['jumpurl']) && $conf['jumpurl'] == 0) {
04025                 $GLOBALS['TSFE']->config['config']['jumpurl_enable'] = 0;
04026                     // if the global jumpURL feature is deactivated, but is wanted for this link, then activate it for now
04027             } else if (!$globalJumpUrlEnabled && $conf['jumpurl']) {
04028                 $GLOBALS['TSFE']->config['config']['jumpurl_enable'] = 1;
04029             }
04030             $theLinkWrap = $this->typoLink('|', $typoLinkConf);
04031 
04032                 // now the original value is set again
04033             $GLOBALS['TSFE']->config['config']['jumpurl_enable'] = $globalJumpUrlEnabled;
04034 
04035             $theSize = filesize($theFile);
04036             $fI = t3lib_div::split_fileref($theFile);
04037             if ($conf['icon']) {
04038                 $iconP = t3lib_extMgm::siteRelPath('cms') . 'tslib/media/fileicons/';
04039                 $icon = @is_file($iconP . $fI['fileext'] . '.gif') ? $iconP . $fI['fileext'] . '.gif' : $iconP . 'default.gif';
04040                     // Checking for images: If image, then return link to thumbnail.
04041                 $IEList = isset($conf['icon_image_ext_list.'])
04042                     ? $this->stdWrap($conf['icon_image_ext_list'], $conf['icon_image_ext_list.'])
04043                     : $conf['icon_image_ext_list'];
04044                 $image_ext_list = str_replace(' ', '', strtolower($IEList));
04045                 if ($fI['fileext'] && t3lib_div::inList($image_ext_list, $fI['fileext'])) {
04046                     if ($conf['iconCObject']) {
04047                         $icon = $this->cObjGetSingle($conf['iconCObject'], $conf['iconCObject.'], 'iconCObject');
04048                     } else {
04049                         if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails']) {
04050                             $thumbSize = '';
04051                             if ($conf['icon_thumbSize'] || $conf['icon_thumbSize.']) {
04052                                 $thumbSize = '&size=' . isset($conf['icon_thumbSize.'])
04053                                     ? $this->stdWrap($conf['icon_thumbSize'], $conf['icon_thumbSize.'])
04054                                     : $conf['icon_thumbSize'];
04055                             }
04056                             $check = basename($theFile) . ':' . filemtime($theFile) . ':' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'];
04057                             $md5sum = '&md5sum=' . t3lib_div::shortMD5($check);
04058                             $icon = 't3lib/thumbs.php?dummy=' . $GLOBALS['EXEC_TIME'] . '&file=' .
04059                                 rawurlencode('../' . $theFile) . $thumbSize . $md5sum;
04060                         } else {
04061                             $icon = t3lib_extMgm::siteRelPath('cms') . 'tslib/media/miscicons/notfound_thumb.gif';
04062                         }
04063                         $icon = '<img src="' . htmlspecialchars($GLOBALS['TSFE']->absRefPrefix . $icon) . '"' .
04064                             $this->getBorderAttr(' border="0"') . '' . $this->getAltParam($conf) . ' />';
04065                     }
04066                 } else {
04067                     $icon = '<img src="' . htmlspecialchars($GLOBALS['TSFE']->absRefPrefix . $icon) .
04068                         '" width="18" height="16"' . $this->getBorderAttr(' border="0"') .
04069                         $this->getAltParam($conf) . ' />';
04070                 }
04071                 if ($conf['icon_link']) {
04072                     $icon = $this->wrap($icon, $theLinkWrap);
04073                 }
04074                 $icon = isset($conf['icon.'])
04075                     ? $this->stdWrap($icon, $conf['icon.'])
04076                     : $icon;
04077             }
04078             if ($conf['size']) {
04079                 $size = isset($conf['size.'])
04080                     ? $this->stdWrap($theSize, $conf['size.'])
04081                     : $theSize;
04082             }
04083 
04084                 // Wrapping file label
04085             if ($conf['removePrependedNumbers']) {
04086                 $theValue = preg_replace('/_[0-9][0-9](\.[[:alnum:]]*)$/', '\1', $theValue);
04087             }
04088             if(isset($conf['labelStdWrap.'])) {
04089                 $theValue = $this->stdWrap($theValue, $conf['labelStdWrap.']);
04090             }
04091 
04092                 // Wrapping file
04093             $wrap = isset($conf['wrap.'])
04094                 ? $this->stdWrap($conf['wrap'], $conf['wrap.'])
04095                 : $conf['wrap'];
04096             if ($conf['ATagBeforeWrap']) {
04097                 $theValue = $this->wrap($this->wrap($theValue, $wrap), $theLinkWrap);
04098             } else {
04099                 $theValue = $this->wrap($this->wrap($theValue, $theLinkWrap), $wrap);
04100             }
04101             $file = isset($conf['file.'])
04102                 ? $this->stdWrap($theValue, $conf['file.'])
04103                 : $theValue;
04104                 // output
04105             $output = $icon . $file . $size;
04106             if(isset($conf['stdWrap.'])) {
04107                 $output = $this->stdWrap($output, $conf['stdWrap.']);
04108             }
04109 
04110             return $output;
04111         }
04112     }
04113 
04114     /**
04115      * Returns a URL parameter string setting parameters for secure downloads by "jumpurl".
04116      * Helper function for filelink()
04117      *
04118      * @param   string      The URL to jump to, basically the filepath
04119      * @param   array       TypoScript properties for the "jumpurl.secure" property of "filelink"
04120      * @return  string      URL parameters like "&juSecure=1....."
04121      * @access private
04122      * @see filelink()
04123      */
04124     function locDataJU($jumpUrl, $conf) {
04125         $fI = pathinfo($jumpUrl);
04126         $mimetype = '';
04127         $mimetypeValue = '';
04128         if ($fI['extension']) {
04129             $mimeTypes = t3lib_div::trimExplode(',', $conf['mimeTypes'], 1);
04130             foreach ($mimeTypes as $v) {
04131                 $parts = explode('=', $v, 2);
04132                 if (strtolower($fI['extension']) == strtolower(trim($parts[0]))) {
04133                     $mimetypeValue = trim($parts[1]);
04134                     $mimetype = '&mimeType=' . rawurlencode($mimetypeValue);
04135                     break;
04136                 }
04137             }
04138         }
04139         $locationData = $GLOBALS['TSFE']->id . ':' . $this->currentRecord;
04140         $rec = '&locationData=' . rawurlencode($locationData);
04141         $hArr = array(
04142             $jumpUrl, $locationData, $mimetypeValue
04143         );
04144         $juHash = '&juHash=' . t3lib_div::hmac(serialize($hArr));
04145         return '&juSecure=1' . $mimetype . $rec . $juHash;
04146     }
04147 
04148     /**
04149      * Performs basic mathematical evaluation of the input string. Does NOT take parathesis and operator precedence into account! (for that, see t3lib_div::calcPriority())
04150      *
04151      * @param   string      The string to evaluate. Example: "3+4*10/5" will generate "35". Only integer numbers can be used.
04152      * @return  integer     The result (might be a float if you did a division of the numbers).
04153      * @see t3lib_div::calcPriority()
04154      */
04155     function calc($val) {
04156         $parts = t3lib_div::splitCalc($val, '+-*/');
04157         $value = 0;
04158         foreach ($parts as $part) {
04159             $theVal = $part[1];
04160             $sign = $part[0];
04161             if ((string) intval($theVal) == (string) $theVal) {
04162                 $theVal = intval($theVal);
04163             } else {
04164                 $theVal = 0;
04165             }
04166             if ($sign == '-') {
04167                 $value -= $theVal;
04168             }
04169             if ($sign == '+') {
04170                 $value += $theVal;
04171             }
04172             if ($sign == '/') {
04173                 if (intval($theVal))
04174                     $value /= intval($theVal);
04175             }
04176             if ($sign == '*') {
04177                 $value *= $theVal;
04178             }
04179         }
04180         return $value;
04181     }
04182 
04183     /**
04184      * This explodes a comma-list into an array where the values are parsed through tslib_cObj::calc() and intval() (so you are sure to have integers in the output array)
04185      * Used to split and calculate min and max values for GMENUs.
04186      *
04187      * @param   string      Delimited to explode by
04188      * @param   string      The string with parts in (where each part is evaluated by ->calc())
04189      * @return  array       And array with evaluated values.
04190      * @see calc(), tslib_gmenu::makeGifs()
04191      */
04192     function calcIntExplode($delim, $string) {
04193         $temp = explode($delim, $string);
04194         foreach ($temp as $key => $val) {
04195             $temp[$key] = intval(tslib_cObj::calc($val));
04196         }
04197         return $temp;
04198     }
04199 
04200     /**
04201      * Implements the "split" property of stdWrap; Splits a string based on a token (given in TypoScript properties), sets the "current" value to each part and then renders a content object pointer to by a number.
04202      * In classic TypoScript (like 'content (default)'/'styles.content (default)') this is used to render tables, splitting rows and cells by tokens and putting them together again wrapped in <td> tags etc.
04203      * Implements the "optionSplit" processing of the TypoScript options for each splitted value to parse.
04204      *
04205      * @param   string      The string value to explode by $conf[token] and process each part
04206      * @param   array       TypoScript properties for "split"
04207      * @return  string      Compiled result
04208      * @access private
04209      * @see stdWrap(), t3lib_menu::procesItemStates()
04210      */
04211     function splitObj($value, $conf) {
04212         $conf['token'] = isset($conf['token.'])
04213             ? $this->stdWrap($conf['token'], $conf['token.'])
04214             : $conf['token'];
04215         if (!$conf['token']) {
04216             return $value;
04217         }
04218         $conf['max'] = isset($conf['max.'])
04219             ? intval($this->stdWrap($conf['max'], $conf['max.']))
04220             : intval($conf['max']);
04221         $conf['min'] = isset($conf['min.'])
04222             ? intval($this->stdWrap($conf['min'], $conf['min.']))
04223             : intval($conf['min']);
04224 
04225         $valArr = explode($conf['token'], $value);
04226 
04227         if (count($valArr) && (t3lib_div::testInt($conf['returnKey']) || $conf['returnKey.'])) {
04228             $key = isset($conf['returnKey.'])
04229                 ? intval($this->stdWrap($conf['returnKey'], $conf['returnKey.']))
04230                 : intval($conf['returnKey']);
04231             $content = isset($valArr[$key]) ? $valArr[$key] : '';
04232         } else {
04233                 // calculate splitCount
04234             $splitCount = count($valArr);
04235             $max = isset($conf['max.'])
04236                 ? $this->stdWrap($conf['max'],$conf['max.'])
04237                 : $conf['max'];
04238             if ($max && $splitCount > $max) {
04239                 $splitCount = $max;
04240             }
04241             $min = isset($conf['min.'])
04242                 ? $this->stdWrap($conf['min'],$conf['min.'])
04243                 : $conf['min'];
04244             if ($min && $splitCount < $min) {
04245                 $splitCount = $min;
04246             }
04247 
04248             $wrap = isset($conf['wrap.'])
04249                 ? $this->stdWrap($conf['wrap'], $conf['wrap.'])
04250                 : $conf['wrap'];
04251             $cObjNum = isset($conf['cObjNum.'])
04252                 ? $this->stdWrap($conf['cObjNum'], $conf['cObjNum.'])
04253                 : $conf['cObjNum'];
04254             if ($wrap || $cObjNum) {
04255                 $splitArr = array();
04256                 $splitArr['wrap'] = $wrap;
04257                 $splitArr['cObjNum'] = $cObjNum;
04258                 $splitArr = $GLOBALS['TSFE']->tmpl->splitConfArray($splitArr, $splitCount);
04259             }
04260 
04261             $content = '';
04262             for ($a = 0; $a < $splitCount; $a++) {
04263                 $GLOBALS['TSFE']->register['SPLIT_COUNT'] = $a;
04264                 $value = '' . $valArr[$a];
04265                 $this->data[$this->currentValKey] = $value;
04266                 if ($splitArr[$a]['cObjNum']) {
04267                     $objName = intval($splitArr[$a]['cObjNum']);
04268                     $value = isset($conf[$objName . '.'])
04269                         ? $this->stdWrap($this->cObjGet($conf[$objName . '.'], $objName . '.'), $conf[$objName . '.'])
04270                         : $this->cObjGet($conf[$objName . '.'], $objName . '.');
04271                 }
04272                 $wrap = isset($splitArr[$a]['wrap.'])
04273                     ? $this->stdWrap($splitArr[$a]['wrap'], $splitArr[$a]['wrap.'])
04274                     : $splitArr[$a]['wrap'];
04275                 if ($wrap) {
04276                     $value = $this->wrap($value, $wrap);
04277                 }
04278                 $content .= $value;
04279             }
04280         }
04281         return $content;
04282     }
04283 
04284     /**
04285      * Implements the stdWrap property "numberFormat"
04286      * This is a Wrapper function for php's number_format()
04287      *
04288      * @param   float   Value to process
04289      * @param   array   TypoScript Configuration for numberFormat
04290      * @return  string  The formated number
04291      */
04292     function numberFormat($content, $conf) {
04293         $decimals = isset($conf['decimals.'])
04294             ? $this->stdWrap($conf['decimals'], $conf['decimals.'])
04295             : $conf['decimals'];
04296         $dec_point = isset($conf['dec_point.'])
04297             ? $this->stdWrap($conf['dec_point'], $conf['dec_point.'])
04298             : $conf['dec_point'];
04299         $thousands_sep = isset($conf['thousands_sep.'])
04300             ? $this->stdWrap($conf['thousands_sep'], $conf['thousands_sep.'])
04301             : $conf['thousands_sep'];
04302         return number_format($content, $decimals, $dec_point, $thousands_sep);
04303     }
04304 
04305     /**
04306      * Implements the stdWrap property, "parseFunc".
04307      * This is a function with a lot of interesting uses. In classic TypoScript this is used to process text
04308      * from the bodytext field; This included highlighting of search words, changing http:// and mailto: prefixed strings into links,
04309      * parsing <typolist>, <typohead> and <typocode> tags etc.
04310      * It is still a very important function for processing of bodytext which is normally stored in the database
04311      * in a format which is not fully ready to be outputted.
04312      * This situation has not become better by having a RTE around...
04313      *
04314      * This function is actually just splitting the input content according to the configuration of "external blocks".
04315      * This means that before the input string is actually "parsed" it will be splitted into the parts configured to BE parsed
04316      * (while other parts/blocks should NOT be parsed).
04317      * Therefore the actual processing of the parseFunc properties goes on in ->_parseFunc()
04318      *
04319      * @param   string      The value to process.
04320      * @param   array       TypoScript configuration for parseFunc
04321      * @param   string      Reference to get configuration from. Eg. "< lib.parseFunc" which means that the configuration of the object path "lib.parseFunc" will be retrieved and MERGED with what is in $conf!
04322      * @return  string      The processed value
04323      * @see _parseFunc()
04324      */
04325     function parseFunc($theValue, $conf, $ref = '') {
04326 
04327             // Fetch / merge reference, if any
04328         if ($ref) {
04329             $temp_conf = array(
04330                 'parseFunc' => $ref, 'parseFunc.' => $conf
04331             );
04332             $temp_conf = $this->mergeTSRef($temp_conf, 'parseFunc');
04333             $conf = $temp_conf['parseFunc.'];
04334         }
04335 
04336             // Process:
04337         if (strcmp($conf['externalBlocks'], '')) {
04338             $tags = strtolower(implode(',', t3lib_div::trimExplode(',', $conf['externalBlocks'])));
04339             $htmlParser = t3lib_div::makeInstance('t3lib_parsehtml');
04340             $parts = $htmlParser->splitIntoBlock($tags, $theValue);
04341 
04342             foreach ($parts as $k => $v) {
04343                 if ($k % 2) { // font:
04344                     $tagName = strtolower($htmlParser->getFirstTagName($v));
04345                     $cfg = $conf['externalBlocks.'][$tagName . '.'];
04346                     if ($cfg['stripNLprev'] || $cfg['stripNL']) {
04347                         $parts[$k - 1] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $parts[$k - 1]);
04348                     }
04349                     if ($cfg['stripNLnext'] || $cfg['stripNL']) {
04350                         $parts[$k + 1] = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', $parts[$k + 1]);
04351                     }
04352                 }
04353             }
04354 
04355             foreach ($parts as $k => $v) {
04356                 if ($k % 2) {
04357                     $tag = $htmlParser->getFirstTag($v);
04358                     $tagName = strtolower($htmlParser->getFirstTagName($v));
04359                     $cfg = $conf['externalBlocks.'][$tagName . '.'];
04360                     if ($cfg['callRecursive']) {
04361                         $parts[$k] = $this->parseFunc($htmlParser->removeFirstAndLastTag($v), $conf);
04362                         if (!$cfg['callRecursive.']['dontWrapSelf']) {
04363                             if ($cfg['callRecursive.']['alternativeWrap']) {
04364                                 $parts[$k] = $this->wrap($parts[$k], $cfg['callRecursive.']['alternativeWrap']);
04365                             } else {
04366                                 if (is_array($cfg['callRecursive.']['tagStdWrap.'])) {
04367                                     $tag = $this->stdWrap($tag, $cfg['callRecursive.']['tagStdWrap.']);
04368                                 }
04369                                 $parts[$k] = $tag . $parts[$k] . '</' . $tagName . '>';
04370                             }
04371                         }
04372                     } elseif ($cfg['HTMLtableCells']) {
04373                         $rowParts = $htmlParser->splitIntoBlock('tr', $parts[$k]);
04374                         foreach ($rowParts as $kk => $vv) {
04375                             if ($kk % 2) {
04376                                 $colParts = $htmlParser->splitIntoBlock('td,th', $vv);
04377                                 $cc = 0;
04378                                 foreach ($colParts as $kkk => $vvv) {
04379                                     if ($kkk % 2) {
04380                                         $cc++;
04381                                         $tag = $htmlParser->getFirstTag($vvv);
04382                                         $tagName = strtolower($htmlParser->getFirstTagName($vvv));
04383                                         $colParts[$kkk] = $htmlParser->removeFirstAndLastTag($vvv);
04384 
04385                                         if ($cfg['HTMLtableCells.'][$cc . '.']['callRecursive'] || (!isset($cfg['HTMLtableCells.'][$cc . '.']['callRecursive']) && $cfg['HTMLtableCells.']['default.']['callRecursive'])) {
04386                                             if ($cfg['HTMLtableCells.']['addChr10BetweenParagraphs'])
04387                                                 $colParts[$kkk] = str_replace('</p><p>', '</p>' . LF . '<p>', $colParts[$kkk]);
04388                                             $colParts[$kkk] = $this->parseFunc($colParts[$kkk], $conf);
04389                                         }
04390 
04391                                         $tagStdWrap = is_array($cfg['HTMLtableCells.'][$cc . '.']['tagStdWrap.']) ? $cfg['HTMLtableCells.'][$cc . '.']['tagStdWrap.'] : $cfg['HTMLtableCells.']['default.']['tagStdWrap.'];
04392                                         if (is_array($tagStdWrap)) {
04393                                             $tag = $this->stdWrap($tag, $tagStdWrap);
04394                                         }
04395 
04396                                         $stdWrap = is_array($cfg['HTMLtableCells.'][$cc . '.']['stdWrap.']) ? $cfg['HTMLtableCells.'][$cc . '.']['stdWrap.'] : $cfg['HTMLtableCells.']['default.']['stdWrap.'];
04397                                         if (is_array($stdWrap)) {
04398                                             $colParts[$kkk] = $this->stdWrap($colParts[$kkk], $stdWrap);
04399                                         }
04400 
04401                                         $colParts[$kkk] = $tag . $colParts[$kkk] . '</' . $tagName . '>';
04402                                     }
04403                                 }
04404                                 $rowParts[$kk] = implode('', $colParts);
04405                             }
04406                         }
04407                         $parts[$k] = implode('', $rowParts);
04408                     }
04409 
04410                     if (is_array($cfg['stdWrap.'])) {
04411                         $parts[$k] = $this->stdWrap($parts[$k], $cfg['stdWrap.']);
04412                     }
04413                 } else {
04414                     $parts[$k] = $this->_parseFunc($parts[$k], $conf);
04415                 }
04416             }
04417 
04418             return implode('', $parts);
04419         } else
04420             return $this->_parseFunc($theValue, $conf);
04421     }
04422 
04423     /**
04424      * Helper function for parseFunc()
04425      *
04426      * @param   string      The value to process.
04427      * @param   array       TypoScript configuration for parseFunc
04428      * @return  string      The processed value
04429      * @access private
04430      * @see parseFunc()
04431      */
04432     function _parseFunc($theValue, $conf) {
04433         if (!$this->checkIf($conf['if.'])) {
04434             return $theValue;
04435         }
04436         $inside = 0; // Indicates that the data is from within a tag.
04437         $pointer = 0; // Pointer to the total string position
04438         $currentTag = ''; // Loaded with the current typo-tag if any.
04439         $stripNL = 0;
04440         $contentAccum = array();
04441         $contentAccumP = 0;
04442 
04443         $allowTags = strtolower(str_replace(' ', '', $conf['allowTags']));
04444         $denyTags = strtolower(str_replace(' ', '', $conf['denyTags']));
04445 
04446         $totalLen = strlen($theValue);
04447         do {
04448             if (!$inside) {
04449                 if (!is_array($currentTag)) {
04450                         // These operations should only be performed on code outside the typotags...
04451                         // data: this checks that we enter tags ONLY if the first char in the tag is alphanumeric OR '/'
04452                     $len_p = 0;
04453                     $c = 100;
04454                     do {
04455                         $len = strcspn(substr($theValue, $pointer + $len_p), '<');
04456                         $len_p += $len + 1;
04457                         $endChar = ord(strtolower(substr($theValue, $pointer + $len_p, 1)));
04458                         $c--;
04459                     } while ($c > 0 && $endChar && ($endChar < 97 || $endChar > 122) && $endChar != 47);
04460                     $len = $len_p - 1;
04461                 } else {
04462                     // If we're inside a currentTag, just take it to the end of that tag!
04463                     $tempContent = strtolower(substr($theValue, $pointer));
04464                     $len = strpos($tempContent, '</' . $currentTag[0]);
04465                     if (is_string($len) && !$len) {
04466                         $len = strlen($tempContent);
04467                     }
04468                 }
04469 
04470                 $data = substr($theValue, $pointer, $len); // $data is the content until the next <tag-start or end is detected. In case of a currentTag set, this would mean all data between the start- and end-tags
04471                 if ($data != '') {
04472                     if ($stripNL) {
04473                             // If the previous tag was set to strip NewLines in the beginning of the next data-chunk.
04474                         $data = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', $data);
04475                     }
04476 
04477                     if (!is_array($currentTag)) { // These operations should only be performed on code outside the tags...
04478                             // Constants
04479                         $tmpConstants = $GLOBALS['TSFE']->tmpl->setup['constants.'];
04480                         if ($conf['constants'] && is_array($tmpConstants)) {
04481                             foreach ($tmpConstants as $key => $val) {
04482                                 if (is_string($val)) {
04483                                     $data = str_replace('###' . $key . '###', $val, $data);
04484                                 }
04485                             }
04486                         }
04487                             // Short
04488                         if (is_array($conf['short.'])) {
04489                             $shortWords = $conf['short.'];
04490                             krsort($shortWords);
04491                             foreach ($shortWords as $key => $val) {
04492                                 if (is_string($val)) {
04493                                     $data = str_replace($key, $val, $data);
04494                                 }
04495                             }
04496                         }
04497 
04498                             // stdWrap
04499                         if (is_array($conf['plainTextStdWrap.'])) {
04500                             $data = $this->stdWrap($data, $conf['plainTextStdWrap.']);
04501                         }
04502                             // userFunc
04503                         if ($conf['userFunc']) {
04504                             $data = $this->callUserFunction($conf['userFunc'], $conf['userFunc.'], $data);
04505                         }
04506 
04507                             // Makelinks: (Before search-words as we need the links to be generated when searchwords go on...!)
04508                         if ($conf['makelinks']) {
04509                             $data = $this->http_makelinks($data, $conf['makelinks.']['http.']);
04510                             $data = $this->mailto_makelinks($data, $conf['makelinks.']['mailto.']);
04511                         }
04512 
04513                             // Search Words:
04514                         if ($GLOBALS['TSFE']->no_cache && $conf['sword'] && is_array($GLOBALS['TSFE']->sWordList) && $GLOBALS['TSFE']->sWordRegEx) {
04515                             $newstring = '';
04516                             do {
04517                                 $pregSplitMode = 'i';
04518                                 if (isset($GLOBALS['TSFE']->config['config']['sword_noMixedCase']) && !empty($GLOBALS['TSFE']->config['config']['sword_noMixedCase'])) {
04519                                     $pregSplitMode = '';
04520                                 }
04521                                 $pieces = preg_split('/' . $GLOBALS['TSFE']->sWordRegEx . '/' . $pregSplitMode, $data, 2);
04522                                 $newstring .= $pieces[0];
04523                                 $match_len = strlen($data) - (strlen($pieces[0]) + strlen($pieces[1]));
04524                                 if (strstr($pieces[0], '<') || strstr($pieces[0], '>')) {
04525                                     $inTag = strrpos($pieces[0], '<') > strrpos($pieces[0], '>'); // Returns TRUE, if a '<' is closer to the string-end than '>'. This is the case if we're INSIDE a tag (that could have been made by makelinks...) and we must secure, that the inside of a tag is not marked up.
04526                                 }
04527                                     // The searchword:
04528                                 $match = substr($data, strlen($pieces[0]), $match_len);
04529 
04530                                 if (trim($match) && strlen($match) > 1 && !$inTag) {
04531                                     $match = $this->wrap($match, $conf['sword']);
04532                                 }
04533                                     // Concatenate the Search Word again.
04534                                 $newstring .= $match;
04535                                 $data = $pieces[1];
04536                             } while ($pieces[1]);
04537                             $data = $newstring;
04538                         }
04539                     }
04540                     $contentAccum[$contentAccumP] .= $data;
04541                 }
04542                 $inside = 1;
04543             } else {
04544                     // tags
04545                 $len = strcspn(substr($theValue, $pointer), '>') + 1;
04546                 $data = substr($theValue, $pointer, $len);
04547 
04548                 $tag = explode(' ', trim(substr($data, 1, -1)), 2);
04549                 $tag[0] = strtolower($tag[0]);
04550                 if (substr($tag[0], 0, 1) == '/') {
04551                     $tag[0] = substr($tag[0], 1);
04552                     $tag['out'] = 1;
04553                 }
04554                 if ($conf['tags.'][$tag[0]]) {
04555                     $treated = 0;
04556                     $stripNL = 0;
04557                         // in-tag
04558                     if (!$currentTag && !$tag['out']) {
04559                         $currentTag = $tag; // $currentTag (array!) is the tag we are currently processing
04560                         $contentAccumP++;
04561                         $treated = 1;
04562                             // in-out-tag: img and other empty tags
04563                         if (preg_match('/^(area|base|br|col|hr|img|input|meta|param)$/i', $tag[0])) {
04564                             $tag['out'] = 1;
04565                         }
04566                     }
04567                         // out-tag
04568                     if ($currentTag[0] == $tag[0] && $tag['out']) {
04569                         $theName = $conf['tags.'][$tag[0]];
04570                         $theConf = $conf['tags.'][$tag[0] . '.'];
04571                         $stripNL = ($theConf['stripNL'] ? 1 : 0); // This flag indicates, that NL- (13-10-chars) should be stripped first and last.
04572                         $breakOut = ($theConf['breakoutTypoTagContent'] ? 1 : 0); // This flag indicates, that this TypoTag section should NOT be included in the nonTypoTag content.
04573 
04574 
04575                         $this->parameters = array();
04576                         if ($currentTag[1]) {
04577                             $params = t3lib_div::get_tag_attributes($currentTag[1]);
04578                             if (is_array($params)) {
04579                                 foreach ($params as $option => $val) {
04580                                     $this->parameters[strtolower($option)] = $val;
04581                                 }
04582                             }
04583                         }
04584                         $this->parameters['allParams'] = trim($currentTag[1]);
04585                         if ($stripNL) { // Removes NL in the beginning and end of the tag-content AND at the end of the currentTagBuffer. $stripNL depends on the configuration of the current tag
04586                             $contentAccum[$contentAccumP - 1] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $contentAccum[$contentAccumP - 1]);
04587                             $contentAccum[$contentAccumP] = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', $contentAccum[$contentAccumP]);
04588                             $contentAccum[$contentAccumP] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $contentAccum[$contentAccumP]);
04589                         }
04590                         $this->data[$this->currentValKey] = $contentAccum[$contentAccumP];
04591                         $newInput = $this->cObjGetSingle($theName, $theConf, '/parseFunc/.tags.' . $tag[0]); // fetch the content object
04592 
04593 
04594                         $contentAccum[$contentAccumP] = $newInput;
04595                         $contentAccumP++;
04596 
04597                             // If the TypoTag section
04598                         if (!$breakOut) {
04599                             $contentAccum[$contentAccumP - 2] .= $contentAccum[$contentAccumP - 1] . $contentAccum[$contentAccumP];
04600                             unset($contentAccum[$contentAccumP]);
04601                             unset($contentAccum[$contentAccumP - 1]);
04602                             $contentAccumP -= 2;
04603                         }
04604 
04605                         unset($currentTag);
04606                         $treated = 1;
04607                     }
04608                         // other tags...
04609                     if (!$treated) {
04610                         $contentAccum[$contentAccumP] .= $data;
04611                     }
04612                 } else {
04613                         // If a tag was not a typo tag, then it is just added to the content
04614                     $stripNL = 0;
04615                     if (t3lib_div::inList($allowTags, $tag[0]) || ($denyTags != '*' && !t3lib_div::inList($denyTags, $tag[0]))) {
04616                         $contentAccum[$contentAccumP] .= $data;
04617                     } else {
04618                         $contentAccum[$contentAccumP] .= HTMLSpecialChars($data);
04619                     }
04620                 }
04621                 $inside = 0;
04622             }
04623             $pointer += $len;
04624         } while ($pointer < $totalLen);
04625 
04626             // Parsing nonTypoTag content (all even keys):
04627         reset($contentAccum);
04628         for ($a = 0; $a < count($contentAccum); $a++) {
04629             if ($a % 2 != 1) {
04630                     // stdWrap
04631                 if (is_array($conf['nonTypoTagStdWrap.'])) {
04632                     $contentAccum[$a] = $this->stdWrap($contentAccum[$a], $conf['nonTypoTagStdWrap.']);
04633                 }
04634                     // userFunc
04635                 if ($conf['nonTypoTagUserFunc']) {
04636                     $contentAccum[$a] = $this->callUserFunction(
04637                         $conf['nonTypoTagUserFunc'],
04638                         $conf['nonTypoTagUserFunc.'],
04639                         $contentAccum[$a]
04640                     );
04641                 }
04642             }
04643         }
04644         return implode('', $contentAccum);
04645     }
04646 
04647     /**
04648      * Lets you split the content by LF and proces each line independently. Used to format content made with the RTE.
04649      *
04650      * @param   string      The input value
04651      * @param   array       TypoScript options
04652      * @return  string      The processed input value being returned; Splitted lines imploded by LF again.
04653      * @access private
04654      */
04655     function encaps_lineSplit($theValue, $conf) {
04656         $lParts = explode(LF, $theValue);
04657 
04658         $encapTags = t3lib_div::trimExplode(',', strtolower($conf['encapsTagList']), 1);
04659         $nonWrappedTag = $conf['nonWrappedTag'];
04660         $defaultAlign = isset($conf['defaultAlign.'])
04661             ? trim($this->stdWrap($conf['defaultAlign'], $conf['defaultAlign.']))
04662             : trim($conf['defaultAlign']);
04663 
04664         if (!strcmp('', $theValue))
04665             return '';
04666 
04667         foreach ($lParts as $k => $l) {
04668             $sameBeginEnd = 0;
04669             $emptyTag = 0;
04670             $l = trim($l);
04671             $attrib = array();
04672             $nWrapped = 0;
04673             if (substr($l, 0, 1) == '<' && substr($l, -1) == '>') {
04674                 $fwParts = explode('>', substr($l, 1), 2);
04675                 list($tagName, $tagParams) = explode(' ',$fwParts[0], 2);
04676                 if (!$fwParts[1]) {
04677                     if (substr($tagName, -1) == '/') {
04678                         $tagName = substr($tagName, 0, -1);
04679                     }
04680                     if (substr($fwParts[0], -1) == '/') {
04681                         $sameBeginEnd = 1;
04682                         $emptyTag = 1;
04683                         $attrib = t3lib_div::get_tag_attributes('<'.substr($fwParts[0], 0, -1).'>');
04684                     }
04685                 } else {
04686                     $backParts = t3lib_div::revExplode('<', substr($fwParts[1],0,-1), 2);
04687                     $attrib = t3lib_div::get_tag_attributes('<'.$fwParts[0].'>');
04688                     $str_content = $backParts[0];
04689                     $sameBeginEnd = (substr(strtolower($backParts[1]),1,strlen($tagName))==strtolower($tagName));
04690                 }
04691             }
04692 
04693             if ($sameBeginEnd && in_array(strtolower($tagName), $encapTags)) {
04694                 $uTagName = strtoupper($tagName);
04695                 $uTagName = strtoupper($conf['remapTag.'][$uTagName] ? $conf['remapTag.'][$uTagName] : $uTagName);
04696             } else {
04697                 $uTagName = strtoupper($nonWrappedTag);
04698                     // The line will be wrapped: $uTagName should not be an empty tag
04699                 $emptyTag = 0;
04700                 $str_content = $lParts[$k];
04701                 $nWrapped = 1;
04702                 $attrib = array();
04703             }
04704 
04705                 // Wrapping all inner-content:
04706             if (is_array($conf['innerStdWrap_all.'])) {
04707                 $str_content = $this->stdWrap($str_content, $conf['innerStdWrap_all.']);
04708             }
04709 
04710             if ($uTagName) {
04711                     // Setting common attributes
04712                 if (is_array($conf['addAttributes.'][$uTagName . '.'])) {
04713                     foreach ($conf['addAttributes.'][$uTagName . '.'] as $kk => $vv) {
04714                         if (!is_array($vv)) {
04715                             if ((string) $conf['addAttributes.'][$uTagName . '.'][$kk . '.']['setOnly'] == 'blank') {
04716                                 if (!strcmp($attrib[$kk], ''))
04717                                     $attrib[$kk] = $vv;
04718                             } elseif ((string) $conf['addAttributes.'][$uTagName . '.'][$kk . '.']['setOnly'] == 'exists') {
04719                                 if (!isset($attrib[$kk]))
04720                                     $attrib[$kk] = $vv;
04721                             } else {
04722                                 $attrib[$kk] = $vv;
04723                             }
04724                         }
04725                     }
04726                 }
04727                     // Wrapping all inner-content:
04728                 if (is_array($conf['encapsLinesStdWrap.'][$uTagName . '.'])) {
04729                     $str_content = $this->stdWrap($str_content, $conf['encapsLinesStdWrap.'][$uTagName . '.']);
04730                 }
04731                     // Default align
04732                 if (!$attrib['align'] && $defaultAlign)
04733                     $attrib['align'] = $defaultAlign;
04734 
04735                 $params = t3lib_div::implodeAttributes($attrib, 1);
04736                 if ($conf['removeWrapping'] && !($emptyTag && $conf['removeWrapping.']['keepSingleTag'])) {
04737                     $str_content = $str_content;
04738                 } else {
04739                     if ($emptyTag) {
04740                         $str_content='<'.strtolower($uTagName).(trim($params)?' '.trim($params):'').' />';
04741                     } else {
04742                         $str_content='<'.strtolower($uTagName).(trim($params)?' '.trim($params):'').'>'.$str_content.'</'.strtolower($uTagName).'>';
04743                     }
04744                 }
04745             }
04746 
04747             if ($nWrapped && $conf['wrapNonWrappedLines']) {
04748                 $str_content = $this->wrap($str_content, $conf['wrapNonWrappedLines']);
04749             }
04750             $lParts[$k] = $str_content;
04751         }
04752 
04753         return implode(LF, $lParts);
04754     }
04755 
04756     /**
04757      * Finds URLS in text and makes it to a real link.
04758      * Will find all strings prefixed with "http://" in the $data string and make them into a link, linking to the URL we should have found.
04759      *
04760      * @param   string      The string in which to search for "http://"
04761      * @param   array       Configuration for makeLinks, see link
04762      * @return  string      The processed input string, being returned.
04763      * @see _parseFunc()
04764      */
04765     function http_makelinks($data, $conf) {
04766         $aTagParams = $this->getATagParams($conf);
04767         $textpieces = explode('http://', $data);
04768         $pieces = count($textpieces);
04769         $textstr = $textpieces[0];
04770         $initP = '?id=' . $GLOBALS['TSFE']->id . '&type=' . $GLOBALS['TSFE']->type;
04771         for ($i = 1; $i < $pieces; $i++) {
04772             $len = strcspn($textpieces[$i], chr(32) . TAB . CRLF);
04773             if (trim(substr($textstr, -1)) == '' && $len) {
04774 
04775                 $lastChar = substr($textpieces[$i], $len - 1, 1);
04776                 if (!preg_match('/[A-Za-z0-9\/#_-]/', $lastChar)) {
04777                     $len--;
04778                 } // Included '\/' 3/12
04779 
04780 
04781                 $parts[0] = substr($textpieces[$i], 0, $len);
04782                 $parts[1] = substr($textpieces[$i], $len);
04783 
04784                 $keep = $conf['keep'];
04785                 $linkParts = parse_url('http://' . $parts[0]);
04786                 $linktxt = '';
04787                 if (strstr($keep, 'scheme')) {
04788                     $linktxt = 'http://';
04789                 }
04790                 $linktxt .= $linkParts['host'];
04791                 if (strstr($keep, 'path')) {
04792                     $linktxt .= $linkParts['path'];
04793                     if (strstr($keep, 'query') && $linkParts['query']) { // added $linkParts['query'] 3/12
04794                         $linktxt .= '?' . $linkParts['query'];
04795                     } elseif ($linkParts['path'] == '/') { // If query is NOT added and the path is '/' then remove the slash ('/')   (added 3/12)
04796                         $linktxt = substr($linktxt, 0, -1);
04797                     }
04798                 }
04799                 $target = isset($conf['extTarget']) ? $conf['extTarget'] : $GLOBALS['TSFE']->extTarget;
04800                 if ($GLOBALS['TSFE']->config['config']['jumpurl_enable']) {
04801                     $res = '<a' . ' href="' . htmlspecialchars($GLOBALS['TSFE']->absRefPrefix .
04802                         $GLOBALS['TSFE']->config['mainScript'] . $initP .
04803                         '&jumpurl=' . rawurlencode('http://' . $parts[0]) . $GLOBALS['TSFE']->getMethodUrlIdToken) . '"' .
04804                         ($target ? ' target="' . $target . '"' : '') .
04805                         $aTagParams . $this->extLinkATagParams('http://' . $parts[0], 'url') .
04806                         '>';
04807                 } else {
04808                     $res = '<a' . ' href="http://' . htmlspecialchars($parts[0]) . '"' .
04809                         ($target ? ' target="' . $target . '"' : '') .
04810                         $aTagParams . $this->extLinkATagParams('http://' . $parts[0], 'url') .
04811                         '>';
04812                 }
04813                 $wrap = isset($conf['wrap.'])
04814                     ? $this->stdWrap($conf['wrap'], $conf['wrap.'])
04815                     : $conf['wrap'];
04816                 if ($conf['ATagBeforeWrap']) {
04817                     $res = $res . $this->wrap($linktxt, $wrap) . '</a>';
04818                 } else {
04819                     $res = $this->wrap($res . $linktxt . '</a>', $wrap);
04820                 }
04821                 $textstr .= $res . $parts[1];
04822             } else {
04823                 $textstr .= 'http://' . $textpieces[$i];
04824             }
04825         }
04826         return $textstr;
04827     }
04828 
04829     /**
04830      * Will find all strings prefixed with "mailto:" in the $data string and make them into a link,
04831      * linking to the email address they point to.
04832      *
04833      * @param   string      The string in which to search for "mailto:"
04834      * @param   array       Configuration for makeLinks, see link
04835      * @return  string      The processed input string, being returned.
04836      * @see _parseFunc()
04837      */
04838     function mailto_makelinks($data, $conf) {
04839             // http-split
04840         $aTagParams = $this->getATagParams($conf);
04841         $textpieces = explode('mailto:', $data);
04842         $pieces = count($textpieces);
04843         $textstr = $textpieces[0];
04844         $initP = '?id=' . $GLOBALS['TSFE']->id . '&type=' . $GLOBALS['TSFE']->type;
04845         for ($i = 1; $i < $pieces; $i++) {
04846             $len = strcspn($textpieces[$i], chr(32) . TAB . CRLF);
04847             if (trim(substr($textstr, -1)) == '' && $len) {
04848                 $lastChar = substr($textpieces[$i], $len - 1, 1);
04849                 if (!preg_match('/[A-Za-z0-9]/', $lastChar)) {
04850                     $len--;
04851                 }
04852 
04853                 $parts[0] = substr($textpieces[$i], 0, $len);
04854                 $parts[1] = substr($textpieces[$i], $len);
04855                 $linktxt = preg_replace('/\?.*/', '', $parts[0]);
04856                 list ($mailToUrl, $linktxt) = $this->getMailTo($parts[0], $linktxt, $initP);
04857                 $mailToUrl = $GLOBALS['TSFE']->spamProtectEmailAddresses === 'ascii' ? $mailToUrl : htmlspecialchars($mailToUrl);
04858                 $res = '<a href="' . $mailToUrl . '"' . $aTagParams . '>';
04859                 $wrap = isset($conf['wrap.'])
04860                     ? $this->stdWrap($conf['wrap'], $conf['wrap.'])
04861                     : $conf['wrap'];
04862                 if ($conf['ATagBeforeWrap']) {
04863                     $res = $res . $this->wrap($linktxt, $wrap) . '</a>';
04864                 } else {
04865                     $res = $this->wrap($res . $linktxt . '</a>', $wrap);
04866                 }
04867                 $textstr .= $res . $parts[1];
04868             } else {
04869                 $textstr .= 'mailto:' . $textpieces[$i];
04870             }
04871         }
04872         return $textstr;
04873     }
04874 
04875     /**
04876      * Creates and returns a TypoScript "imgResource".
04877      * The value ($file) can either be a file reference (TypoScript resource) or the string "GIFBUILDER".
04878      * In the first case a current image is returned, possibly scaled down or otherwise processed.
04879      * In the latter case a GIFBUILDER image is returned; This means an image is made by TYPO3 from layers of elements as GIFBUILDER defines.
04880      * In the function IMG_RESOURCE() this function is called like $this->getImgResource($conf['file'],$conf['file.']);
04881      *
04882      * @param   string      A "imgResource" TypoScript data type. Either a TypoScript file resource or the string GIFBUILDER. See description above.
04883      * @param   array       TypoScript properties for the imgResource type
04884      * @return  array       Returns info-array. info[origFile] = original file.
04885      * @see IMG_RESOURCE(), cImage(), tslib_gifBuilder
04886      */
04887     function getImgResource($file, $fileArray) {
04888         if (is_array($fileArray)) {
04889             switch ($file) {
04890                 case 'GIFBUILDER' :
04891                     $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
04892                     $gifCreator->init();
04893                     $theImage = '';
04894                     if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) {
04895                         $gifCreator->start($fileArray, $this->data);
04896                         $theImage = $gifCreator->gifBuild();
04897                     }
04898                     $imageResource = $gifCreator->getImageDimensions($theImage);
04899                 break;
04900                 default :
04901                     if ($fileArray['import.']) {
04902                         $ifile = $this->stdWrap('', $fileArray['import.']);
04903                         if ($ifile) {
04904                             $file = $fileArray['import'] . $ifile;
04905                         }
04906                     }
04907                     $theImage = $GLOBALS['TSFE']->tmpl->getFileName($file);
04908                     if ($theImage) {
04909                         $fileArray['width'] = isset($fileArray['width.'])
04910                             ? $this->stdWrap($fileArray['width'], $fileArray['width.'])
04911                             : $fileArray['width'];
04912                         $fileArray['height'] = isset($fileArray['height.'])
04913                             ? $this->stdWrap($fileArray['height'], $fileArray['height.'])
04914                             : $fileArray['height'];
04915                         $fileArray['ext'] = isset($fileArray['ext.'])
04916                             ? $this->stdWrap($fileArray['ext'], $fileArray['ext.'])
04917                             : $fileArray['ext'];
04918                         $fileArray['maxW'] = isset($fileArray['maxW.'])
04919                             ? intval($this->stdWrap($fileArray['maxW'], $fileArray['maxW.']))
04920                             : intval($fileArray['maxW']);
04921                         $fileArray['maxH'] = isset($fileArray['maxH.'])
04922                             ? intval($this->stdWrap($fileArray['maxH'], $fileArray['maxH.']))
04923                             : intval($fileArray['maxH']);
04924                         $fileArray['minW'] = isset($fileArray['minW.'])
04925                             ? intval($this->stdWrap($fileArray['minW'], $fileArray['minW.']))
04926                             : intval($fileArray['minW']);
04927                         $fileArray['minH'] = isset($fileArray['minH.'])
04928                             ? intval($this->stdWrap($fileArray['minH'], $fileArray['minH.']))
04929                             : intval($fileArray['minH']);
04930                         $fileArray['noScale'] = isset($fileArray['noScale.'])
04931                             ? $this->stdWrap($fileArray['noScale'], $fileArray['noScale.'])
04932                             : $fileArray['noScale'];
04933                         $maskArray = $fileArray['m.'];
04934                         $maskImages = array();
04935                         if (is_array($fileArray['m.'])) { // Must render mask images and include in hash-calculating - else we cannot be sure the filename is unique for the setup!
04936                             $maskImages['m_mask'] = $this->getImgResource($maskArray['mask'], $maskArray['mask.']);
04937                             $maskImages['m_bgImg'] = $this->getImgResource($maskArray['bgImg'], $maskArray['bgImg.']);
04938                             $maskImages['m_bottomImg'] = $this->getImgResource($maskArray['bottomImg'], $maskArray['bottomImg.']);
04939                             $maskImages['m_bottomImg_mask'] = $this->getImgResource($maskArray['bottomImg_mask'], $maskArray['bottomImg_mask.']);
04940                         }
04941                         $hash = t3lib_div::shortMD5($theImage . serialize($fileArray) . serialize($maskImages));
04942                         if (!isset($GLOBALS['TSFE']->tmpl->fileCache[$hash])) {
04943                             $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
04944                             $gifCreator->init();
04945 
04946                             if ($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix']) {
04947                                 $filename = basename($theImage);
04948                                     // remove extension
04949                                 $filename = substr($filename, 0, strrpos($filename, '.'));
04950                                     // strip everything non-ascii
04951                                 $filename = preg_replace('/[^A-Za-z0-9_-]/', '', trim($filename));
04952                                 $gifCreator->filenamePrefix = substr($filename, 0, intval($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix'])) . '_';
04953                                 unset($filename);
04954                             }
04955 
04956                             if ($fileArray['sample']) {
04957                                 $gifCreator->scalecmd = '-sample';
04958                                 $GLOBALS['TT']->setTSlogMessage('Sample option: Images are scaled with -sample.');
04959                             }
04960                             if ($fileArray['alternativeTempPath'] && t3lib_div::inList($GLOBALS['TYPO3_CONF_VARS']['FE']['allowedTempPaths'], $fileArray['alternativeTempPath'])) {
04961                                 $gifCreator->tempPath = $fileArray['alternativeTempPath'];
04962                                 $GLOBALS['TT']->setTSlogMessage('Set alternativeTempPath: ' . $fileArray['alternativeTempPath']);
04963                             }
04964 
04965                             if (!trim($fileArray['ext'])) {
04966                                 $fileArray['ext'] = 'web';
04967                             }
04968                             $options = array();
04969                             if ($fileArray['maxW']) {
04970                                 $options['maxW'] = $fileArray['maxW'];
04971                             }
04972                             if ($fileArray['maxH']) {
04973                                 $options['maxH'] = $fileArray['maxH'];
04974                             }
04975                             if ($fileArray['minW']) {
04976                                 $options['minW'] = $fileArray['minW'];
04977                             }
04978                             if ($fileArray['minH']) {
04979                                 $options['minH'] = $fileArray['minH'];
04980                             }
04981                             if ($fileArray['noScale']) {
04982                                 $options['noScale'] = $fileArray['noScale'];
04983                             }
04984 
04985                                 // checks to see if m (the mask array) is defined
04986                             if (is_array($maskArray) && $GLOBALS['TYPO3_CONF_VARS']['GFX']['im']) {
04987                                     // Filename:
04988                                 $fI = t3lib_div::split_fileref($theImage);
04989                                 $imgExt = (strtolower($fI['fileext']) == $gifCreator->gifExtension ? $gifCreator->gifExtension : 'jpg');
04990                                 $dest = $gifCreator->tempPath . $hash . '.' . $imgExt;
04991                                 if (!file_exists($dest)) { // Generate!
04992                                     $m_mask = $maskImages['m_mask'];
04993                                     $m_bgImg = $maskImages['m_bgImg'];
04994                                     if ($m_mask && $m_bgImg) {
04995                                         $negate = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_negate_mask'] ? ' -negate' : '';
04996 
04997                                         $temp_ext = 'png';
04998                                         if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_mask_temp_ext_gif']) { // If ImageMagick version 5+
04999                                             $temp_ext = $gifCreator->gifExtension;
05000                                         }
05001 
05002                                         $tempFileInfo = $gifCreator->imageMagickConvert($theImage, $temp_ext, $fileArray['width'], $fileArray['height'], $fileArray['params'], $fileArray['frame'], $options);
05003                                         if (is_array($tempFileInfo)) {
05004                                             $m_bottomImg = $maskImages['m_bottomImg'];
05005                                             if ($m_bottomImg) {
05006                                                 $m_bottomImg_mask = $maskImages['m_bottomImg_mask'];
05007                                             }
05008                                                 //  Scaling:    ****
05009                                             $tempScale = array();
05010                                             $command = '-geometry ' . $tempFileInfo[0] . 'x' . $tempFileInfo[1] . '!';
05011                                             $command = $this->modifyImageMagickStripProfileParameters($command, $fileArray);
05012                                             $tmpStr = $gifCreator->randomName();
05013 
05014                                                 //  m_mask
05015                                             $tempScale['m_mask'] = $tmpStr . '_mask.' . $temp_ext;
05016                                             $gifCreator->imageMagickExec($m_mask[3], $tempScale['m_mask'], $command . $negate);
05017                                                 //  m_bgImg
05018                                             $tempScale['m_bgImg'] = $tmpStr . '_bgImg.' . trim($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_mask_temp_ext_noloss']);
05019                                             $gifCreator->imageMagickExec($m_bgImg[3], $tempScale['m_bgImg'], $command);
05020 
05021                                                 //  m_bottomImg / m_bottomImg_mask
05022                                             if ($m_bottomImg && $m_bottomImg_mask) {
05023                                                 $tempScale['m_bottomImg'] = $tmpStr . '_bottomImg.' . $temp_ext;
05024                                                 $gifCreator->imageMagickExec($m_bottomImg[3], $tempScale['m_bottomImg'], $command);
05025                                                 $tempScale['m_bottomImg_mask'] = $tmpStr . '_bottomImg_mask.' . $temp_ext;
05026                                                 $gifCreator->imageMagickExec($m_bottomImg_mask[3], $tempScale['m_bottomImg_mask'], $command . $negate);
05027 
05028                                                     // BEGIN combining:
05029                                                     // The image onto the background
05030                                                 $gifCreator->combineExec($tempScale['m_bgImg'], $tempScale['m_bottomImg'], $tempScale['m_bottomImg_mask'], $tempScale['m_bgImg']);
05031                                             }
05032                                                 // The image onto the background
05033                                             $gifCreator->combineExec($tempScale['m_bgImg'], $tempFileInfo[3], $tempScale['m_mask'], $dest);
05034                                                 // Unlink the temp-images...
05035                                             foreach ($tempScale as $file) {
05036                                                 if (@is_file($file)) {
05037                                                     unlink($file);
05038                                                 }
05039                                             }
05040                                         }
05041                                     }
05042                                 }
05043                                     // Finish off
05044                                 if (($fileArray['reduceColors'] || ($imgExt == 'png' && !$gifCreator->png_truecolor)) && is_file($dest)) {
05045                                     $reduced = $gifCreator->IMreduceColors($dest, t3lib_div::intInRange($fileArray['reduceColors'], 256, $gifCreator->truecolorColors, 256));
05046                                     if (is_file($reduced)) {
05047                                         unlink($dest);
05048                                         rename($reduced, $dest);
05049                                     }
05050                                 }
05051                                 $GLOBALS['TSFE']->tmpl->fileCache[$hash] = $gifCreator->getImageDimensions($dest);
05052                             } else { // Normal situation:
05053                                 $fileArray['params'] = $this->modifyImageMagickStripProfileParameters($fileArray['params'], $fileArray);
05054                                 $GLOBALS['TSFE']->tmpl->fileCache[$hash] = $gifCreator->imageMagickConvert($theImage, $fileArray['ext'], $fileArray['width'], $fileArray['height'], $fileArray['params'], $fileArray['frame'], $options);
05055                                 if (($fileArray['reduceColors'] || ($imgExt == 'png' && !$gifCreator->png_truecolor)) && is_file($GLOBALS['TSFE']->tmpl->fileCache[$hash][3])) {
05056                                     $reduced = $gifCreator->IMreduceColors($GLOBALS['TSFE']->tmpl->fileCache[$hash][3], t3lib_div::intInRange($fileArray['reduceColors'], 256, $gifCreator->truecolorColors, 256));
05057                                     if (is_file($reduced)) {
05058                                         unlink($GLOBALS['TSFE']->tmpl->fileCache[$hash][3]);
05059                                         rename($reduced, $GLOBALS['TSFE']->tmpl->fileCache[$hash][3]);
05060                                     }
05061                                 }
05062                             }
05063                             $GLOBALS['TSFE']->tmpl->fileCache[$hash]['origFile'] = $theImage;
05064                             $GLOBALS['TSFE']->tmpl->fileCache[$hash]['origFile_mtime'] = @filemtime($theImage); // This is needed by tslib_gifbuilder, ln 100ff in order for the setup-array to create a unique filename hash.
05065                             $GLOBALS['TSFE']->tmpl->fileCache[$hash]['fileCacheHash'] = $hash;
05066                         }
05067                         $imageResource = $GLOBALS['TSFE']->tmpl->fileCache[$hash];
05068                     }
05069 
05070                 break;
05071             }
05072         }
05073         $theImage = $GLOBALS['TSFE']->tmpl->getFileName($file);
05074             // If image was processed by GIFBUILDER:
05075             // ($imageResource indicates that it was processed the regular way)
05076         if (!isset($imageResource) && $theImage) {
05077             $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
05078             /* @var $gifCreator tslib_gifbuilder */
05079             $gifCreator->init();
05080             $info = $gifCreator->imageMagickConvert($theImage, 'WEB', '', '', '', '', '');
05081             $info['origFile'] = $theImage;
05082             $info['origFile_mtime'] = @filemtime($theImage); // This is needed by tslib_gifbuilder, ln 100ff in order for the setup-array to create a unique filename hash.
05083             $imageResource = $info;
05084         }
05085 
05086             // Hook 'getImgResource': Post-processing of image resources
05087         if (isset($imageResource)) {
05088             foreach ($this->getGetImgResourceHookObjects() as $hookObject) {
05089                 $imageResource = $hookObject->getImgResourcePostProcess($file, (array) $fileArray, $imageResource, $this);
05090             }
05091         }
05092 
05093         return $imageResource;
05094     }
05095 
05096     /**
05097      * Modifies the parameters for ImageMagick for stripping of profile information.
05098      *
05099      * @param   string      $parameters: The parameters to be modified (if required)
05100      * @param   array       $configuration: The TypoScript configuration of [IMAGE].file
05101      * @param   string      The modified parameters
05102      */
05103     protected function modifyImageMagickStripProfileParameters($parameters, array $configuration) {
05104             // Strips profile information of image to save some space:
05105         if (isset($configuration['stripProfile'])) {
05106             if ($configuration['stripProfile']) {
05107                 $parameters = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_stripProfileCommand'] . $parameters;
05108             } else {
05109                 $parameters .= '###SkipStripProfile###';
05110             }
05111         }
05112         return $parameters;
05113     }
05114 
05115 
05116 
05117     /***********************************************
05118      *
05119      * Data retrieval etc.
05120      *
05121      ***********************************************/
05122 
05123 
05124     /**
05125      * Returns the value for the field from $this->data. If "//" is found in the $field value that token will split the field values apart and the first field having a non-blank value will be returned.
05126      *
05127      * @param   string      The fieldname, eg. "title" or "navtitle // title" (in the latter case the value of $this->data[navtitle] is returned if not blank, otherwise $this->data[title] will be)
05128      * @return  string
05129      */
05130     function getFieldVal($field) {
05131         if (!strstr($field, '//')) {
05132             return $this->data[trim($field)];
05133         } else {
05134             $sections = t3lib_div::trimExplode('//', $field, 1);
05135             foreach ($sections as $k) {
05136                 if (strcmp($this->data[$k], ''))
05137                     return $this->data[$k];
05138             }
05139         }
05140     }
05141 
05142     /**
05143      * Implements the TypoScript data type "getText". This takes a string with parameters and based on those a value from somewhere in the system is returned.
05144      *
05145      * @param   string      The parameter string, eg. "field : title" or "field : navtitle // field : title" (in the latter case and example of how the value is FIRST splitted by "//" is shown)
05146      * @param   mixed       Alternative field array; If you set this to an array this variable will be used to look up values for the "field" key. Otherwise the current page record in $GLOBALS['TSFE']->page is used.
05147      * @return  string      The value fetched
05148      * @see getFieldVal()
05149      */
05150     function getData($string, $fieldArray) {
05151         global $TYPO3_CONF_VARS;
05152 
05153         if (!is_array($fieldArray)) {
05154             $fieldArray = $GLOBALS['TSFE']->page;
05155         }
05156         $retVal = '';
05157         $sections = explode('//', $string);
05158 
05159         while (!$retVal and list ($secKey, $secVal) = each($sections)) {
05160             $parts = explode(':', $secVal, 2);
05161             $key = trim($parts[1]);
05162             if ((string) $key != '') {
05163                 $type = strtolower(trim($parts[0]));
05164                 switch ($type) {
05165                     case 'gpvar' :
05166                         t3lib_div::deprecationLog('Using gpvar in TypoScript getText is deprecated since TYPO3 4.3 - Use gp instead of gpvar.');
05167                         // Fall Through
05168                     case 'gp' :
05169                             // Merge GET and POST and get $key out of the merged array
05170                         $retVal = $this->getGlobal($key, t3lib_div::array_merge_recursive_overrule(t3lib_div::_GET(), t3lib_div::_POST()));
05171                     break;
05172                     case 'tsfe' :
05173                         $retVal = $this->getGlobal('TSFE|' . $key);
05174                     break;
05175                     case 'getenv' :
05176                         $retVal = getenv($key);
05177                     break;
05178                     case 'getindpenv' :
05179                         $retVal = t3lib_div::getIndpEnv($key);
05180                     break;
05181                     case 'field' :
05182                         $retVal = $fieldArray[$key];
05183                     break;
05184                     case 'parameters' :
05185                         $retVal = $this->parameters[$key];
05186                     break;
05187                     case 'register' :
05188                         $retVal = $GLOBALS['TSFE']->register[$key];
05189                     break;
05190                     case 'global' :
05191                         $retVal = $this->getGlobal($key);
05192                     break;
05193                     case 'leveltitle' :
05194                         $nkey = $this->getKey($key, $GLOBALS['TSFE']->tmpl->rootLine);
05195                         $retVal = $this->rootLineValue($nkey, 'title', stristr($key, 'slide'));
05196                     break;
05197                     case 'levelmedia' :
05198                         $nkey = $this->getKey($key, $GLOBALS['TSFE']->tmpl->rootLine);
05199                         $retVal = $this->rootLineValue($nkey, 'media', stristr($key, 'slide'));
05200                     break;
05201                     case 'leveluid' :
05202                         $nkey = $this->getKey($key, $GLOBALS['TSFE']->tmpl->rootLine);
05203                         $retVal = $this->rootLineValue($nkey, 'uid', stristr($key, 'slide'));
05204                     break;
05205                     case 'levelfield' :
05206                         $keyP = t3lib_div::trimExplode(',', $key);
05207                         $nkey = $this->getKey($keyP[0], $GLOBALS['TSFE']->tmpl->rootLine);
05208                         $retVal = $this->rootLineValue($nkey, $keyP[1], strtolower($keyP[2]) == 'slide');
05209                     break;
05210                     case 'fullrootline' :
05211                         $keyP = t3lib_div::trimExplode(',', $key);
05212                         $fullKey = intval($keyP[0]) - count($GLOBALS['TSFE']->tmpl->rootLine) + count($GLOBALS['TSFE']->rootLine);
05213                         if ($fullKey >= 0) {
05214                             $retVal = $this->rootLineValue($fullKey, $keyP[1], stristr($keyP[2], 'slide'), $GLOBALS['TSFE']->rootLine);
05215                         }
05216                     break;
05217                     case 'date' :
05218                         if (!$key) {
05219                             $key = 'd/m Y';
05220                         }
05221                         $retVal = date($key, $GLOBALS['EXEC_TIME']);
05222                     break;
05223                     case 'page' :
05224                         $retVal = $GLOBALS['TSFE']->page[$key];
05225                     break;
05226                     case 'current' :
05227                         $retVal = $this->data[$this->currentValKey];
05228                     break;
05229                     case 'level' :
05230                         $retVal = count($GLOBALS['TSFE']->tmpl->rootLine) - 1;
05231                     break;
05232                     case 'db' :
05233                         $selectParts = t3lib_div::trimExplode(':', $key);
05234                         $db_rec = $GLOBALS['TSFE']->sys_page->getRawRecord($selectParts[0], $selectParts[1]);
05235                         if (is_array($db_rec) && $selectParts[2]) {
05236                             $retVal = $db_rec[$selectParts[2]];
05237                         }
05238                     break;
05239                     case 'lll' :
05240                         $retVal = $GLOBALS['TSFE']->sL('LLL:' . $key);
05241                     break;
05242                     case 'path' :
05243                         $retVal = $GLOBALS['TSFE']->tmpl->getFileName($key);
05244                     break;
05245                     case 'cobj' :
05246                         switch ((string) $key) {
05247                             case 'parentRecordNumber' :
05248                                 $retVal = $this->parentRecordNumber;
05249                             break;
05250                         }
05251                     break;
05252                     case 'debug' :
05253                         switch ((string) $key) {
05254                             case 'rootLine' :
05255                                 $retVal = t3lib_utility_Debug::viewArray($GLOBALS['TSFE']->tmpl->rootLine);
05256                             break;
05257                             case 'fullRootLine' :
05258                                 $retVal = t3lib_utility_Debug::viewArray($GLOBALS['TSFE']->rootLine);
05259                             break;
05260                             case 'data' :
05261                                 $retVal = t3lib_utility_Debug::viewArray($this->data);
05262                             break;
05263                         }
05264                     break;
05265                 }
05266             }
05267 
05268             if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['getData'])) {
05269                 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['getData'] as $classData) {
05270                     $hookObject = t3lib_div::getUserObj($classData);
05271 
05272                     if (!($hookObject instanceof tslib_content_getDataHook)) {
05273                         throw new UnexpectedValueException('$hookObject must implement interface tslib_content_getDataHook', 1195044480);
05274                     }
05275 
05276                     $retVal = $hookObject->getDataExtension($string, $fieldArray, $secVal, $retVal, $this);
05277                 }
05278             }
05279         }
05280 
05281         return $retVal;
05282     }
05283 
05284     /**
05285      * Returns a value from the current rootline (site) from $GLOBALS['TSFE']->tmpl->rootLine;
05286      *
05287      * @param   string      Which level in the root line
05288      * @param   string      The field in the rootline record to return (a field from the pages table)
05289      * @param   boolean     If set, then we will traverse through the rootline from outer level towards the root level until the value found is TRUE
05290      * @param   mixed       If you supply an array for this it will be used as an alternative root line array
05291      * @return  string      The value from the field of the rootline.
05292      * @access private
05293      * @see getData()
05294      */
05295     function rootLineValue($key, $field, $slideBack = 0, $altRootLine = '') {
05296         $rootLine = is_array($altRootLine) ? $altRootLine : $GLOBALS['TSFE']->tmpl->rootLine;
05297         if (!$slideBack) {
05298             return $rootLine[$key][$field];
05299         } else {
05300             for ($a = $key; $a >= 0; $a--) {
05301                 $val = $rootLine[$a][$field];
05302                 if ($val) {
05303                     return $val;
05304                 }
05305             }
05306         }
05307     }
05308 
05309     /**
05310      * Return global variable where the input string $var defines array keys separated by "|"
05311      * Example: $var = "HTTP_SERVER_VARS | something" will return the value $GLOBALS['HTTP_SERVER_VARS']['something'] value
05312      *
05313      * @param   string      Global var key, eg. "HTTP_GET_VAR" or "HTTP_GET_VARS|id" to get the GET parameter "id" back.
05314      * @param   array       Alternative array than $GLOBAL to get variables from.
05315      * @return  mixed       Whatever value. If none, then blank string.
05316      * @see getData()
05317      */
05318     function getGlobal($keyString, $source = NULL) {
05319         $keys = explode('|', $keyString);
05320         $numberOfLevels = count($keys);
05321         $rootKey = trim($keys[0]);
05322         $value = isset($source) ? $source[$rootKey] : $GLOBALS[$rootKey];
05323 
05324         for ($i = 1; $i < $numberOfLevels && isset($value); $i++) {
05325             $currentKey = trim($keys[$i]);
05326             if (is_object($value)) {
05327                 $value = $value->$currentKey;
05328             } elseif (is_array($value)) {
05329                 $value = $value[$currentKey];
05330             } else {
05331                 $value = '';
05332                 break;
05333             }
05334         }
05335 
05336         if (!is_scalar($value)) {
05337             $value = '';
05338         }
05339         return $value;
05340     }
05341 
05342     /**
05343      * Processing of key values pointing to entries in $arr; Here negative values are converted to positive keys pointer to an entry in the array but from behind (based on the negative value).
05344      * Example: entrylevel = -1 means that entryLevel ends up pointing at the outermost-level, -2 means the level before the outermost...
05345      *
05346      * @param   integer     The integer to transform
05347      * @param   array       array in which the key should be found.
05348      * @return  integer     The processed integer key value.
05349      * @access private
05350      * @see getData()
05351      */
05352     function getKey($key, $arr) {
05353         $key = intval($key);
05354         if (is_array($arr)) {
05355             if ($key < 0) {
05356                 $key = count($arr) + $key;
05357             }
05358             if ($key < 0) {
05359                 $key = 0;
05360             }
05361         }
05362         return $key;
05363     }
05364 
05365 
05366     /**
05367      * Looks up the incoming value in the defined TCA configuration
05368      * Works only with TCA-type 'select' and options defined in 'items'
05369      *
05370      * @param   mixed       Comma-separated list of values to look up
05371      * @param   array       TS-configuration array, see TSref for details
05372      * @return  string      String of translated values, seperated by $delimiter. If no matches were found, the input value is simply returned.
05373      * @todo    It would be nice it this function basically looked up any type of value, db-relations etc.
05374      */
05375     function TCAlookup($inputValue, $conf) {
05376         global $TCA;
05377 
05378         $table = $conf['table'];
05379         $field = $conf['field'];
05380         $delimiter = $conf['delimiter'] ? $conf['delimiter'] : ' ,';
05381 
05382         $GLOBALS['TSFE']->includeTCA();
05383         t3lib_div::loadTCA($table);
05384 
05385         if (is_array($TCA[$table]) && is_array($TCA[$table]['columns'][$field]) && is_array($TCA[$table]['columns'][$field]['config']['items'])) {
05386             $values = t3lib_div::trimExplode(',', $inputValue);
05387             $output = array();
05388             foreach ($values as $value) {
05389                     // Traverse the items-array...
05390                 foreach ($TCA[$table]['columns'][$field]['config']['items'] as $item) {
05391                         // ... and return the first found label where the value was equal to $key
05392                     if (!strcmp($item[1], trim($value))) {
05393                         $output[] = $GLOBALS['TSFE']->sL($item[0]);
05394                     }
05395                 }
05396             }
05397             $returnValue = implode($delimiter, $output);
05398         } else {
05399             $returnValue = $inputValue;
05400         }
05401         return $returnValue;
05402     }
05403 
05404 
05405 
05406     /***********************************************
05407      *
05408      * Link functions (typolink)
05409      *
05410      ***********************************************/
05411 
05412 
05413     /**
05414      * Implements the "typolink" property of stdWrap (and others)
05415      * Basically the input string, $linktext, is (typically) wrapped in a <a>-tag linking to some page, email address, file or URL based on a parameter defined by the configuration array $conf.
05416      * This function is best used from internal functions as is. There are some API functions defined after this function which is more suited for general usage in external applications.
05417      * Generally the concept "typolink" should be used in your own applications as an API for making links to pages with parameters and more. The reason for this is that you will then automatically make links compatible with all the centralized functions for URL simulation and manipulation of parameters into hashes and more.
05418      * For many more details on the parameters and how they are intepreted, please see the link to TSref below.
05419      *
05420      * @param   string      The string (text) to link
05421      * @param   array       TypoScript configuration (see link below)
05422      * @return  string      A link-wrapped string.
05423      * @see stdWrap(), tslib_pibase::pi_linkTP()
05424      */
05425     function typoLink($linktxt, $conf) {
05426         $LD = array();
05427         $finalTagParts = array();
05428         $finalTagParts['aTagParams'] = $this->getATagParams($conf);
05429 
05430         $link_param = isset($conf['parameter.'])
05431             ? trim($this->stdWrap($conf['parameter'], $conf['parameter.']))
05432             : trim($conf['parameter']);
05433 
05434         $sectionMark = isset($conf['section.'])
05435             ? trim($this->stdWrap($conf['section'], $conf['section.']))
05436             : trim($conf['section']);
05437         $sectionMark = $sectionMark ? (t3lib_div::testInt($sectionMark) ? '#c' : '#') . $sectionMark : '';
05438         $initP = '?id=' . $GLOBALS['TSFE']->id . '&type=' . $GLOBALS['TSFE']->type;
05439         $this->lastTypoLinkUrl = '';
05440         $this->lastTypoLinkTarget = '';
05441         if ($link_param) {
05442             $enableLinksAcrossDomains = $GLOBALS['TSFE']->config['config']['typolinkEnableLinksAcrossDomains'];
05443             $link_paramA = t3lib_div::unQuoteFilenames($link_param, TRUE);
05444 
05445                 // Check for link-handler keyword:
05446             list ($linkHandlerKeyword, $linkHandlerValue) = explode(':', trim($link_paramA[0]), 2);
05447             if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword] && strcmp($linkHandlerValue, '')) {
05448                 $linkHandlerObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword]);
05449 
05450                 if (method_exists($linkHandlerObj, 'main')) {
05451                     return $linkHandlerObj->main($linktxt, $conf, $linkHandlerKeyword, $linkHandlerValue, $link_param, $this);
05452                 }
05453             }
05454 
05455             $link_param = trim($link_paramA[0]); // Link parameter value
05456             $linkClass = trim($link_paramA[2]); // Link class
05457             if ($linkClass == '-')
05458                 $linkClass = ''; // The '-' character means 'no class'. Necessary in order to specify a title as fourth parameter without setting the target or class!
05459             $forceTarget = trim($link_paramA[1]); // Target value
05460             if ($forceTarget == '-') {
05461                 $forceTarget = '';  // The '-' character means 'no target'. Necessary in order to specify a class as third parameter without setting the target!
05462             }
05463             $forceTitle = trim($link_paramA[3]); // Title value
05464             if ($forceTitle == '-') {
05465                 $forceTitle = '';   // The '-' character means 'no title'. Necessary in order to specify further parameters without setting the title!
05466             }
05467             if (isset($link_paramA[4]) && strlen(trim($link_paramA[4])) > 0) {
05468                 $forceParams = trim($link_paramA[4]);   // params value
05469                 $conf['additionalParams'] .= $forceParams[0] == '&' ? $forceParams : '&' . $forceParams;
05470             }
05471 
05472                 // Check, if the target is coded as a JS open window link:
05473             $JSwindowParts = array();
05474             $JSwindowParams = '';
05475             $onClick = '';
05476             if ($forceTarget && preg_match('/^([0-9]+)x([0-9]+)(:(.*)|.*)$/', $forceTarget, $JSwindowParts)) {
05477                     // Take all pre-configured and inserted parameters and compile parameter list, including width+height:
05478                 $JSwindow_tempParamsArr = t3lib_div::trimExplode(',', strtolower($conf['JSwindow_params'] . ',' . $JSwindowParts[4]), TRUE);
05479                 $JSwindow_paramsArr = array();
05480                 foreach ($JSwindow_tempParamsArr as $JSv) {
05481                     list ($JSp, $JSv) = explode('=', $JSv);
05482                     $JSwindow_paramsArr[$JSp] = $JSp . '=' . $JSv;
05483                 }
05484                     // Add width/height:
05485                 $JSwindow_paramsArr['width'] = 'width=' . $JSwindowParts[1];
05486                 $JSwindow_paramsArr['height'] = 'height=' . $JSwindowParts[2];
05487                     // Imploding into string:
05488                 $JSwindowParams = implode(',', $JSwindow_paramsArr);
05489                 $forceTarget = ''; // Resetting the target since we will use onClick.
05490             }
05491 
05492                 // Internal target:
05493             $target = isset($conf['target']) ? $conf['target'] : $GLOBALS['TSFE']->intTarget;
05494             if ($conf['target.']) {
05495                 $target = $this->stdWrap($target, $conf['target.']);
05496             }
05497 
05498                 // Title tag
05499             $title = $conf['title'];
05500             if ($conf['title.']) {
05501                 $title = $this->stdWrap($title, $conf['title.']);
05502             }
05503 
05504                 // Parse URL:
05505             $pU = parse_url($link_param);
05506 
05507                 // Detecting kind of link:
05508             if (strstr($link_param, '@') && (!$pU['scheme'] || $pU['scheme'] == 'mailto')) { // If it's a mail address:
05509                 $link_param = preg_replace('/^mailto:/i', '', $link_param);
05510                 list ($this->lastTypoLinkUrl, $linktxt) = $this->getMailTo($link_param, $linktxt, $initP);
05511                 $finalTagParts['url'] = $this->lastTypoLinkUrl;
05512                 $finalTagParts['TYPE'] = 'mailto';
05513             } else {
05514                 $isLocalFile = 0;
05515                 $fileChar = intval(strpos($link_param, '/'));
05516                 $urlChar = intval(strpos($link_param, '.'));
05517 
05518                     // Firsts, test if $link_param is numeric and page with such id exists. If yes, do not attempt to link to file
05519                 if (!t3lib_div::testInt($link_param) || count($GLOBALS['TSFE']->sys_page->getPage_noCheck($link_param)) == 0) {
05520                         // Detects if a file is found in site-root (or is a 'virtual' simulateStaticDocument file!) and if so it will be treated like a normal file.
05521                     list ($rootFileDat) = explode('?', rawurldecode($link_param));
05522                     $containsSlash = strstr($rootFileDat, '/');
05523                     $rFD_fI = pathinfo($rootFileDat);
05524                     if (trim($rootFileDat) && !$containsSlash && (@is_file(PATH_site . $rootFileDat) || t3lib_div::inList('php,html,htm', strtolower($rFD_fI['extension'])))) {
05525                         $isLocalFile = 1;
05526                     } elseif ($containsSlash) {
05527                         $isLocalFile = 2; // Adding this so realurl directories are linked right (non-existing).
05528                     }
05529                 }
05530 
05531                 if ($pU['scheme'] || ($isLocalFile != 1 && $urlChar && (!$containsSlash || $urlChar < $fileChar))) { // url (external): If doubleSlash or if a '.' comes before a '/'.
05532                     $target = isset($conf['extTarget']) ? $conf['extTarget'] : $GLOBALS['TSFE']->extTarget;
05533                     if ($conf['extTarget.']) {
05534                         $target = $this->stdWrap($target, $conf['extTarget.']);
05535                     }
05536                     if ($forceTarget) {
05537                         $target = $forceTarget;
05538                     }
05539                     if ($linktxt == '')
05540                         $linktxt = $link_param;
05541                     if (!$pU['scheme']) {
05542                         $scheme = 'http://';
05543                     } else {
05544                         $scheme = '';
05545                     }
05546                     if ($GLOBALS['TSFE']->config['config']['jumpurl_enable']) {
05547                         $this->lastTypoLinkUrl = $GLOBALS['TSFE']->absRefPrefix .
05548                             $GLOBALS['TSFE']->config['mainScript'] . $initP .
05549                             '&jumpurl=' . rawurlencode($scheme . $link_param) .
05550                             $GLOBALS['TSFE']->getMethodUrlIdToken;
05551                     } else {
05552                         $this->lastTypoLinkUrl = $scheme . $link_param;
05553                     }
05554                     $this->lastTypoLinkTarget = $target;
05555                     $finalTagParts['url'] = $this->lastTypoLinkUrl;
05556                     $finalTagParts['targetParams'] = $target ? ' target="' . $target . '"' : '';
05557                     $finalTagParts['TYPE'] = 'url';
05558                     $finalTagParts['aTagParams'] .= $this->extLinkATagParams($finalTagParts['url'], $finalTagParts['TYPE']);
05559                 } elseif ($containsSlash || $isLocalFile) { // file (internal)
05560                     $splitLinkParam = explode('?', $link_param);
05561                     if (file_exists(rawurldecode($splitLinkParam[0])) || $isLocalFile) {
05562                         if ($linktxt == '')
05563                             $linktxt = rawurldecode($link_param);
05564                         if ($GLOBALS['TSFE']->config['config']['jumpurl_enable'] || $conf['jumpurl']) {
05565                             $theFileEnc = str_replace('%2F', '/', rawurlencode(rawurldecode($link_param)));
05566                             $this->lastTypoLinkUrl = $GLOBALS['TSFE']->absRefPrefix .
05567                                 $GLOBALS['TSFE']->config['mainScript'] . $initP .
05568                                 '&jumpurl=' . rawurlencode($link_param) .
05569                                 ($conf['jumpurl.']['secure'] ? $this->locDataJU($theFileEnc, $conf['jumpurl.']['secure.']) : '') .
05570                                 $GLOBALS['TSFE']->getMethodUrlIdToken;
05571                         } else {
05572                             $this->lastTypoLinkUrl = $GLOBALS['TSFE']->absRefPrefix . $link_param;
05573                         }
05574                         $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf);
05575                         $target = isset($conf['fileTarget']) ? $conf['fileTarget'] : $GLOBALS['TSFE']->fileTarget;
05576                         if ($conf['fileTarget.']) {
05577                             $target = $this->stdWrap($target, $conf['fileTarget.']);
05578                         }
05579                         if ($forceTarget) {
05580                             $target = $forceTarget;
05581                         }
05582                         $this->lastTypoLinkTarget = $target;
05583 
05584                         $finalTagParts['url'] = $this->lastTypoLinkUrl;
05585                         $finalTagParts['targetParams'] = $target ? ' target="' . $target . '"' : '';
05586                         $finalTagParts['TYPE'] = 'file';
05587                         $finalTagParts['aTagParams'] .= $this->extLinkATagParams($finalTagParts['url'], $finalTagParts['TYPE']);
05588                     } else {
05589                         $GLOBALS['TT']->setTSlogMessage(
05590                             "typolink(): File '" . $splitLinkParam[0] . "' did not exist, so '" . $linktxt . "' was not linked.", 1
05591                         );
05592                         return $linktxt;
05593                     }
05594                 } else { // integer or alias (alias is without slashes or periods or commas, that is 'nospace,alphanum_x,lower,unique' according to definition in $TCA!)
05595                     if ($conf['no_cache.']) {
05596                         $conf['no_cache'] = $this->stdWrap($conf['no_cache'], $conf['no_cache.']);
05597                     }
05598                         // Splitting the parameter by ',' and if the array counts more than 1 element it's a id/type/parameters triplet
05599                     $pairParts = t3lib_div::trimExplode(',', $link_param, TRUE);
05600                     $link_param = $pairParts[0];
05601                     $link_params_parts = explode('#', $link_param);
05602                     $link_param = trim($link_params_parts[0]); // Link-data del
05603                     if (!strcmp($link_param, '')) {
05604                         $link_param = $GLOBALS['TSFE']->id;
05605                     } // If no id or alias is given
05606                     if ($link_params_parts[1] && !$sectionMark) {
05607                         $sectionMark = trim($link_params_parts[1]);
05608                         $sectionMark = (t3lib_div::testInt($sectionMark) ? '#c' : '#') . $sectionMark;
05609                     }
05610 
05611                     if (count($pairParts) > 1) {
05612                         $theTypeP = isset($pairParts[1]) ? $pairParts[1] : 0; // Overruling 'type'
05613                         $conf['additionalParams'] .= isset($pairParts[2]) ? $pairParts[2] : '';
05614                     }
05615                         // Checking if the id-parameter is an alias.
05616                     if (!t3lib_div::testInt($link_param)) {
05617                         $link_param = $GLOBALS['TSFE']->sys_page->getPageIdFromAlias($link_param);
05618                     }
05619 
05620                         // Link to page even if access is missing?
05621                     if (strlen($conf['linkAccessRestrictedPages'])) {
05622                         $disableGroupAccessCheck = ($conf['linkAccessRestrictedPages'] ? TRUE : FALSE);
05623                     } else {
05624                         $disableGroupAccessCheck = ($GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages'] ? TRUE : FALSE);
05625                     }
05626 
05627                         // Looking up the page record to verify its existence:
05628                     $page = $GLOBALS['TSFE']->sys_page->getPage($link_param, $disableGroupAccessCheck);
05629 
05630                     if (count($page)) {
05631                             // MointPoints, look for closest MPvar:
05632                         $MPvarAcc = array();
05633                         if (!$GLOBALS['TSFE']->config['config']['MP_disableTypolinkClosestMPvalue']) {
05634                             $temp_MP = $this->getClosestMPvalueForPage($page['uid'], TRUE);
05635                             if ($temp_MP)
05636                                 $MPvarAcc['closest'] = $temp_MP;
05637                         }
05638                             // Look for overlay Mount Point:
05639                         $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($page['uid'], $page);
05640                         if (is_array($mount_info) && $mount_info['overlay']) {
05641                             $page = $GLOBALS['TSFE']->sys_page->getPage($mount_info['mount_pid'], $disableGroupAccessCheck);
05642                             if (!count($page)) {
05643                                 $GLOBALS['TT']->setTSlogMessage(
05644                                     "typolink(): Mount point '" . $mount_info['mount_pid'] . "' was not available, so '" .
05645                                     $linktxt . "' was not linked.", 1
05646                                 );
05647                                 return $linktxt;
05648                             }
05649                             $MPvarAcc['re-map'] = $mount_info['MPvar'];
05650                         }
05651 
05652                             // Setting title if blank value to link:
05653                         if ($linktxt == '')
05654                             $linktxt = $page['title'];
05655 
05656                             // Query Params:
05657                         $addQueryParams = $conf['addQueryString'] ? $this->getQueryArguments($conf['addQueryString.']) : '';
05658                         $addQueryParams .= isset($conf['additionalParams.'])
05659                             ? trim($this->stdWrap($conf['additionalParams'], $conf['additionalParams.']))
05660                             : trim($conf['additionalParams']);
05661                         if ($addQueryParams == '&' || substr($addQueryParams, 0, 1) != '&') {
05662                             $addQueryParams = '';
05663                         }
05664                         if ($conf['useCacheHash']) {
05665                                 // Mind the order below! See http://bugs.typo3.org/view.php?id=5117
05666                             $params = $GLOBALS['TSFE']->linkVars . $addQueryParams;
05667                             if (trim($params, '& ') != '') {
05668                                 $addQueryParams .= '&cHash=' . t3lib_div::generateCHash($params);
05669                             }
05670                             unset($params);
05671                         }
05672 
05673                         $targetDomain = '';
05674                         $currentDomain = t3lib_div::getIndpEnv('HTTP_HOST');
05675                             // Mount pages are always local and never link to another domain
05676                         if (count($MPvarAcc)) {
05677                                 // Add "&MP" var:
05678                             $addQueryParams .= '&MP=' . rawurlencode(implode(',', $MPvarAcc));
05679                         } elseif (strpos($addQueryParams, '&MP=') === FALSE && $GLOBALS['TSFE']->config['config']['typolinkCheckRootline']) {
05680 
05681                                 // We do not come here if additionalParams had '&MP='. This happens when typoLink is called from
05682                                 // menu. Mount points always work in the content of the current domain and we must not change
05683                                 // domain if MP variables exist.
05684 
05685 
05686                                 // If we link across domains and page is free type shortcut, we must resolve the shortcut first!
05687                                 // If we do not do it, TYPO3 will fail to (1) link proper page in RealURL/CoolURI because
05688                                 // they return relative links and (2) show proper page if no RealURL/CoolURI exists when link is clicked
05689                             if ($enableLinksAcrossDomains && $page['doktype'] == t3lib_pageSelect::DOKTYPE_SHORTCUT && $page['shortcut_mode'] == t3lib_pageSelect::SHORTCUT_MODE_NONE) {
05690                                 $page2 = $page; // Save in case of broken destination or endless loop
05691                                 $maxLoopCount = 20; // Same as in RealURL, seems enough
05692                                 while ($maxLoopCount && is_array($page) && $page['doktype'] == t3lib_pageSelect::DOKTYPE_SHORTCUT && $page['shortcut_mode'] == t3lib_pageSelect::SHORTCUT_MODE_NONE) {
05693                                     $page = $GLOBALS['TSFE']->sys_page->getPage($page['shortcut'], $disableGroupAccessCheck);
05694                                     $maxLoopCount--;
05695                                 }
05696                                 if (count($page) == 0 || $maxLoopCount == 0) {
05697                                         // We revert if shortcut is broken or maximum number of loops is exceeded (indicates endless loop)
05698                                     $page = $page2;
05699                                 }
05700                             }
05701 
05702                                 // Find all domain records in the rootline of the target page
05703                             $targetPageRootline = $GLOBALS['TSFE']->sys_page->getRootLine($page['uid']);
05704                             $foundDomains = array();
05705                             $firstFoundDomains = array();
05706                             $firstFoundForcedDomains = array();
05707                             $targetPageRootlinePids = array();
05708                             foreach ($targetPageRootline as $data) {
05709                                 $targetPageRootlinePids[] = intval($data['uid']);
05710                             }
05711                             $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
05712                                 'pid, domainName, forced',
05713                                 'sys_domain',
05714                                 'pid IN (' . implode(',', $targetPageRootlinePids) . ') ' . ' AND redirectTo=\'\' ' . $this->enableFields('sys_domain'),
05715                                 '',
05716                                 'sorting ASC'
05717                             );
05718                                 // TODO maybe it makes sense to hold all sys_domain records in a cache to save additional DB querys on each typolink
05719                             while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
05720                                 $foundDomains[] = preg_replace('/\/$/', '', $row['domainName']);
05721                                 if (!isset($firstFoundDomains[$row['pid']])) {
05722                                     $firstFoundDomains[$row['pid']] = preg_replace('/\/$/', '', $row['domainName']);
05723                                 }
05724                                 if ($row['forced'] && !isset($firstFoundForcedDomains[$row['pid']])) {
05725                                     $firstFoundForcedDomains[$row['pid']] = preg_replace('/\/$/', '', $row['domainName']);
05726                                 }
05727                             }
05728                             $GLOBALS['TYPO3_DB']->sql_free_result($res);
05729 
05730                                 // Set targetDomain to first found domain record if the target page cannot be reached within the current domain
05731                             if (count($foundDomains) > 0 && (!in_array($currentDomain, $foundDomains) || count($firstFoundForcedDomains) > 0)) {
05732                                 foreach ($targetPageRootlinePids as $pid) {
05733                                         // Always use the 'forced' domain if we found one
05734                                     if (isset($firstFoundForcedDomains[$pid])) {
05735                                         $targetDomain = $firstFoundForcedDomains[$pid];
05736                                         break;
05737                                     }
05738                                         // Use the first found domain record
05739                                     if ($targetDomain === '' && isset($firstFoundDomains[$pid])) {
05740                                         $targetDomain = $firstFoundDomains[$pid];
05741                                     }
05742                                 }
05743                                     // Do not prepend the domain if its the current hostname
05744                                 if ($targetDomain === $currentDomain) {
05745                                     $targetDomain = '';
05746                                 }
05747                             }
05748                         }
05749 
05750                         $absoluteUrlScheme = 'http';
05751                             // URL shall be absolute:
05752                         if (isset($conf['forceAbsoluteUrl']) && $conf['forceAbsoluteUrl'] || $page['url_scheme'] > 0) {
05753                                 // Override scheme:
05754                             if (isset($conf['forceAbsoluteUrl.']['scheme']) && $conf['forceAbsoluteUrl.']['scheme']) {
05755                                 $absoluteUrlScheme = $conf['forceAbsoluteUrl.']['scheme'];
05756                             } elseif ($page['url_scheme'] > 0) {
05757                                 $absoluteUrlScheme = ((int) $page['url_scheme'] === t3lib_utility_http::SCHEME_HTTP) ? 'http' : 'https';
05758                             }
05759 
05760                                 // If no domain records are defined, use current domain:
05761                             if ($targetDomain === '' && $conf['forceAbsoluteUrl'] ||
05762                                     $absoluteUrlScheme !== parse_url(t3lib_div::getIndpEnv('TYPO3_REQUEST_URL'), PHP_URL_SCHEME)) {
05763                                 $targetDomain = $currentDomain;
05764                             }
05765                         }
05766 
05767                             // If target page has a different domain and the current domain's linking scheme (e.g. simulateStaticDocuments/RealURL/...) should not be used
05768                         if (strlen($targetDomain) && $targetDomain !== $currentDomain && !$enableLinksAcrossDomains) {
05769                             $target = isset($conf['extTarget']) ? $conf['extTarget'] : $GLOBALS['TSFE']->extTarget;
05770                             if ($conf['extTarget.']) {
05771                                 $target = $this->stdWrap($target, $conf['extTarget.']);
05772                             }
05773                             if ($forceTarget) {
05774                                 $target = $forceTarget;
05775                             }
05776                             $LD['target'] = $target;
05777                             $this->lastTypoLinkUrl = $this->URLqMark(
05778                                 $absoluteUrlScheme . '://' . $targetDomain . '/index.php?id=' . $page['uid'], $addQueryParams
05779                             ) . $sectionMark;
05780                         } else { // Internal link or current domain's linking scheme should be used
05781                             if ($forceTarget) {
05782                                 $target = $forceTarget;
05783                             }
05784                             $LD = $GLOBALS['TSFE']->tmpl->linkData(
05785                                 $page,
05786                                 $target,
05787                                 $conf['no_cache'],
05788                                 '',
05789                                 '',
05790                                 $addQueryParams,
05791                                 $theTypeP,
05792                                 $targetDomain
05793                             );
05794                             if (strlen($targetDomain)) {
05795                                     // We will add domain only if URL does not have it already.
05796 
05797 
05798                                     if ($enableLinksAcrossDomains) {
05799                                         // Get rid of the absRefPrefix if necessary. absRefPrefix is applicable only
05800                                         // to the current web site. If we have domain here it means we link across
05801                                         // domains. absRefPrefix can contain domain name, which will screw up
05802                                         // the link to the external domain.
05803                                     $prefixLength = strlen($GLOBALS['TSFE']->config['config']['absRefPrefix']);
05804                                     if (substr($LD['totalURL'], 0, $prefixLength) == $GLOBALS['TSFE']->config['config']['absRefPrefix']) {
05805                                         $LD['totalURL'] = substr($LD['totalURL'], $prefixLength);
05806                                     }
05807                                 }
05808                                 $urlParts = parse_url($LD['totalURL']);
05809                                 if ($urlParts['host'] == '') {
05810                                     $LD['totalURL'] = $absoluteUrlScheme . '://' . $targetDomain .
05811                                         ($LD['totalURL']{0} == '/' ? '' : '/') . $LD['totalURL'];
05812                                 }
05813                             }
05814                             $this->lastTypoLinkUrl = $this->URLqMark($LD['totalURL'], '') . $sectionMark;
05815                         }
05816 
05817                         $this->lastTypoLinkTarget = $LD['target'];
05818                         $targetPart = $LD['target'] ? ' target="' . $LD['target'] . '"' : '';
05819 
05820                             // If sectionMark is set, there is no baseURL AND the current page is the page the link is to, check if there are any additional parameters or addQueryString parameters and if not, drop the url.
05821                         if ($sectionMark && !$GLOBALS['TSFE']->config['config']['baseURL']
05822                             && $page['uid'] == $GLOBALS['TSFE']->id && !trim($addQueryParams)
05823                             && !($conf['addQueryString'] && $conf['addQueryString.'])) {
05824 
05825                             list (, $URLparams) = explode('?', $this->lastTypoLinkUrl);
05826                             list ($URLparams) = explode('#', $URLparams);
05827                             parse_str($URLparams . $LD['orig_type'], $URLparamsArray);
05828                             if (intval($URLparamsArray['type']) == $GLOBALS['TSFE']->type) { // type nums must match as well as page ids
05829                                 unset($URLparamsArray['id']);
05830                                 unset($URLparamsArray['type']);
05831                                 if (!count($URLparamsArray)) { // If there are no parameters left.... set the new url.
05832                                     $this->lastTypoLinkUrl = $sectionMark;
05833                                 }
05834                             }
05835                         }
05836 
05837                             // If link is to a access restricted page which should be redirected, then find new URL:
05838                         if ($GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages']
05839                             && $GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages'] !== 'NONE'
05840                             && !$GLOBALS['TSFE']->checkPageGroupAccess($page)) {
05841 
05842                             $thePage = $GLOBALS['TSFE']->sys_page->getPage($GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages']);
05843 
05844                             $addParams = $GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages_addParams'];
05845                             $addParams = str_replace('###RETURN_URL###', rawurlencode($this->lastTypoLinkUrl), $addParams);
05846                             $addParams = str_replace('###PAGE_ID###', $page['uid'], $addParams);
05847                             $this->lastTypoLinkUrl = $this->getTypoLink_URL(
05848                                 $thePage['uid'] . ($theTypeP ? ',' . $theTypeP : ''),
05849                                 $addParams,
05850                                 $target
05851                             );
05852                             $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf);
05853                             $this->lastTypoLinkLD['totalUrl'] = $this->lastTypoLinkUrl;
05854                             $LD = $this->lastTypoLinkLD;
05855                         }
05856 
05857                             // Rendering the tag.
05858                         $finalTagParts['url'] = $this->lastTypoLinkUrl;
05859                         $finalTagParts['targetParams'] = $targetPart;
05860                         $finalTagParts['TYPE'] = 'page';
05861                     } else {
05862                         $GLOBALS['TT']->setTSlogMessage(
05863                             "typolink(): Page id '" . $link_param . "' was not found, so '" . $linktxt . "' was not linked.", 1
05864                         );
05865                         return $linktxt;
05866                     }
05867                 }
05868             }
05869 
05870             $this->lastTypoLinkLD = $LD;
05871 
05872             if ($forceTitle) {
05873                 $title = $forceTitle;
05874             }
05875 
05876             if ($JSwindowParams) {
05877 
05878                     // Create TARGET-attribute only if the right doctype is used
05879                 if (!t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype)) {
05880                     $target = ' target="FEopenLink"';
05881                 } else {
05882                     $target = '';
05883                 }
05884 
05885                 $onClick = "vHWin=window.open('" . $GLOBALS['TSFE']->baseUrlWrap($finalTagParts['url']) .
05886                     "','FEopenLink','" . $JSwindowParams . "');vHWin.focus();return false;";
05887                 $res = '<a href="' . htmlspecialchars($finalTagParts['url']) . '"' .
05888                     $target . ' onclick="' . htmlspecialchars($onClick) . '"' .
05889                     ($title ? ' title="' . $title . '"' : '') .
05890                     ($linkClass ? ' class="' . $linkClass . '"' : '') .
05891                     $finalTagParts['aTagParams'] . '>';
05892             } else {
05893                 if ($GLOBALS['TSFE']->spamProtectEmailAddresses === 'ascii' && $finalTagParts['TYPE'] === 'mailto') {
05894                     $res = '<a href="' . $finalTagParts['url'] . '"' .
05895                         ($title ? ' title="' . $title . '"' : '') .
05896                         $finalTagParts['targetParams'] .
05897                         ($linkClass ? ' class="' . $linkClass . '"' : '') .
05898                         $finalTagParts['aTagParams'] . '>';
05899                 } else {
05900                     $res = '<a href="' . htmlspecialchars($finalTagParts['url']) . '"' .
05901                         ($title ? ' title="' . $title . '"' : '') .
05902                         $finalTagParts['targetParams'] .
05903                         ($linkClass ? ' class="' . $linkClass . '"' : '') .
05904                         $finalTagParts['aTagParams'] . '>';
05905                 }
05906             }
05907 
05908                 // Call user function:
05909             if ($conf['userFunc']) {
05910                 $finalTagParts['TAG'] = $res;
05911                 $res = $this->callUserFunction($conf['userFunc'], $conf['userFunc.'], $finalTagParts);
05912             }
05913 
05914                 // Hook: Call post processing function for link rendering:
05915             if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'])
05916                 && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'])) {
05917 
05918                 $_params = array(
05919                     'conf' => &$conf,
05920                     'linktxt' => &$linktxt,
05921                     'finalTag' => &$res,
05922                     'finalTagParts' => &$finalTagParts
05923                 );
05924                 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'] as $_funcRef) {
05925                     t3lib_div::callUserFunction($_funcRef, $_params, $this);
05926                 }
05927             }
05928 
05929                 // If flag "returnLastTypoLinkUrl" set, then just return the latest URL made:
05930             if ($conf['returnLast']) {
05931                 switch ($conf['returnLast']) {
05932                     case 'url' :
05933                         return $this->lastTypoLinkUrl;
05934                     break;
05935                     case 'target' :
05936                         return $this->lastTypoLinkTarget;
05937                     break;
05938                 }
05939             }
05940 
05941             $wrap = isset($conf['wrap.'])
05942                 ? $this->stdWrap($conf['wrap'], $conf['wrap.'])
05943                 : $conf['wrap'];
05944             if ($conf['ATagBeforeWrap']) {
05945                 return $res . $this->wrap($linktxt, $wrap) . '</a>';
05946             } else {
05947                 return $this->wrap($res . $linktxt . '</a>', $wrap);
05948             }
05949         } else {
05950             return $linktxt;
05951         }
05952     }
05953 
05954     /**
05955      * Forces a given URL to be absolute.
05956      *
05957      * @param string $url The URL to be forced to be absolute
05958      * @param array $configuration TypoScript configuration of typolink
05959      * @return string The absolute URL
05960      */
05961     protected function forceAbsoluteUrl($url, array $configuration) {
05962         if (!empty($url) && isset($configuration['forceAbsoluteUrl']) && $configuration['forceAbsoluteUrl']) {
05963             if (preg_match('#^(?:([a-z]+)(://))?([^/]*)(.*)$#', $url, $matches)) {
05964                 $urlParts = array(
05965                     'scheme' => $matches[1],
05966                     'delimiter' => '://',
05967                     'host' => $matches[3],
05968                     'path' => $matches[4]
05969                 );
05970 
05971                     // Set scheme and host if not yet part of the URL:
05972                 if (empty($urlParts['host'])) {
05973                     $urlParts['scheme'] = 'http';
05974                     $urlParts['host'] = t3lib_div::getIndpEnv('HTTP_HOST');
05975                     $isUrlModified = TRUE;
05976                 }
05977 
05978                     // Override scheme:
05979                 $forceAbsoluteUrl = & $configuration['forceAbsoluteUrl.']['scheme'];
05980                 if (!empty($forceAbsoluteUrl) && $urlParts['scheme'] !== $forceAbsoluteUrl) {
05981                     $urlParts['scheme'] = $forceAbsoluteUrl;
05982                     $isUrlModified = TRUE;
05983                 }
05984 
05985                     // Recreate the absolute URL:
05986                 if ($isUrlModified) {
05987                     $url = implode('', $urlParts);
05988                 }
05989             }
05990         }
05991 
05992         return $url;
05993     }
05994 
05995     /**
05996      * Based on the input "TypoLink" TypoScript configuration this will return the generated URL
05997      *
05998      * @param   array       TypoScript properties for "typolink"
05999      * @return  string      The URL of the link-tag that typolink() would by itself return
06000      * @see typoLink()
06001      */
06002     function typoLink_URL($conf) {
06003         $this->typolink('|', $conf);
06004         return $this->lastTypoLinkUrl;
06005     }
06006 
06007     /**
06008      * Returns a linked string made from typoLink parameters.
06009      *
06010      * This function takes $label as a string, wraps it in a link-tag based on the $params string, which should contain data like that you would normally pass to the popular <LINK>-tag in the TSFE.
06011      * Optionally you can supply $urlParameters which is an array with key/value pairs that are rawurlencoded and appended to the resulting url.
06012      *
06013      * @param   string      Text string being wrapped by the link.
06014      * @param   string      Link parameter; eg. "123" for page id, "kasperYYYY@typo3.com" for email address, "http://...." for URL, "fileadmin/blabla.txt" for file.
06015      * @param   array       An array with key/value pairs representing URL parameters to set. Values NOT URL-encoded yet.
06016      * @param   string      Specific target set, if any. (Default is using the current)
06017      * @return  string      The wrapped $label-text string
06018      * @see getTypoLink_URL()
06019      */
06020     function getTypoLink($label, $params, $urlParameters = array(), $target = '') {
06021         $conf = array();
06022         $conf['parameter'] = $params;
06023         if ($target) {
06024             $conf['target'] = $target;
06025             $conf['extTarget'] = $target;
06026             $conf['fileTarget'] = $target;
06027         }
06028         if (is_array($urlParameters)) {
06029             if (count($urlParameters)) {
06030                 $conf['additionalParams'] .= t3lib_div::implodeArrayForUrl('', $urlParameters);
06031             }
06032         } else {
06033             $conf['additionalParams'] .= $urlParameters;
06034         }
06035         $out = $this->typolink($label, $conf);
06036         return $out;
06037     }
06038 
06039     /**
06040      * Returns the URL of a "typolink" create from the input parameter string, url-parameters and target
06041      *
06042      * @param   string      Link parameter; eg. "123" for page id, "kasperYYYY@typo3.com" for email address, "http://...." for URL, "fileadmin/blabla.txt" for file.
06043      * @param   array       An array with key/value pairs representing URL parameters to set. Values NOT URL-encoded yet.
06044      * @param   string      Specific target set, if any. (Default is using the current)
06045      * @return  string      The URL
06046      * @see getTypoLink()
06047      */
06048     function getTypoLink_URL($params, $urlParameters = array(), $target = '') {
06049         $this->getTypoLink('', $params, $urlParameters, $target);
06050         return $this->lastTypoLinkUrl;
06051     }
06052 
06053     /**
06054      * Generates a typolink and returns the two link tags - start and stop - in an array
06055      *
06056      * @param   array       "typolink" TypoScript properties
06057      * @return  array       An array with two values in key 0+1, each value being the start and close <a>-tag of the typolink properties being inputted in $conf
06058      * @see typolink()
06059      */
06060     function typolinkWrap($conf) {
06061         $k = md5(microtime());
06062         return explode($k, $this->typolink($k, $conf));
06063     }
06064 
06065     /**
06066      * Returns the current page URL
06067      *
06068      * @param   array       Optionally you can specify additional URL parameters. An array with key/value pairs representing URL parameters to set. Values NOT URL-encoded yet.
06069      * @param   integer     An alternative ID to the current id ($GLOBALS['TSFE']->id)
06070      * @return  string      The URL
06071      * @see getTypoLink_URL()
06072      */
06073     function currentPageUrl($urlParameters = array(), $id = 0) {
06074         return $this->getTypoLink_URL($id ? $id : $GLOBALS['TSFE']->id, $urlParameters, $GLOBALS['TSFE']->sPre);
06075     }
06076 
06077     /**
06078      * Returns the &MP variable value for a page id.
06079      * The function will do its best to find a MP value that will keep the page id inside the current Mount Point rootline if any.
06080      *
06081      * @param   integer     page id
06082      * @param   boolean     If TRUE, the MPvalue is returned raw. Normally it is encoded as &MP=... variable
06083      * @return  string      MP value, prefixed with &MP= (depending on $raw)
06084      * @see typolink()
06085      */
06086     function getClosestMPvalueForPage($pageId, $raw = FALSE) {
06087             // MointPoints:
06088         if ($GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids'] && $GLOBALS['TSFE']->MP) {
06089 
06090             if (!strcmp($GLOBALS['TSFE']->id, $pageId)) { // same page as current.
06091                 $MP = $GLOBALS['TSFE']->MP;
06092             } else { // ... otherwise find closest meeting point:
06093                 $tCR_rootline = $GLOBALS['TSFE']->sys_page->getRootLine($pageId, '', TRUE); // Gets rootline of linked-to page
06094                 $inverseTmplRootline = array_reverse($GLOBALS['TSFE']->tmpl->rootLine);
06095 
06096                 $rl_mpArray = array();
06097                 $startMPaccu = FALSE;
06098 
06099                     // Traverse root line of link uid and inside of that the REAL root line of current position.
06100                 foreach ($tCR_rootline as $tCR_data) {
06101                     foreach ($inverseTmplRootline as $rlKey => $invTmplRLRec) {
06102 
06103                             // Force accumulating when in overlay mode: Links to this page have to stay within the current branch
06104                         if ($invTmplRLRec['_MOUNT_OL'] && ($tCR_data['uid'] == $invTmplRLRec['uid'])) {
06105                             $startMPaccu = TRUE;
06106                         }
06107 
06108                             // Accumulate MP data:
06109                         if ($startMPaccu && $invTmplRLRec['_MP_PARAM']) {
06110                             $rl_mpArray[] = $invTmplRLRec['_MP_PARAM'];
06111                         }
06112 
06113                             // If two PIDs matches and this is NOT the site root, start accumulation of MP data (on the next level):
06114                             // (The check for site root is done so links to branches outsite the site but sharing the site roots PID
06115                             // is NOT detected as within the branch!)
06116                         if ($tCR_data['pid'] == $invTmplRLRec['pid'] && count($inverseTmplRootline) != $rlKey + 1) {
06117                             $startMPaccu = TRUE;
06118                         }
06119                     }
06120                     if ($startMPaccu)
06121                         break; // Good enough...
06122                 }
06123 
06124                 if (count($rl_mpArray)) {
06125                     $MP = implode(',', array_reverse($rl_mpArray));
06126                 }
06127             }
06128         }
06129 
06130         return !$raw ? ($MP ? '&MP=' . rawurlencode($MP) : '') : $MP;
06131     }
06132 
06133     /**
06134      * Creates a href attibute for given $mailAddress.
06135      * The function uses spamProtectEmailAddresses and Jumpurl functionality for encoding the mailto statement.
06136      * If spamProtectEmailAddresses is disabled, it'll just return a string like "mailto:user@example.tld".
06137      *
06138      * @param   string      Email address
06139      * @param   string      Link text, default will be the email address.
06140      * @param   string      Initial link parameters, only used if Jumpurl functionality is enabled. Example: ?id=5&type=0
06141      * @return  string      Returns a numerical array with two elements: 1) $mailToUrl, string ready to be inserted into the href attribute of the <a> tag, b) $linktxt: The string between starting and ending <a> tag.
06142      */
06143     function getMailTo($mailAddress, $linktxt, $initP = '?') {
06144         if (!strcmp($linktxt, '')) {
06145             $linktxt = $mailAddress;
06146         }
06147 
06148         $mailToUrl = 'mailto:' . $mailAddress;
06149 
06150         if (!$GLOBALS['TSFE']->config['config']['jumpurl_enable'] || $GLOBALS['TSFE']->config['config']['jumpurl_mailto_disable']) {
06151             if ($GLOBALS['TSFE']->spamProtectEmailAddresses) {
06152                 if ($GLOBALS['TSFE']->spamProtectEmailAddresses === 'ascii') {
06153                     $mailToUrl = $GLOBALS['TSFE']->encryptEmail($mailToUrl);
06154                 } else {
06155                     $mailToUrl = "javascript:linkTo_UnCryptMailto('" . $GLOBALS['TSFE']->encryptEmail($mailToUrl) . "');";
06156                 }
06157                 if ($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_atSubst']) {
06158                     $atLabel = trim($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_atSubst']);
06159                 }
06160                 $spamProtectedMailAddress = str_replace('@', ($atLabel ? $atLabel : '(at)'), $mailAddress);
06161 
06162                 if ($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_lastDotSubst']) {
06163                     $lastDotLabel = trim($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_lastDotSubst']);
06164                     $lastDotLabel = $lastDotLabel ? $lastDotLabel : '(dot)';
06165                     $spamProtectedMailAddress = preg_replace('/\.([^\.]+)$/', $lastDotLabel . '$1', $spamProtectedMailAddress);
06166                 }
06167                 $linktxt = str_ireplace($mailAddress, $spamProtectedMailAddress, $linktxt);
06168             }
06169         } else {
06170             $mailToUrl = $GLOBALS['TSFE']->absRefPrefix . $GLOBALS['TSFE']->config['mainScript'] .
06171                 $initP . '&jumpurl=' . rawurlencode($mailToUrl) . $GLOBALS['TSFE']->getMethodUrlIdToken;
06172         }
06173         return array(
06174             $mailToUrl, $linktxt
06175         );
06176     }
06177 
06178     /**
06179      * Gets the query arguments and assembles them for URLs.
06180      * Arguments may be removed or set, depending on configuration.
06181      *
06182      * @param   string      Configuration
06183      * @param   array       Multidimensional key/value pairs that overrule incoming query arguments
06184      * @param   boolean     If set, key/value pairs not in the query but the overrule array will be set
06185      * @return  string      The URL query part (starting with a &)
06186      */
06187     public function getQueryArguments($conf, $overruleQueryArguments = array(), $forceOverruleArguments = FALSE) {
06188         switch ((string) $conf['method']) {
06189             case 'GET' :
06190                 $currentQueryArray = t3lib_div::_GET();
06191             break;
06192             case 'POST' :
06193                 $currentQueryArray = t3lib_div::_POST();
06194             break;
06195             case 'GET,POST' :
06196                 $currentQueryArray = array_merge(t3lib_div::_GET(), t3lib_div::_POST());
06197             break;
06198             case 'POST,GET' :
06199                 $currentQueryArray = array_merge(t3lib_div::_POST(), t3lib_div::_GET());
06200             break;
06201             default :
06202                 $currentQueryArray = t3lib_div::explodeUrl2Array(t3lib_div::getIndpEnv('QUERY_STRING'), TRUE);
06203         }
06204 
06205         if ($conf['exclude']) {
06206             $exclude = str_replace(',', '&', $conf['exclude']);
06207             $exclude = t3lib_div::explodeUrl2Array($exclude, TRUE);
06208                 // never repeat id
06209             $exclude['id'] = 0;
06210             $newQueryArray = t3lib_div::arrayDiffAssocRecursive($currentQueryArray, $exclude);
06211         } else {
06212             $newQueryArray = $currentQueryArray;
06213         }
06214 
06215         if ($forceOverruleArguments) {
06216             $newQueryArray = t3lib_div::array_merge_recursive_overrule($newQueryArray, $overruleQueryArguments);
06217         } else {
06218             $newQueryArray = t3lib_div::array_merge_recursive_overrule($newQueryArray, $overruleQueryArguments, TRUE);
06219         }
06220 
06221         return t3lib_div::implodeArrayForUrl('', $newQueryArray);
06222     }
06223 
06224 
06225 
06226     /***********************************************
06227      *
06228      * Miscellaneous functions, stand alone
06229      *
06230      ***********************************************/
06231 
06232     /**
06233      * Wrapping a string.
06234      * Implements the TypoScript "wrap" property.
06235      * Example: $content = "HELLO WORLD" and $wrap = "<strong> | </strong>", result: "<strong>HELLO WORLD</strong>"
06236      *
06237      * @param   string      The content to wrap
06238      * @param   string      The wrap value, eg. "<strong> | </strong>"
06239      * @param   string      The char used to split the wrapping value, default is "|"
06240      * @return  string      Wrapped input string
06241      * @see noTrimWrap()
06242      */
06243     function wrap($content, $wrap, $char = '|') {
06244         if ($wrap) {
06245             $wrapArr = explode($char, $wrap);
06246             return trim($wrapArr[0]) . $content . trim($wrapArr[1]);
06247         } else
06248             return $content;
06249     }
06250 
06251     /**
06252      * Wrapping a string, preserving whitespace in wrap value.
06253      * Notice that the wrap value uses part 1/2 to wrap (and not 0/1 which wrap() does)
06254      *
06255      * @param   string      The content to wrap, eg. "HELLO WORLD"
06256      * @param   string      The wrap value, eg. " | <strong> | </strong>"
06257      * @return  string      Wrapped input string, eg. " <strong> HELLO WORD </strong>"
06258      * @see wrap()
06259      */
06260     function noTrimWrap($content, $wrap) {
06261         if ($wrap) {
06262             $wrapArr = explode('|', $wrap);
06263             return $wrapArr[1] . $content . $wrapArr[2];
06264         } else
06265             return $content;
06266     }
06267 
06268     /**
06269      * Adds space above/below the input HTML string. It is done by adding a clear-gif and <br /> tag before and/or after the content.
06270      *
06271      * @param   string      The content to add space above/below to.
06272      * @param   string      A value like "10 | 20" where the first part denotes the space BEFORE and the second part denotes the space AFTER (in pixels)
06273      * @param   array       Configuration from TypoScript
06274      * @return  string      Wrapped string
06275      */
06276     function wrapSpace($content, $wrap, array $conf = NULL) {
06277         if (trim($wrap)) {
06278             $wrapArray = explode('|', $wrap);
06279             $wrapBefore = intval($wrapArray[0]);
06280             $wrapAfter = intval($wrapArray[1]);
06281             $useDivTag = (isset($conf['useDiv']) && $conf['useDiv']);
06282             if ($wrapBefore) {
06283                 if ($useDivTag) {
06284                     $content = '<div class="content-spacer spacer-before" style="height:' . $wrapBefore . 'px;"></div>' . $content;
06285                 } else {
06286                     $content = '<img src="' . $GLOBALS['TSFE']->absRefPrefix .
06287                         'clear.gif" width="1" height="' . $wrapBefore . '"' .
06288                     $this->getBorderAttr(' border="0"') . ' class="spacer-gif" alt="" title="" /><br />' . $content;
06289                 }
06290             }
06291             if ($wrapAfter) {
06292                 if ($useDivTag) {
06293                     $content .= '<div class="content-spacer spacer-after" style="height:' . $wrapAfter . 'px;"></div>';
06294                 } else {
06295                     $content .= '<img src="' . $GLOBALS['TSFE']->absRefPrefix .
06296                         'clear.gif" width="1" height="' . $wrapAfter . '"' .
06297                     $this->getBorderAttr(' border="0"') . ' class="spacer-gif" alt="" title="" /><br />';
06298                 }
06299             }
06300         }
06301         return $content;
06302     }
06303 
06304     /**
06305      * Calling a user function/class-method
06306      * Notice: For classes the instantiated object will have the internal variable, $cObj, set to be a *reference* to $this (the parent/calling object).
06307      *
06308      * @param   string      The functionname, eg "user_myfunction" or "user_myclass->main". Notice that there are rules for the names of functions/classes you can instantiate. If a function cannot be called for some reason it will be seen in the TypoScript log in the AdminPanel.
06309      * @param   array       The TypoScript configuration to pass the function
06310      * @param   string      The content string to pass the function
06311      * @return  string      The return content from the function call. Should probably be a string.
06312      * @see USER(), stdWrap(), typoLink(), _parseFunc()
06313      */
06314     function callUserFunction($funcName, $conf, $content) {
06315         $pre = $GLOBALS['TSFE']->TYPO3_CONF_VARS['FE']['userFuncClassPrefix'];
06316         if ($pre && !t3lib_div::isFirstPartOfStr(trim($funcName), $pre) && !t3lib_div::isFirstPartOfStr(trim($funcName), 'tx_')) {
06317             $GLOBALS['TT']->setTSlogMessage('Function "' . $funcName . '" was not prepended with "' . $pre . '"', 3);
06318             return $content;
06319         }
06320             // Split parts
06321         $parts = explode('->', $funcName);
06322         if (count($parts) == 2) { // Class
06323             // Check whether class is available and try to reload includeLibs if possible:
06324             if ($this->isClassAvailable($parts[0], $conf)) {
06325                 $classObj = t3lib_div::makeInstance($parts[0]);
06326                 if (is_object($classObj) && method_exists($classObj, $parts[1])) {
06327                     $classObj->cObj = $this;
06328                     $content = call_user_func_array(array(
06329                         $classObj, $parts[1]
06330                     ), array(
06331                         $content, $conf
06332                     ));
06333                 } else {
06334                     $GLOBALS['TT']->setTSlogMessage('Method "' . $parts[1] . '" did not exist in class "' . $parts[0] . '"', 3);
06335                 }
06336             } else {
06337                 $GLOBALS['TT']->setTSlogMessage('Class "' . $parts[0] . '" did not exist', 3);
06338             }
06339         } else { // Function
06340             if (function_exists($funcName)) {
06341                 $content = call_user_func($funcName, $content, $conf);
06342             } else {
06343                 $GLOBALS['TT']->setTSlogMessage('Function "' . $funcName . '" did not exist', 3);
06344             }
06345         }
06346         return $content;
06347     }
06348 
06349     /**
06350      * Parses a set of text lines with "[parameters] = [values]" into an array with parameters as keys containing the value
06351      * If lines are empty or begins with "/" or "#" then they are ignored.
06352      *
06353      * @param   string      Text which the parameters
06354      * @return  array       array with the parameters as key/value pairs
06355      */
06356     function processParams($params) {
06357         $paramArr = array();
06358         $lines = t3lib_div::trimExplode(LF, $params, 1);
06359         foreach ($lines as $val) {
06360             $pair = explode('=', $val, 2);
06361             if (!t3lib_div::inList('#,/', substr(trim($pair[0]), 0, 1))) {
06362                 $paramArr[trim($pair[0])] = trim($pair[1]);
06363             }
06364         }
06365         return $paramArr;
06366     }
06367 
06368     /**
06369      * Cleans up a string of keywords. Keywords at splitted by "," (comma)  ";" (semi colon) and linebreak
06370      *
06371      * @param   string      String of keywords
06372      * @return  string      Cleaned up string, keywords will be separated by a comma only.
06373      */
06374     function keywords($content) {
06375         $listArr = preg_split('/[,;' . LF . ']/', $content);
06376         foreach ($listArr as $k => $v) {
06377             $listArr[$k] = trim($v);
06378         }
06379         return implode(',', $listArr);
06380     }
06381 
06382     /**
06383      * Changing character case of a string, converting typically used western charset characters as well.
06384      *
06385      * @param   string      The string to change case for.
06386      * @param   string      The direction; either "upper" or "lower"
06387      * @return  string
06388      * @see HTMLcaseshift()
06389      */
06390     function caseshift($theValue, $case) {
06391         $case = strtolower($case);
06392         switch ($case) {
06393             case 'upper' :
06394                 $theValue = $GLOBALS['TSFE']->csConvObj->conv_case($GLOBALS['TSFE']->renderCharset, $theValue, 'toUpper');
06395             break;
06396             case 'lower' :
06397                 $theValue = $GLOBALS['TSFE']->csConvObj->conv_case($GLOBALS['TSFE']->renderCharset, $theValue, 'toLower');
06398             break;
06399         }
06400         return $theValue;
06401     }
06402 
06403     /**
06404      * Shifts the case of characters outside of HTML tags in the input string
06405      *
06406      * @param   string      The string to change case for.
06407      * @param   string      The direction; either "upper" or "lower"
06408      * @return  string
06409      * @see caseshift()
06410      */
06411     function HTMLcaseshift($theValue, $case) {
06412         $inside = 0;
06413         $newVal = '';
06414         $pointer = 0;
06415         $totalLen = strlen($theValue);
06416         do {
06417             if (!$inside) {
06418                 $len = strcspn(substr($theValue, $pointer), '<');
06419                 $newVal .= $this->caseshift(substr($theValue, $pointer, $len), $case);
06420                 $inside = 1;
06421             } else {
06422                 $len = strcspn(substr($theValue, $pointer), '>') + 1;
06423                 $newVal .= substr($theValue, $pointer, $len);
06424                 $inside = 0;
06425             }
06426             $pointer += $len;
06427         } while ($pointer < $totalLen);
06428         return $newVal;
06429     }
06430 
06431     /**
06432      * Returns the 'age' of the tstamp $seconds
06433      *
06434      * @param   integer     Seconds to return age for. Example: "70" => "1 min", "3601" => "1 hrs"
06435      * @param   string      $labels are the labels of the individual units. Defaults to : ' min| hrs| days| yrs'
06436      * @return  string      The formatted string
06437      */
06438     function calcAge($seconds, $labels) {
06439         if (t3lib_div::testInt($labels)) {
06440             $labels = ' min| hrs| days| yrs| min| hour| day| year';
06441         } else {
06442             $labels = str_replace('"', '', $labels);
06443         }
06444 
06445         $labelArr = explode('|', $labels);
06446         if (count($labelArr) == 4) {
06447             $labelArr = array_merge($labelArr, $labelArr);
06448         }
06449         $absSeconds = abs($seconds);
06450         $sign = ($seconds > 0 ? 1 : -1);
06451         if ($absSeconds < 3600) {
06452             $val = round($absSeconds / 60);
06453             $seconds = ($sign * $val) . ($val == 1 ? $labelArr[4] : $labelArr[0]);
06454         } elseif ($absSeconds < 24 * 3600) {
06455             $val = round($absSeconds / 3600);
06456             $seconds = ($sign * $val) . ($val == 1 ? $labelArr[5] : $labelArr[1]);
06457         } elseif ($absSeconds < 365 * 24 * 3600) {
06458             $val = round($absSeconds / (24 * 3600));
06459             $seconds = ($sign * $val) . ($val == 1 ? $labelArr[6] : $labelArr[2]);
06460         } else {
06461             $val = round($absSeconds / (365 * 24 * 3600));
06462             $seconds = ($sign * $val) . ($val == 1 ? $labelArr[7] : $labelArr[3]);
06463         }
06464         return $seconds;
06465     }
06466 
06467     /**
06468      * Sending a notification email using $GLOBALS['TSFE']->plainMailEncoded()
06469      *
06470      * @param   string      The message content. If blank, no email is sent.
06471      * @param   string      Comma list of recipient email addresses
06472      * @param   string      Email address of recipient of an extra mail. The same mail will be sent ONCE more; not using a CC header but sending twice.
06473      * @param   string      "From" email address
06474      * @param   string      Optional "From" name
06475      * @param   string      Optional "Reply-To" header email address.
06476      * @return  boolean     Returns TRUE if sent
06477      */
06478     function sendNotifyEmail($msg, $recipients, $cc, $email_from, $email_fromName = '', $replyTo = '') {
06479             // Sends order emails:
06480         $headers = array();
06481         if ($email_from) {
06482             $headers[] = 'From: ' . $email_fromName . ' <' . $email_from . '>';
06483         }
06484         if ($replyTo) {
06485             $headers[] = 'Reply-To: ' . $replyTo;
06486         }
06487 
06488         $recipients = implode(',', t3lib_div::trimExplode(',', $recipients, 1));
06489 
06490         $emailContent = trim($msg);
06491         if ($emailContent) {
06492             $parts = explode(LF, $emailContent, 2); // First line is subject
06493             $subject = trim($parts[0]);
06494             $plain_message = trim($parts[1]);
06495 
06496             if ($recipients)
06497                 $GLOBALS['TSFE']->plainMailEncoded($recipients, $subject, $plain_message, implode(LF, $headers));
06498             if ($cc)
06499                 $GLOBALS['TSFE']->plainMailEncoded($cc, $subject, $plain_message, implode(LF, $headers));
06500             return TRUE;
06501         }
06502     }
06503 
06504     /**
06505      * Checks if $url has a '?' in it and if not, a '?' is inserted between $url and $params, which are anyway concatenated and returned
06506      *
06507      * @param   string      Input URL
06508      * @param   string      URL parameters
06509      * @return  string
06510      */
06511     function URLqMark($url, $params) {
06512         if ($params && !strstr($url, '?')) {
06513             return $url . '?' . $params;
06514         } else {
06515             return $url . $params;
06516         }
06517     }
06518 
06519     /**
06520      * Clears TypoScript properties listed in $propList from the input TypoScript array.
06521      *
06522      * @param   array       TypoScript array of values/properties
06523      * @param   string      List of properties to clear both value/properties for. Eg. "myprop,another_property"
06524      * @return  array       The TypoScript array
06525      * @see gifBuilderTextBox()
06526      */
06527     function clearTSProperties($TSArr, $propList) {
06528         $list = explode(',', $propList);
06529         foreach ($list as $prop) {
06530             $prop = trim($prop);
06531             unset($TSArr[$prop]);
06532             unset($TSArr[$prop . '.']);
06533         }
06534         return $TSArr;
06535     }
06536 
06537     /**
06538      * Resolves a TypoScript reference value to the full set of properties BUT overridden with any local properties set.
06539      * So the reference is resolved but overlaid with local TypoScript properties of the reference value.
06540      *
06541      * @param   array       The TypoScript array
06542      * @param   string      The property name: If this value is a reference (eg. " < plugins.tx_something") then the reference will be retrieved and inserted at that position (into the properties only, not the value...) AND overlaid with the old properties if any.
06543      * @return  array       The modified TypoScript array
06544      * @see user_plaintext::typolist(),user_plaintext::typohead()
06545      */
06546     function mergeTSRef($confArr, $prop) {
06547         if (substr($confArr[$prop], 0, 1) == '<') {
06548             $key = trim(substr($confArr[$prop], 1));
06549             $cF = t3lib_div::makeInstance('t3lib_TSparser');
06550             // $name and $conf is loaded with the referenced values.
06551             $old_conf = $confArr[$prop . '.'];
06552             list ($name, $conf) = $cF->getVal($key, $GLOBALS['TSFE']->tmpl->setup);
06553             if (is_array($old_conf) && count($old_conf)) {
06554                 $conf = $this->joinTSarrays($conf, $old_conf);
06555             }
06556             $confArr[$prop . '.'] = $conf;
06557         }
06558         return $confArr;
06559     }
06560 
06561     /**
06562      * Merges two TypoScript propery array, overlaing the $old_conf onto the $conf array
06563      *
06564      * @param   array       TypoScript property array, the "base"
06565      * @param   array       TypoScript property array, the "overlay"
06566      * @return  array       The resulting array
06567      * @see mergeTSRef(), tx_tstemplatestyler_modfunc1::joinTSarrays()
06568      */
06569     function joinTSarrays($conf, $old_conf) {
06570         if (is_array($old_conf)) {
06571             foreach ($old_conf as $key => $val) {
06572                 if (is_array($val)) {
06573                     $conf[$key] = $this->joinTSarrays($conf[$key], $val);
06574                 } else {
06575                     $conf[$key] = $val;
06576                 }
06577             }
06578         }
06579         return $conf;
06580     }
06581 
06582     /**
06583      * This function creates a number of TEXT-objects in a Gifbuilder configuration in order to create a text-field like thing. Used with the script tslib/media/scripts/postit.inc
06584      *
06585      * @param   array       TypoScript properties for Gifbuilder - TEXT GIFBUILDER objects are added to this array and returned.
06586      * @param   array       TypoScript properties for this function
06587      * @param   string      The text string to write onto the GIFBUILDER file
06588      * @return  array       The modified $gifbuilderConf array
06589      * @see media/scripts/postit.inc
06590      */
06591     function gifBuilderTextBox($gifbuilderConf, $conf, $text) {
06592         $chars = intval($conf['chars']) ? intval($conf['chars']) : 20;
06593         $lineDist = intval($conf['lineDist']) ? intval($conf['lineDist']) : 20;
06594         $Valign = strtolower(trim($conf['Valign']));
06595         $tmplObjNumber = intval($conf['tmplObjNumber']);
06596         $maxLines = intval($conf['maxLines']);
06597 
06598         if ($tmplObjNumber && $gifbuilderConf[$tmplObjNumber] == 'TEXT') {
06599             $textArr = $this->linebreaks($text, $chars, $maxLines);
06600             $angle = intval($gifbuilderConf[$tmplObjNumber . '.']['angle']);
06601             foreach ($textArr as $c => $textChunk) {
06602                 $index = $tmplObjNumber + 1 + ($c * 2);
06603                     // Workarea
06604                 $gifbuilderConf = $this->clearTSProperties($gifbuilderConf, $index);
06605                 $rad_angle = 2 * pi() / 360 * $angle;
06606                 $x_d = sin($rad_angle) * $lineDist;
06607                 $y_d = cos($rad_angle) * $lineDist;
06608 
06609                 $diff_x_d = 0;
06610                 $diff_y_d = 0;
06611                 if ($Valign == 'center') {
06612                     $diff_x_d = $x_d * count($textArr);
06613                     $diff_x_d = $diff_x_d / 2;
06614                     $diff_y_d = $y_d * count($textArr);
06615                     $diff_y_d = $diff_y_d / 2;
06616                 }
06617 
06618 
06619                 $x_d = round($x_d * $c - $diff_x_d);
06620                 $y_d = round($y_d * $c - $diff_y_d);
06621 
06622                 $gifbuilderConf[$index] = 'WORKAREA';
06623                 $gifbuilderConf[$index . '.']['set'] = $x_d . ',' . $y_d;
06624                     // Text
06625                 $index++;
06626                 $gifbuilderConf = $this->clearTSProperties($gifbuilderConf, $index);
06627                 $gifbuilderConf[$index] = 'TEXT';
06628                 $gifbuilderConf[$index . '.'] = $this->clearTSProperties($gifbuilderConf[$tmplObjNumber . '.'], 'text');
06629                 $gifbuilderConf[$index . '.']['text'] = $textChunk;
06630             }
06631             $gifbuilderConf = $this->clearTSProperties($gifbuilderConf, $tmplObjNumber);
06632         }
06633         return $gifbuilderConf;
06634     }
06635 
06636     /**
06637      * Splits a text string into lines and returns an array with these lines but a max number of lines.
06638      *
06639      * @param   string      The string to break
06640      * @param   integer     Max number of characters per line.
06641      * @param   integer     Max number of lines in all.
06642      * @return  array       array with lines.
06643      * @access private
06644      * @see gifBuilderTextBox()
06645      */
06646     function linebreaks($string, $chars, $maxLines = 0) {
06647         $lines = explode(LF, $string);
06648         $lineArr = array();
06649         $c = 0;
06650         foreach ($lines as $paragraph) {
06651             $words = explode(' ', $paragraph);
06652             foreach ($words as $word) {
06653                 if (strlen($lineArr[$c] . $word) > $chars) {
06654                     $c++;
06655                 }
06656                 if (!$maxLines || $c < $maxLines) {
06657                     $lineArr[$c] .= $word . ' ';
06658                 }
06659             }
06660             $c++;
06661         }
06662         return $lineArr;
06663     }
06664 
06665     /**
06666      * Returns a JavaScript <script> section with some function calls to JavaScript functions from "t3lib/jsfunc.updateform.js" (which is also included by setting a reference in $GLOBALS['TSFE']->additionalHeaderData['JSincludeFormupdate'])
06667      * The JavaScript codes simply transfers content into form fields of a form which is probably used for editing information by frontend users. Used by fe_adminLib.inc.
06668      *
06669      * @param   array       Data array which values to load into the form fields from $formName (only field names found in $fieldList)
06670      * @param   string      The form name
06671      * @param   string      A prefix for the data array
06672      * @param   string      The list of fields which are loaded
06673      * @return  string
06674      * @access private
06675      * @see user_feAdmin::displayCreateScreen()
06676      */
06677     function getUpdateJS($dataArray, $formName, $arrPrefix, $fieldList) {
06678         $JSPart = '';
06679         $updateValues = t3lib_div::trimExplode(',', $fieldList);
06680         foreach ($updateValues as $fKey) {
06681             $value = $dataArray[$fKey];
06682             if (is_array($value)) {
06683                 foreach ($value as $Nvalue) {
06684                     $JSPart .= "
06685     updateForm('" . $formName . "','" . $arrPrefix . "[" . $fKey . "][]'," . t3lib_div::quoteJSvalue($Nvalue, TRUE) . ");";
06686                 }
06687 
06688             } else {
06689                 $JSPart .= "
06690     updateForm('" . $formName . "','" . $arrPrefix . "[" . $fKey . "]'," . t3lib_div::quoteJSvalue($value, TRUE) . ");";
06691             }
06692         }
06693         $JSPart = '<script type="text/javascript">
06694     /*<![CDATA[*/ ' . $JSPart . '
06695     /*]]>*/
06696 </script>
06697 ';
06698         $GLOBALS['TSFE']->additionalHeaderData['JSincludeFormupdate'] = '<script type="text/javascript" src="' . t3lib_div::createVersionNumberedFilename($GLOBALS['TSFE']->absRefPrefix . 't3lib/jsfunc.updateform.js') . '"></script>';
06699         return $JSPart;
06700     }
06701 
06702     /**
06703      * Includes resources if the config property 'includeLibs' is set.
06704      *
06705      * @param   array       $config: TypoScript configuration
06706      * @return  boolean     Whether a configuration for including libs was found and processed
06707      */
06708     public function includeLibs(array $config) {
06709         $librariesIncluded = FALSE;
06710 
06711         if (isset($config['includeLibs']) && $config['includeLibs']) {
06712             $libraries = t3lib_div::trimExplode(',', $config['includeLibs'], TRUE);
06713             $GLOBALS['TSFE']->includeLibraries($libraries);
06714             $librariesIncluded = TRUE;
06715         }
06716 
06717         return $librariesIncluded;
06718     }
06719 
06720     /**
06721      * Checks whether a PHP class is available. If the check fails, the method tries to
06722      * determine the correct includeLibs to make the class available automatically.
06723      *
06724      * TypoScript example that can cause this:
06725      * | plugin.tx_myext_pi1 = USER
06726      * | plugin.tx_myext_pi1 {
06727      * |   includeLibs = EXT:myext/pi1/class.tx_myext_pi1.php
06728      * |   userFunc = tx_myext_pi1->main
06729      * | }
06730      * | 10 = USER
06731      * | 10.userFunc = tx_myext_pi1->renderHeader
06732      *
06733      * @param   string      $className: The name of the PHP class to be checked
06734      * @param   array       $config: TypoScript configuration (naturally of a USER or COA cObject)
06735      * @return  boolean     Whether the class is available
06736      * @link    http://bugs.typo3.org/view.php?id=9654
06737      * @TODO    This method was introduced in TYPO3 4.3 and can be removed if the autoload was integrated
06738      */
06739     protected function isClassAvailable($className, array $config = NULL) {
06740         if (class_exists($className)) {
06741             return TRUE;
06742         } elseif ($config) {
06743             $pluginConfiguration = & $GLOBALS['TSFE']->tmpl->setup['plugin.'][$className . '.'];
06744             if (isset($pluginConfiguration['includeLibs']) && $pluginConfiguration['includeLibs']) {
06745                 $config['includeLibs'] = $pluginConfiguration['includeLibs'];
06746                 return $this->includeLibs($config);
06747             }
06748         }
06749         return FALSE;
06750     }
06751 
06752 
06753 
06754     /***********************************************
06755      *
06756      * Database functions, making of queries
06757      *
06758      ***********************************************/
06759 
06760     /**
06761      * Returns an UPDATE/DELETE sql query which will "delete" the record.
06762      * If the $TCA config for the table tells us to NOT "physically" delete the record but rather set the "deleted" field to "1" then an UPDATE query is returned doing just that. Otherwise it truely is a DELETE query.
06763      *
06764      * @param   string      The table name, should be in $TCA
06765      * @param   integer     The UID of the record from $table which we are going to delete
06766      * @param   boolean     If set, the query is executed. IT'S HIGHLY RECOMMENDED TO USE THIS FLAG to execute the query directly!!!
06767      * @return  string      The query, ready to execute unless $doExec was TRUE in which case the return value is FALSE.
06768      * @see DBgetUpdate(), DBgetInsert(), user_feAdmin
06769      */
06770     function DBgetDelete($table, $uid, $doExec = FALSE) {
06771         if (intval($uid)) {
06772             if ($GLOBALS['TCA'][$table]['ctrl']['delete']) {
06773                 if ($doExec) {
06774                     return $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid=' . intval($uid), array(
06775                         $GLOBALS['TCA'][$table]['ctrl']['delete'] => 1
06776                     ));
06777                 } else {
06778                     return $GLOBALS['TYPO3_DB']->UPDATEquery($table, 'uid=' . intval($uid), array(
06779                         $GLOBALS['TCA'][$table]['ctrl']['delete'] => 1
06780                     ));
06781                 }
06782             } else {
06783                 if ($doExec) {
06784                     return $GLOBALS['TYPO3_DB']->exec_DELETEquery($table, 'uid=' . intval($uid));
06785                 } else {
06786                     return $GLOBALS['TYPO3_DB']->DELETEquery($table, 'uid=' . intval($uid));
06787                 }
06788             }
06789         }
06790     }
06791 
06792     /**
06793      * Returns an UPDATE sql query.
06794      * If a "tstamp" field is configured for the $table tablename in $TCA then that field is automatically updated to the current time.
06795      * Notice: It is YOUR responsibility to make sure the data being updated is valid according the tablefield types etc. Also no logging is performed of the update. It's just a nice general usage API function for creating a quick query.
06796      * NOTICE: From TYPO3 3.6.0 this function ALWAYS adds slashes to values inserted in the query.
06797      *
06798      * @param   string      The table name, should be in $TCA
06799      * @param   integer     The UID of the record from $table which we are going to update
06800      * @param   array       The data array where key/value pairs are fieldnames/values for the record to update.
06801      * @param   string      Comma list of fieldnames which are allowed to be updated. Only values from the data record for fields in this list will be updated!!
06802      * @param   boolean     If set, the query is executed. IT'S HIGHLY RECOMMENDED TO USE THIS FLAG to execute the query directly!!!
06803      * @return  string      The query, ready to execute unless $doExec was TRUE in which case the return value is FALSE.
06804      * @see DBgetInsert(), DBgetDelete(), user_feAdmin
06805      */
06806     function DBgetUpdate($table, $uid, $dataArr, $fieldList, $doExec = FALSE) {
06807         unset($dataArr['uid']); // uid can never be set
06808         $uid = intval($uid);
06809 
06810         if ($uid) {
06811             $fieldList = implode(',', t3lib_div::trimExplode(',', $fieldList, 1));
06812             $updateFields = array();
06813 
06814             foreach ($dataArr as $f => $v) {
06815                 if (t3lib_div::inList($fieldList, $f)) {
06816                     $updateFields[$f] = $v;
06817                 }
06818             }
06819 
06820             if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
06821                 $updateFields[$GLOBALS['TCA'][$table]['ctrl']['tstamp']] = $GLOBALS['EXEC_TIME'];
06822             }
06823 
06824             if (count($updateFields)) {
06825                 if ($doExec) {
06826                     return $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid=' . intval($uid), $updateFields);
06827                 } else {
06828                     return $GLOBALS['TYPO3_DB']->UPDATEquery($table, 'uid=' . intval($uid), $updateFields);
06829                 }
06830             }
06831         }
06832     }
06833 
06834     /**
06835      * Returns an INSERT sql query which automatically added "system-fields" according to $TCA
06836      * Automatically fields for "tstamp", "crdate", "cruser_id", "fe_cruser_id" and "fe_crgroup_id" is updated if they are configured in the "ctrl" part of $TCA.
06837      * The "pid" field is overridden by the input $pid value if >= 0 (zero). "uid" can never be set as a field
06838      * NOTICE: From TYPO3 3.6.0 this function ALWAYS adds slashes to values inserted in the query.
06839      *
06840      * @param   string      The table name, should be in $TCA
06841      * @param   integer     The PID value for the record to insert
06842      * @param   array       The data array where key/value pairs are fieldnames/values for the record to insert
06843      * @param   string      Comma list of fieldnames which are allowed to be inserted. Only values from the data record for fields in this list will be inserted!!
06844      * @param   boolean     If set, the query is executed. IT'S HIGHLY RECOMMENDED TO USE THIS FLAG to execute the query directly!!!
06845      * @return  string      The query, ready to execute unless $doExec was TRUE in which case the return value is FALSE.
06846      * @see DBgetUpdate(), DBgetDelete(), user_feAdmin
06847      */
06848     function DBgetInsert($table, $pid, $dataArr, $fieldList, $doExec = FALSE) {
06849         $extraList = 'pid';
06850         if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
06851             $field = $GLOBALS['TCA'][$table]['ctrl']['tstamp'];
06852             $dataArr[$field] = $GLOBALS['EXEC_TIME'];
06853             $extraList .= ',' . $field;
06854         }
06855         if ($GLOBALS['TCA'][$table]['ctrl']['crdate']) {
06856             $field = $GLOBALS['TCA'][$table]['ctrl']['crdate'];
06857             $dataArr[$field] = $GLOBALS['EXEC_TIME'];
06858             $extraList .= ',' . $field;
06859         }
06860         if ($GLOBALS['TCA'][$table]['ctrl']['cruser_id']) {
06861             $field = $GLOBALS['TCA'][$table]['ctrl']['cruser_id'];
06862             $dataArr[$field] = 0;
06863             $extraList .= ',' . $field;
06864         }
06865         if ($GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']) {
06866             $field = $GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id'];
06867             $dataArr[$field] = intval($GLOBALS['TSFE']->fe_user->user['uid']);
06868             $extraList .= ',' . $field;
06869         }
06870         if ($GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']) {
06871             $field = $GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id'];
06872             list ($dataArr[$field]) = explode(',', $GLOBALS['TSFE']->fe_user->user['usergroup']);
06873             $dataArr[$field] = intval($dataArr[$field]);
06874             $extraList .= ',' . $field;
06875         }
06876 
06877         unset($dataArr['uid']); // uid can never be set
06878         if ($pid >= 0) {
06879             $dataArr['pid'] = $pid;
06880         } // Set pid < 0 and the dataarr-pid will be used!
06881         $fieldList = implode(',', t3lib_div::trimExplode(',', $fieldList . ',' . $extraList, 1));
06882 
06883         $insertFields = array();
06884         foreach ($dataArr as $f => $v) {
06885             if (t3lib_div::inList($fieldList, $f)) {
06886                 $insertFields[$f] = $v;
06887             }
06888         }
06889 
06890         if ($doExec) {
06891             return $GLOBALS['TYPO3_DB']->exec_INSERTquery($table, $insertFields);
06892         } else {
06893             return $GLOBALS['TYPO3_DB']->INSERTquery($table, $insertFields);
06894         }
06895     }
06896 
06897     /**
06898      * Checks if a frontend user is allowed to edit a certain record
06899      *
06900      * @param   string      The table name, found in $TCA
06901      * @param   array       The record data array for the record in question
06902      * @param   array       The array of the fe_user which is evaluated, typ. $GLOBALS['TSFE']->fe_user->user
06903      * @param   string      Commalist of the only fe_groups uids which may edit the record. If not set, then the usergroup field of the fe_user is used.
06904      * @param   boolean     True, if the fe_user may edit his own fe_user record.
06905      * @return  boolean
06906      * @see user_feAdmin
06907      */
06908     function DBmayFEUserEdit($table, $row, $feUserRow, $allowedGroups = '', $feEditSelf = 0) {
06909         $groupList = $allowedGroups
06910             ? implode(',', array_intersect(
06911                     t3lib_div::trimExplode(',', $feUserRow['usergroup'], 1),
06912                     t3lib_div::trimExplode(',', $allowedGroups, 1)
06913             ))
06914             : $feUserRow['usergroup'];
06915         $ok = 0;
06916             // points to the field that allows further editing from frontend if not set. If set the record is locked.
06917         if (!$GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock'] || !$row[$GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock']]) {
06918                 // points to the field (integer) that holds the fe_users-id of the creator fe_user
06919             if ($GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']) {
06920                 $rowFEUser = intval($row[$GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']]);
06921                 if ($rowFEUser && $rowFEUser == $feUserRow['uid']) {
06922                     $ok = 1;
06923                 }
06924             }
06925                 // If $feEditSelf is set, fe_users may always edit them selves...
06926             if ($feEditSelf && $table == 'fe_users' && !strcmp($feUserRow['uid'], $row['uid'])) {
06927                 $ok = 1;
06928             }
06929                 // points to the field (integer) that holds the fe_group-id of the creator fe_user's first group
06930             if ($GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']) {
06931                 $rowFEUser = intval($row[$GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']]);
06932                 if ($rowFEUser) {
06933                     if (t3lib_div::inList($groupList, $rowFEUser)) {
06934                         $ok = 1;
06935                     }
06936                 }
06937             }
06938         }
06939         return $ok;
06940     }
06941 
06942     /**
06943      * Returns part of a where clause for selecting records from the input table name which the user may edit.
06944      * Conceptually close to the function DBmayFEUserEdit(); It does the same thing but not for a single record,
06945      * rather for a select query selecting all records which the user HAS access to.
06946      *
06947      * @param   string      The table name
06948      * @param   array       The array of the fe_user which is evaluated, typ. $GLOBALS['TSFE']->fe_user->user
06949      * @param   string      Commalist of the only fe_groups uids which may edit the record. If not set, then the usergroup field of the fe_user is used.
06950      * @param   boolean     True, if the fe_user may edit his own fe_user record.
06951      * @return  string      The where clause part. ALWAYS returns a string. If no access at all, then " AND 1=0"
06952      * @see DBmayFEUserEdit(), user_feAdmin::displayEditScreen()
06953      */
06954     function DBmayFEUserEditSelect($table, $feUserRow, $allowedGroups = '', $feEditSelf = 0) {
06955             // Returns where-definition that selects user-editable records.
06956         $groupList = $allowedGroups ? implode(',', array_intersect(t3lib_div::trimExplode(',', $feUserRow['usergroup'], 1), t3lib_div::trimExplode(',', $allowedGroups, 1))) : $feUserRow['usergroup'];
06957         $OR_arr = array();
06958             // points to the field (integer) that holds the fe_users-id of the creator fe_user
06959         if ($GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']) {
06960             $OR_arr[] = $GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id'] . '=' . $feUserRow['uid'];
06961         }
06962             // points to the field (integer) that holds the fe_group-id of the creator fe_user's first group
06963         if ($GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']) {
06964             $values = t3lib_div::intExplode(',', $groupList);
06965             foreach ($values as $theGroupUid) {
06966                 if ($theGroupUid) {
06967                     $OR_arr[] = $GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id'] . '=' . $theGroupUid;
06968                 }
06969             }
06970         }
06971             // If $feEditSelf is set, fe_users may always edit them selves...
06972         if ($feEditSelf && $table == 'fe_users') {
06973             $OR_arr[] = 'uid=' . intval($feUserRow['uid']);
06974         }
06975 
06976         $whereDef = ' AND 1=0';
06977         if (count($OR_arr)) {
06978             $whereDef = ' AND (' . implode(' OR ', $OR_arr) . ')';
06979             if ($GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock']) {
06980                 $whereDef .= ' AND ' . $GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock'] . '=0';
06981             }
06982         }
06983         return $whereDef;
06984     }
06985 
06986     /**
06987      * Returns a part of a WHERE clause which will filter out records with start/end times or hidden/fe_groups fields
06988      * set to values that should de-select them according to the current time, preview settings or user login.
06989      * Definitely a frontend function.
06990      * THIS IS A VERY IMPORTANT FUNCTION: Basically you must add the output from this function for EVERY select query you create
06991      * for selecting records of tables in your own applications - thus they will always be filtered according to the "enablefields"
06992      * configured in TCA
06993      * Simply calls t3lib_pageSelect::enableFields() BUT will send the show_hidden flag along!
06994      * This means this function will work in conjunction with the preview facilities of the frontend engine/Admin Panel.
06995      *
06996      * @param   string      The table for which to get the where clause
06997      * @param   boolean     If set, then you want NOT to filter out hidden records. Otherwise hidden record are filtered based on the current preview settings.
06998      * @return  string      The part of the where clause on the form " AND [fieldname]=0 AND ...". Eg. " AND hidden=0 AND starttime < 123345567"
06999      * @see t3lib_pageSelect::enableFields()
07000      */
07001     function enableFields($table, $show_hidden = 0) {
07002         return $GLOBALS['TSFE']->sys_page->enableFields(
07003             $table,
07004             $show_hidden ? $show_hidden : ($table == 'pages' ? $GLOBALS['TSFE']->showHiddenPage : $GLOBALS['TSFE']->showHiddenRecords)
07005         );
07006     }
07007 
07008     /**
07009      * Generates a list of Page-uid's from $id. List does not include $id itself
07010      * (unless the id specified is negative in which case it does!)
07011      * The only pages WHICH PREVENTS DECENDING in a branch are
07012      * - deleted pages,
07013      * - pages in a recycler (doktype = 255) or of the Backend User Section (doktpe = 6) type
07014      * - pages that has the extendToSubpages set, WHERE start/endtime, hidden
07015      * and fe_users would hide the records.
07016      * Apart from that, pages with enable-fields excluding them, will also be
07017      * removed. HOWEVER $dontCheckEnableFields set will allow
07018      * enableFields-excluded pages to be included anyway - including
07019      * extendToSubpages sections!
07020      * Mount Pages are also descended but notice that these ID numbers are not
07021      * useful for links unless the correct MPvar is set.
07022      *
07023      * @param   integer     The id of the start page from which point in the page tree to decend. IF NEGATIVE the id itself is included in the end of the list (only if $begin is 0) AND the output does NOT contain a last comma. Recommended since it will resolve the input ID for mount pages correctly and also check if the start ID actually exists!
07024      * @param   integer     The number of levels to decend. If you want to decend infinitely, just set this to 100 or so. Should be at least "1" since zero will just make the function return (no decend...)
07025      * @param   integer     $begin is an optional integer that determines at which level in the tree to start collecting uid's. Zero means 'start right away', 1 = 'next level and out'
07026      * @param   boolean     See function description
07027      * @param   string      Additional fields to select. Syntax: ",[fieldname],[fieldname],..."
07028      * @param   string      Additional where clauses. Syntax: " AND [fieldname]=[value] AND ..."
07029      * @param   array       array of IDs from previous recursions. In order to prevent infinite loops with mount pages.
07030      * @param   integer     Internal: Zero for the first recursion, incremented for each recursive call.
07031      * @return  string      Returns the list with a comma in the end (if any pages selected and not if $id is negative and $id is added itself) - which means the input page id can comfortably be appended to the output string if you need it to.
07032      * @see tslib_fe::checkEnableFields(), tslib_fe::checkPagerecordForIncludeSection()
07033      */
07034     public function getTreeList($id, $depth, $begin = 0, $dontCheckEnableFields = FALSE, $addSelectFields = '', $moreWhereClauses = '', array $prevId_array = array(), $recursionLevel = 0) {
07035 
07036             // Init vars:
07037         $allFields = 'uid,hidden,starttime,endtime,fe_group,extendToSubpages,doktype,php_tree_stop,mount_pid,mount_pid_ol,t3ver_state' .
07038             $addSelectFields;
07039         $depth = intval($depth);
07040         $begin = intval($begin);
07041         $id = intval($id);
07042         $theList = '';
07043         $addId = 0;
07044         $requestHash = '';
07045 
07046         if ($id) {
07047 
07048                 // First level, check id (second level, this is done BEFORE the recursive call)
07049             if (!$recursionLevel) {
07050 
07051                     // check tree list cache
07052 
07053                     // first, create the hash for this request - not sure yet whether we need all these parameters though
07054                 $parameters = array(
07055                     $id,
07056                     $depth,
07057                     $begin,
07058                     $dontCheckEnableFields,
07059                     $addSelectFields,
07060                     $moreWhereClauses,
07061                     $prevId_array,
07062                     $GLOBALS['TSFE']->gr_list
07063                 );
07064                 $requestHash = md5(serialize($parameters));
07065 
07066                 $cacheEntry = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
07067                     'treelist',
07068                     'cache_treelist',
07069                     'md5hash = \'' . $requestHash . '\' AND ( expires > ' . $GLOBALS['EXEC_TIME'] .
07070                     ' OR expires = 0 )'
07071                 );
07072 
07073                 if (is_array($cacheEntry)) {
07074                         // cache hit
07075                     return $cacheEntry['treelist'];
07076                 }
07077 
07078                     // If Id less than zero it means we should add the real id to list:
07079                 if ($id < 0) {
07080                     $addId = $id = abs($id);
07081                 }
07082                     // Check start page:
07083                 if ($GLOBALS['TSFE']->sys_page->getRawRecord('pages', $id, 'uid')) {
07084 
07085                         // Find mount point if any:
07086                     $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($id);
07087                     if (is_array($mount_info)) {
07088                         $id = $mount_info['mount_pid'];
07089                             // In Overlay mode, use the mounted page uid as added ID!:
07090                         if ($addId && $mount_info['overlay']) {
07091                             $addId = $id;
07092                         }
07093                     }
07094                 } else {
07095                     return ''; // Return blank if the start page was NOT found at all!
07096                 }
07097             }
07098 
07099                 // Add this ID to the array of IDs
07100             if ($begin <= 0) {
07101                 $prevId_array[] = $id;
07102             }
07103 
07104                 // Select sublevel:
07105             if ($depth > 0) {
07106                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
07107                     $allFields,
07108                     'pages',
07109                     'pid = ' . intval($id) . ' AND deleted = 0 ' . $moreWhereClauses, '', 'sorting'
07110                 );
07111 
07112                 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
07113                     $GLOBALS['TSFE']->sys_page->versionOL('pages', $row);
07114 
07115                     if ($row['doktype'] == t3lib_pageSelect::DOKTYPE_RECYCLER || $row['doktype'] == t3lib_pageSelect::DOKTYPE_BE_USER_SECTION || $row['t3ver_state'] > 0) {
07116                             // Doing this after the overlay to make sure changes
07117                             // in the overlay are respected.
07118                             // However, we do not process pages below of and
07119                             // including of type recycler and BE user section
07120                         continue;
07121                     }
07122 
07123                         // Find mount point if any:
07124                     $next_id = $row['uid'];
07125                     $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($next_id, $row);
07126 
07127                         // Overlay mode:
07128                     if (is_array($mount_info) && $mount_info['overlay']) {
07129                         $next_id = $mount_info['mount_pid'];
07130 
07131                         $res2 = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
07132                             $allFields,
07133                             'pages',
07134                             'uid = ' . intval($next_id) . ' AND deleted = 0 ' . $moreWhereClauses,
07135                             '',
07136                             'sorting'
07137                         );
07138                         $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res2);
07139                         $GLOBALS['TYPO3_DB']->sql_free_result($res2);
07140 
07141                         $GLOBALS['TSFE']->sys_page->versionOL('pages', $row);
07142 
07143                         if ($row['doktype'] == t3lib_pageSelect::DOKTYPE_RECYCLER || $row['doktype'] == t3lib_pageSelect::DOKTYPE_BE_USER_SECTION || $row['t3ver_state'] > 0) {
07144                                 // Doing this after the overlay to make sure
07145                                 // changes in the overlay are respected.
07146 
07147                                 // see above
07148                             continue;
07149                         }
07150                     }
07151                         // Add record:
07152                     if ($dontCheckEnableFields || $GLOBALS['TSFE']->checkPagerecordForIncludeSection($row)) {
07153                             // Add ID to list:
07154                         if ($begin <= 0) {
07155                             if ($dontCheckEnableFields || $GLOBALS['TSFE']->checkEnableFields($row)) {
07156                                 $theList .= $next_id . ',';
07157                             }
07158                         }
07159                             // Next level:
07160                         if ($depth > 1 && !$row['php_tree_stop']) {
07161                                 // Normal mode:
07162                             if (is_array($mount_info) && !$mount_info['overlay']) {
07163                                 $next_id = $mount_info['mount_pid'];
07164                             }
07165                                 // Call recursively, if the id is not in prevID_array:
07166                             if (!in_array($next_id, $prevId_array)) {
07167                                 $theList .= tslib_cObj::getTreeList(
07168                                     $next_id,
07169                                     $depth - 1,
07170                                     $begin - 1,
07171                                     $dontCheckEnableFields,
07172                                     $addSelectFields,
07173                                     $moreWhereClauses,
07174                                     $prevId_array,
07175                                     $recursionLevel + 1
07176                                 );
07177                             }
07178                         }
07179                     }
07180                 }
07181                 $GLOBALS['TYPO3_DB']->sql_free_result($res);
07182             }
07183 
07184                 // If first run, check if the ID should be returned:
07185             if (!$recursionLevel) {
07186                 if ($addId) {
07187                     if ($begin > 0) {
07188                         $theList .= 0;
07189                     } else {
07190                         $theList .= $addId;
07191                     }
07192                 }
07193 
07194                 $GLOBALS['TYPO3_DB']->exec_INSERTquery(
07195                     'cache_treelist',
07196                     array(
07197                         'md5hash' => $requestHash,
07198                         'pid' => $id,
07199                         'treelist' => $theList,
07200                         'tstamp' => $GLOBALS['EXEC_TIME']
07201                     )
07202                 );
07203             }
07204         }
07205             // Return list:
07206         return $theList;
07207     }
07208 
07209     /**
07210      * Executes a SELECT query for joining three tables according to the MM-relation standards used for tables configured in $TCA. That means MM-joins where the join table has the fields "uid_local" and "uid_foreign"
07211      *
07212      * @param   string      List of fields to select
07213      * @param   string      The local table
07214      * @param   string      The join-table; The "uid_local" field of this table will be matched with $local_table's "uid" field.
07215      * @param   string      Optionally: The foreign table; The "uid" field of this table will be matched with $mm_table's "uid_foreign" field. If you set this field to blank the join will be over only the $local_table and $mm_table
07216      * @param   string      Optional additional WHERE clauses put in the end of the query. DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
07217      * @param   string      Optional GROUP BY field(s), if none, supply blank string.
07218      * @param   string      Optional ORDER BY field(s), if none, supply blank string.
07219      * @param   string      Optional LIMIT value ([begin,]max), if none, supply blank string.
07220      * @return  pointer     SQL result pointer
07221      * @see mm_query_uidList()
07222      */
07223     function exec_mm_query($select, $local_table, $mm_table, $foreign_table, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '') {
07224         return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
07225             $select,
07226             $local_table . ',' . $mm_table . ($foreign_table ? ',' . $foreign_table : ''),
07227             $local_table . '.uid=' . $mm_table . '.uid_local' .
07228                 ($foreign_table ? ' AND ' . $foreign_table . '.uid=' . $mm_table . '.uid_foreign' : '') .
07229                 $whereClause, // whereClauseMightContainGroupOrderBy
07230             $groupBy,
07231             $orderBy,
07232             $limit
07233         );
07234     }
07235 
07236     /**
07237      * Executes a SELECT query for joining two tables according to the MM-relation standards used for tables configured in $TCA. That means MM-joins where the join table has the fields "uid_local" and "uid_foreign"
07238      * The two tables joined is the join table ($mm_table) and the foreign table ($foreign_table) - so the "local table" is not included but instead you can supply a list of UID integers from the local table to match in the join-table.
07239      *
07240      * @param   string      List of fields to select
07241      * @param   string      List of UID integers, eg. "1,2,3,456"
07242      * @param   string      The join-table; The "uid_local" field of this table will be matched with the list of UID numbers from $local_table_uidlist
07243      * @param   string      Optionally: The foreign table; The "uid" field of this table will be matched with $mm_table's "uid_foreign" field. If you set this field to blank only records from the $mm_table is returned. No join performed.
07244      * @param   string      Optional additional WHERE clauses put in the end of the query. DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
07245      * @param   string      Optional GROUP BY field(s), if none, supply blank string.
07246      * @param   string      Optional ORDER BY field(s), if none, supply blank string.
07247      * @param   string      Optional LIMIT value ([begin,]max), if none, supply blank string.
07248      * @return  pointer     SQL result pointer
07249      * @see mm_query()
07250      */
07251     function exec_mm_query_uidList($select, $local_table_uidlist, $mm_table, $foreign_table = '', $whereClause = '', $groupBy = '', $orderBy = '', $limit = '') {
07252         return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
07253             $select,
07254             $mm_table . ($foreign_table ? ',' . $foreign_table : ''),
07255             $mm_table . '.uid_local IN (' . $local_table_uidlist . ')' .
07256                 ($foreign_table ? ' AND ' . $foreign_table . '.uid=' . $mm_table . '.uid_foreign' : '') .
07257                 $whereClause, // whereClauseMightContainGroupOrderBy
07258             $groupBy,
07259             $orderBy,
07260             $limit
07261         );
07262     }
07263 
07264     /**
07265      * Generates a search where clause based on the input search words (AND operation - all search words must be found in record.)
07266      * Example: The $sw is "content management, system" (from an input form) and the $searchFieldList is "bodytext,header" then the output will be ' AND (bodytext LIKE "%content%" OR header LIKE "%content%") AND (bodytext LIKE "%management%" OR header LIKE "%management%") AND (bodytext LIKE "%system%" OR header LIKE "%system%")'
07267      *
07268      * @param   string      The search words. These will be separated by space and comma.
07269      * @param   string      The fields to search in
07270      * @param   string      The table name you search in (recommended for DBAL compliance. Will be prepended field names as well)
07271      * @return  string      The WHERE clause.
07272      */
07273     function searchWhere($sw, $searchFieldList, $searchTable = '') {
07274         global $TYPO3_DB;
07275 
07276         $prefixTableName = $searchTable ? $searchTable . '.' : '';
07277         $where = '';
07278         if ($sw) {
07279             $searchFields = explode(',', $searchFieldList);
07280             $kw = preg_split('/[ ,]/', $sw);
07281 
07282             foreach ($kw as $val) {
07283                 $val = trim($val);
07284                 $where_p = array();
07285                 if (strlen($val) >= 2) {
07286                     $val = $TYPO3_DB->escapeStrForLike($TYPO3_DB->quoteStr($val, $searchTable), $searchTable);
07287                     foreach ($searchFields as $field) {
07288                         $where_p[] = $prefixTableName . $field . ' LIKE \'%' . $val . '%\'';
07289                     }
07290                 }
07291                 if (count($where_p)) {
07292                     $where .= ' AND (' . implode(' OR ', $where_p) . ')';
07293                 }
07294             }
07295         }
07296         return $where;
07297     }
07298 
07299     /**
07300      * Executes a SELECT query for records from $table and with conditions based on the configuration in the $conf array
07301      * This function is preferred over ->getQuery() if you just need to create and then execute a query.
07302      *
07303      * @param   string      The table name
07304      * @param   array       The TypoScript configuration properties
07305      * @return  mixed       A SQL result pointer
07306      * @see getQuery()
07307      */
07308     function exec_getQuery($table, $conf) {
07309         $queryParts = $this->getQuery($table, $conf, TRUE);
07310 
07311         return $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts);
07312     }
07313 
07314     /**
07315      * Creates and returns a SELECT query for records from $table and with conditions based on the configuration in the $conf array
07316      * Implements the "select" function in TypoScript
07317      *
07318      * @param   string      See ->exec_getQuery()
07319      * @param   array       See ->exec_getQuery()
07320      * @param   boolean     If set, the function will return the query not as a string but array with the various parts. RECOMMENDED!
07321      * @return  mixed       A SELECT query if $returnQueryArray is FALSE, otherwise the SELECT query in an array as parts.
07322      * @access private
07323      * @see CONTENT(), numRows()
07324      */
07325     function getQuery($table, $conf, $returnQueryArray = FALSE) {
07326 
07327             // Handle PDO-style named parameter markers first
07328         $queryMarkers = $this->getQueryMarkers($table, $conf);
07329 
07330             // replace the markers in the non-stdWrap properties
07331         foreach ($queryMarkers as $marker => $markerValue) {
07332             $properties = array(
07333                 'uidInList', 'selectFields', 'where', 'max', 'begin', 'groupBy', 'orderBy', 'join', 'leftjoin', 'rightjoin'
07334             );
07335             foreach ($properties as $property) {
07336                 if ($conf[$property]) {
07337                     $conf[$property] = str_replace('###' . $marker . '###', $markerValue, $conf[$property]);
07338                 }
07339             }
07340         }
07341 
07342             // Construct WHERE clause:
07343         $conf['pidInList'] = isset($conf['pidInList.'])
07344             ? trim($this->stdWrap($conf['pidInList'], $conf['pidInList.']))
07345             : trim($conf['pidInList']);
07346 
07347             // Handle recursive function for the pidInList
07348         if (isset($conf['recursive'])) {
07349             $conf['recursive'] = intval($conf['recursive']);
07350             if ($conf['recursive'] > 0) {
07351                 foreach (explode(',', $conf['pidInList']) as $value) {
07352                     if ($value === 'this') {
07353                         $value = $GLOBALS['TSFE']->id;
07354                     }
07355                     $pidList .= $value . ',' . $this->getTreeList($value, $conf['recursive']);
07356                 }
07357                 $conf['pidInList'] = trim($pidList, ',');
07358             }
07359         }
07360 
07361         if (!strcmp($conf['pidInList'], '')) {
07362             $conf['pidInList'] = 'this';
07363         }
07364         $queryParts = $this->getWhere($table, $conf, TRUE);
07365 
07366             // Fields:
07367         $queryParts['SELECT'] = $conf['selectFields'] ? $conf['selectFields'] : '*';
07368 
07369             // Setting LIMIT:
07370         if ($conf['max'] || $conf['begin']) {
07371             $error = 0;
07372 
07373             // Finding the total number of records, if used:
07374             if (strstr(strtolower($conf['begin'] . $conf['max']), 'total')) {
07375                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $table, $queryParts['WHERE'], $queryParts['GROUPBY']);
07376                 if ($error = $GLOBALS['TYPO3_DB']->sql_error()) {
07377                     $GLOBALS['TT']->setTSlogMessage($error);
07378                 } else {
07379                     $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
07380                     $conf['max'] = str_ireplace('total', $row[0], $conf['max']);
07381                     $conf['begin'] = str_ireplace('total', $row[0], $conf['begin']);
07382                 }
07383                 $GLOBALS['TYPO3_DB']->sql_free_result($res);
07384             }
07385             if (!$error) {
07386                 $conf['begin'] = t3lib_div::intInRange(ceil($this->calc($conf['begin'])), 0);
07387                 $conf['max'] = t3lib_div::intInRange(ceil($this->calc($conf['max'])), 0);
07388                 if ($conf['begin'] && !$conf['max']) {
07389                     $conf['max'] = 100000;
07390                 }
07391 
07392                 if ($conf['begin'] && $conf['max']) {
07393                     $queryParts['LIMIT'] = $conf['begin'] . ',' . $conf['max'];
07394                 } elseif (!$conf['begin'] && $conf['max']) {
07395                     $queryParts['LIMIT'] = $conf['max'];
07396                 }
07397             }
07398         }
07399 
07400         if (!$error) {
07401 
07402                 // Setting up tablejoins:
07403             $joinPart = '';
07404             if ($conf['join']) {
07405                 $joinPart = 'JOIN ' . trim($conf['join']);
07406             } elseif ($conf['leftjoin']) {
07407                 $joinPart = 'LEFT OUTER JOIN ' . trim($conf['leftjoin']);
07408             } elseif ($conf['rightjoin']) {
07409                 $joinPart = 'RIGHT OUTER JOIN ' . trim($conf['rightjoin']);
07410             }
07411 
07412                 // Compile and return query:
07413             $queryParts['FROM'] = trim($table . ' ' . $joinPart);
07414 
07415                 // replace the markers in the queryParts to handle stdWrap
07416                 // enabled properties
07417             foreach ($queryMarkers as $marker => $markerValue) {
07418                 foreach ($queryParts as $queryPartKey => &$queryPartValue) {
07419                     $queryPartValue = str_replace('###' . $marker . '###', $markerValue, $queryPartValue);
07420                 }
07421             }
07422 
07423             $query = $GLOBALS['TYPO3_DB']->SELECTquery(
07424                 $queryParts['SELECT'],
07425                 $queryParts['FROM'],
07426                 $queryParts['WHERE'],
07427                 $queryParts['GROUPBY'],
07428                 $queryParts['ORDERBY'],
07429                 $queryParts['LIMIT']
07430             );
07431 
07432             return $returnQueryArray ? $queryParts : $query;
07433         }
07434     }
07435 
07436     /**
07437      * Helper function for getQuery(), creating the WHERE clause of the SELECT query
07438      *
07439      * @param   string      The table name
07440      * @param   array       The TypoScript configuration properties
07441      * @param   boolean     If set, the function will return the query not as a string but array with the various parts. RECOMMENDED!
07442      * @return  mixed       A WHERE clause based on the relevant parts of the TypoScript properties for a "select" function in TypoScript, see link. If $returnQueryArray is FALSE the where clause is returned as a string with WHERE, GROUP BY and ORDER BY parts, otherwise as an array with these parts.
07443      * @access private
07444      * @see getQuery()
07445      */
07446     function getWhere($table, $conf, $returnQueryArray = FALSE) {
07447         global $TCA;
07448 
07449         // Init:
07450         $query = '';
07451         $pid_uid_flag = 0;
07452         $queryParts = array(
07453             'SELECT' => '',
07454             'FROM' => '',
07455             'WHERE' => '',
07456             'GROUPBY' => '',
07457             'ORDERBY' => '',
07458             'LIMIT' => ''
07459         );
07460 
07461         if (trim($conf['uidInList'])) {
07462             $listArr = t3lib_div::intExplode(',', str_replace('this', $GLOBALS['TSFE']->contentPid, $conf['uidInList']));
07463             if (count($listArr) == 1) {
07464                 $query .= ' AND ' . $table . '.uid=' . intval($listArr[0]);
07465             } else {
07466                 $query .= ' AND ' . $table . '.uid IN (' . implode(',', $GLOBALS['TYPO3_DB']->cleanIntArray($listArr)) . ')';
07467             }
07468             $pid_uid_flag++;
07469         }
07470             // static_* tables are allowed to be fetched from root page
07471         if (substr($table, 0, 7) == 'static_') {
07472             $pid_uid_flag++;
07473         }
07474         if (trim($conf['pidInList'])) {
07475             $listArr = t3lib_div::intExplode(',', str_replace('this', $GLOBALS['TSFE']->contentPid, $conf['pidInList']));
07476                 // removes all pages which are not visible for the user!
07477             $listArr = $this->checkPidArray($listArr);
07478             if (count($listArr)) {
07479                 $query .= ' AND ' . $table . '.pid IN (' . implode(',', $GLOBALS['TYPO3_DB']->cleanIntArray($listArr)) . ')';
07480                 $pid_uid_flag++;
07481             } else {
07482                 $pid_uid_flag = 0; // If not uid and not pid then uid is set to 0 - which results in nothing!!
07483             }
07484         }
07485         if (!$pid_uid_flag) { // If not uid and not pid then uid is set to 0 - which results in nothing!!
07486             $query .= ' AND ' . $table . '.uid=0';
07487         }
07488         if ($where = trim($conf['where'])) {
07489             $query .= ' AND ' . $where;
07490         }
07491 
07492         if ($conf['languageField']) {
07493             if ($GLOBALS['TSFE']->sys_language_contentOL && $TCA[$table] && $TCA[$table]['ctrl']['languageField']
07494                 && $TCA[$table]['ctrl']['transOrigPointerField']) {
07495                     // Sys language content is set to zero/-1 - and it is expected that whatever routine processes the output will
07496                     // OVERLAY the records with localized versions!
07497                 $sys_language_content = '0,-1';
07498             } else {
07499                 $sys_language_content = intval($GLOBALS['TSFE']->sys_language_content);
07500             }
07501             $query .= ' AND ' . $conf['languageField'] . ' IN (' . $sys_language_content . ')';
07502         }
07503 
07504         $andWhere = isset($conf['andWhere.'])
07505             ? trim($this->stdWrap($conf['andWhere'], $conf['andWhere.']))
07506             : trim($conf['andWhere']);
07507         if ($andWhere) {
07508             $query .= ' AND ' . $andWhere;
07509         }
07510 
07511             // enablefields
07512         if ($table == 'pages') {
07513             $query .= ' ' . $GLOBALS['TSFE']->sys_page->where_hid_del . $GLOBALS['TSFE']->sys_page->where_groupAccess;
07514         } else {
07515             $query .= $this->enableFields($table);
07516         }
07517 
07518             // MAKE WHERE:
07519         if ($query) {
07520             $queryParts['WHERE'] = trim(substr($query, 4)); // Stripping of " AND"...
07521             $query = 'WHERE ' . $queryParts['WHERE'];
07522         }
07523 
07524             // GROUP BY
07525         if (trim($conf['groupBy'])) {
07526             $queryParts['GROUPBY'] = isset($conf['groupBy.'])
07527                 ? trim($this->stdWrap($conf['groupBy'], $conf['groupBy.']))
07528                 : trim($conf['groupBy']);
07529         }
07530 
07531             // ORDER BY
07532         if (trim($conf['orderBy'])) {
07533             $queryParts['ORDERBY'] = isset($conf['orderBy.'])
07534                 ? trim($this->stdWrap($conf['orderBy'], $conf['orderBy.']))
07535                 : trim($conf['orderBy']);
07536             $query .= ' ORDER BY ' . $queryParts['ORDERBY'];
07537         }
07538 
07539             // Return result:
07540         return $returnQueryArray ? $queryParts : $query;
07541     }
07542 
07543     /**
07544      * Removes Page UID numbers from the input array which are not available due to enableFields() or the list of bad doktype numbers ($this->checkPid_badDoktypeList)
07545      *
07546      * @param   array       array of Page UID numbers for select and for which pages with enablefields and bad doktypes should be removed.
07547      * @return  array       Returns the array of remaining page UID numbers
07548      * @access private
07549      * @see getWhere(),checkPid()
07550      */
07551     function checkPidArray($listArr) {
07552         $outArr = array();
07553         if (is_array($listArr) && count($listArr)) {
07554             $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
07555                 'uid',
07556                 'pages',
07557                 'uid IN (' . implode(',', $listArr) . ')' . $this->enableFields('pages') .
07558                     ' AND doktype NOT IN (' . $this->checkPid_badDoktypeList . ')'
07559             );
07560             if ($error = $GLOBALS['TYPO3_DB']->sql_error()) {
07561                 $GLOBALS['TT']->setTSlogMessage($error . ': ' . $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery, 3);
07562             } else {
07563                 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
07564                     $outArr[] = $row['uid'];
07565                 }
07566             }
07567             $GLOBALS['TYPO3_DB']->sql_free_result($res);
07568         }
07569         return $outArr;
07570     }
07571 
07572     /**
07573      * Checks if a page UID is available due to enableFields() AND the list of bad doktype numbers ($this->checkPid_badDoktypeList)
07574      *
07575      * @param   integer     Page UID to test
07576      * @return  boolean     True if OK
07577      * @access private
07578      * @see getWhere(), checkPidArray()
07579      */
07580     function checkPid($uid) {
07581         $uid = intval($uid);
07582         if (!isset($this->checkPid_cache[$uid])) {
07583             $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
07584                 'uid',
07585                 'pages',
07586                 'uid=' . intval($uid) . $this->enableFields('pages') .
07587                     ' AND doktype NOT IN (' . $this->checkPid_badDoktypeList . ')'
07588             );
07589             $this->checkPid_cache[$uid] = (bool) $count;
07590         }
07591         return $this->checkPid_cache[$uid];
07592     }
07593 
07594     /**
07595      * Builds list of marker values for handling PDO-like parameter markers in select parts.
07596      * Marker values support stdWrap functionality thus allowing a way to use stdWrap functionality in various properties of 'select' AND prevents SQL-injection problems by quoting and escaping of numeric values, strings, NULL values and comma separated lists.
07597      *
07598      * @param   string $table Table to select records from
07599      * @param   array $conf Select part of CONTENT definition
07600      * @return  array List of values to replace markers with
07601      * @access private
07602      * @see getQuery()
07603      */
07604     function getQueryMarkers($table, $conf) {
07605 
07606             // parse markers and prepare their values
07607         $markerValues = array();
07608         if (is_array($conf['markers.'])) {
07609             foreach ($conf['markers.'] as $dottedMarker => $dummy) {
07610                 $marker = rtrim($dottedMarker, '.');
07611                 if ($dottedMarker == $marker . '.') {
07612                         // parse definition
07613                     $tempValue = isset($conf['markers.'][$dottedMarker])
07614                         ? $this->stdWrap($conf['markers.'][$dottedMarker]['value'], $conf['markers.'][$dottedMarker])
07615                         : $conf['markers.'][$dottedMarker]['value'];
07616                         // quote/escape if needed
07617                     if (is_numeric($tempValue)) {
07618                         if ((int) $tempValue == $tempValue) {
07619                                 // handle integer
07620                             $markerValues[$marker] = intval($tempValue);
07621                         } else {
07622                                 // handle float
07623                             $markerValues[$marker] = floatval($tempValue);
07624                         }
07625                     } elseif (is_null($tempValue)) {
07626                             // it represents NULL
07627                         $markerValues[$marker] = 'NULL';
07628                     } elseif ($conf['markers.'][$dottedMarker]['commaSeparatedList'] == 1) {
07629                             // see if it is really a comma separated list of values
07630                         $explodeValues = t3lib_div::trimExplode(',', $tempValue);
07631                         if (count($explodeValues) > 1) {
07632                                 // handle each element of list separately
07633                             $tempArray = array();
07634                             foreach ($explodeValues as $listValue) {
07635                                 if (is_numeric($listValue)) {
07636                                     if ((int) $listValue == $listValue) {
07637                                         $tempArray[] = intval($listValue);
07638                                     } else {
07639                                         $tempArray[] = floatval($listValue);
07640                                     }
07641                                 } else {
07642                                         // if quoted, remove quotes before
07643                                         // escaping.
07644                                     if (preg_match('/^\'([^\']*)\'$/', $listValue, $matches)) {
07645                                         $listValue = $matches[1];
07646                                     } elseif (preg_match('/^\"([^\"]*)\"$/', $listValue, $matches)) {
07647                                         $listValue = $matches[1];
07648                                     }
07649                                     $tempArray[] = $GLOBALS['TYPO3_DB']->fullQuoteStr($listValue, $table);
07650                                 }
07651                             }
07652                             $markerValues[$marker] = implode(',', $tempArray);
07653                         } else {
07654                                 // handle remaining values as string
07655                             $markerValues[$marker] = $GLOBALS['TYPO3_DB']->fullQuoteStr($tempValue, $table);
07656                         }
07657                     } else {
07658                             // handle remaining values as string
07659                         $markerValues[$marker] = $GLOBALS['TYPO3_DB']->fullQuoteStr($tempValue, $table);
07660                     }
07661                 }
07662             }
07663         }
07664         return $markerValues;
07665     }
07666 
07667 
07668 
07669     /***********************************************
07670      *
07671      * Frontend editing functions
07672      *
07673      ***********************************************/
07674 
07675     /**
07676      * Generates the "edit panels" which can be shown for a page or records on a page when the Admin Panel is enabled for a backend users surfing the frontend.
07677      * With the "edit panel" the user will see buttons with links to editing, moving, hiding, deleting the element
07678      * This function is used for the cObject EDITPANEL and the stdWrap property ".editPanel"
07679      *
07680      * @param   string      A content string containing the content related to the edit panel. For cObject "EDITPANEL" this is empty but not so for the stdWrap property. The edit panel is appended to this string and returned.
07681      * @param   array       TypoScript configuration properties for the editPanel
07682      * @param   string      The "table:uid" of the record being shown. If empty string then $this->currentRecord is used. For new records (set by $conf['newRecordFromTable']) it's auto-generated to "[tablename]:NEW"
07683      * @param   array       Alternative data array to use. Default is $this->data
07684      * @return  string      The input content string with the editPanel appended. This function returns only an edit panel appended to the content string if a backend user is logged in (and has the correct permissions). Otherwise the content string is directly returned.
07685      */
07686     function editPanel($content, $conf, $currentRecord = '', $dataArr = array()) {
07687 
07688         if ($GLOBALS['TSFE']->beUserLogin && ($GLOBALS['BE_USER']->frontendEdit instanceof t3lib_frontendedit)) {
07689             if (!$currentRecord) {
07690                 $currentRecord = $this->currentRecord;
07691             }
07692 
07693             if (!count($dataArr)) {
07694                 $dataArr = $this->data;
07695             }
07696 
07697             // Delegate rendering of the edit panel to the t3lib_frontendedit class.
07698             $content = $GLOBALS['BE_USER']->frontendEdit->displayEditPanel($content, $conf, $currentRecord, $dataArr);
07699         }
07700 
07701         return $content;
07702     }
07703 
07704     /**
07705      * Adds an edit icon to the content string. The edit icon links to alt_doc.php with proper parameters for editing the table/fields of the context.
07706      * This implements TYPO3 context sensitive editing facilities. Only backend users will have access (if properly configured as well).
07707      *
07708      * @param   string      The content to which the edit icons should be appended
07709      * @param   string      The parameters defining which table and fields to edit. Syntax is [tablename]:[fieldname],[fieldname],[fieldname],... OR [fieldname],[fieldname],[fieldname],... (basically "[tablename]:" is optional, default table is the one of the "current record" used in the function). The fieldlist is sent as "&columnsOnly=" parameter to alt_doc.php
07710      * @param   array       TypoScript properties for configuring the edit icons.
07711      * @param   string      The "table:uid" of the record being shown. If empty string then $this->currentRecord is used. For new records (set by $conf['newRecordFromTable']) it's auto-generated to "[tablename]:NEW"
07712      * @param   array       Alternative data array to use. Default is $this->data
07713      * @param   string      Additional URL parameters for the link pointing to alt_doc.php
07714      * @return  string      The input content string, possibly with edit icons added (not necessarily in the end but just after the last string of normal content.
07715      */
07716     function editIcons($content, $params, array $conf = array(), $currentRecord = '', $dataArr = array(), $addUrlParamStr = '') {
07717         if ($GLOBALS['TSFE']->beUserLogin && ($GLOBALS['BE_USER']->frontendEdit instanceof t3lib_frontendedit)) {
07718             if (!$currentRecord) {
07719                 $currentRecord = $this->currentRecord;
07720             }
07721 
07722             if (!count($dataArr)) {
07723                 $dataArr = $this->data;
07724             }
07725 
07726                 // Delegate rendering of the edit panel to the t3lib_frontendedit class.
07727             $content = $GLOBALS['BE_USER']->frontendEdit->displayEditIcons(
07728                 $content,
07729                 $params,
07730                 $conf,
07731                 $currentRecord,
07732                 $dataArr,
07733                 $addUrlParamStr
07734             );
07735         }
07736 
07737         return $content;
07738     }
07739 
07740 
07741     /**
07742      * Returns TRUE if the input table/row would be hidden in the frontend (according nto the current time and simulate user group)
07743      *
07744      * @param   string      The table name
07745      * @param   array       The data record
07746      * @return  boolean
07747      * @access private
07748      * @see editPanelPreviewBorder()
07749      */
07750     function isDisabled($table, $row) {
07751         global $TCA;
07752         if (($TCA[$table]['ctrl']['enablecolumns']['disabled']
07753             && $row[$TCA[$table]['ctrl']['enablecolumns']['disabled']])
07754             || ($TCA[$table]['ctrl']['enablecolumns']['fe_group'] && $GLOBALS['TSFE']->simUserGroup
07755             && $row[$TCA[$table]['ctrl']['enablecolumns']['fe_group']] == $GLOBALS['TSFE']->simUserGroup)
07756             || ($TCA[$table]['ctrl']['enablecolumns']['starttime']
07757             && $row[$TCA[$table]['ctrl']['enablecolumns']['starttime']] > $GLOBALS['EXEC_TIME'])
07758             || ($TCA[$table]['ctrl']['enablecolumns']['endtime']
07759             && $row[$TCA[$table]['ctrl']['enablecolumns']['endtime']]
07760             && $row[$TCA[$table]['ctrl']['enablecolumns']['endtime']] < $GLOBALS['EXEC_TIME'])) {
07761 
07762             return TRUE;
07763         }
07764     }
07765 }
07766 
07767 
07768 
07769 /**
07770  * Rendering of framesets
07771  *
07772  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
07773  * @package TYPO3
07774  * @subpackage tslib
07775  */
07776 class tslib_frameset {
07777 
07778     /**
07779      * Generates a frameset based on input configuration in a TypoScript array.
07780      *
07781      * @param   array       The TypoScript properties of the PAGE object property "frameSet.". See link.
07782      * @return  string      A <frameset> tag.
07783      * @see TSpagegen::renderContentWithHeader()
07784      */
07785     function make($setup) {
07786         $content = '';
07787         if (is_array($setup)) {
07788             $sKeyArray = t3lib_TStemplate::sortedKeyList($setup);
07789             foreach ($sKeyArray as $theKey) {
07790                 $theValue = $setup[$theKey];
07791                 if (intval($theKey) && $conf = $setup[$theKey . '.']) {
07792                     switch ($theValue) {
07793                         case 'FRAME' :
07794                             $typeNum = intval($GLOBALS['TSFE']->tmpl->setup[$conf['obj'] . '.']['typeNum']);
07795                             if (!$conf['src'] && !$typeNum) {
07796                                 $typeNum = -1;
07797                             }
07798                             $content .= '<frame' . $this->frameParams($conf, $typeNum) . ' />' . LF;
07799                         break;
07800                         case 'FRAMESET' :
07801                             $frameset = t3lib_div::makeInstance('tslib_frameset');
07802                             $content .= $frameset->make($conf) . LF;
07803                         break;
07804                     }
07805                 }
07806             }
07807             return '<frameset' . $this->framesetParams($setup) . '>' . LF . $content . '</frameset>';
07808         }
07809     }
07810 
07811     /**
07812      * Creates the attributes for a <frame> tag based on a $conf array and the type number
07813      *
07814      * @param   array       Configuration for the parameter generation for the FRAME set. See link
07815      * @param   integer     The typenumber to use for the link.
07816      * @return  string      String with attributes for the frame-tag. With a prefixed space character.
07817      * @access private
07818      * @link http://typo3.org/documentation/document-library/references/doc_core_tsref/current/view/7/9/
07819      * @see make(), t3lib_TStemplate::linkData()
07820      */
07821     function frameParams($setup, $typeNum) {
07822         $paramStr = '';
07823         $name = $setup['obj'];
07824 
07825         if ($setup['src'] || $setup['src.']) {
07826             $src = $setup['src'];
07827             if (is_array($setup['src.'])) {
07828                 $src = $GLOBALS['TSFE']->cObj->stdWrap($src, $setup['src.']);
07829             }
07830             $paramStr .= ' src="' . htmlspecialchars($src) . '"';
07831         } else {
07832             $LD = $GLOBALS['TSFE']->tmpl->linkData(
07833                 $GLOBALS['TSFE']->page,
07834                 '',
07835                 $GLOBALS['TSFE']->no_cache,
07836                 '',
07837                 '',
07838                 ($setup['options'] ? '&' . $setup['options'] : '') .
07839                     $GLOBALS['TSFE']->cObj->getClosestMPvalueForPage($GLOBALS['TSFE']->page['uid']), intval($typeNum)
07840             );
07841             $finalURL = $LD['totalURL'];
07842             $paramStr .= ' src="' . htmlspecialchars($finalURL) . '"';
07843         }
07844         if ($setup['name']) {
07845             $paramStr .= ' name="' . $setup['name'] . '"';
07846         } else {
07847             $paramStr .= ' name="' . $name . '"';
07848         }
07849         if ($setup['params']) {
07850             $paramStr .= ' ' . $setup['params'];
07851         }
07852         return $paramStr;
07853     }
07854 
07855     /**
07856      * Creates the attributes for a <frameset> tag based on a conf array($setup)
07857      *
07858      * @param   array       The setup array(TypoScript properties)
07859      * @return  string      Attributes with preceeding space.
07860      * @access private
07861      * @see make()
07862      */
07863     function framesetParams($setup) {
07864         $paramStr = '';
07865         if ($setup['cols']) {
07866             $paramStr .= ' cols="' . $setup['cols'] . '"';
07867         }
07868         if ($setup['rows']) {
07869             $paramStr .= ' rows="' . $setup['rows'] . '"';
07870         }
07871         if ($setup['params']) {
07872             $paramStr .= ' ' . $setup['params'];
07873         }
07874         return $paramStr;
07875     }
07876 }
07877 
07878 
07879 
07880 /**
07881  * Rendering of tables for offset
07882  *
07883  * @see tslib_cObj::OTABLE(), tslib_cObj::stdWrap()
07884  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
07885  * @package TYPO3
07886  * @subpackage tslib
07887  */
07888 class tslib_tableOffset {
07889     var $tableParams = 'border="0" cellspacing="0" cellpadding="0"';
07890     var $default_tableParams = 'border="0" cellspacing="0" cellpadding="0"';
07891     var $tdParams = ' width="99%" valign="top"';
07892 
07893     /**
07894      * Wrapping the input content string in a table which will space it out from top/left/right/bottom
07895      *
07896      * @param   string      The HTML content string
07897      * @param   string      List of offset parameters; x,y,r,b,w,h
07898      * @return  string      The HTML content string being wrapped in a <table> offsetting the content as the $offset parameters defined
07899      */
07900     function start($content, $offset) {
07901         $valPairs = t3lib_div::intExplode(',', $offset . ',,,,,');
07902 
07903         if ($valPairs[0] || $valPairs[1] || $valPairs[2] || $valPairs[3] || $valPairs[4] || $valPairs[5]) {
07904                 // If width is defined AND there has been no change to the default table params, then extend them to a tablewidth of 1
07905             if ($valPairs[4] && $this->default_tableParams == $this->tableParams) {
07906                 $this->tableParams .= ' width="1"';
07907             }
07908                 // Init:
07909             $this->begin = LF . '<table ' . $this->tableParams . '>';
07910             $this->end = '</table>';
07911             $rows = array();
07912             $widthImg = '';
07913             $heightImg = '';
07914                 // If width is required, set so bottom column will display for sure
07915             if ($valPairs[4]) {
07916                 if (!$valPairs[3])
07917                     $valPairs[3] = 1;
07918                 $widthImg = '<img src="' . $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="' .
07919                     $valPairs[4] . '" height="1" alt="" title="" />';
07920             }
07921                 // If height is required, set so right column will display for sure
07922             if ($valPairs[5]) {
07923                 if (!$valPairs[2])
07924                     $valPairs[2] = 1;
07925                 $valPairs[2] = 1;
07926                 $heightImg = '<img src="' . $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="1" height="' .
07927                     $valPairs[5] . '" alt="" title="" />';
07928             }
07929 
07930                 // First row:
07931             if ($valPairs[1]) { // top
07932                 $rows[1] .= '<tr>';
07933                 $rows[1] .= '<td><img src="' . $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="' .
07934                     ($valPairs[0] ? $valPairs[0] : 1) . '" height="' . $valPairs[1] . '" alt="" title="" /></td>';
07935                 if ($valPairs[0])
07936                     $rows[1] .= '<td></td>';
07937                 if ($valPairs[2])
07938                     $rows[1] .= '<td></td>';
07939                 $rows[1] .= '</tr>';
07940             }
07941                 // Middle row:
07942             $rows[2] .= '<tr>';
07943             if ($valPairs[0]) {
07944                 $rows[2] .= $valPairs[1] ? '<td></td>' : '<td><img src="' . $GLOBALS['TSFE']->absRefPrefix .
07945                     'clear.gif" width="' . $valPairs[0] . '" height="1" alt="" title="" /></td>';
07946             }
07947             $rows[2] .= '<td' . $this->tdParams . '>' . $content . '</td>';
07948             if ($valPairs[2]) {
07949                 $rows[2] .= $valPairs[3] ? '<td>' . $heightImg . '</td>' : '<td><img src="' .
07950                     $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="' . $valPairs[2] . '" height="' .
07951                     ($valPairs[5] ? $valPairs[5] : 1) . '" alt="" title="" /></td>';
07952             }
07953             $rows[2] .= '</tr>';
07954                 // Bottom row:
07955             if ($valPairs[3]) { // bottom
07956                 $rows[3] .= '<tr>';
07957                 if ($valPairs[0])
07958                     $rows[3] .= '<td></td>';
07959                 if ($valPairs[2])
07960                     $rows[3] .= '<td>' . $widthImg . '</td>';
07961                 $rows[3] .= '<td><img src="' . $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="' .
07962                     ($valPairs[2] ? $valPairs[2] : ($valPairs[4] ? $valPairs[4] : 1)) . '" height="' .
07963                     $valPairs[3] . '" alt="" title="" /></td>';
07964                 $rows[3] .= '</tr>';
07965             }
07966             return $this->begin . implode('', $rows) . $this->end;
07967         } else
07968             return $content;
07969     }
07970 }
07971 
07972 
07973 
07974 /**
07975  * Rendering of tables for content positioning
07976  *
07977  * @see tslib_cObj::CTABLE()
07978  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
07979  * @package TYPO3
07980  * @subpackage tslib
07981  */
07982 class tslib_controlTable {
07983     var $offX = 0; // offset, x
07984     var $offY = 0; // offset, y
07985 
07986 
07987     var $tm = ''; // top menu
07988     var $lm = ''; // left menu
07989     var $rm = ''; // right menu
07990     var $bm = ''; // bottom menu
07991     var $content = ''; // content
07992 
07993 
07994     var $tmTDparams = 'valign="top"'; // top menu TDparams
07995     var $lmTDparams = 'valign="top"'; // left menu TDparams
07996     var $rmTDparams = 'valign="top"'; // right menu TDparams
07997     var $bmTDparams = 'valign="top"'; // bottom menu TDparams
07998     var $contentTDparams = 'valign="top"'; // content TDparams
07999 
08000 
08001     var $cMl = 1; // content margin, left
08002     var $cMr = 1; // content margin, right
08003     var $cMt = 0; // content margin, top
08004     var $cMb = 1; // content margin, bottom
08005 
08006 
08007     var $contentW = 0; // Places a little gif-spacer in the bottom of the content frame
08008 
08009 
08010     var $tableParams = 'border="0" cellspacing="0" cellpadding="0"';
08011 
08012     /**
08013      * Wrapping internal vars ->tm, ->lm, ->rm, ->bm and ->content in a table where each content part is stored in a cell.
08014      * The two arguments to this function defines some offsets and margins to use in the arrangement of the content in the table.
08015      *
08016      * @param   string      List of offset parameters; x,y
08017      * @param   string      List of margin parameters; left, top, right, bottom
08018      * @return  string      The content strings wrapped in a <table> as the parameters defined
08019      * @see tslib_cObj::CTABLE()
08020      */
08021     function start($offset, $cMargins) {
08022         $offArr = t3lib_div::intExplode(',', $offset);
08023         $cMargArr = t3lib_div::intExplode(',', $cMargins);
08024 
08025         $cols = 0;
08026         $rows = 0;
08027 
08028         if ($this->lm)
08029             $cols++;
08030         if ($this->rm)
08031             $cols++;
08032         if ($cMargArr[0])
08033             $cols++;
08034         if ($cMargArr[2])
08035             $cols++;
08036         if ($cMargArr[1] || $cMargArr[3] || $this->tm || $this->bm || $this->content || $this->contentW)
08037             $cols++;
08038 
08039         if ($cMargArr[1])
08040             $rows++;
08041         if ($cMargArr[3])
08042             $rows++;
08043         if ($this->tm)
08044             $rows++;
08045         if ($this->bm)
08046             $rows++;
08047         if ($this->content)
08048             $rows++;
08049         if ($this->contentW)
08050             $rows++;
08051         if (!$rows && $cols)
08052             $rows = 1; // If there are no rows in the middle but still som columns...
08053 
08054 
08055         if ($rows && $cols) {
08056             $res = LF . '<table ' . $this->tableParams . '>';
08057                 // top offset:
08058             if ($offArr[1]) {
08059                 $xoff = $offArr[0] ? 1 : 0;
08060                 if ($cols + $xoff > 1) {
08061                     $colspan = ' colspan="' . ($cols + $xoff) . '"';
08062                 }
08063                 $res .= '<tr><td' . $colspan . '><img src="' . $GLOBALS['TSFE']->absRefPrefix .
08064                     'clear.gif" width="1" height="' . $offArr[1] . '" alt="" title="" /></td></tr>';
08065             }
08066                 // The rows:
08067             if ($rows > 1) {
08068                 $rowspan = ' rowspan="' . ($rows) . '"';
08069             }
08070             $res .= '<tr>';
08071             if ($offArr[0]) {
08072                 $res .= '<td' . $rowspan . '><img src="' . $GLOBALS['TSFE']->absRefPrefix .
08073                     'clear.gif" height="1" width="' . $offArr[0] . '" alt="" title="" /></td>';
08074             }
08075             if ($this->lm) {
08076                 $res .= '<td' . $rowspan . ' ' . $this->lmTDparams . '>' . $this->lm . '</td>';
08077             }
08078             if ($cMargArr[0]) {
08079                 $res .= '<td' . $rowspan . '><img src="' . $GLOBALS['TSFE']->absRefPrefix .
08080                     'clear.gif" height="1" width="' . $cMargArr[0] . '" alt="" title="" /></td>';
08081             }
08082                 // content...
08083 
08084 
08085             $middle = array();
08086             if ($this->tm) {
08087                 $middle[] = '<td ' . $this->tmTDparams . '>' . $this->tm . '</td>';
08088             }
08089             if ($cMargArr[1]) {
08090                 $middle[] = '<td><img src="' . $GLOBALS['TSFE']->absRefPrefix .
08091                     'clear.gif" width="1" height="' . $cMargArr[1] . '" alt="" title="" /></td>';
08092             }
08093             if ($this->content) {
08094                 $middle[] = '<td ' . $this->contentTDparams . '>' . $this->content . '</td>';
08095             }
08096             if ($cMargArr[3]) {
08097                 $middle[] = '<td><img src="' . $GLOBALS['TSFE']->absRefPrefix .
08098                     'clear.gif" width="1" height="' . $cMargArr[3] . '" alt="" title="" /></td>';
08099             }
08100             if ($this->bm) {
08101                 $middle[] = '<td ' . $this->bmTDparams . '>' . $this->bm . '</td>';
08102             }
08103             if ($this->contentW) {
08104                 $middle[] = '<td><img src="' . $GLOBALS['TSFE']->absRefPrefix .
08105                     'clear.gif" height="1" width="' . $this->contentW . '" alt="" title="" /></td>';
08106             }
08107             if (isset($middle[0])) {
08108                 $res .= $middle[0];
08109             }
08110 
08111                 // Left of content
08112             if ($cMargArr[2]) {
08113                 $res .= '<td' . $rowspan . '><img src="' . $GLOBALS['TSFE']->absRefPrefix .
08114                     'clear.gif" height="1" width="' . $cMargArr[2] . '" alt="" title="" /></td>';
08115             }
08116             if ($this->rm) {
08117                 $res .= '<td' . $rowspan . ' ' . $this->rmTDparams . '>' . $this->rm . '</td>';
08118             }
08119             $res .= '</tr>';
08120 
08121                 // More than the two rows
08122             $mCount = count($middle);
08123             for ($a = 1; $a < $mCount; $a++) {
08124                 $res .= '<tr>' . $middle[$a] . '</tr>';
08125             }
08126             $res .= '</table>';
08127             return $res;
08128         }
08129     }
08130 }
08131 
08132 
08133 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_content.php'])) {
08134     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_content.php']);
08135 }
08136 
08137 ?>