[BUGFIX] Untrusted GP data is unserialized in wizard_colorpicker.php and view_help.php
[Packages/TYPO3.CMS.git] / typo3 / wizard_colorpicker.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2011 Kasper Skårhøj (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 * Colorpicker wizard
29 *
30 * Revised for TYPO3 3.7 May/2004 by Kasper Skårhøj
31 *
32 * @author Mathias Schreiber <schreiber@wmdb.de>
33 * @author Peter Kühn <peter@kuehn.com>
34 * @author Kasper Skårhøj <typo3@typo3.com>
35 */
36
37
38 $GLOBALS['BACK_PATH'] = '';
39 require('init.php');
40 require('template.php');
41 $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_wizards.xml');
42
43 /**
44 * Script Class for colorpicker wizard
45 *
46 * @author Mathias Schreiber <schreiber@wmdb.de>
47 * @author Peter Kühn <peter@kuehn.com>
48 * @author Kasper Skårhøj <typo3@typo3.com>
49 * @package TYPO3
50 * @subpackage core
51 */
52 class SC_wizard_colorpicker {
53
54 // GET vars:
55 var $P; // Wizard parameters, coming from TCEforms linking to the wizard.
56 var $colorValue; // Value of the current color picked.
57 var $fieldChangeFunc; // Serialized functions for changing the field... Necessary to call when the value is transferred to the TCEform since the form might need to do internal processing. Otherwise the value is simply not be saved.
58 protected $fieldChangeFuncHash;
59 var $fieldName; // Form name (from opener script)
60 var $formName; // Field name (from opener script)
61 var $md5ID; // ID of element in opener script for which to set color.
62 var $showPicker; // Internal: If FALSE, a frameset is rendered, if TRUE the content of the picker script.
63
64 // Static:
65 var $HTMLcolorList = "aqua,black,blue,fuchsia,gray,green,lime,maroon,navy,olive,purple,red,silver,teal,yellow,white";
66
67 // Internal:
68 var $pickerImage = '';
69 var $imageError = ''; // Error message if image not found.
70
71 /**
72 * document template object
73 *
74 * @var smallDoc
75 */
76 var $doc;
77 var $content; // Accumulated content.
78
79
80
81
82 /**
83 * Initialises the Class
84 *
85 * @return void
86 */
87 function init() {
88 // Setting GET vars (used in frameset script):
89 $this->P = t3lib_div::_GP('P',1);
90
91 // Setting GET vars (used in colorpicker script):
92 $this->colorValue = t3lib_div::_GP('colorValue');
93 $this->fieldChangeFunc = t3lib_div::_GP('fieldChangeFunc');
94 $this->fieldChangeFuncHash = t3lib_div::_GP('fieldChangeFuncHash');
95 $this->fieldName = t3lib_div::_GP('fieldName');
96 $this->formName = t3lib_div::_GP('formName');
97 $this->md5ID = t3lib_div::_GP('md5ID');
98 $this->exampleImg = t3lib_div::_GP('exampleImg');
99
100
101 // Resolving image (checking existence etc.)
102 $this->imageError = '';
103 if ($this->exampleImg) {
104 $this->pickerImage = t3lib_div::getFileAbsFileName($this->exampleImg,1,1);
105 if (!$this->pickerImage || !@is_file($this->pickerImage)) {
106 $this->imageError = 'ERROR: The image, "'.$this->exampleImg.'", could not be found!';
107 }
108 }
109
110 // Setting field-change functions:
111 $fieldChangeFuncArr = unserialize($this->fieldChangeFunc);
112 $update = '';
113 if ($this->areFieldChangeFunctionsValid()) {
114 unset($fieldChangeFuncArr['alert']);
115 foreach($fieldChangeFuncArr as $v) {
116 $update.= '
117 parent.opener.'.$v;
118 }
119 }
120
121 // Initialize document object:
122 $this->doc = t3lib_div::makeInstance('smallDoc');
123 $this->doc->backPath = $GLOBALS['BACK_PATH'];
124 $this->doc->JScode = $this->doc->wrapScriptTags('
125 function checkReference() { //
126 if (parent.opener && parent.opener.document && parent.opener.document.'.$this->formName.' && parent.opener.document.'.$this->formName.'["'.$this->fieldName.'"]) {
127 return parent.opener.document.'.$this->formName.'["'.$this->fieldName.'"];
128 } else {
129 close();
130 }
131 }
132 function changeBGcolor(color) { // Changes the color in the table sample back in the TCEform.
133 if (parent.opener.document.layers) {
134 parent.opener.document.layers["'.$this->md5ID.'"].bgColor = color;
135 } else if (parent.opener.document.all) {
136 parent.opener.document.all["'.$this->md5ID.'"].style.background = color;
137 } else if (parent.opener.document.getElementById && parent.opener.document.getElementById("'.$this->md5ID.'")) {
138 parent.opener.document.getElementById("'.$this->md5ID.'").bgColor = color;
139 }
140 }
141 function setValue(input) { //
142 var field = checkReference();
143 if (field) {
144 field.value = input;
145 '.$update.'
146 changeBGcolor(input);
147 }
148 }
149 function getValue() { //
150 var field = checkReference();
151 return field.value;
152 }
153 ');
154
155 // Start page:
156 $this->content.=$this->doc->startPage($GLOBALS['LANG']->getLL('colorpicker_title'));
157 }
158
159 /**
160 * Main Method, rendering either colorpicker or frameset depending on ->showPicker
161 *
162 * @return void
163 */
164 function main() {
165 if(!t3lib_div::_GP('showPicker')) { // Show frameset by default:
166 $this->frameSet();
167 } else {
168
169 // Putting together the items into a form:
170 $content = '
171 <form name="colorform" method="post" action="wizard_colorpicker.php">
172 '.$this->colorMatrix().'
173 '.$this->colorList().'
174 '.$this->colorImage().'
175
176 <!-- Value box: -->
177 <p class="c-head">'.$GLOBALS['LANG']->getLL('colorpicker_colorValue',1).'</p>
178 <table border="0" cellpadding="0" cellspacing="3">
179 <tr>
180 <td><input type="text" '.$this->doc->formWidth(7).' maxlength="10" name="colorValue" value="'.htmlspecialchars($this->colorValue).'" /></td>
181 <td style="background-color:'.htmlspecialchars($this->colorValue).'; border: 1px solid black;">&nbsp;<span style="color: black;">'.$GLOBALS['LANG']->getLL('colorpicker_black',1).'</span>&nbsp;<span style="color: white;">'.$GLOBALS['LANG']->getLL('colorpicker_white',1).'</span>&nbsp;</td>
182 <td><input type="submit" name="save_close" value="'.$GLOBALS['LANG']->getLL('colorpicker_setClose',1).'" /></td>
183 </tr>
184 </table>
185
186 <!-- Hidden fields with values that has to be kept constant -->
187 <input type="hidden" name="showPicker" value="1" />
188 <input type="hidden" name="fieldChangeFunc" value="'.htmlspecialchars($this->fieldChangeFunc).'" />
189 <input type="hidden" name="fieldChangeFuncHash" value="'.htmlspecialchars($this->fieldChangeFuncHash).'" />
190 <input type="hidden" name="fieldName" value="'.htmlspecialchars($this->fieldName).'" />
191 <input type="hidden" name="formName" value="'.htmlspecialchars($this->formName).'" />
192 <input type="hidden" name="md5ID" value="'.htmlspecialchars($this->md5ID).'" />
193 <input type="hidden" name="exampleImg" value="'.htmlspecialchars($this->exampleImg).'" />
194 </form>';
195
196 // If the save/close button is clicked, then close:
197 if(t3lib_div::_GP('save_close')) {
198 $content.=$this->doc->wrapScriptTags('
199 setValue(\''.$this->colorValue.'\');
200 parent.close();
201 ');
202 }
203
204 // Output:
205 $this->content.=$this->doc->section($GLOBALS['LANG']->getLL('colorpicker_title'), $content, 0,1);
206 }
207 }
208
209 /**
210 * Returnes the sourcecode to the browser
211 *
212 * @return void
213 */
214 function printContent() {
215 $this->content.= $this->doc->endPage();
216 $this->content = $this->doc->insertStylesAndJS($this->content);
217 echo $this->content;
218 }
219
220 /**
221 * Returnes a frameset so our JavaScript Reference isn't lost
222 * Took some brains to figure this one out ;-)
223 * If Peter wouldn't have been I would've gone insane...
224 *
225 * @return void
226 */
227 function frameSet() {
228 // Set doktype:
229 $GLOBALS['TBE_TEMPLATE']->docType = 'xhtml_frames';
230 $GLOBALS['TBE_TEMPLATE']->JScode = $GLOBALS['TBE_TEMPLATE']->wrapScriptTags('
231 if (!window.opener) {
232 alert("ERROR: Sorry, no link to main window... Closing");
233 close();
234 }
235 ');
236
237 $this->content = $GLOBALS['TBE_TEMPLATE']->startPage($GLOBALS['LANG']->getLL('colorpicker_title'));
238
239 // URL for the inner main frame:
240 $url = 'wizard_colorpicker.php?showPicker=1'.
241 '&colorValue='.rawurlencode($this->P['currentValue']).
242 '&fieldName='.rawurlencode($this->P['itemName']).
243 '&formName='.rawurlencode($this->P['formName']).
244 '&exampleImg='.rawurlencode($this->P['exampleImg']).
245 '&md5ID='.rawurlencode($this->P['md5ID']).
246 '&fieldChangeFunc='.rawurlencode(serialize($this->P['fieldChangeFunc'])) .
247 '&fieldChangeFuncHash=' . $this->P['fieldChangeFuncHash'];
248
249 $this->content.='
250 <frameset rows="*,1" framespacing="0" frameborder="0" border="0">
251 <frame name="content" src="'.htmlspecialchars($url).'" marginwidth="0" marginheight="0" frameborder="0" scrolling="auto" noresize="noresize" />
252 <frame name="menu" src="dummy.php" marginwidth="0" marginheight="0" frameborder="0" scrolling="no" noresize="noresize" />
253 </frameset>
254 ';
255
256 $this->content.='
257 </html>';
258 }
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274 /************************************
275 *
276 * Rendering of various color selectors
277 *
278 ************************************/
279
280 /**
281 * Creates a color matrix table
282 *
283 * @return void
284 */
285 function colorMatrix() {
286 $steps = 51;
287
288 // Get colors:
289 $color = array();
290
291 for($rr=0;$rr<256;$rr+=$steps) {
292 for($gg=0;$gg<256;$gg+=$steps) {
293 for($bb=0;$bb<256;$bb+=$steps) {
294 $color[] = '#'.
295 substr('0'.dechex($rr),-2).
296 substr('0'.dechex($gg),-2).
297 substr('0'.dechex($bb),-2);
298 }
299 }
300 }
301
302 // Traverse colors:
303 $columns = 24;
304
305 $rows = 0;
306 $tRows = array();
307 while(isset($color[$columns*$rows])) {
308 $tCells = array();
309 for($i=0;$i<$columns;$i++) {
310 $tCells[] = '
311 <td bgcolor="'.$color[$columns*$rows+$i].'" onclick="document.colorform.colorValue.value = \''.$color[$columns*$rows+$i].'\'; document.colorform.submit();" title="'.$color[$columns*$rows+$i].'">&nbsp;&nbsp;</td>';
312 }
313 $tRows[] = '
314 <tr>'.implode('',$tCells).'
315 </tr>';
316 $rows++;
317 }
318
319 $table = '
320 <p class="c-head">'.$GLOBALS['LANG']->getLL('colorpicker_fromMatrix',1).'</p>
321 <table border="0" cellpadding="1" cellspacing="1" style="width:100%; border: 1px solid black; cursor:crosshair;">'.implode('',$tRows).'
322 </table>';
323
324 return $table;
325 }
326
327 /**
328 * Creates a selector box with all HTML color names.
329 *
330 * @return void
331 */
332 function colorList() {
333 // Initialize variables:
334 $colors = explode(',',$this->HTMLcolorList);
335 $currentValue = strtolower($this->colorValue);
336 $opt = array();
337 $opt[] = '<option value=""></option>';
338
339 // Traverse colors, making option tags for selector box.
340 foreach($colors as $colorName) {
341 $opt[] = '<option style="background-color: '.$colorName.';" value="'.htmlspecialchars($colorName).'"'.($currentValue==$colorName ? ' selected="selected"' : '').'>'.htmlspecialchars($colorName).'</option>';
342 }
343
344 // Compile selector box and return result:
345 $output = '
346 <p class="c-head">'.$GLOBALS['LANG']->getLL('colorpicker_fromList',1).'</p>
347 <select onchange="document.colorform.colorValue.value = this.options[this.selectedIndex].value; document.colorform.submit(); return false;">
348 '.implode('
349 ',$opt).'
350 </select><br />';
351
352 return $output;
353 }
354
355 /**
356 * Creates a color image selector
357 *
358 * @return void
359 */
360 function colorImage() {
361 // Handling color-picker image if any:
362 if (!$this->imageError) {
363 if ($this->pickerImage) {
364 if(t3lib_div::_POST('coords_x')) {
365 $this->colorValue = '#'.$this->getIndex(t3lib_stdgraphic::imageCreateFromFile($this->pickerImage),t3lib_div::_POST('coords_x'),t3lib_div::_POST('coords_y'));
366 }
367 $pickerFormImage = '
368 <p class="c-head">'.$GLOBALS['LANG']->getLL('colorpicker_fromImage',1).'</p>
369 <input type="image" src="../'.substr($this->pickerImage,strlen(PATH_site)).'" name="coords" style="cursor:crosshair;" /><br />';
370 } else {
371 $pickerFormImage = '';
372 }
373 } else {
374 $pickerFormImage = '
375 <p class="c-head">'.htmlspecialchars($this->imageError).'</p>';
376 }
377
378 return $pickerFormImage;
379 }
380
381 /**
382 * Gets the HTML (Hex) Color Code for the selected pixel of an image
383 * This method handles the correct imageResource no matter what format
384 *
385 * @param pointer Valid ImageResource returned by t3lib_stdgraphic::imageCreateFromFile
386 * @param integer X-Coordinate of the pixel that should be checked
387 * @param integer Y-Coordinate of the pixel that should be checked
388 * @return string HEX RGB value for color
389 * @see colorImage()
390 */
391 function getIndex($im,$x,$y) {
392 $rgb = ImageColorAt($im, $x, $y);
393 $colorrgb = imagecolorsforindex($im,$rgb);
394 $index['r'] = dechex($colorrgb['red']);
395 $index['g'] = dechex($colorrgb['green']);
396 $index['b'] = dechex($colorrgb['blue']);
397 foreach ($index as $value) {
398 if(strlen($value) == 1) {
399 $hexvalue[] = strtoupper('0'.$value);
400 } else {
401 $hexvalue[] = strtoupper($value);
402 }
403 }
404 $hex = implode('',$hexvalue);
405 return $hex;
406 }
407
408 /**
409 * Determines whether submitted field change functions are valid
410 * and are coming from the system and not from an external abuse.
411 *
412 * @return boolean Whether the submitted field change functions are valid
413 */
414 protected function areFieldChangeFunctionsValid() {
415 return (
416 $this->fieldChangeFunc && $this->fieldChangeFuncHash
417 && $this->fieldChangeFuncHash === t3lib_div::hmac($this->fieldChangeFunc)
418 );
419 }
420 }
421
422
423 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/wizard_colorpicker.php'])) {
424 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/wizard_colorpicker.php']);
425 }
426
427
428
429 // Make instance:
430 $SOBE = t3lib_div::makeInstance('SC_wizard_colorpicker');
431 $SOBE->init();
432 $SOBE->main();
433 $SOBE->printContent();
434
435 ?>