* Fixed bug #12305: XSS vulnerability in view_help.php / tfID parameter (thanks to...
[Packages/TYPO3.CMS.git] / typo3 / view_help.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Document for viewing the online help texts, also known as TCA_DESCR.
29 * See Inside TYPO3 for details.
30 *
31 * $Id$
32 * Revised for TYPO3 3.7 5/2004 by Kasper Skaarhoj
33 * XHTML-trans compliant
34 *
35 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
36 */
37 /**
38 * [CLASS/FUNCTION INDEX of SCRIPT]
39 *
40 *
41 *
42 * 91: class local_t3lib_parsehtml extends t3lib_parsehtml
43 * 102: function processContent($value,$dir,$conf)
44 *
45 *
46 * 122: class SC_view_help
47 * 146: function init()
48 * 167: function main()
49 * 198: function printContent()
50 *
51 * SECTION: Rendering main modes
52 * 221: function render_TOC()
53 * 338: function render_TOC_el($table, $tocCat, &$outputSections, &$tocArray, &$CSHkeys)
54 * 370: function render_TOC_makeTocList($tocArray)
55 * 409: function render_Table($table)
56 * 469: function render_Single($table,$field)
57 *
58 * SECTION: Rendering CSH items
59 * 515: function make_seeAlso($value,$anchorTable='')
60 * 564: function printImage($images,$descr)
61 * 599: function headerLine($str,$type=0)
62 * 620: function prepareContent($str)
63 * 635: function printItem($table,$field,$anchors=0)
64 * 668: function getTableFieldNames($table,$field)
65 * 691: function getTableFieldLabel($table,$field='',$mergeToken=': ')
66 *
67 * SECTION: Glossary related
68 * 726: function createGlossaryIndex()
69 * 785: function substituteGlossaryWords($code)
70 * 801: function substituteGlossaryWords_htmlcleaner_callback($code)
71 *
72 * TOTAL FUNCTIONS: 19
73 * (This index is automatically created/updated by the extension "extdeveval")
74 *
75 */
76
77 require('init.php');
78 require('template.php');
79 $LANG->includeLLFile('EXT:lang/locallang_view_help.xml');
80
81
82 /**
83 * Extension of the parse_html class.
84 *
85 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
86 * @package TYPO3
87 * @subpackage core
88 */
89 class local_t3lib_parsehtml extends t3lib_parsehtml {
90
91 /**
92 * Processing content between tags for HTML_cleaner
93 *
94 * @param string The value
95 * @param integer Direction, either -1 or +1. 0 (zero) means no change to input value.
96 * @param mixed Not used, ignore.
97 * @return string The processed value.
98 * @access private
99 */
100 function processContent($value,$dir,$conf) {
101 $value = $this->pObj->substituteGlossaryWords_htmlcleaner_callback($value);
102
103 return $value;
104 }
105 }
106
107
108
109
110
111
112
113 /**
114 * Script Class for rendering the Context Sensitive Help documents, either the single display in the small pop-up window or the full-table view in the larger window.
115 *
116 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
117 * @package TYPO3
118 * @subpackage core
119 */
120 class SC_view_help {
121 var $allowedHTML = '<strong><em><b><i>';
122
123 // For these vars, see init()
124 var $limitAccess; // If set access to fields and tables is checked. Should be done for true database tables.
125 var $table; // The "table" key
126 var $field; // The "field" key
127
128 // Internal, static: GPvar:
129 var $tfID; // Table/FIeld id.
130 var $ffID; // Flexform file/field information
131 var $back; // Back (previous tfID)
132 var $renderALL; // If set, then in TOC mode the FULL manual will be printed as well!
133
134 // Internal, dynamic:
135 var $content; // Content accumulation.
136 var $glossaryWords; // Glossary words
137
138
139
140 /**
141 * Initialize the class for various input etc.
142 *
143 * @return void
144 */
145 function init() {
146 global $LANG, $TCA;
147
148 // Setting GPvars:
149 $this->tfID = t3lib_div::_GP('tfID');
150 // Sanitizes the tfID using whitelisting.
151 if (!preg_match('/^[a-zA-Z0-9_\-\.]*$/', $this->tfID)) {
152 $this->tfID = '';
153 }
154 if (!$this->tfID) {
155 if (($this->ffID = t3lib_div::_GP('ffID'))) {
156 $this->ffID = unserialize(base64_decode($this->ffID));
157 }
158 }
159 $this->back = t3lib_div::_GP('back');
160 $this->renderALL = t3lib_div::_GP('renderALL');
161
162 // Set internal table/field to the parts of "tfID" incoming var.
163 list($this->table,$this->field) = explode('.',$this->tfID);
164
165 // limitAccess is checked if the $this->table really IS a table (and if the user is NOT a translator who should see all!)
166 $showAllToUser = t3lib_BEfunc::isModuleSetInTBE_MODULES('txllxmltranslateM1') && $GLOBALS['BE_USER']->check('modules','txllxmltranslateM1');
167 $this->limitAccess = isset($TCA[$this->table]) ? !$showAllToUser : FALSE;
168 }
169
170 /**
171 * Main function, rendering the display
172 *
173 * @return void
174 */
175 function main() {
176 global $BE_USER,$LANG,$TCA_DESCR,$TCA,$TBE_TEMPLATE;
177
178 // Start HTML output accumulation:
179 $TBE_TEMPLATE->divClass = 'typo3-view-help';
180 $this->content.= $TBE_TEMPLATE->startPage($LANG->getLL('title'));
181
182 if ($this->field=='*') { // If ALL fields is supposed to be shown:
183 $this->createGlossaryIndex();
184 $this->content.= $this->render_Table($this->table);
185 } elseif ($this->tfID) { // ... otherwise show only single field:
186 $this->createGlossaryIndex();
187 $this->content.= $this->render_Single($this->table,$this->field);
188 }
189 elseif (is_array($this->ffID)) {
190 $this->content.= $this->render_SingleFlex();
191 } else { // Render Table Of Contents if nothing else:
192 $this->content.= $this->render_TOC();
193 }
194
195 // Print close-button:
196 # $this->content.='<br /><form action=""><input type="submit" value="'.htmlspecialchars($LANG->getLL('close')).'" onclick="self.close(); return false;" /></form><br/>';
197
198 // End page:
199 $this->content.= '<br/>';
200 $this->content.= $TBE_TEMPLATE->endPage();
201 }
202
203 /**
204 * Outputting the accumulated content to screen
205 *
206 * @return void
207 */
208 function printContent() {
209 echo $this->content;
210 }
211
212
213
214
215
216
217
218
219
220 /************************************
221 *
222 * Rendering main modes
223 *
224 ************************************/
225
226 /**
227 * Creates Table Of Contents and possibly "Full Manual" mode if selected.
228 *
229 * @return string HTML content
230 */
231 function render_TOC() {
232 global $TCA_DESCR,$TCA,$LANG,$BE_USER,$TBE_MODULES;
233
234 // Initialize:
235 $CSHkeys = array_flip(array_keys($TCA_DESCR));
236 $TCAkeys = array_keys($TCA);
237
238 $outputSections = array();
239 $tocArray = array();
240
241
242 // TYPO3 Core Features:
243 $LANG->loadSingleTableDescription('xMOD_csh_corebe');
244 $this->render_TOC_el('xMOD_csh_corebe', 'core', $outputSections, $tocArray, $CSHkeys);
245
246 // Backend Modules:
247 $loadModules = t3lib_div::makeInstance('t3lib_loadModules');
248 $loadModules->load($TBE_MODULES);
249 foreach($loadModules->modules as $mainMod => $info) {
250 $cshKey = '_MOD_'.$mainMod;
251 if ($CSHkeys[$cshKey]) {
252 $LANG->loadSingleTableDescription($cshKey);
253 $this->render_TOC_el($cshKey, 'modules', $outputSections, $tocArray, $CSHkeys);
254 }
255
256 if (is_array($info['sub'])) {
257 foreach($info['sub'] as $subMod => $subInfo) {
258 $cshKey = '_MOD_'.$mainMod.'_'.$subMod;
259 if ($CSHkeys[$cshKey]) {
260 $LANG->loadSingleTableDescription($cshKey);
261 $this->render_TOC_el($cshKey, 'modules', $outputSections, $tocArray, $CSHkeys);
262 }
263 }
264 }
265 }
266
267 // Database Tables:
268 foreach($TCAkeys as $table) {
269 // Load descriptions for table $table
270 $LANG->loadSingleTableDescription($table);
271 if (is_array($TCA_DESCR[$table]['columns']) && $BE_USER->check('tables_select',$table)) {
272 $this->render_TOC_el($table, 'tables', $outputSections, $tocArray, $CSHkeys);
273 }
274 }
275
276 // Extensions
277 foreach($CSHkeys as $cshKey => $value) {
278 if (t3lib_div::isFirstPartOfStr($cshKey, 'xEXT_') && !isset($TCA[$cshKey])) {
279 $LANG->loadSingleTableDescription($cshKey);
280 $this->render_TOC_el($cshKey, 'extensions', $outputSections, $tocArray, $CSHkeys);
281 }
282 }
283
284 // Glossary
285 foreach($CSHkeys as $cshKey => $value) {
286 if (t3lib_div::isFirstPartOfStr($cshKey, 'xGLOSSARY_') && !isset($TCA[$cshKey])) {
287 $LANG->loadSingleTableDescription($cshKey);
288 $this->render_TOC_el($cshKey, 'glossary', $outputSections, $tocArray, $CSHkeys);
289 }
290 }
291
292 // Other:
293 foreach($CSHkeys as $cshKey => $value) {
294 if (!t3lib_div::isFirstPartOfStr($cshKey, '_MOD_') && !isset($TCA[$cshKey])) {
295 $LANG->loadSingleTableDescription($cshKey);
296 $this->render_TOC_el($cshKey, 'other', $outputSections, $tocArray, $CSHkeys);
297 }
298 }
299
300
301 // COMPILE output:
302 $output = '';
303 $output.= '
304
305 <h1>'.$LANG->getLL('manual_title',1).'</h1>';
306
307 $output.= '
308
309 <h2>'.$LANG->getLL('introduction',1).'</h2>
310 <p>'.$LANG->getLL('description',1).'</p>';
311
312 $output.= '
313
314 <h2>'.$LANG->getLL('TOC',1).'</h2>'.
315 $this->render_TOC_makeTocList($tocArray);
316
317 if (!$this->renderALL) {
318 $output.= '
319 <br/>
320 <p class="c-nav"><a href="view_help.php?renderALL=1">'.$LANG->getLL('full_manual',1).'</a></p>';
321 }
322
323 if ($this->renderALL) {
324 $output.= '
325
326 <h2>'.$LANG->getLL('full_manual_chapters',1).'</h2>'.
327 implode('
328
329
330 <!-- NEW SECTION: -->
331 ',$outputSections);
332 }
333
334 $output .= '<hr /><p class="manual-title">'.t3lib_BEfunc::TYPO3_copyRightNotice().'</p>';
335
336 return $output;
337 }
338
339 /**
340 * Creates a TOC list element and renders corresponding HELP content if "renderALL" mode is set.
341 *
342 * @param string CSH key / Table name
343 * @param string TOC category keyword: "core", "modules", "tables", "other"
344 * @param array Array for accumulation of rendered HELP Content (in "renderALL" mode). Passed by reference!
345 * @param array TOC array; Here TOC index elements are created. Passed by reference!
346 * @param array CSH keys array. Every item rendered will be unset in this array so finally we can see what CSH keys are not processed yet. Passed by reference!
347 * @return void
348 */
349 function render_TOC_el($table, $tocCat, &$outputSections, &$tocArray, &$CSHkeys) {
350 global $LANG;
351
352 if ($this->renderALL) { // Render full manual right here!
353 $outputSections[$table] = $this->render_Table($table);
354
355 if ($outputSections[$table]) {
356 $outputSections[$table] = '
357
358 <!-- New CSHkey/Table: '.$table.' -->
359 <p class="c-nav"><a name="ANCHOR_'.$table.'" href="#">'.$LANG->getLL('to_top',1).'</a></p>
360 <h2>'.$this->getTableFieldLabel($table).'</h2>
361
362 '.$outputSections[$table];
363 $tocArray[$tocCat][$table] = '<a href="#ANCHOR_'.$table.'">'.$this->getTableFieldLabel($table).'</a>';
364 } else {
365 unset($outputSections[$table]);
366 }
367 } else { // Only TOC:
368 $tocArray[$tocCat][$table] = '<p><a href="view_help.php?tfID='.rawurlencode($table.'.*').'">'.$this->getTableFieldLabel($table).'</a></p>';
369 }
370
371 // Unset CSH key:
372 unset($CSHkeys[$table]);
373 }
374
375 /**
376 * Renders the TOC index as a HTML bullet list from TOC array
377 *
378 * @param array ToC Array.
379 * @return string HTML bullet list for index.
380 */
381 function render_TOC_makeTocList($tocArray) {
382 global $LANG;
383
384 // The Various manual sections:
385 $keys = explode(',', 'core,modules,tables,extensions,glossary,other');
386
387 // Create TOC bullet list:
388 $output = '';
389 foreach($keys as $tocKey) {
390 if (is_array($tocArray[$tocKey])) {
391 $output.='
392 <li>'.$LANG->getLL('TOC_'.$tocKey,1).'
393 <ul>
394 <li>'.implode('</li>
395 <li>',$tocArray[$tocKey]).'</li>
396 </ul>
397 </li>';
398 }
399 }
400
401 // Compile TOC:
402 $output = '
403
404 <!-- TOC: -->
405 <div class="c-toc">
406 <ul>
407 '.$output.'
408 </ul>
409 </div>';
410
411 return $output;
412 }
413
414 /**
415 * Render CSH for a full cshKey/table
416 *
417 * @param string CSH key / table name
418 * @return string HTML output
419 */
420 function render_Table($table) {
421 global $BE_USER,$TCA_DESCR,$TCA,$LANG;
422
423 $output = '';
424
425 // Load table TCA
426 t3lib_div::loadTCA($table);
427
428 // Load descriptions for table $table
429 $LANG->loadSingleTableDescription($table);
430
431 if (is_array($TCA_DESCR[$table]['columns']) && (!$this->limitAccess || $BE_USER->check('tables_select',$table))) {
432 // Initialize variables:
433 $parts = array();
434 $parts[0] = ''; // Reserved for header of table
435
436 // Traverse table columns as listed in TCA_DESCR
437 reset($TCA_DESCR[$table]['columns']);
438 while(list($field) = each($TCA_DESCR[$table]['columns'])) {
439
440 $fieldValue = isset($TCA[$table]) && strcmp($field,'') ? $TCA[$table]['columns'][$field] : array();
441
442 if (is_array($fieldValue) && (!$this->limitAccess || !$fieldValue['exclude'] || $BE_USER->check('non_exclude_fields',$table.':'.$field))) {
443 if (!$field) {
444 $parts[0] = $this->printItem($table,'',1); // Header
445 } else {
446 $parts[] = $this->printItem($table,$field,1); // Field
447 }
448 }
449 }
450
451 if (!strcmp($parts,'')) unset($parts[0]);
452 $output.= implode('<br />',$parts);
453 }
454
455 // Substitute glossary words:
456 $output = $this->substituteGlossaryWords($output);
457
458 // TOC link:
459 if (!$this->renderALL) {
460 $tocLink = '<p class="c-nav"><a href="view_help.php">'.$LANG->getLL('goToToc',1).'</a></p>';
461
462 $output =
463 $tocLink.'
464 <br/>'.
465 $output.'
466 <br />'.
467 $tocLink;
468 }
469
470 return $output;
471 }
472
473 /**
474 * Renders CSH for a single field.
475 *
476 * @param string CSH key / table name
477 * @param string Sub key / field name
478 * @return string HTML output
479 */
480 function render_Single($table,$field) {
481 global $LANG, $TCA;
482
483 $output = '';
484
485 // Load descriptions for table $table
486 $LANG->loadSingleTableDescription($table);
487
488 // Render single item:
489 $output.= $this->printItem($table,$field);
490
491 // Substitute glossary words:
492 $output = $this->substituteGlossaryWords($output);
493
494 // Link to Full table description and TOC:
495 $getLLKey = $this->limitAccess ? 'fullDescription' : 'fullDescription_module';
496 $output.= '<br />
497 <p class="c-nav"><a href="view_help.php?tfID='.rawurlencode($table.'.*').'">'.$LANG->getLL($getLLKey,1).'</a></p>
498 <p class="c-nav"><a href="view_help.php">'.$LANG->getLL('goToToc',1).'</a></p>';
499
500 return $output;
501 }
502
503
504 /**
505 * Renders CSH for a single field.
506 *
507 * @param string CSH key / table name
508 * @param string Sub key / field name
509 * @return string HTML output
510 */
511 function render_SingleFlex() {
512 $output = '';
513
514 // Render
515 $output.= $this->printItemFlex();
516
517 // Substitute glossary words:
518 return $this->substituteGlossaryWords($output);
519 }
520
521
522 /************************************
523 *
524 * Rendering CSH items
525 *
526 ************************************/
527
528 /**
529 * Make seeAlso links from $value
530 *
531 * @param string See-also input codes
532 * @param string If $anchorTable is set to a tablename, then references to this table will be made as anchors, not URLs.
533 * @return string See-also links HTML
534 */
535 function make_seeAlso($value,$anchorTable='') {
536 global $TCA,$BE_USER,$TCA_DESCR;
537
538 // Split references by comma or linebreak
539 $items = preg_split('/[,' . chr(10) . ']/', $value);
540 $lines = array();
541
542 foreach($items as $val) {
543 $val = trim($val);
544 if ($val) {
545 $iP = explode(':',$val);
546 $iPUrl = t3lib_div::trimExplode('|',$val);
547 // URL reference:
548 if (substr($iPUrl[1],0,4)=='http') {
549 $lines[] = '<a href="'.htmlspecialchars($iPUrl[1]).'" target="_blank"><em>'.htmlspecialchars($iPUrl[0]).'</em></a>';
550 } elseif (substr($iPUrl[1],0,5)=='FILE:') {
551 $fileName = t3lib_div::getFileAbsFileName(substr($iPUrl[1],5),1,1);
552 if ($fileName && @is_file($fileName)) {
553 $fileName = '../'.substr($fileName,strlen(PATH_site));
554 $lines[] = '<a href="'.htmlspecialchars($fileName).'" target="_blank"><em>'.htmlspecialchars($iPUrl[0]).'</em></a>';
555 }
556 } else {
557 // "table" reference
558 t3lib_div::loadTCA($iP[0]);
559
560 if (!isset($TCA[$iP[0]]) || ((!$iP[1] || is_array($TCA[$iP[0]]['columns'][$iP[1]])) && (!$this->limitAccess || ($BE_USER->check('tables_select',$iP[0]) && (!$iP[1] || !$TCA[$iP[0]]['columns'][$iP[1]]['exclude'] || $BE_USER->check('non_exclude_fields',$iP[0].':'.$iP[1])))))) { // Checking read access:
561
562 // Load table descriptions:
563 #$LANG->loadSingleTableDescription($iP[0]);
564 if (isset($TCA_DESCR[$iP[0]])) {
565 // Make see-also link:
566 $href = ($this->renderALL || ($anchorTable && $iP[0]==$anchorTable) ? '#'.implode('.',$iP) : 'view_help.php?tfID='.rawurlencode(implode('.',$iP)).'&back='.$this->tfID);
567 $label = $this->getTableFieldLabel($iP[0],$iP[1],' / ');
568 $lines[] = '<a href="'.htmlspecialchars($href).'">'.htmlspecialchars($label).'</a>';
569 }
570 }
571 }
572 }
573 }
574 return implode('<br />',$lines);
575 }
576
577 /**
578 * Will return an image tag with description in italics.
579 *
580 * @param string Image file reference (list of)
581 * @param string Description string (divided for each image by line break)
582 * @return string Image HTML codes
583 */
584 function printImage($images,$descr) {
585 $code = '';
586 // Splitting:
587 $imgArray = t3lib_div::trimExplode(',', $images, 1);
588 if (count($imgArray)) {
589 $descrArray = explode(chr(10),$descr,count($imgArray));
590
591 foreach($imgArray as $k => $image) {
592 $descr = $descrArray[$k];
593
594 $absImagePath = t3lib_div::getFileAbsFileName($image,1,1);
595 if ($absImagePath && @is_file($absImagePath)) {
596 $imgFile = substr($absImagePath,strlen(PATH_site));
597 $imgInfo = @getimagesize($absImagePath);
598 if (is_array($imgInfo)) {
599 $imgFile = '../'.$imgFile;
600 $code.= '<br /><img src="'.$imgFile.'" '.$imgInfo[3].' class="c-inlineimg" alt="" /><br />
601 ';
602 $code.= '<p><em>'.$GLOBALS['LANG']->hscAndCharConv($descr,1).'</em></p>
603 ';
604 } else $code.= '<div style="background-color: red; border: 1px solid black; color: white;">NOT AN IMAGE: '.$imgFile.'</div>';
605 } else $code.= '<div style="background-color: red; border: 1px solid black; color: white;">IMAGE FILE NOT FOUND: '.$image.'</div>';
606 }
607 }
608
609 return $code;
610 }
611
612 /**
613 * Returns header HTML content
614 *
615 * @param string Header text
616 * @param string Header type (1, 0)
617 * @return string The HTML for the header.
618 */
619 function headerLine($str,$type=0) {
620 switch($type) {
621 case 1:
622 $str='<h3>'.htmlspecialchars($str).'</h3>
623 ';
624 break;
625 case 0:
626 $str='<h4 class="uppercase">'.htmlspecialchars($str).'</h4>
627 ';
628 break;
629 }
630
631 return $str;
632 }
633
634 /**
635 * Returns prepared content
636 *
637 * @param string Content to format.
638 * @return string Formatted content.
639 */
640 function prepareContent($str) {
641 $str = $GLOBALS['LANG']->hscAndCharConv($str,0);
642 return '<p>'.nl2br(trim(strip_tags($str,$this->allowedHTML))).'</p>
643 ';
644 }
645
646 /**
647 * Prints a single $table/$field information piece
648 * If $anchors is set, then seeAlso references to the same table will be page-anchors, not links.
649 *
650 * @param string Table name
651 * @param string Field name
652 * @param boolean If anchors is to be shown.
653 * @return string HTML content
654 */
655 function printItem($table,$field,$anchors=0) {
656 global $TCA_DESCR, $LANG, $TCA, $BE_USER;
657
658 // Load full table definition in $TCA
659 t3lib_div::loadTCA($table);
660
661 if ($table && (!$field || is_array($TCA_DESCR[$table]['columns'][$field]))) {
662 // Make seeAlso references.
663 $seeAlsoRes = $this->make_seeAlso($TCA_DESCR[$table]['columns'][$field]['seeAlso'],$anchors?$table:'');
664
665 // Making item:
666 $out= '<a name="'.$table.'.'.$field.'"></a>
667 '.
668 $this->headerLine($this->getTableFieldLabel($table,$field),1).
669 $this->prepareContent($TCA_DESCR[$table]['columns'][$field]['description']).
670 ($TCA_DESCR[$table]['columns'][$field]['details'] ? $this->headerLine($LANG->getLL('details').':').$this->prepareContent($TCA_DESCR[$table]['columns'][$field]['details']) : '').
671 ($TCA_DESCR[$table]['columns'][$field]['syntax'] ? $this->headerLine($LANG->getLL('syntax').':').$this->prepareContent($TCA_DESCR[$table]['columns'][$field]['syntax']) : '').
672 ($TCA_DESCR[$table]['columns'][$field]['image'] ? $this->printImage($TCA_DESCR[$table]['columns'][$field]['image'],$TCA_DESCR[$table]['columns'][$field]['image_descr']) : '').
673 ($TCA_DESCR[$table]['columns'][$field]['seeAlso'] && $seeAlsoRes ? $this->headerLine($LANG->getLL('seeAlso').':').'<p>'.$seeAlsoRes.'</p>' : '').
674 ($this->back ? '<br /><p><a href="'.htmlspecialchars('view_help.php?tfID='.rawurlencode($this->back)).'" class="typo3-goBack">'.htmlspecialchars($LANG->getLL('goBack')).'</a></p>' : '').
675 '<br />';
676 }
677 return $out;
678 }
679
680 /**
681 * Prints a single $table/$field information piece
682 * If $anchors is set, then seeAlso references to the same table will be page-anchors, not links.
683 *
684 * @param string Table name
685 * @param string Field name
686 * @param boolean If anchors is to be shown.
687 * @return string HTML content
688 */
689 function printItemFlex() {
690 // Get all texts
691 foreach (explode(',', 'description,details,syntax,image,image_descr,seeAlso') as $var) {
692 // Double $ below is not a error!
693 $$var = $GLOBALS['LANG']->sL($this->ffID['cshFile'] . ':' . $this->ffID['field'] . '.' . $var);
694 }
695 // Make seeAlso references.
696 $seeAlsoRes = $this->make_seeAlso($seeAlso);
697
698 // Making item:
699 $out= $this->headerLine($this->ffID['title'], 1) .
700 $this->prepareContent($description) .
701 ($details ? $this->headerLine($GLOBALS['LANG']->getLL('details').':') . $this->prepareContent($details) : '') .
702 ($syntax ? $this->headerLine($GLOBALS['LANG']->getLL('syntax').':') . $this->prepareContent($syntax) : '') .
703 ($image ? $this->printImage($image, $image_descr) : '') .
704 ($seeAlso && $seeAlsoRes ? $this->headerLine($GLOBALS['LANG']->getLL('seeAlso').':').'<p>'.$seeAlsoRes.'</p>' : '') .
705 '<br />';
706 return $out;
707 }
708
709 /**
710 * Returns labels for $table and $field.
711 * If $table is "_MOD_" prefixed, the part after "_MOD_" is returned (non-tables, fx. modules)
712 *
713 * @param string Table name
714 * @param string Field name
715 * @return array Table and field labels in a numeric array
716 */
717 function getTableFieldNames($table,$field) {
718 global $TCA, $TCA_DESCR, $LANG;
719
720 $LANG->loadSingleTableDescription($table);
721
722 $tableName = is_array($TCA_DESCR[$table]['columns']['']) && $TCA_DESCR[$table]['columns']['']['alttitle'] ?
723 $TCA_DESCR[$table]['columns']['']['alttitle'] :
724 (isset($TCA[$table]) ? $TCA[$table]['ctrl']['title'] : preg_replace('/^_MOD_/','',$table));
725 $fieldName = is_array($TCA_DESCR[$table]['columns'][$field]) && $TCA_DESCR[$table]['columns'][$field]['alttitle'] ?
726 $TCA_DESCR[$table]['columns'][$field]['alttitle'] :
727 (isset($TCA[$table])&&isset($TCA[$table]['columns'][$field]) ? $TCA[$table]['columns'][$field]['label'] : $field);
728 return array($tableName,$fieldName);
729 }
730
731 /**
732 * Returns composite label for table/field
733 *
734 * @param string Table name
735 * @param string Field name
736 * @param string Token to merge the two strings with.
737 * @return array Table and field labels in a numeric array
738 * @see getTableFieldNames()
739 */
740 function getTableFieldLabel($table,$field='',$mergeToken=': ') {
741 global $LANG;
742
743 // Get table / field parts:
744 list($tableName,$fieldName) = $this->getTableFieldNames($table,$field);
745
746 // Create label:
747 $labelStr = $LANG->sL($tableName).
748 ($field ? $mergeToken.rtrim(trim($LANG->sL($fieldName)), ':'):'');
749
750 return $labelStr;
751 }
752
753
754
755
756
757
758
759
760
761
762
763 /******************************
764 *
765 * Glossary related
766 *
767 ******************************/
768
769 /**
770 * Creates glossary index in $this->glossaryWords
771 * Glossary is cached in cache_hash cache and so will be updated only when cache is cleared.
772 *
773 * @return void
774 */
775 function createGlossaryIndex() {
776 global $TCA_DESCR,$TCA,$LANG;
777
778 // Create hash string and try to retrieve glossary array:
779 $hash = md5('typo3/view_help.php:glossary');
780 list($this->glossaryWords,$this->substWords) = unserialize(t3lib_BEfunc::getHash($hash));
781
782 // Generate glossary words if not found:
783 if (!is_array($this->glossaryWords)) {
784
785 // Initialize:
786 $this->glossaryWords = array();
787 $this->substWords = array();
788 $CSHkeys = array_flip(array_keys($TCA_DESCR));
789
790 // Glossary
791 foreach($CSHkeys as $cshKey => $value) {
792 if (t3lib_div::isFirstPartOfStr($cshKey, 'xGLOSSARY_') && !isset($TCA[$cshKey])) {
793 $LANG->loadSingleTableDescription($cshKey);
794
795 if (is_array($TCA_DESCR[$cshKey]['columns'])) {
796
797 // Traverse table columns as listed in TCA_DESCR
798 reset($TCA_DESCR[$cshKey]['columns']);
799 while(list($field,$data) = each($TCA_DESCR[$cshKey]['columns'])) {
800 if ($field) {
801 $this->glossaryWords[$cshKey.'.'.$field] = array(
802 'title' => trim($data['alttitle'] ? $data['alttitle'] : $cshKey),
803 'description' => str_replace('%22','%23%23%23', rawurlencode($data['description'])),
804 );
805 }
806 }
807 }
808 }
809 }
810
811 // First, create unique list of words:
812 foreach($this->glossaryWords as $key => $value) {
813 $word = strtolower($value['title']); // Making word lowercase in order to filter out same words in different cases.
814
815 if ($word!=='') {
816 $this->substWords[$word] = $value;
817 $this->substWords[$word]['key'] = $key;
818 }
819 }
820
821 krsort($this->substWords);
822
823 t3lib_BEfunc::storeHash($hash,serialize(array($this->glossaryWords,$this->substWords)),'Glossary');
824 }
825 }
826
827 /**
828 * Processing of all non-HTML content in the output
829 * Will be done by a call-back to ->substituteGlossaryWords_htmlcleaner_callback()
830 *
831 * @param string Input HTML code
832 * @return string Output HTML code
833 */
834 function substituteGlossaryWords($code) {
835 $htmlParser = t3lib_div::makeInstance('local_t3lib_parsehtml');
836 $htmlParser->pObj = $this;
837 $code = $htmlParser->HTMLcleaner($code, array(), 1);
838
839 return $code;
840 }
841
842 /**
843 * Substituting glossary words in the CSH
844 * (This is a call-back function from "class local_t3lib_parsehtml extends t3lib_parsehtml", see top of this script)
845 *
846 * @param string Input HTML string
847 * @return string HTML with substituted words in.
848 * @coauthor alex widschwendter, media.res kommunikationsloesungen
849 */
850 function substituteGlossaryWords_htmlcleaner_callback($code) {
851 if (is_array($this->substWords) && count($this->substWords) && strlen(trim($code))) {
852
853 // Substitute words:
854 foreach($this->substWords as $wordKey => $wordSet) {
855 // quoteMeta used so special chars (which should not occur though) in words will not break the regex. Seemed to work (- kasper)
856 $parts = preg_split('/( |[\(])('.quoteMeta($wordSet['title']).')([\.\!\)\?\:\,]+| )/i', ' '.$code.' ', 2, PREG_SPLIT_DELIM_CAPTURE);
857 if (count($parts) == 5) {
858 $parts[2] = '<a class="glossary-term" href="'.htmlspecialchars('view_help.php?tfID='.rawurlencode($wordSet['key']).'&back='.$this->tfID).'" title="'.rawurlencode(htmlspecialchars(t3lib_div::fixed_lgd_cs(rawurldecode($wordSet['description']),80))).'">'.
859 htmlspecialchars($parts[2]).
860 '</a>';
861 $code = substr(implode('',$parts),1,-1);
862
863 // Disable entry so it doesn't get used next time:
864 unset($this->substWords[$wordKey]);
865 }
866 }
867 $code = str_replace('###', '&quot;',rawurldecode($code));
868 }
869
870 return $code;
871 }
872
873 }
874
875
876
877 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/view_help.php']) {
878 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/view_help.php']);
879 }
880
881
882
883 // Make instance:
884 $SOBE = t3lib_div::makeInstance('SC_view_help');
885 $SOBE->init();
886 $SOBE->main();
887 $SOBE->printContent();
888
889 ?>