Bug #6682: GMENU property disableAltText clears the content of alt param, but does...
[Packages/TYPO3.CMS.git] / typo3 / sysext / cms / tslib / class.tslib_menu.php
index 5b2f6fa..c67566c 100755 (executable)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  (c) 1999-2007 Kasper Skaarhoj (kasperYYYY@typo3.com)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
  *
  *
  *
- *  143: class tslib_menu
- *  187:     function start(&$tmpl,&$sys_page,$id,$conf,$menuNumber)
- *  313:     function makeMenu()
- *  822:     function includeMakeMenu($conf,$altSortField)
- *  838:     function filterMenuPages(&$data,$banUidArray,$spacer)
- *  894:     function procesItemStates($splitCount)
- * 1082:     function link($key,$altTarget='',$typeOverride='')
- * 1142:     function subMenu($uid)
- * 1184:     function isNext($uid, $MPvar='')
- * 1205:     function isActive($uid, $MPvar='')
- * 1226:     function isCurrent($uid, $MPvar='')
- * 1241:     function isSubMenu($uid)
- * 1266:     function isItemState($kind,$key)
- * 1303:     function accessKey($title)
- * 1329:     function userProcess($mConfKey,$passVar)
- * 1344:     function setATagParts()
- * 1357:     function getPageTitle($title,$nav_title)
- * 1369:     function getMPvar($key)
- * 1384:     function getDoktypeExcludeWhere()
+ *  145: class tslib_menu
+ *  191:     function start(&$tmpl,&$sys_page,$id,$conf,$menuNumber,$objSuffix='')
+ *  324:     function makeMenu()
+ *  865:     function includeMakeMenu($conf,$altSortField)
+ *  881:     function filterMenuPages(&$data,$banUidArray,$spacer)
+ *  937:     function procesItemStates($splitCount)
+ * 1147:     function link($key,$altTarget='',$typeOverride='')
+ * 1212:     function changeLinksForAccessRestrictedPages(&$LD, $page, $mainTarget, $typeOverride)
+ * 1233:     function subMenu($uid, $objSuffix='')
+ * 1278:     function isNext($uid, $MPvar='')
+ * 1299:     function isActive($uid, $MPvar='')
+ * 1320:     function isCurrent($uid, $MPvar='')
+ * 1335:     function isSubMenu($uid)
+ * 1360:     function isItemState($kind,$key)
+ * 1400:     function accessKey($title)
+ * 1426:     function userProcess($mConfKey,$passVar)
+ * 1441:     function setATagParts()
+ * 1454:     function getPageTitle($title,$nav_title)
+ * 1466:     function getMPvar($key)
+ * 1481:     function getDoktypeExcludeWhere()
+ * 1491:     function getBannedUids()
  *
  *
- * 1416: class tslib_tmenu extends tslib_menu
- * 1425:     function generate()
- * 1441:     function writeMenu()
- * 1582:     function getBeforeAfter($pref)
- * 1612:     function addJScolorShiftFunction()
- * 1634:     function extProc_init()
- * 1645:     function extProc_RO($key)
- * 1656:     function extProc_beforeLinking($key)
- * 1668:     function extProc_afterLinking($key)
- * 1685:     function extProc_beforeAllWrap($item,$key)
- * 1696:     function extProc_finish()
+ * 1530: class tslib_tmenu extends tslib_menu
+ * 1539:     function generate()
+ * 1555:     function writeMenu()
+ * 1699:     function getBeforeAfter($pref)
+ * 1729:     function addJScolorShiftFunction()
+ * 1751:     function extProc_init()
+ * 1762:     function extProc_RO($key)
+ * 1773:     function extProc_beforeLinking($key)
+ * 1785:     function extProc_afterLinking($key)
+ * 1802:     function extProc_beforeAllWrap($item,$key)
+ * 1813:     function extProc_finish()
  *
  *
- * 1732: class tslib_gmenu extends tslib_menu
- * 1741:     function generate()
- * 1779:     function makeGifs($conf, $resKey)
- * 1984:     function findLargestDims($conf,$items,$Hobjs,$Wobjs,$minDim,$maxDim)
- * 2056:     function writeMenu()
- * 2173:     function extProc_init()
- * 2184:     function extProc_RO($key)
- * 2195:     function extProc_beforeLinking($key)
- * 2208:     function extProc_afterLinking($key)
- * 2225:     function extProc_beforeAllWrap($item,$key)
- * 2236:     function extProc_finish()
+ * 1849: class tslib_gmenu extends tslib_menu
+ * 1858:     function generate()
+ * 1896:     function makeGifs($conf, $resKey)
+ * 2101:     function findLargestDims($conf,$items,$Hobjs,$Wobjs,$minDim,$maxDim)
+ * 2173:     function writeMenu()
+ * 2294:     function extProc_init()
+ * 2305:     function extProc_RO($key)
+ * 2316:     function extProc_beforeLinking($key)
+ * 2329:     function extProc_afterLinking($key)
+ * 2346:     function extProc_beforeAllWrap($item,$key)
+ * 2357:     function extProc_finish()
  *
  *
- * 2270: class tslib_imgmenu extends tslib_menu
- * 2279:     function generate()
- * 2297:     function makeImageMap($conf)
- * 2480:     function writeMenu()
+ * 2391: class tslib_imgmenu extends tslib_menu
+ * 2400:     function generate()
+ * 2418:     function makeImageMap($conf)
+ * 2604:     function writeMenu()
  *
  *
- * 2523: class tslib_jsmenu extends tslib_menu
- * 2530:     function generate()
- * 2538:     function writeMenu()
- * 2599:     function generate_level($levels,$count,$pid,$menuItemArray='',$MP_array=array())
+ * 2647: class tslib_jsmenu extends tslib_menu
+ * 2654:     function generate()
+ * 2662:     function writeMenu()
+ * 2723:     function generate_level($levels,$count,$pid,$menuItemArray='',$MP_array=array())
  *
- * TOTAL FUNCTIONS: 44
+ * TOTAL FUNCTIONS: 46
  * (This index is automatically created/updated by the extension "extdeveval")
  *
  */
