24b094effe714a843a9a709a6e4bf3b4f430d4b4
[squirrelmail.git] / functions / options.php
1 <?php
2
3 /**
4 * options.php
5 *
6 * Functions needed to display the options pages.
7 *
8 * @copyright &copy; 1999-2006 The SquirrelMail Project Team
9 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
10 * @version $Id$
11 * @package squirrelmail
12 * @subpackage prefs
13 */
14
15 /**********************************************/
16 /* Define constants used in the options code. */
17 /**********************************************/
18
19 /* Define constants for the various option types. */
20 define('SMOPT_TYPE_STRING', 0);
21 define('SMOPT_TYPE_STRLIST', 1);
22 define('SMOPT_TYPE_TEXTAREA', 2);
23 define('SMOPT_TYPE_INTEGER', 3);
24 define('SMOPT_TYPE_FLOAT', 4);
25 define('SMOPT_TYPE_BOOLEAN', 5);
26 define('SMOPT_TYPE_HIDDEN', 6);
27 define('SMOPT_TYPE_COMMENT', 7);
28 define('SMOPT_TYPE_FLDRLIST', 8);
29
30 /* Define constants for the options refresh levels. */
31 define('SMOPT_REFRESH_NONE', 0);
32 define('SMOPT_REFRESH_FOLDERLIST', 1);
33 define('SMOPT_REFRESH_ALL', 2);
34
35 /* Define constants for the options size. */
36 define('SMOPT_SIZE_TINY', 0);
37 define('SMOPT_SIZE_SMALL', 1);
38 define('SMOPT_SIZE_MEDIUM', 2);
39 define('SMOPT_SIZE_LARGE', 3);
40 define('SMOPT_SIZE_HUGE', 4);
41 define('SMOPT_SIZE_NORMAL', 5);
42
43 define('SMOPT_SAVE_DEFAULT', 'save_option');
44 define('SMOPT_SAVE_NOOP', 'save_option_noop');
45
46 /**
47 * SquirrelOption: An option for SquirrelMail.
48 *
49 * @package squirrelmail
50 * @subpackage prefs
51 */
52 class SquirrelOption {
53 /**
54 * The name of this setting
55 * @var string
56 */
57 var $name;
58 /**
59 * The text that prefaces setting on the preferences page
60 * @var string
61 */
62 var $caption;
63 /**
64 * The type of INPUT element
65 *
66 * See SMOPT_TYPE_* defines
67 * @var integer
68 */
69 var $type;
70 /**
71 * Indicates if a link should be shown to refresh part
72 * or all of the window
73 *
74 * See SMOPT_REFRESH_* defines
75 * @var integer
76 */
77 var $refresh_level;
78 /**
79 * Specifies the size of certain input items
80 *
81 * See SMOPT_SIZE_* defines
82 * @var integer
83 */
84 var $size;
85 /**
86 * Text that follows a text input or
87 * select list input on the preferences page
88 *
89 * useful for indicating units, meanings of special values, etc.
90 * @var string
91 */
92 var $trailing_text;
93 /**
94 * text displayed to the user
95 *
96 * Used with SMOPT_TYPE_COMMENT options
97 * @var string
98 */
99 var $comment;
100 /**
101 * additional javascript or other code added to the user input
102 * @var string
103 */
104 var $script;
105 /**
106 * script (usually Javascript) that will be placed after (outside of)
107 * the INPUT tag
108 * @var string
109 */
110 var $post_script;
111
112 /**
113 * The name of the Save Function for this option.
114 * @var string
115 */
116 var $save_function;
117
118 /* The various 'values' for this options. */
119 /**
120 * default/preselected value for this option
121 * @var mixed
122 */
123 var $value;
124 /**
125 * new option value
126 * @var mixed
127 */
128 var $new_value;
129 /**
130 * associative array, where each key is an actual input value
131 * and the corresponding value is what is displayed to the user
132 * for that list item in the drop-down list
133 * @var array
134 */
135 var $possible_values;
136 /**
137 * disables html sanitizing.
138 *
139 * WARNING - don't use it, if user input is possible in option
140 * or use own sanitizing functions. Currently works only with
141 * SMOPT_TYPE_STRLIST.
142 * @var bool
143 */
144 var $htmlencoded=false;
145 /**
146 * Controls folder list limits in SMOPT_TYPE_FLDRLIST widget.
147 * See $flag argument in sqimap_mailbox_option_list() function.
148 * @var string
149 * @since 1.5.1
150 */
151 var $folder_filter='noselect';
152
153 /**
154 * Constructor function
155 * @param string $name
156 * @param string $caption
157 * @param integer $type
158 * @param integer $refresh_level
159 * @param mixed $initial_value
160 * @param array $possible_values
161 * @param bool $htmlencoded
162 */
163 function SquirrelOption
164 ($name, $caption, $type, $refresh_level, $initial_value = '', $possible_values = '', $htmlencoded = false) {
165 /* Set the basic stuff. */
166 $this->name = $name;
167 $this->caption = $caption;
168 $this->type = $type;
169 $this->refresh_level = $refresh_level;
170 $this->possible_values = $possible_values;
171 $this->htmlencoded = $htmlencoded;
172 $this->size = SMOPT_SIZE_MEDIUM;
173 $this->trailing_text = '';
174 $this->comment = '';
175 $this->script = '';
176 $this->post_script = '';
177
178 //Check for a current value.
179 if (isset($GLOBALS[$name])) {
180 $this->value = $GLOBALS[$name];
181 } else if (!empty($initial_value)) {
182 $this->value = $initial_value;
183 } else {
184 $this->value = '';
185 }
186
187 /* Check for a new value. */
188 if ( !sqgetGlobalVar("new_$name", $this->new_value, SQ_POST ) ) {
189 $this->new_value = '';
190 }
191
192 /* Set the default save function. */
193 if (($type != SMOPT_TYPE_HIDDEN) && ($type != SMOPT_TYPE_COMMENT)) {
194 $this->save_function = SMOPT_SAVE_DEFAULT;
195 } else {
196 $this->save_function = SMOPT_SAVE_NOOP;
197 }
198 }
199
200 /**
201 * Set the value for this option.
202 * @param mixed $value
203 */
204 function setValue($value) {
205 $this->value = $value;
206 }
207
208 /**
209 * Set the new value for this option.
210 * @param mixed $new_value
211 */
212 function setNewValue($new_value) {
213 $this->new_value = $new_value;
214 }
215
216 /**
217 * Set the size for this option.
218 * @param integer $size
219 */
220 function setSize($size) {
221 $this->size = $size;
222 }
223
224 /**
225 * Set the trailing_text for this option.
226 * @param string $trailing_text
227 */
228 function setTrailingText($trailing_text) {
229 $this->trailing_text = $trailing_text;
230 }
231
232 /**
233 * Set the comment for this option.
234 * @param string $comment
235 */
236 function setComment($comment) {
237 $this->comment = $comment;
238 }
239
240 /**
241 * Set the script for this option.
242 * @param string $script
243 */
244 function setScript($script) {
245 $this->script = $script;
246 }
247
248 /**
249 * Set the "post script" for this option.
250 * @param string $post_script
251 */
252 function setPostScript($post_script) {
253 $this->post_script = $post_script;
254 }
255
256 /**
257 * Set the save function for this option.
258 * @param string $save_function
259 */
260 function setSaveFunction($save_function) {
261 $this->save_function = $save_function;
262 }
263
264 /**
265 * Set the trailing_text for this option.
266 * @param string $folder_filter
267 * @since 1.5.1
268 */
269 function setFolderFilter($folder_filter) {
270 $this->folder_filter = $folder_filter;
271 }
272
273 /**
274 * Creates fields on option pages according to option type
275 *
276 * Function that calls other createWidget* functions.
277 * @return string html formated option field
278 */
279 function createHTMLWidget() {
280 global $color;
281
282 // Use new value if available
283 if (!empty($this->new_value)) {
284 $tempValue = $this->value;
285 $this->value = $this->new_value;
286 }
287
288 /* Get the widget for this option type. */
289 switch ($this->type) {
290 case SMOPT_TYPE_STRING:
291 $result = $this->createWidget_String();
292 break;
293 case SMOPT_TYPE_STRLIST:
294 $result = $this->createWidget_StrList();
295 break;
296 case SMOPT_TYPE_TEXTAREA:
297 $result = $this->createWidget_TextArea();
298 break;
299 case SMOPT_TYPE_INTEGER:
300 $result = $this->createWidget_Integer();
301 break;
302 case SMOPT_TYPE_FLOAT:
303 $result = $this->createWidget_Float();
304 break;
305 case SMOPT_TYPE_BOOLEAN:
306 $result = $this->createWidget_Boolean();
307 break;
308 case SMOPT_TYPE_HIDDEN:
309 $result = $this->createWidget_Hidden();
310 break;
311 case SMOPT_TYPE_COMMENT:
312 $result = $this->createWidget_Comment();
313 break;
314 case SMOPT_TYPE_FLDRLIST:
315 $result = $this->createWidget_FolderList();
316 break;
317 default:
318 $result = '<font color="' . $color[2] . '">'
319 . sprintf(_("Option Type '%s' Not Found"), $this->type)
320 . '</font>';
321 }
322
323 /* Add the "post script" for this option. */
324 $result .= $this->post_script;
325
326 // put correct value back if need be
327 if (!empty($this->new_value)) {
328 $this->value = $tempValue;
329 }
330
331 /* Now, return the created widget. */
332 return ($result);
333 }
334
335 /**
336 * Create string field
337 * @return string html formated option field
338 */
339 function createWidget_String() {
340 switch ($this->size) {
341 case SMOPT_SIZE_TINY:
342 $width = 5;
343 break;
344 case SMOPT_SIZE_SMALL:
345 $width = 12;
346 break;
347 case SMOPT_SIZE_LARGE:
348 $width = 38;
349 break;
350 case SMOPT_SIZE_HUGE:
351 $width = 50;
352 break;
353 case SMOPT_SIZE_NORMAL:
354 default:
355 $width = 25;
356 }
357
358 $result = "<input type=\"text\" name=\"new_$this->name\" value=\"" .
359 htmlspecialchars($this->value) .
360 "\" size=\"$width\" $this->script />$this->trailing_text\n";
361 return ($result);
362 }
363
364 /**
365 * Create selection box
366 * @return string html formated selection box
367 */
368 function createWidget_StrList() {
369 /* Begin the select tag. */
370 $result = "<select name=\"new_$this->name\" $this->script>\n";
371
372 /* Add each possible value to the select list. */
373 foreach ($this->possible_values as $real_value => $disp_value) {
374 /* Start the next new option string. */
375 $new_option = '<option value="' .
376 ($this->htmlencoded ? $real_value : htmlspecialchars($real_value)) . '"';
377
378 /* If this value is the current value, select it. */
379 if ($real_value == $this->value) {
380 $new_option .= ' selected="selected"';
381 }
382
383 /* Add the display value to our option string. */
384 $new_option .= '>' . ($this->htmlencoded ? $disp_value : htmlspecialchars($disp_value)) . "</option>\n";
385
386 /* And add the new option string to our select tag. */
387 $result .= $new_option;
388 }
389
390 /* Close the select tag and return our happy result. */
391 $result .= "</select>$this->trailing_text\n";
392 return ($result);
393 }
394
395 /**
396 * Create folder selection box
397 * @return string html formated selection box
398 */
399 function createWidget_FolderList() {
400 $selected = array(strtolower($this->value));
401
402 /* set initial value */
403 $result = '';
404
405 /* Add each possible value to the select list. */
406 foreach ($this->possible_values as $real_value => $disp_value) {
407 if ( is_array($disp_value) ) {
408 /* For folder list, we passed in the array of boxes.. */
409 $new_option = sqimap_mailbox_option_list(0, $selected, 0, $disp_value, $this->folder_filter);
410 } else {
411 /* Start the next new option string. */
412 $new_option = '<option value="' . htmlspecialchars($real_value) . '"';
413
414 /* If this value is the current value, select it. */
415 if ($real_value == $this->value) {
416 $new_option .= ' selected="selected"';
417 }
418
419 /* Add the display value to our option string. */
420 $new_option .= '>' . htmlspecialchars($disp_value) . "</option>\n";
421 }
422 /* And add the new option string to our select tag. */
423 $result .= $new_option;
424 }
425
426
427 if (empty($result)) {
428 // string is displayed when interface can't build folder selection box
429 return _("unavailable");
430 } else {
431 /* Begin the select tag. */
432 $ret = "<select name=\"new_$this->name\" $this->script>\n";
433 $ret.= $result;
434 /* Close the select tag and return our happy result. */
435 $ret.= "</select>\n";
436 return ($ret);
437 }
438 }
439
440 /**
441 * Creates textarea
442 * @return string html formated textarea field
443 */
444 function createWidget_TextArea() {
445 switch ($this->size) {
446 case SMOPT_SIZE_TINY: $rows = 3; $cols = 10; break;
447 case SMOPT_SIZE_SMALL: $rows = 4; $cols = 30; break;
448 case SMOPT_SIZE_LARGE: $rows = 10; $cols = 60; break;
449 case SMOPT_SIZE_HUGE: $rows = 20; $cols = 80; break;
450 case SMOPT_SIZE_NORMAL:
451 default: $rows = 5; $cols = 50;
452 }
453 //FIXME: we need to change $this->script into $this->aExtraAttribs, and anyone who wants to add some javascript or other attributes to an options widget can put them in an array and pass them as extra attributes (key == attrib name, value == attrib value).... for now, this is the only place it is used, and there is no place in the code that text areas get extra attribs or javascript... in fact the only place that was using $this->script is include/options/display.php:200, so that's easy to change.... just have to go through this file and change all the places that use "script"
454 $this->aExtraAttribs = array();
455 return addTextArea('new_' . $this->name, $this->value, $cols, $rows, $this->aExtraAttribs);
456 }
457
458 /**
459 * Creates field for integer
460 *
461 * Difference from createWidget_String is visible only when javascript is enabled
462 * @return string html formated option field
463 */
464 function createWidget_Integer() {
465
466 // add onChange javascript handler to a regular string widget
467 // which will strip out all non-numeric chars
468 if (checkForJavascript())
469 return preg_replace('/\/>/', ' onChange="origVal=this.value; newVal=\'\'; '
470 . 'for (i=0;i<origVal.length;i++) { if (origVal.charAt(i)>=\'0\' '
471 . '&& origVal.charAt(i)<=\'9\') newVal += origVal.charAt(i); } '
472 . 'this.value=newVal;" />', $this->createWidget_String());
473 else
474 return $this->createWidget_String();
475 }
476
477 /**
478 * Creates field for floating number
479 * Difference from createWidget_String is visible only when javascript is enabled
480 * @return string html formated option field
481 */
482 function createWidget_Float() {
483
484 // add onChange javascript handler to a regular string widget
485 // which will strip out all non-numeric (period also OK) chars
486 if (checkForJavascript())
487 return preg_replace('/\/>/', ' onChange="origVal=this.value; newVal=\'\'; '
488 . 'for (i=0;i<origVal.length;i++) { if ((origVal.charAt(i)>=\'0\' '
489 . '&& origVal.charAt(i)<=\'9\') || origVal.charAt(i)==\'.\') '
490 . 'newVal += origVal.charAt(i); } this.value=newVal;" />'
491 , $this->createWidget_String());
492 else
493 return $this->createWidget_String();
494 }
495
496 /**
497 * Creates radio field (yes/no)
498 * @return string html formated radio field
499 */
500 function createWidget_Boolean() {
501 /* Do the whole current value thing. */
502 if ($this->value != SMPREF_NO) {
503 $yes_chk = ' checked="checked"';
504 $no_chk = '';
505 } else {
506 $yes_chk = '';
507 $no_chk = ' checked="checked"';
508 }
509
510 /* Build the yes choice. */
511 $yes_option = '<input type="radio" id="new_' . $this->name . '_yes" '
512 . 'name="new_' . $this->name . '" value="' . SMPREF_YES . '"'
513 . $yes_chk . ' ' . $this->script . ' />&nbsp;'
514 . '<label for="new_'.$this->name.'_yes">' . _("Yes") . '</label>';
515
516 /* Build the no choice. */
517 $no_option = '<input type="radio" id="new_' . $this->name . '_no" '
518 . 'name="new_' . $this->name . '" value="' . SMPREF_NO . '"'
519 . $no_chk . ' ' . $this->script . ' />&nbsp;'
520 . '<label for="new_'.$this->name.'_no">' . _("No") . '</label>';
521
522 /* Build and return the combined "boolean widget". */
523 $result = "$yes_option&nbsp;&nbsp;&nbsp;&nbsp;$no_option";
524 return ($result);
525 }
526
527 /**
528 * Creates hidden field
529 * @return string html formated hidden input field
530 */
531 function createWidget_Hidden() {
532 $result = '<input type="hidden" name="new_' . $this->name
533 . '" value="' . htmlspecialchars($this->value)
534 . '" ' . $this->script . ' />';
535 return ($result);
536 }
537
538 /**
539 * Creates comment
540 * @return string comment
541 */
542 function createWidget_Comment() {
543 $result = $this->comment;
544 return ($result);
545 }
546
547 /**
548 *
549 */
550 function save() {
551 $function = $this->save_function;
552 $function($this);
553 }
554
555 /**
556 *
557 */
558 function changed() {
559 return ($this->value != $this->new_value);
560 }
561 } /* End of SquirrelOption class*/
562
563 /**
564 * Saves option
565 * @param object $option object that holds option name and new_value
566 */
567 function save_option($option) {
568 if ( !sqgetGlobalVar('username', $username, SQ_SESSION ) ) {
569 /* Can't save the pref if we don't have the username */
570 return;
571 }
572 global $data_dir;
573 setPref($data_dir, $username, $option->name, $option->new_value);
574 }
575
576 /**
577 * save function that does not save
578 * @param object $option
579 */
580 function save_option_noop($option) {
581 /* Do nothing here... */
582 }
583
584 /**
585 * Create hidden 'optpage' input field with value set by argument
586 * @param string $optpage identification of option page
587 * @return string html formated hidden input field
588 */
589 function create_optpage_element($optpage) {
590 return create_hidden_element('optpage', $optpage);
591 }
592
593 /**
594 * Create hidden 'optmode' input field with value set by argument
595 * @param string $optmode
596 * @return string html formated hidden input field
597 */
598 function create_optmode_element($optmode) {
599 return create_hidden_element('optmode', $optmode);
600 }
601
602 /**
603 * Create hidden field.
604 * @param string $name field name
605 * @param string $value field value
606 * @return string html formated hidden input field
607 */
608 function create_hidden_element($name, $value) {
609 $result = '<input type="hidden" '
610 . 'name="' . $name . '" '
611 . 'value="' . htmlspecialchars($value) . '" />';
612 return ($result);
613 }
614
615 /**
616 * @param array $optgrps
617 * @param array $optvals
618 * @return array
619 */
620 function create_option_groups($optgrps, $optvals) {
621 /* Build a simple array with which to start. */
622 $result = array();
623
624 /* Create option group for each option group name. */
625 foreach ($optgrps as $grpkey => $grpname) {
626 $result[$grpkey] = array();
627 $result[$grpkey]['name'] = $grpname;
628 $result[$grpkey]['options'] = array();
629 }
630
631 /* Create a new SquirrelOption for each set of option values. */
632 foreach ($optvals as $grpkey => $grpopts) {
633 foreach ($grpopts as $optset) {
634 /* Create a new option with all values given. */
635 $next_option = new SquirrelOption(
636 $optset['name'],
637 $optset['caption'],
638 $optset['type'],
639 (isset($optset['refresh']) ? $optset['refresh'] : SMOPT_REFRESH_NONE),
640 (isset($optset['initial_value']) ? $optset['initial_value'] : ''),
641 (isset($optset['posvals']) ? $optset['posvals'] : ''),
642 (isset($optset['htmlencoded']) ? $optset['htmlencoded'] : false)
643 );
644
645 /* If provided, set the size for this option. */
646 if (isset($optset['size'])) {
647 $next_option->setSize($optset['size']);
648 }
649
650 /* If provided, set the trailing_text for this option. */
651 if (isset($optset['trailing_text'])) {
652 $next_option->setTrailingText($optset['trailing_text']);
653 }
654
655 /* If provided, set the comment for this option. */
656 if (isset($optset['comment'])) {
657 $next_option->setComment($optset['comment']);
658 }
659
660 /* If provided, set the save function for this option. */
661 if (isset($optset['save'])) {
662 $next_option->setSaveFunction($optset['save']);
663 }
664
665 /* If provided, set the script for this option. */
666 if (isset($optset['script'])) {
667 $next_option->setScript($optset['script']);
668 }
669
670 /* If provided, set the "post script" for this option. */
671 if (isset($optset['post_script'])) {
672 $next_option->setPostScript($optset['post_script']);
673 }
674
675 /* If provided, set the folder_filter for this option. */
676 if (isset($optset['folder_filter'])) {
677 $next_option->setFolderFilter($optset['folder_filter']);
678 }
679
680 /* Add this option to the option array. */
681 $result[$grpkey]['options'][] = $next_option;
682 }
683 }
684
685 /* Return our resulting array. */
686 return ($result);
687 }
688
689 // vim: et ts=4