@@ -149,15 +151,33 @@ class tslib_menu {
        var $imgNamePrefix = 'img';
        var $imgNameNotRandom=0;
        var $debug = 0;
-       var $parent_cObj ='';                           // Loaded with the parent cObj-object when a new HMENU is made
+
+       /**
+        * Loaded with the parent cObj-object when a new HMENU is made
+        *
+        * @var tslib_cObj
+        */
+       var $parent_cObj;
        var $GMENU_fixKey='gmenu';
        var $MP_array=array();                          // accumulation of mount point data
 
                // internal
        var $conf = Array();                            // HMENU configuration
        var $mconf = Array();                           // xMENU configuration (TMENU, GMENU etc)
-       var $tmpl;              // template-object
-       var $sys_page;  // sys_page-object
+
+       /**
+        * template-object
+        *
+        * @var t3lib_TStemplate
+        */
+       var $tmpl;
+
+       /**
+        * sys_page-object, pagefunctions
+        *
+        * @var t3lib_pageSelect
+        */
+       var $sys_page;
        var $id;                                                        // The base page-id of the menu.
        var $nextActive;                                        // Holds the page uid of the NEXT page in the root line from the page pointed to by entryLevel; Used to expand the menu automatically if in a certain root line.
        var $menuArr;   // The array of menuItems which is built
@@ -195,7 +215,7 @@ class tslib_menu {
                $this->debug=$GLOBALS['TSFE']->debug;
 
                        // In XHTML there is no "name" attribute anymore
-               switch ($GLOBALS['TSFE']->config['config']['doctype'])  {
+               switch ($GLOBALS['TSFE']->xhtmlDoctype) {
                        case 'xhtml_strict':
                        case 'xhtml_11':
                        case 'xhtml_2':
@@ -371,12 +391,19 @@ class tslib_menu {
                                                        } else {
                                                                $iState = $GLOBALS['TSFE']->sys_language_uid==$sUid ? 'ACT' : 'NO';
                                                        }
+
+                                                       if ($this->conf['addQueryString'])      {
+                                                               $getVars = $this->parent_cObj->getQueryArguments($this->conf['addQueryString.'],array('L'=>$sUid),true);
+                                                       } else {
+                                                               $getVars = '&L='.$sUid;
+                                                       }
+
                                                                // Adding menu item:
                                                        $temp[] = array_merge(
                                                                array_merge($currentPageWithNoOverlay, $lRecs),
                                                                array(
                                                                        'ITEM_STATE' => $iState,
-                                                                       '_ADD_GETVARS' => '&L='.$sUid,
+                                                                       '_ADD_GETVARS' => $getVars,
                                                                        '_SAFE' => TRUE
                                                                )
                                                        );
@@ -506,7 +533,7 @@ class tslib_menu {
                                                        break;
                                                }
                                                        // Get
-                                               $extraWhere = ' AND pages.nav_hide=0'.$this->getDoktypeExcludeWhere();
+                                               $extraWhere = ($this->conf['includeNotInMenu'] ? '' : ' AND pages.nav_hide=0').$this->getDoktypeExcludeWhere();
 
                                                if ($this->conf['special.']['excludeNoSearchPages']) {
                                                        $extraWhere.= ' AND pages.no_search=0';
@@ -564,7 +591,7 @@ class tslib_menu {
                                                        $depth=20;
                                                }
                                                $limit = t3lib_div::intInRange($this->conf['special.']['limit'],0,100); // max number of items
-                                               $extraWhere = ' AND pages.uid!='.$value.' AND pages.nav_hide=0'.$this->getDoktypeExcludeWhere();
+                                               $extraWhere = ' AND pages.uid!='.$value.($this->conf['includeNotInMenu'] ? '' : ' AND pages.nav_hide=0').$this->getDoktypeExcludeWhere();
                                                if ($this->conf['special.']['excludeNoSearchPages']) {
                                                        $extraWhere.= ' AND pages.no_search=0';
                                                }
@@ -637,69 +664,69 @@ class tslib_menu {
                                                        $value=$GLOBALS['TSFE']->page['uid'];
                                                }
                                                if ($value!=$this->tmpl->rootLine[0]['uid'])    {       // Will not work out of rootline
-                                                       $recArr=array();
-                                                       $value_rec=$this->sys_page->getPage($value);    // The page record of the 'value'.
-                                                       if ($value_rec['pid'])  {       // 'up' page cannot be outside rootline
-                                                               $recArr['up']=$this->sys_page->getPage($value_rec['pid']);      // The page record of 'up'.
-                                                       }
-                                                       if ($recArr['up']['pid'] && $value_rec['pid']!=$this->tmpl->rootLine[0]['uid']) {       // If the 'up' item was NOT level 0 in rootline...
-                                                               $recArr['index']=$this->sys_page->getPage($recArr['up']['pid']);        // The page record of "index".
-                                                       }
-
-                                                               // prev / next is found
-                                                       $prevnext_menu = $this->sys_page->getMenu($value_rec['pid'],'*',$altSortField);
-                                                       $lastKey=0;
-                                                       $nextActive=0;
-                                                       reset($prevnext_menu);
-                                                       while(list($k_b,$v_b)=each($prevnext_menu))     {
-                                                               if ($nextActive)        {
-                                                                       $recArr['next']=$v_b;
-                                                                       $nextActive=0;
+                                                       $recArr=array();
+                                                       $value_rec=$this->sys_page->getPage($value);    // The page record of the 'value'.
+                                                       if ($value_rec['pid'])  {       // 'up' page cannot be outside rootline
+                                                               $recArr['up']=$this->sys_page->getPage($value_rec['pid']);      // The page record of 'up'.
+                                                       }
+                                                       if ($recArr['up']['pid'] && $value_rec['pid']!=$this->tmpl->rootLine[0]['uid']) {       // If the 'up' item was NOT level 0 in rootline...
+                                                               $recArr['index']=$this->sys_page->getPage($recArr['up']['pid']);        // The page record of "index".
+                                                       }
+
+                                                               // prev / next is found
+                                                       $prevnext_menu = $this->sys_page->getMenu($value_rec['pid'],'*',$altSortField);
+                                                       $lastKey=0;
+                                                       $nextActive=0;
+                                                       reset($prevnext_menu);
+                                                       while(list($k_b,$v_b)=each($prevnext_menu))     {
+                                                               if ($nextActive)        {
+                                                                       $recArr['next']=$v_b;
+                                                                       $nextActive=0;
                                                                }
-                                                               if ($v_b['uid']==$value)        {
-                                                                       if ($lastKey)   {
-                                                                               $recArr['prev']=$prevnext_menu[$lastKey];
-                                                                       }
-                                                                       $nextActive=1;
+                                                               if ($v_b['uid']==$value)        {
+                                                                       if ($lastKey)   {
+                                                                               $recArr['prev']=$prevnext_menu[$lastKey];
+                                                                       }
+                                                                       $nextActive=1;
                                                                }
-                                                               $lastKey=$k_b;
-                                                       }
-                                                       reset($prevnext_menu);
+                                                               $lastKey=$k_b;
+                                                       }
+                                                       reset($prevnext_menu);
                                                        $recArr['first']=pos($prevnext_menu);
                                                        end($prevnext_menu);
                                                        $recArr['last']=pos($prevnext_menu);
 
-                                                               // prevsection / nextsection is found
+                                                               // prevsection / nextsection is found
                                                        if (is_array($recArr['index'])) {       // You can only do this, if there is a valid page two levels up!
-                                                               $prevnextsection_menu = $this->sys_page->getMenu($recArr['index']['uid'],'*',$altSortField);
-                                                               $lastKey=0;
-                                                               $nextActive=0;
-                                                               reset($prevnextsection_menu);
-                                                               while(list($k_b,$v_b)=each($prevnextsection_menu))      {
-                                                                       if ($nextActive)        {
+                                                               $prevnextsection_menu = $this->sys_page->getMenu($recArr['index']['uid'],'*',$altSortField);
+                                                               $lastKey=0;
+                                                               $nextActive=0;
+                                                               reset($prevnextsection_menu);
+                                                               while(list($k_b,$v_b)=each($prevnextsection_menu))      {
+                                                                       if ($nextActive)        {
                                                                                $sectionRec_temp = $this->sys_page->getMenu($v_b['uid'],'*',$altSortField);
                                                                                if (count($sectionRec_temp))    {
                                                                                        reset($sectionRec_temp);
-                                                                                       $recArr['nextsection']=pos($sectionRec_temp);
+                                                                                       $recArr['nextsection']=pos($sectionRec_temp);
                                                                                        end ($sectionRec_temp);
-                                                                                       $recArr['nextsection_last']=pos($sectionRec_temp);
-                                                                                       $nextActive=0;
+                                                                                       $recArr['nextsection_last']=pos($sectionRec_temp);
+                                                                                       $nextActive=0;
                                                                                }
                                                                        }
-                                                                       if ($v_b['uid']==$value_rec['pid'])     {
-                                                                               if ($lastKey)   {
+                                                                       if ($v_b['uid']==$value_rec['pid'])     {
+                                                                               if ($lastKey)   {
                                                                                        $sectionRec_temp = $this->sys_page->getMenu($prevnextsection_menu[$lastKey]['uid'],'*',$altSortField);
                                                                                        if (count($sectionRec_temp))    {
                                                                                                reset($sectionRec_temp);
-                                                                                               $recArr['prevsection']=pos($sectionRec_temp);
+                                                                                               $recArr['prevsection']=pos($sectionRec_temp);
                                                                                                end ($sectionRec_temp);
-                                                                                               $recArr['prevsection_last']=pos($sectionRec_temp);
+                                                                                               $recArr['prevsection_last']=pos($sectionRec_temp);
                                                                                        }
-                                                                               }
-                                                                               $nextActive=1;
+                                                                               }
+                                                                               $nextActive=1;
                                                                        }
-                                                                       $lastKey=$k_b;
-                                                               }
+                                                                       $lastKey=$k_b;
+                                                               }
                                                        }
                                                        if ($this->conf['special.']['items.']['prevnextToSection'])     {
                                                                if (!is_array($recArr['prev']) && is_array($recArr['prevsection_last']))        {
@@ -710,15 +737,15 @@ class tslib_menu {
                                                                }
                                                        }
 
-                                                       $items = explode('|',$this->conf['special.']['items']);
+                                                       $items = explode('|',$this->conf['special.']['items']);
                                                        $c=0;
-                                                       while(list($k_b,$v_b)=each($items))     {
-                                                               $v_b=strtolower(trim($v_b));
+                                                       while(list($k_b,$v_b)=each($items))     {
+                                                               $v_b=strtolower(trim($v_b));
                                                                if (intval($this->conf['special.'][$v_b.'.']['uid']))   {
                                                                        $recArr[$v_b] = $this->sys_page->getPage(intval($this->conf['special.'][$v_b.'.']['uid']));     // fetches the page in case of a hardcoded pid in template
                                                                }
-                                                               if (is_array($recArr[$v_b]))    {
-                                                                       $temp[$c]=$recArr[$v_b];
+                                                               if (is_array($recArr[$v_b]))    {
+                                                                       $temp[$c]=$recArr[$v_b];
                                                                        if ($this->conf['special.'][$v_b.'.']['target'])        {
                                                                                $temp[$c]['target']=$this->conf['special.'][$v_b.'.']['target'];
                                                                        }
@@ -730,7 +757,7 @@ class tslib_menu {
                                                                        }
                                                                        $c++;
                                                                }
-                                                       }
+                                                       }
                                                }
                                        break;
                                }
@@ -762,19 +789,20 @@ class tslib_menu {
                                                $GLOBALS['TSFE']->sys_page->versionOL('tt_content',$row);
 
                                                if (is_array($row))     {
-                                                       $temp[$row['uid']]=$basePageRow;
-                                                       $temp[$row['uid']]['title']=$row['header'];
-                                                       $temp[$row['uid']]['subtitle']=$row['subheader'];
-                                                       $temp[$row['uid']]['starttime']=$row['starttime'];
-                                                       $temp[$row['uid']]['endtime']=$row['endtime'];
-                                                       $temp[$row['uid']]['fe_group']=$row['fe_group'];
-                                                       $temp[$row['uid']]['media']=$row['media'];
-
-                                                       $temp[$row['uid']]['header_layout']=$row['header_layout'];
-                                                       $temp[$row['uid']]['bodytext']=$row['bodytext'];
-                                                       $temp[$row['uid']]['image']=$row['image'];
-
-                                                       $temp[$row['uid']]['sectionIndex_uid']=$row['uid'];
+                                                       $temp[$row['uid']] = $basePageRow;
+                                                       $temp[$row['uid']]['title'] = $row['header'];
+                                                       $temp[$row['uid']]['nav_title'] = $row['header'];
+                                                       $temp[$row['uid']]['subtitle'] = $row['subheader'];
+                                                       $temp[$row['uid']]['starttime'] = $row['starttime'];
+                                                       $temp[$row['uid']]['endtime'] = $row['endtime'];
+                                                       $temp[$row['uid']]['fe_group'] = $row['fe_group'];
+                                                       $temp[$row['uid']]['media'] = $row['media'];
+
+                                                       $temp[$row['uid']]['header_layout'] = $row['header_layout'];
+                                                       $temp[$row['uid']]['bodytext'] = $row['bodytext'];
+                                                       $temp[$row['uid']]['image'] = $row['image'];
+
+                                                       $temp[$row['uid']]['sectionIndex_uid'] = $row['uid'];
                                                }
                                        }
                                }
@@ -788,10 +816,7 @@ class tslib_menu {
                        $maxItems = intval($this->mconf['maxItems'] ? $this->mconf['maxItems'] : $this->conf['maxItems']);
                        $begin = tslib_cObj::calc($this->mconf['begin'] ? $this->mconf['begin'] : $this->conf['begin']);
 
-                       $banUidArray=array();
-                       if (trim($this->conf['excludeUidList']))        {
-                               $banUidArray = t3lib_div::intExplode(',', $this->conf['excludeUidList']);
-                       }
+                       $banUidArray = $this->getBannedUids();
 
                                // Fill in the menuArr with elements that should go into the menu:
                        $this->menuArr = Array();
@@ -829,12 +854,18 @@ class tslib_menu {
                        }
                        $this->hash = md5(serialize($this->menuArr).serialize($this->mconf).serialize($this->tmpl->rootLine).serialize($this->MP_array));
 
-                       $serData = $this->sys_page->getHash($this->hash, 60*60*24);
+                               // Get the cache timeout:
+                       if ($this->conf['cache_period']) {
+                               $cacheTimeout = $this->conf['cache_period'];
+                       } else {
+                               $cacheTimeout = $GLOBALS['TSFE']->get_cache_timeout();
+                       }
+                       $serData = $this->sys_page->getHash($this->hash, $cacheTimeout);
                        if (!$serData)  {
                                $this->generate();
                                $this->sys_page->storeHash($this->hash, serialize($this->result),'MENUDATA');
                        } else {
-                               $this->result=unserialize($serData);
+                               $this->result = unserialize($serData);
                        }
 
                                // End showAccessRestrictedPages
@@ -848,7 +879,7 @@ class tslib_menu {
        /**
         * Includes the PHP script defined for the HMENU special type "userdefined".
         * This script is supposed to populate the array $menuItemsArray with a set of page records comprising the menu.
-        * The "userdefined" type is depreciated since "userfunction" has arrived since and is a better choice for many reasons (like using classes/functions for rendering the menu)
+        * The "userdefined" type is deprecated since "userfunction" has arrived since and is a better choice for many reasons (like using classes/functions for rendering the menu)
         *
         * @param       array           TypoScript parameters for "special.". In particular the property "file" is reserved and specifies the file to include. Seems like any other property can be used freely by the script.
         * @param       string          The sorting field. Can be used from the script in the $incFile.
@@ -878,7 +909,7 @@ class tslib_menu {
                $uid = $data['uid'];
                if ($this->mconf['SPC'] || !$spacer)    {       // If the spacer-function is not enabled, spacers will not enter the $menuArr
                        if (!t3lib_div::inList($this->doktypeExcludeList,$data['doktype']))     {               // Page may not be 'not_in_menu' or 'Backend User Section'
-                               if (!$data['nav_hide']) {       // Not hidden in navigation
+                               if (!$data['nav_hide'] || $this->conf['includeNotInMenu'])      {       // Not hidden in navigation
                                        if (!t3lib_div::inArray($banUidArray,$uid))     {       // not in banned uid's
 
                                                        // Checks if the default language version can be shown:
@@ -899,9 +930,9 @@ class tslib_menu {
 
                                                                        // Checking if "&L" should be modified so links to non-accessible pages will not happen.
                                                                if ($this->conf['protectLvar']) {
-                                                                       $Lvar = intval(t3lib_div::_GP('L'));
-                                                                       if (($this->conf['protectLvar']=='all' || t3lib_div::hideIfNotTranslated($data['l18n_cfg'])) && $Lvar!=$GLOBALS['TSFE']->sys_language_uid)      {       // page cannot be access in locaization and Lvar is different than sys_language uid - this means we must check!
-                                                                               $olRec = $GLOBALS['TSFE']->sys_page->getPageOverlay($data['uid'], $Lvar);
+                                                                       $languageUid = intval($GLOBALS['TSFE']->config['config']['sys_language_uid']);
+                                                                       if ($languageUid && ($this->conf['protectLvar']=='all' || t3lib_div::hideIfNotTranslated($data['l18n_cfg'])))   {
+                                                                               $olRec = $GLOBALS['TSFE']->sys_page->getPageOverlay($data['uid'], $languageUid);
                                                                                if (!count($olRec))     {
                                                                                                // If no pages_language_overlay record then page can NOT be accessed in the language pointed to by "&L" and therefore we protect the link by setting "&L=0"
                                                                                        $data['_ADD_GETVARS'].= '&L=0';
@@ -1162,7 +1193,14 @@ class tslib_menu {
                        $thePage = $this->sys_page->getPage($this->menuArr[$key]['pid']);
                        $LD = $this->tmpl->linkData($thePage,$mainTarget,'','',$overrideArray, $this->mconf['addParams'].$MP_params.$this->menuArr[$key]['_ADD_GETVARS'], $typeOverride);
                } else {
-                       $LD = $this->tmpl->linkData($this->menuArr[$key],$mainTarget,'','',$overrideArray, $this->mconf['addParams'].$MP_params.$this->menuArr[$key]['_ADD_GETVARS'], $typeOverride);
+                       $LD = $this->tmpl->linkData($this->menuArr[$key],$mainTarget,'','',$overrideArray, $this->mconf['addParams'].$MP_params.$this->I['val']['additionalParams'].$this->menuArr[$key]['_ADD_GETVARS'], $typeOverride);
+               }
+
+                       // Override URL if using "External URL" as doktype with a valid e-mail address:
+               if ($this->menuArr[$key]['doktype'] == 3 && $this->menuArr[$key]['urltype'] == 3 && t3lib_div::validEmail($this->menuArr[$key]['url'])) {
+                               // Create mailto-link using tslib_cObj::typolink (concerning spamProtectEmailAddresses):
+                       $LD['totalURL'] = $this->parent_cObj->typoLink_URL(array('parameter' => $this->menuArr[$key]['url']));
+                       $LD['target'] = '';
                }
 
                        // Manipulation in case of access restricted pages:
@@ -1196,16 +1234,16 @@ class tslib_menu {
        /**
         * Will change $LD (passed by reference) if the page is access restricted
         *
-        * @param       array   $LD, the array from the linkData() function
-        * @param       array   Page array
-        * @param       string  Main target value
-        * @param       string  Type number override if any
-        * @return      void    ($LD passed by reference might be changed.)
+        * @param       array           $LD, the array from the linkData() function
+        * @param       array           Page array
+        * @param       string          Main target value
+        * @param       string          Type number override if any
+        * @return      void            ($LD passed by reference might be changed.)
         */
        function changeLinksForAccessRestrictedPages(&$LD, $page, $mainTarget, $typeOverride)   {
 
                        // If access restricted pages should be shown in menus, change the link of such pages to link to a redirection page:
-               if ($this->mconf['showAccessRestrictedPages'] && $this->mconf['showAccessRestrictedPages']!=='NONE' && !$GLOBALS['TSFE']->checkPageGroupAccess($page))          {
+               if ($this->mconf['showAccessRestrictedPages'] && $this->mconf['showAccessRestrictedPages']!=='NONE' && !$GLOBALS['TSFE']->checkPageGroupAccess($page))  {
                        $thePage = $this->sys_page->getPage($this->mconf['showAccessRestrictedPages']);
 
                        $addParams = $this->mconf['showAccessRestrictedPages.']['addParams'];
@@ -1245,6 +1283,7 @@ class tslib_menu {
                        }
 
                                // especially scripts that build the submenu needs the parent data
+                       $submenu->parent_cObj = &$this->parent_cObj;
                        $submenu->parentMenuArr = $this->menuArr;
 
                                // Setting alternativeMenuTempArray (will be effective only if an array)
@@ -1333,9 +1372,9 @@ class tslib_menu {
                        $uid = $mount_info['mount_pid'];
                }
 
-               $recs = $this->sys_page->getMenu($uid,'uid,pid,doktype,mount_pid,mount_pid_ol,nav_hide');
+               $recs = $this->sys_page->getMenu($uid,'uid,pid,doktype,mount_pid,mount_pid_ol,nav_hide,shortcut,shortcut_mode');
                foreach($recs as $theRec)       {
-                       if (!t3lib_div::inList($this->doktypeExcludeList,$theRec['doktype']) && !$theRec['nav_hide'])   {       // If a menu item seems to be another type than 'Not in menu', then return true (there were items!)
+                       if (!t3lib_div::inList($this->doktypeExcludeList,$theRec['doktype']) && (!$theRec['nav_hide'] || $this->conf['includeNotInMenu']))      {       // If a menu item seems to be another type than 'Not in menu', then return true (there were items!)
                                return TRUE;
                        }
                }
@@ -1384,7 +1423,7 @@ class tslib_menu {
        }
 
        /**
-        * Creates an access-key for a GMENU menu item based on the menu item titles first letter
+        * Creates an access-key for a TMENU/GMENU menu item based on the menu item titles first letter
         *
         * @param       string          Menu item title.
         * @return      array           Returns an array with keys "code" ("accesskey" attribute for the img-tag) and "alt" (text-addition to the "alt" attribute) if an access key was defined. Otherwise array was empty
@@ -1394,13 +1433,15 @@ class tslib_menu {
                        // The global array ACCESSKEY is used to globally control if letters are already used!!
                $result = Array();
 
+               $title = trim(strip_tags($title));
                $titleLen = strlen($title);
                for ($a=0;$a<$titleLen;$a++)    {
-                       $key = strtoupper(trim(substr($title,$a,1)));
-                       if (preg_match('/[a-zA-Z]/', $key) && !isset($GLOBALS['TSFE']->accessKey[$key]))        {
-                               $GLOBALS['TSFE']->accessKey[$key]=1;
+                       $key = strtoupper(substr($title,$a,1));
+                       if (preg_match('/[A-Z]/', $key) && !isset($GLOBALS['TSFE']->accessKey[$key]))   {
+                               $GLOBALS['TSFE']->accessKey[$key] = 1;
                                $result['code'] = ' accesskey="'.$key.'"';
                                $result['alt'] = ' (ALT+'.$key.')';
+                               $result['key'] = $key;
                                break;
                        }
                }
@@ -1432,7 +1473,7 @@ class tslib_menu {
         * @access private
         */
        function setATagParts() {
-               $this->I['A1'] = '<a '.t3lib_div::implodeAttributes($this->I['linkHREF'],1).$this->I['val']['ATagParams'].$this->I['addATagParams'].$this->I['accessKey']['code'].'>';
+               $this->I['A1'] = '<a '.t3lib_div::implodeAttributes($this->I['linkHREF'],1).' '.$this->I['val']['ATagParams'].$this->I['accessKey']['code'].'>';
                $this->I['A2'] = '</a>';
        }
 
@@ -1475,6 +1516,23 @@ class tslib_menu {
                return $this->doktypeExcludeList ? ' AND pages.doktype NOT IN ('.$this->doktypeExcludeList.')' : '';
        }
 
+       /**
+        * Returns an array of banned UIDs (from excludeUidList)
+        *
+        * @return      array           Array of banned UIDs
+        * @access private
+        */
+       function getBannedUids() {
+               $banUidArray = array();
+
+               if (trim($this->conf['excludeUidList']))        {
+                       $banUidList = str_replace('current', $GLOBALS['TSFE']->page['uid'], $this->conf['excludeUidList']);
+                       $banUidArray = t3lib_div::intExplode(',', $banUidList);
+               }
+
+               return $banUidArray;
+       }
+
 }
 
 
@@ -1530,8 +1588,8 @@ class tslib_tmenu extends tslib_menu {
         */
        function writeMenu()    {
                if (is_array($this->result) && count($this->result))    {
-                       $this->WMcObj =t3lib_div::makeInstance('tslib_cObj');   // Create new tslib_cObj for our use
-                       $this->WMresult='';
+                       $this->WMcObj = t3lib_div::makeInstance('tslib_cObj');  // Create new tslib_cObj for our use
+                       $this->WMresult = '';
                        $this->INPfixMD5 = substr(md5(microtime().'tmenu'),0,4);
                        $this->WMmenuItems = count($this->result);
 
@@ -1543,10 +1601,11 @@ class tslib_tmenu extends tslib_menu {
                                $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']++;
                                $GLOBALS['TSFE']->register['count_MENUOBJ']++;
 
-                               $this->I=array();
                                $this->WMcObj->start($this->menuArr[$key],'pages');             // Initialize the cObj with the page record of the menu item
+
+                               $this->I = array();
                                $this->I['key'] = $key;
-                               $this->I['INPfix']= $this->imgNameNotRandom?'':'_'.$this->INPfixMD5.'_'.$key;
+                               $this->I['INPfix'] = ($this->imgNameNotRandom ? '' : '_'.$this->INPfixMD5).'_'.$key;
                                $this->I['val'] = $val;
                                $this->I['title'] = $this->WMcObj->stdWrap($this->getPageTitle($this->menuArr[$key]['title'],$this->menuArr[$key]['nav_title']),$this->I['val']['stdWrap.']);
                                $this->I['uid'] = $this->menuArr[$key]['uid'];
@@ -1554,12 +1613,20 @@ class tslib_tmenu extends tslib_menu {
                                $this->I['pid'] = $this->menuArr[$key]['pid'];
                                $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
 
+                                       // Set access key
+                               if ($this->mconf['accessKey'])  {
+                                       $this->I['accessKey'] = $this->accessKey($this->I['title']);
+                               } else {
+                                       $this->I['accessKey'] = Array();
+                               }
+
                                        // Make link tag
-                               $this->I['val']['ATagParams'] = $this->I['val']['ATagParams'] ? ' '.$this->I['val']['ATagParams'] : '';
-                               $this->I['linkHREF'] =  $this->link($key,$this->I['val']['altTarget'],$this->mconf['forceTypeValue']);
+                               $this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
+                               $this->I['val']['additionalParams'] = $this->WMcObj->stdWrap($this->I['val']['additionalParams'],$this->I['val']['additionalParams.']);
+                               $this->I['linkHREF'] = $this->link($key,$this->I['val']['altTarget'],$this->mconf['forceTypeValue']);
 
                                        // Title attribute of links:
-                               $titleAttrValue = $this->WMcObj->stdWrap($this->I['val']['ATagTitle'],$this->I['val']['ATagTitle.']);
+                               $titleAttrValue = $this->WMcObj->stdWrap($this->I['val']['ATagTitle'],$this->I['val']['ATagTitle.']).$this->I['accessKey']['alt'];
                                if (strlen($titleAttrValue))    {
                                        $this->I['linkHREF']['title'] = $titleAttrValue;
                                }
@@ -1610,7 +1677,7 @@ class tslib_tmenu extends tslib_menu {
                                        $this->I['A2'] = '';
                                }
 
-                                       // ATAGBeforeWrap processing:
+                                       // ATagBeforeWrap processing:
                                if ($this->I['val']['ATagBeforeWrap'])  {
                                        $wrapPartsBefore = explode('|',$this->I['val']['linkWrap']);
                                        $wrapPartsAfter = array('','');
@@ -1687,7 +1754,7 @@ class tslib_tmenu extends tslib_menu {
                                }
                        }
                        $GLOBALS['TSFE']->imagesOnPage[]=$imgInfo[3];
-                       $res='<img src="'.$GLOBALS['TSFE']->absRefPrefix.$imgInfo[3].'" width="'.$imgInfo[0].'" height="'.$imgInfo[1].'"'.$name.($this->I['val'][$pref.'ImgTagParams']?" ".$this->I['val'][$pref.'ImgTagParams']:'').' border="0"';
+                       $res='<img src="'.$GLOBALS['TSFE']->absRefPrefix.$imgInfo[3].'" width="'.$imgInfo[0].'" height="'.$imgInfo[1].'"'.$name.($this->I['val'][$pref.'ImgTagParams']?" ".$this->I['val'][$pref.'ImgTagParams']:'').tslib_cObj::getBorderAttr('border="0"');
                        if (!strstr($res,'alt="'))      $res.=' alt=""';        // Adding alt attribute if not set.
                        $res.=' />';
                        if ($this->I['val'][$pref.'ImgLink'])   {$res=$this->I['A1'].$res.$this->I['A2'];}
@@ -1787,6 +1854,10 @@ class tslib_tmenu extends tslib_menu {
         * @see writeMenu(), tslib_tmenu_layers::extProc_finish()
         */
        function extProc_finish()       {
+                       // stdWrap:
+               if (is_array($this->mconf['stdWrap.'])) {
+                       $this->WMresult = $this->WMcObj->stdWrap($this->WMresult,$this->mconf['stdWrap.']);
+               }
                return $this->tmpl->wrap($this->WMresult,$this->mconf['wrap']).$this->WMextraScript;
        }
 }
@@ -2026,12 +2097,14 @@ class tslib_gmenu extends tslib_menu {
                                $gifFileName = $gifCreator->fileName('menu/');
                        }
 
+                       $this->result[$resKey][$key] = $conf[$key];
+
                                // Generation of image file:
                        if (@file_exists($gifFileName)) {               // File exists
                                $info = @getimagesize($gifFileName);
                                $this->result[$resKey][$key]['output_w']=intval($info[0]);
                                $this->result[$resKey][$key]['output_h']=intval($info[1]);
-                               $this->result[$resKey][$key]['output_file']=$gifFileName;
+                               $this->result[$resKey][$key]['output_file'] = $gifFileName;
                        } elseif ($isGD) {              // file is generated
                                $gifCreator->make();
                                $this->result[$resKey][$key]['output_w']=$gifCreator->w;
@@ -2040,22 +2113,13 @@ class tslib_gmenu extends tslib_menu {
                                $gifCreator->output($this->result[$resKey][$key]['output_file']);
                                $gifCreator->destroy();
                        }
+
                        $this->result[$resKey][$key]['output_file'] = t3lib_div::png_to_gif_by_imagemagick($this->result[$resKey][$key]['output_file']);
-                       $this->result[$resKey][$key]['noLink']=$conf[$key]['noLink'];
-                       $this->result[$resKey][$key]['altTarget']=$conf[$key]['altTarget'];
-                       $this->result[$resKey][$key]['imgParams']=$conf[$key]['imgParams'];
-                       $this->result[$resKey][$key]['ATagTitle'] = $conf[$key]['ATagTitle'];
-                       $this->result[$resKey][$key]['ATagTitle.'] = $conf[$key]['ATagTitle.'];
-                       $this->result[$resKey][$key]['wrap'] = $conf[$key]['wrap'];
-                       $this->result[$resKey][$key]['allWrap'] = $conf[$key]['allWrap'];
-                       $this->result[$resKey][$key]['allWrap.'] = $conf[$key]['allWrap.'];
-                       $this->result[$resKey][$key]['subst_elementUid'] = $conf[$key]['subst_elementUid'];
-                       $this->result[$resKey][$key]['allStdWrap.'] = $conf[$key]['allStdWrap.'];
 
                        $Hcounter+=$this->result[$resKey][$key]['output_h'];            // counter is increased
                        $Wcounter+=$this->result[$resKey][$key]['output_w'];            // counter is increased
 
-                       if ($maxFlag){break;}
+                       if ($maxFlag)   break;
                }
        }
 
@@ -2149,7 +2213,7 @@ class tslib_gmenu extends tslib_menu {
        function writeMenu()    {
                if (is_array($this->menuArr) && is_array($this->result) && count($this->result) && is_array($this->result['NO']))       {
                        $this->WMcObj = t3lib_div::makeInstance('tslib_cObj');  // Create new tslib_cObj for our use
-                       $this->WMresult='';
+                       $this->WMresult = '';
                        $this->INPfixMD5 = substr(md5(microtime().$this->GMENU_fixKey),0,4);
                        $this->WMmenuItems = count($this->result['NO']);
 
@@ -2160,9 +2224,9 @@ class tslib_gmenu extends tslib_menu {
                                if ($this->result['NO'][$key]['output_file'])   {
                                        $this->WMcObj->start($this->menuArr[$key],'pages');             // Initialize the cObj with the page record of the menu item
 
-                                       $this->I =array();
+                                       $this->I = array();
                                        $this->I['key'] = $key;
-                                       $this->I['INPfix']= $this->imgNameNotRandom?'':'_'.$this->INPfixMD5.'_'.$key;
+                                       $this->I['INPfix']= ($this->imgNameNotRandom ? '' : '_'.$this->INPfixMD5).'_'.$key;
                                        $this->I['val'] = $this->result['NO'][$key];
                                        $this->I['title'] = $this->getPageTitle($this->menuArr[$key]['title'],$this->menuArr[$key]['nav_title']);
                                        $this->I['uid'] = $this->menuArr[$key]['uid'];
@@ -2171,17 +2235,20 @@ class tslib_gmenu extends tslib_menu {
                                        $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
                                        if (!$this->I['uid'] && !$this->menuArr[$key]['_OVERRIDE_HREF']) {$this->I['spacer']=1;}
                                        $this->I['noLink'] = ($this->I['spacer'] || $this->I['val']['noLink'] || !count($this->menuArr[$key]));         // !count($this->menuArr[$key]) means that this item is a dummyItem
-                                       $this->I['name']='';
+                                       $this->I['name'] = '';
 
                                                // Set access key
                                        if ($this->mconf['accessKey'])  {
                                                $this->I['accessKey'] = $this->accessKey($this->I['title']);
                                        } else {
-                                               $this->I['accessKey']=Array();
+                                               $this->I['accessKey'] = array();
                                        }
 
-                                               // Get link.
+                                               // Make link tag
+                                       $this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
+                                       $this->I['val']['additionalParams'] = $this->WMcObj->stdWrap($this->I['val']['additionalParams'],$this->I['val']['additionalParams.']);
                                        $this->I['linkHREF'] = $this->link($key,$this->I['val']['altTarget'],$this->mconf['forceTypeValue']);
+
                                                // Title attribute of links:
                                        $titleAttrValue = $this->WMcObj->stdWrap($this->I['val']['ATagTitle'],$this->I['val']['ATagTitle.']).$this->I['accessKey']['alt'];
                                        if (strlen($titleAttrValue))    {
@@ -2206,7 +2273,7 @@ class tslib_gmenu extends tslib_menu {
                                        }
 
                                                // Set altText
-                                       $this->I['altText'] = $this->mconf['disableAltText'] ? '' : $this->I['title'].$this->I['accessKey']['alt'];
+                                       $this->I['altText'] = $this->I['title'].$this->I['accessKey']['alt'];
 
                                                // Calling extra processing function
                                        $this->extProc_beforeLinking($key);
@@ -2218,7 +2285,7 @@ class tslib_gmenu extends tslib_menu {
                                                $this->I['A1'] = '';
                                                $this->I['A2'] = '';
                                        }
-                                       $this->I['IMG'] = '<img src="'.$GLOBALS['TSFE']->absRefPrefix.$this->I['val']['output_file'].'" width="'.$this->I['val']['output_w'].'" height="'.$this->I['val']['output_h'].'" border="0" alt="'.htmlspecialchars($this->I['altText']).'"'.$this->I['name'].($this->I['val']['imgParams']?' '.$this->I['val']['imgParams']:'').' />';
+                                       $this->I['IMG'] = '<img src="'.$GLOBALS['TSFE']->absRefPrefix.$this->I['val']['output_file'].'" width="'.$this->I['val']['output_w'].'" height="'.$this->I['val']['output_h'].'" '.tslib_cObj::getBorderAttr('border="0"').($this->mconf['disableAltText'] ? '' : ' alt="'.htmlspecialchars($this->I['altText']).'"').$this->I['name'].($this->I['val']['imgParams']?' '.$this->I['val']['imgParams']:'').' />';
 
                                                // Make before, middle and after parts
                                        $this->I['parts'] = array();
@@ -2331,6 +2398,10 @@ class tslib_gmenu extends tslib_menu {
         * @see writeMenu(), tslib_gmenu_layers::extProc_finish()
         */
        function extProc_finish()       {
+                       // stdWrap:
+               if (is_array($this->mconf['stdWrap.'])) {
+                       $this->WMresult = $this->WMcObj->stdWrap($this->WMresult,$this->mconf['stdWrap.']);
+               }
                return $this->tmpl->wrap($this->WMresult,$this->mconf['wrap']).$this->WMextraScript;
        }
 }
@@ -2579,7 +2650,7 @@ class tslib_imgmenu extends tslib_menu {
         */
        function writeMenu()    {
                if ($this->result)      {
-                       $res = $this->result;
+                       $res = &$this->result;
                        $menuName = 'menu_'.t3lib_div::shortMD5($res['imgMap']);        // shortMD5 260900
                        $result = '<img src="'.$GLOBALS['TSFE']->absRefPrefix.$res['output_file'].'" width="'.$res['output_w'].'" height="'.$res['output_h'].'" usemap="#'.$menuName.'" border="0" '.$this->mconf['params'];
                        if (!strstr($result,'alt="'))   $result.=' alt="Menu Image Map"';       // Adding alt attribute if not set.
@@ -2711,10 +2782,7 @@ class tslib_jsmenu extends tslib_menu {
                $MP_params = $MP_var ? '&MP='.rawurlencode($MP_var) : '';
 
                        // UIDs to ban:
-               $banUidArray=array();
-               if (trim($this->conf['excludeUidList']))        {
-                       $banUidArray = t3lib_div::intExplode(',', $this->conf['excludeUidList']);
-               }
+               $banUidArray = $this->getBannedUids();
 
                        // Initializing variables:
                $var = $this->JSVarName;
@@ -2727,13 +2795,13 @@ class tslib_jsmenu extends tslib_menu {
                foreach($menuItems as $uid => $data)    {
                        $spacer = (t3lib_div::inList($this->spacerIDList,$data['doktype'])?1:0);                // if item is a spacer, $spacer is set
                        if ($this->mconf['SPC'] || !$spacer)    {       // If the spacer-function is not enabled, spacers will not enter the $menuArr
-                               if (!t3lib_div::inList($this->doktypeExcludeList,$data['doktype']) && !$data['nav_hide'] && !t3lib_div::inArray($banUidArray,$uid))     {               // Page may not be 'not_in_menu' or 'Backend User Section' + not in banned uid's
+                               if (!t3lib_div::inList($this->doktypeExcludeList,$data['doktype']) && (!$data['nav_hide'] || $this->conf['includeNotInMenu']) && !t3lib_div::inArray($banUidArray,$uid))        {               // Page may not be 'not_in_menu' or 'Backend User Section' + not in banned uid's
                                        if ($count<$levels)     {
                                                $addLines = $this->generate_level($levels,$count+1,$data['uid'],'',$MP_array);
                                        } else {
                                                $addLines = '';
                                        }
-                                       $title=rawurlencode($data['title']);
+                                       $title=$data['title'];
                                        $url='';
                                        $target='';
                                        if ((!$addLines && !$levelConf['noLink']) || $levelConf['alwaysLink']) {
@@ -2742,10 +2810,10 @@ class tslib_jsmenu extends tslib_menu {
                                                        // If access restricted pages should be shown in menus, change the link of such pages to link to a redirection page:
                                                $this->changeLinksForAccessRestrictedPages($LD, $data, $this->mconf['target'], $this->mconf['forceTypeValue']);
 
-                                               $url = rawurlencode($LD['totalURL']);
-                                               $target = rawurlencode($LD['target']);
+                                               $url = $GLOBALS['TSFE']->baseUrlWrap($LD['totalURL']);
+                                               $target = $LD['target'];
                                        }
-                                       $codeLines.="\n".$var.$count."=".$menuName.".add(".$parent.",".$prev.",0,'".$title."','".$GLOBALS['TSFE']->baseUrlWrap($url)."','".$target."');";
+                                       $codeLines.="\n".$var.$count."=".$menuName.".add(".$parent.",".$prev.",0,".t3lib_div::quoteJSvalue($title, true).",".t3lib_div::quoteJSvalue($url, true).",".t3lib_div::quoteJSvalue($target, true).");";
                                                // If the active one should be chosen...
                                        $active = ($levelConf['showActive'] && $data['uid'] == $this->tmpl->rootLine[$count]['uid']);
                                                // If the first item should be shown
@@ -2770,7 +2838,7 @@ class tslib_jsmenu extends tslib_menu {
                        $levelConf['firstLabel'] = $this->mconf['firstLabelGeneral'];
                }
                if ($levelConf['firstLabel'] && $codeLines)     {
-                       $codeLines.="\n".$menuName.".defTopTitle[".$count."] = unescape('".rawurlencode($levelConf['firstLabel'])."');";
+                       $codeLines.= chr(10).$menuName.'.defTopTitle['.$count.'] = '.t3lib_div::quoteJSvalue($levelConf['firstLabel'], true).';';
                }
                return $codeLines;
        }
@@ -2781,4 +2849,4 @@ if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['tslib/class
        include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['tslib/class.tslib_menu.php']);
 }
 
-?>
\ No newline at end of file
+?>