Source for file options.php

Documentation is available at options.php

  1. <?php
  2.  
  3. /**
  4.  * options.php
  5.  *
  6.  * Functions needed to display the options pages.
  7.  *
  8.  * @copyright 1999-2012 The SquirrelMail Project Team
  9.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  10.  * @version $Id: options.php 14345 2012-12-09 11:58:17Z kink $
  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. define('SMOPT_TYPE_FLDRLIST_MULTI'9);
  30. define('SMOPT_TYPE_EDIT_LIST'10);
  31. define('SMOPT_TYPE_STRLIST_MULTI'11);
  32. define('SMOPT_TYPE_BOOLEAN_CHECKBOX'12);
  33. define('SMOPT_TYPE_BOOLEAN_RADIO'13);
  34. define('SMOPT_TYPE_STRLIST_RADIO'14);
  35. define('SMOPT_TYPE_SUBMIT'15);
  36. define('SMOPT_TYPE_INFO'16);
  37. define('SMOPT_TYPE_PASSWORD'17);
  38.  
  39. /* Define constants for the layout scheme for edit lists. */
  40. define('SMOPT_EDIT_LIST_LAYOUT_LIST'0);
  41. define('SMOPT_EDIT_LIST_LAYOUT_SELECT'1);
  42.  
  43. /* Define constants for the options refresh levels. */
  44. define('SMOPT_REFRESH_NONE'0);
  45. define('SMOPT_REFRESH_FOLDERLIST'1);
  46. define('SMOPT_REFRESH_ALL'2);
  47.  
  48. /* Define constants for the options size. */
  49. define('SMOPT_SIZE_TINY'0);
  50. define('SMOPT_SIZE_SMALL'1);
  51. define('SMOPT_SIZE_MEDIUM'2);
  52. define('SMOPT_SIZE_LARGE'3);
  53. define('SMOPT_SIZE_HUGE'4);
  54. define('SMOPT_SIZE_NORMAL'5);
  55.  
  56. define('SMOPT_SAVE_DEFAULT''save_option');
  57. define('SMOPT_SAVE_NOOP''save_option_noop');
  58.  
  59. /**
  60.  * SquirrelOption: An option for Squirrelmail.
  61.  *
  62.  * This class is a work in progress. When complete, it will handle
  63.  * presentation and saving of Squirrelmail user options in a simple,
  64.  * streamline manner. Stay tuned for more stuff.
  65.  *
  66.  * Also, I'd like to ask that people leave this alone (mostly :) until
  67.  * I get it a little further along. That should only be a day or two or
  68.  * three. I will remove this message when it is ready for primetime usage.
  69.  * @package squirrelmail
  70.  */
  71. class SquirrelOption {
  72.     /* The basic stuff. */
  73.     var $raw_option_array;
  74.     var $name;
  75.     var $caption;
  76.     var $caption_wrap;
  77.     var $type;
  78.     var $refresh_level;
  79.     var $size;
  80.     var $layout_type;
  81.     var $comment;
  82.     var $script;
  83.     var $post_script;
  84.     var $trailing_text;
  85.     var $yes_text;
  86.     var $no_text;
  87.     var $use_add_widget;
  88.     var $use_delete_widget;
  89.  
  90.     /* The name of the Save Function for this option. */
  91.     var $save_function;
  92.  
  93.     /* The various 'values' for this options. */
  94.     var $value;
  95.     var $new_value;
  96.     var $possible_values;
  97.     var $htmlencoded=false;
  98.  
  99.     function SquirrelOption
  100.     ($raw_option_array$name$caption$type$refresh_level$initial_value ''$possible_values ''$htmlencoded false{
  101.         /* Set the basic stuff. */
  102.         $this->raw_option_array = $raw_option_array;
  103.         $this->name = $name;
  104.         $this->caption = $caption;
  105.         $this->caption_wrap = TRUE;
  106.         $this->type = $type;
  107.         $this->refresh_level = $refresh_level;
  108.         $this->possible_values = $possible_values;
  109.         $this->htmlencoded = $htmlencoded;
  110. // FIXME: why isn't this set by default to NORMAL?
  111.         $this->size = SMOPT_SIZE_MEDIUM;
  112.         $this->layout_type = 0;
  113.         $this->comment = '';
  114.         $this->script = '';
  115.         $this->post_script = '';
  116.         $this->trailing_text = '';
  117.         $this->yes_text = '';
  118.         $this->no_text = '';
  119.         $this->use_add_widget = TRUE;
  120.         $this->use_delete_widget = TRUE;
  121.  
  122.         /* Check for a current value. */
  123.         if (isset($GLOBALS[$name])) {
  124.             $this->value = $GLOBALS[$name];
  125.         else if (!empty($initial_value)) {
  126.             $this->value = $initial_value;
  127.         else {
  128.             $this->value = '';
  129.         }
  130.  
  131.         /* Check for a new value. */
  132.     if !sqgetGlobalVar("new_$name"$this->new_valueSQ_POST ) ) {
  133.             $this->new_value = NULL;
  134.         }
  135.  
  136.         /* Set the default save function. */
  137.         if ($type != SMOPT_TYPE_HIDDEN
  138.          && $type != SMOPT_TYPE_INFO
  139.          && $type != SMOPT_TYPE_COMMENT{
  140.             $this->save_function = SMOPT_SAVE_DEFAULT;
  141.         else {
  142.             $this->save_function = SMOPT_SAVE_NOOP;
  143.         }
  144.     }
  145.  
  146.     /** Convenience function that identifies which types of
  147.         widgets are stored as (serialized) array values. */
  148.     function is_multiple_valued({
  149.         return ($this->type == SMOPT_TYPE_FLDRLIST_MULTI
  150.              || $this->type == SMOPT_TYPE_STRLIST_MULTI
  151.              || $this->type == SMOPT_TYPE_EDIT_LIST);
  152.     }
  153.  
  154.     /* Set the value for this option. */
  155.     function setValue($value{
  156.         $this->value = $value;
  157.     }
  158.  
  159.     /* Set the new value for this option. */
  160.     function setNewValue($new_value{
  161.         $this->new_value = $new_value;
  162.     }
  163.  
  164.     /* Set whether the caption is allowed to wrap for this option. */
  165.     function setCaptionWrap($caption_wrap{
  166.         $this->caption_wrap = $caption_wrap;
  167.     }
  168.  
  169.     /* Set the size for this option. */
  170.     function setSize($size{
  171.         $this->size = $size;
  172.     }
  173.  
  174.     /* Set the trailing text for this option. */
  175.     function setTrailingText($trailing_text{
  176.         $this->trailing_text = $trailing_text;
  177.     }
  178.  
  179.     /* Set the yes text for this option. */
  180.     function setYesText($yes_text{
  181.         $this->yes_text = $yes_text;
  182.     }
  183.  
  184.     /* Set the no text for this option. */
  185.     function setNoText($no_text{
  186.         $this->no_text = $no_text;
  187.     }
  188.  
  189.     /* Set the "use add widget" value for this option. */
  190.     function setUseAddWidget($use_add_widget{
  191.         $this->use_add_widget = $use_add_widget;
  192.     }
  193.  
  194.     /* Set the "use delete widget" value for this option. */
  195.     function setUseDeleteWidget($use_delete_widget{
  196.         $this->use_delete_widget = $use_delete_widget;
  197.     }
  198.  
  199.     /* Set the layout type for this option. */
  200.     function setLayoutType($layout_type{
  201.         $this->layout_type = $layout_type;
  202.     }
  203.  
  204.     /* Set the comment for this option. */
  205.     function setComment($comment{
  206.         $this->comment = $comment;
  207.     }
  208.  
  209.     /* Set the script for this option. */
  210.     function setScript($script{
  211.         $this->script = $script;
  212.     }
  213.  
  214.     /* Set the "post script" for this option. */
  215.     function setPostScript($post_script{
  216.         $this->post_script = $post_script;
  217.     }
  218.  
  219.     /* Set the save function for this option. */
  220.     function setSaveFunction($save_function{
  221.         $this->save_function = $save_function;
  222.     }
  223.  
  224.     function createHTMLWidget({
  225.         global $javascript_on$color;
  226.  
  227.         // Use new value if available
  228.         if (!is_null($this->new_value)) {
  229.             $tempValue $this->value;
  230.             $this->value = $this->new_value;
  231.         }
  232.  
  233.         /* Get the widget for this option type. */
  234.         switch ($this->type{
  235.             case SMOPT_TYPE_STRING:
  236.                 $result $this->createWidget_String();
  237.                 break;
  238.             case SMOPT_TYPE_PASSWORD:
  239.                 $result $this->createWidget_String(TRUE);
  240.                 break;
  241.             case SMOPT_TYPE_STRLIST:
  242.                 $result $this->createWidget_StrList();
  243.                 break;
  244.             case SMOPT_TYPE_TEXTAREA:
  245.                 $result $this->createWidget_TextArea();
  246.                 break;
  247.             case SMOPT_TYPE_INTEGER:
  248.                 $result $this->createWidget_Integer();
  249.                 break;
  250.             case SMOPT_TYPE_FLOAT:
  251.                 $result $this->createWidget_Float();
  252.                 break;
  253.             case SMOPT_TYPE_BOOLEAN:
  254.                 $result $this->createWidget_Boolean();
  255.                 break;
  256.             case SMOPT_TYPE_BOOLEAN_CHECKBOX:
  257.                 $result $this->createWidget_Boolean(TRUE);
  258.                 break;
  259.             case SMOPT_TYPE_BOOLEAN_RADIO:
  260.                 $result $this->createWidget_Boolean(FALSE);
  261.                 break;
  262.             case SMOPT_TYPE_HIDDEN:
  263.                 $result $this->createWidget_Hidden();
  264.                 break;
  265.             case SMOPT_TYPE_COMMENT:
  266.                 $result $this->createWidget_Comment();
  267.                 break;
  268.             case SMOPT_TYPE_FLDRLIST:
  269.                 $result $this->createWidget_FolderList();
  270.                 break;
  271.             case SMOPT_TYPE_FLDRLIST_MULTI:
  272.                 $result $this->createWidget_FolderList(TRUE);
  273.                 break;
  274.             case SMOPT_TYPE_EDIT_LIST:
  275.                 $result $this->createWidget_EditList();
  276.                 break;
  277.             case SMOPT_TYPE_STRLIST_MULTI:
  278.                 $result $this->createWidget_StrList(TRUE);
  279.                 break;
  280.             case SMOPT_TYPE_STRLIST_RADIO:
  281.                 $result $this->createWidget_StrList(FALSETRUE);
  282.                 break;
  283.             case SMOPT_TYPE_SUBMIT:
  284.                 $result $this->createWidget_Submit();
  285.                 break;
  286.             case SMOPT_TYPE_INFO:
  287.                 $result $this->createWidget_Info();
  288.                 break;
  289.             default:
  290.                $result '<font color="' $color[2'">'
  291.                        . sprintf(_("Option Type '%s' Not Found")$this->type)
  292.                        . '</font>';
  293.         }
  294.  
  295.         /* Add the "post script" for this option. */
  296.         $result .= $this->post_script;
  297.  
  298.         // put correct value back if need be
  299.         if (!is_null($this->new_value)) {
  300.             $this->value = $tempValue;
  301.         }
  302.  
  303.         /* Now, return the created widget. */
  304.         return $result;
  305.     }
  306.  
  307.     function createWidget_Info({
  308.         $result sm_encode_html_special_chars($this->value"\n";
  309.         return $result;
  310.     }
  311.  
  312.     /**
  313.      * Create text box
  314.      *
  315.      * @param boolean $password When TRUE, the text in the input
  316.      *                           widget will be obscured (OPTIONAL;
  317.      *                           default = FALSE).
  318.      *
  319.      * @return string html formated text input
  320.      *
  321.      */
  322.     function createWidget_String($password=FALSE{
  323.         switch ($this->size{
  324.             case SMOPT_SIZE_TINY:
  325.                 $width 5;
  326.                 break;
  327.             case SMOPT_SIZE_SMALL:
  328.                 $width 12;
  329.                 break;
  330.             case SMOPT_SIZE_LARGE:
  331.                 $width 38;
  332.                 break;
  333.             case SMOPT_SIZE_HUGE:
  334.                 $width 50;
  335.                 break;
  336.             case SMOPT_SIZE_NORMAL:
  337.             default:
  338.                 $width 25;
  339.         }
  340.  
  341.         $result "<input type=\"" 
  342.                 . ($password 'password' 'text'
  343.                 . "\" name=\"new_$this->name\" value=\""
  344.                 . sm_encode_html_special_chars($this->value)
  345.                 . "\" size=\"$width\" $this->script /> 
  346.                 . sm_encode_html_special_chars($this->trailing_text"\n";
  347.         return $result;
  348.     }
  349.  
  350.     /**
  351.      * Create selection box or radio group
  352.      *
  353.      * When $this->htmlencoded is TRUE, the keys and values in
  354.      * $this->possible_values are assumed to be display-safe.
  355.      * Use with care!
  356.      *
  357.      * Note that when building radio buttons instead of a select
  358.      * widget, if the "size" attribute is SMOPT_SIZE_TINY, the
  359.      * radio buttons will be output one after another without
  360.      * linebreaks between them.  Otherwise, each radio button
  361.      * goes on a line of its own.
  362.      *
  363.      * @param boolean $multiple_select When TRUE, the select widget
  364.      *                                  will allow multiple selections
  365.      *                                  (OPTIONAL; default is FALSE
  366.      *                                  (single select list))
  367.      * @param boolean $radio_buttons   When TRUE, the widget will
  368.      *                                  instead be built as a group
  369.      *                                  of radio buttons (and
  370.      *                                  $multiple_select will be
  371.      *                                  forced to FALSE) (OPTIONAL;
  372.      *                                  default is FALSE (select widget))
  373.      *
  374.      * @return string html formated selection box or radio buttons
  375.      *
  376.      */
  377.     function createWidget_StrList($multiple_select=FALSE$radio_buttons=FALSE{
  378.  
  379.         // radio buttons instead of select widget?
  380.         //
  381.         if ($radio_buttons{
  382.  
  383.             $result '';
  384.             foreach ($this->possible_values as $real_value => $disp_value{
  385.                 $result .= "\n" '<input type="radio" name="new_' $this->name 
  386.                          . '" id="new_' $this->name . '_' 
  387.                          . ($this->htmlencoded ? $real_value sm_encode_html_special_chars($real_value))
  388.                          . '" value="'
  389.                          . ($this->htmlencoded ? $real_value sm_encode_html_special_chars($real_value))
  390.                          . '"' ($real_value == $this->value ? ' checked="checked"' '')
  391.                          . ' /> <label for="new_' $this->name . '_'
  392.                          . ($this->htmlencoded ? $real_value sm_encode_html_special_chars($real_value))
  393.                          . '">'
  394.                          . ($this->htmlencoded ? $disp_value sm_encode_html_special_chars($disp_value))
  395.                          . '</label>';
  396.                 if ($this->size != SMOPT_SIZE_TINY)
  397.                     $result .= '<br />';
  398.             }
  399.  
  400.             return $result;
  401.         }
  402.  
  403.  
  404.         // everything below applies to select widgets
  405.         //
  406.         switch ($this->size{
  407. //FIXME: not sure about these sizes... seems like we could add another on the "large" side...
  408.             case SMOPT_SIZE_TINY:
  409.                 $height 3;
  410.                 break;
  411.             case SMOPT_SIZE_SMALL:
  412.                 $height 8;
  413.                 break;
  414.             case SMOPT_SIZE_LARGE:
  415.                 $height 15;
  416.                 break;
  417.             case SMOPT_SIZE_HUGE:
  418.                 $height 25;
  419.                 break;
  420.             case SMOPT_SIZE_NORMAL:
  421.             default:
  422.                 $height 5;
  423.         }
  424.  
  425.         // multiple select lists should already have array values
  426.         if (is_array($this->value))
  427.             $selected $this->value;
  428.         else
  429.             $selected array(strtolower($this->value));
  430.  
  431.         /* Begin the select tag. */
  432.         $result '<select name="new_' $this->name
  433.             . ($multiple_select '[]" multiple="multiple" size="' $height '" ' '" ')
  434.             . $this->script . ">\n";
  435.  
  436.         /* Add each possible value to the select list. */
  437.         foreach ($this->possible_values as $real_value => $disp_value{
  438.             /* Start the next new option string. */
  439.             $new_option '<option value="' .
  440.                 ($this->htmlencoded ? $real_value sm_encode_html_special_chars($real_value)) '"';
  441.  
  442.             // multiple select lists have possibly more than one default selection
  443.             if ($multiple_select{
  444.                 foreach ($selected as $default{
  445.                     if ((string)$default == (string)$real_value{
  446.                         $new_option .= ' selected="selected"';
  447.                         break;
  448.                     }
  449.                 }
  450.             }
  451.  
  452.             /* If this value is the current value, select it. */
  453.             else if ($real_value == $this->value{
  454.                $new_option .= ' selected="selected"';
  455.             }
  456.  
  457.             /* Add the display value to our option string. */
  458.             $new_option .= '>' ($this->htmlencoded ? $disp_value sm_encode_html_special_chars($disp_value)) "</option>\n";
  459.             /* And add the new option string to our select tag. */
  460.             $result .= $new_option;
  461.         }
  462.  
  463.         /* Close the select tag and return our happy result. */
  464.         $result .= '</select>' sm_encode_html_special_chars($this->trailing_text"\n";
  465.         return $result;
  466.     }
  467.  
  468.     /**
  469.      * Create folder selection box
  470.      *
  471.      * @param boolean $multiple_select When TRUE, the select widget
  472.      *                                  will allow multiple selections
  473.      *                                  (OPTIONAL; default is FALSE
  474.      *                                  (single select list))
  475.      *
  476.      * @return string html formated selection box
  477.      *
  478.      */
  479.     function createWidget_FolderList($multiple_select=FALSE{
  480.  
  481.         switch ($this->size{
  482. //FIXME: not sure about these sizes... seems like we could add another on the "large" side...
  483.             case SMOPT_SIZE_TINY:
  484.                 $height 3;
  485.                 break;
  486.             case SMOPT_SIZE_SMALL:
  487.                 $height 8;
  488.                 break;
  489.             case SMOPT_SIZE_LARGE:
  490.                 $height 15;
  491.                 break;
  492.             case SMOPT_SIZE_HUGE:
  493.                 $height 25;
  494.                 break;
  495.             case SMOPT_SIZE_NORMAL:
  496.             default:
  497.                 $height 5;
  498.         }
  499.  
  500.         // multiple select lists should already have array values
  501.         if (is_array($this->value))
  502.             $selected $this->value;
  503.         else
  504.             $selected array(strtolower($this->value));
  505.  
  506.         /* Begin the select tag. */
  507.         $result '<select name="new_' $this->name
  508.                 . ($multiple_select '[]" multiple="multiple" size="' $height '"' '"')
  509.                 . " $this->script>\n";
  510.  
  511.         /* Add each possible value to the select list. */
  512.         foreach ($this->possible_values as $real_value => $disp_value{
  513.  
  514.             if is_array($disp_value) ) {
  515.                 /* For folder list, we passed in the array of boxes.. */
  516.                 $selected_lowercase array();
  517.                 foreach ($selected as $i => $box
  518.                     $selected_lowercase[$istrtolower($box);
  519.                 $new_option sqimap_mailbox_option_list(0$selected_lowercase0$disp_value);
  520.  
  521.             else {
  522.                 /* Start the next new option string. */
  523.                 $new_option '<option value="' sm_encode_html_special_chars($real_value'"';
  524.  
  525.                 // multiple select lists have possibly more than one default selection
  526.                 if ($multiple_select{
  527.                     foreach ($selected as $default{
  528.                         if ((string)$default == (string)$real_value{
  529.                             $new_option .= ' selected="selected"';
  530.                             break;
  531.                         }
  532.                     }
  533.                 }
  534.  
  535.                 /* If this value is the current value, select it. */
  536.                 else if ($real_value == $this->value{
  537.                    $new_option .= ' selected="selected"';
  538.                 }
  539.  
  540.                 /* Add the display value to our option string. */
  541.                 $new_option .= '>' sm_encode_html_special_chars($disp_value"</option>\n";
  542.             }
  543.             /* And add the new option string to our select tag. */
  544.             $result .= $new_option;
  545.         }
  546.         /* Close the select tag and return our happy result. */
  547.         $result .= '</select>' sm_encode_html_special_chars($this->trailing_text"\n";
  548.         return $result;
  549.     }
  550.  
  551.  
  552.     function createWidget_TextArea({
  553.         switch ($this->size{
  554.             case SMOPT_SIZE_TINY:  $rows 3$cols =  10break;
  555.             case SMOPT_SIZE_SMALL$rows 4$cols =  30break;
  556.             case SMOPT_SIZE_LARGE$rows 10$cols =  60break;
  557.             case SMOPT_SIZE_HUGE:  $rows 20$cols =  80break;
  558.             case SMOPT_SIZE_NORMAL:
  559.             default$rows 5$cols =  50;
  560.         }
  561.         $result "<textarea name=\"new_$this->name\" rows=\"$rows\" "
  562.                 . "cols=\"$cols\" $this->script>"
  563.                 . sm_encode_html_special_chars($this->value"</textarea>\n";
  564.         return ($result);
  565.     }
  566.  
  567.     function createWidget_Integer({
  568.  
  569.         global $javascript_on;
  570.  
  571.         // add onChange javascript handler to a regular string widget
  572.         // which will strip out all non-numeric chars
  573.         if ($javascript_on)
  574.            return preg_replace('/\/>/'' onChange="origVal=this.value; newVal=\'\'; '
  575.                     . 'for (i=0;i<origVal.length;i++) { if (origVal.charAt(i)>=\'0\' '
  576.                     . '&& origVal.charAt(i)<=\'9\') newVal += origVal.charAt(i); } '
  577.                     . 'this.value=newVal;" />'$this->createWidget_String());
  578.         else
  579.            return $this->createWidget_String();
  580.     }
  581.  
  582.     function createWidget_Float({
  583.  
  584.         global $javascript_on;
  585.  
  586.         // add onChange javascript handler to a regular string widget
  587.         // which will strip out all non-numeric (period also OK) chars
  588.         if ($javascript_on)
  589.            return preg_replace('/\/>/'' onChange="origVal=this.value; newVal=\'\'; '
  590.                     . 'for (i=0;i<origVal.length;i++) { if ((origVal.charAt(i)>=\'0\' '
  591.                     . '&& origVal.charAt(i)<=\'9\') || origVal.charAt(i)==\'.\') '
  592.                     . 'newVal += origVal.charAt(i); } this.value=newVal;" />'
  593.                 $this->createWidget_String());
  594.         else
  595.            return $this->createWidget_String();
  596.     }
  597.  
  598.     /**
  599.      * Create boolean widget
  600.      *
  601.      * When creating Yes/No radio buttons, the "yes_text"
  602.      * and "no_text" option attributes are used to override
  603.      * the typical "Yes" and "No" text.
  604.      *
  605.      * @param boolean $checkbox When TRUE, the widget will be
  606.      *                           constructed as a checkbox,
  607.      *                           otherwise it will be a set of
  608.      *                           Yes/No radio buttons (OPTIONAL;
  609.      *                           default is TRUE (checkbox)).
  610.      *
  611.      * @return string html formated boolean widget
  612.      *
  613.      */
  614.     function createWidget_Boolean($checkbox=TRUE{
  615.         /* Do the whole current value thing. */
  616.         if ($this->value != SMPREF_NO{
  617.             $yes_chk ' checked="checked"';
  618.             $no_chk '';
  619.         else {
  620.             $yes_chk '';
  621.             $no_chk ' checked="checked"';
  622.         }
  623.  
  624.         // checkbox...
  625.         //
  626.         if ($checkbox{
  627.             $result '<input type="checkbox" name="new_' $this->name
  628.                     . '" id="new_' $this->name . '" value="' SMPREF_YES
  629.                     . "\" $yes_chk $this->script . ' />&nbsp;'
  630.                     . '<label for="new_' $this->name . '">' 
  631.                     . sm_encode_html_special_chars($this->trailing_text'</label>';
  632.         }
  633.  
  634.         // radio buttons...
  635.         //
  636.         else {
  637.  
  638.             /* Build the yes choice. */
  639.             $yes_option '<input type="radio" name="new_' $this->name 
  640.                         . '" id="new_' $this->name . '_yes"'
  641.                         . ' value="' SMPREF_YES "\"$yes_chk $this->script />&nbsp;"
  642.                         . '<label for="new_' $this->name . '_yes">' (!empty($this->yes_textsm_encode_html_special_chars($this->yes_text_("Yes")) '</label>';
  643.  
  644.             /* Build the no choice. */
  645.             $no_option '<input type="radio" name="new_' $this->name
  646.                        . '" id="new_' $this->name . '_no"'
  647.                        . ' value="' SMPREF_NO "\"$no_chk $this->script />&nbsp;"
  648.                        . '<label for="new_' $this->name . '_no">' (!empty($this->no_textsm_encode_html_special_chars($this->no_text_("No")) '</label>';
  649.     
  650.             /* Build the combined "boolean widget". */
  651.             $result "$yes_option&nbsp;&nbsp;&nbsp;&nbsp;$no_option";
  652.  
  653.         }
  654.  
  655.         return ($result);
  656.     }
  657.  
  658.     function createWidget_Hidden({
  659.         $result '<input type="hidden" name="new_' $this->name
  660.                 . '" value="' sm_encode_html_special_chars($this->value)
  661.                 . '" ' $this->script . ' />';
  662.         return ($result);
  663.     }
  664.  
  665.     function createWidget_Comment({
  666.         $result $this->comment;
  667.         return ($result);
  668.     }
  669.  
  670.     /**
  671.      * Creates an edit list
  672.      *
  673.      * Note that multiple layout types are supported for this widget.
  674.      * $this->layout_type must be one of the SMOPT_EDIT_LIST_LAYOUT_*
  675.      * constants.
  676.      *
  677.      * @return string html formated list of edit fields and
  678.      *                 their associated controls
  679.      */
  680.     function createWidget_EditList({
  681.  
  682.         switch ($this->size{
  683.             case SMOPT_SIZE_TINY:
  684.                 $height 3;
  685.                 break;
  686.             case SMOPT_SIZE_SMALL:
  687.                 $height 8;
  688.                 break;
  689.             case SMOPT_SIZE_MEDIUM:
  690.                 $height 15;
  691.                 break;
  692.             case SMOPT_SIZE_LARGE:
  693.                 $height 25;
  694.                 break;
  695.             case SMOPT_SIZE_HUGE:
  696.                 $height 40;
  697.                 break;
  698.             case SMOPT_SIZE_NORMAL:
  699.             default:
  700.                 $height 5;
  701.         }
  702.  
  703.  
  704.         // ensure correct format of current value(s)
  705.         //
  706.         if (empty($this->possible_values)) $this->possible_values = array();
  707.         if (!is_array($this->possible_values)) $this->possible_values = array($this->possible_values);
  708.  
  709.  
  710.         global $javascript_on$color;
  711.  
  712.         switch ($this->layout_type{
  713.             case SMOPT_EDIT_LIST_LAYOUT_SELECT:
  714.                 $result '';
  715.                 if ($this->use_add_widget)
  716.                     $result .= _("Add"'&nbsp;<input name="add_' $this->name 
  717.                              . '" size="38" /><br />';
  718.                 $result .= '<select name="new_' $this->name
  719.                     . '[]" multiple="multiple" size="' $height '"'
  720.                     . ($javascript_on ' onchange="if (typeof(window.addinput_' $this->name . ') == \'undefined\') { var f = document.forms.length; var i = 0; var pos = -1; while( pos == -1 && i < f ) { var e = document.forms[i].elements.length; var j = 0; while( pos == -1 && j < e ) { if ( document.forms[i].elements[j].type == \'text\' && document.forms[i].elements[j].name == \'add_' $this->name . '\' ) { pos = j; } j++; } i++; } if( pos >= 0 ) { window.addinput_' $this->name . ' = document.forms[i-1].elements[pos]; } } for (x = 0; x < this.length; x++) { if (this.options[x].selected) { window.addinput_' $this->name . '.value = this.options[x].text; break; } }"' '')
  721.                     . ' ' $this->script . ">\n";
  722.  
  723.  
  724.                 if (is_array($this->value))
  725.                     $selected $this->value;
  726.                 else
  727.                     $selected array($this->value);
  728.  
  729.  
  730.                 // Add each possible value to the select list.
  731.                 //
  732.                 foreach ($this->possible_values as $value{
  733.  
  734.                     // Start the next new option string.
  735.                     //
  736.                     $result .= '<option value="' sm_encode_html_special_chars($value'"';
  737.  
  738.                     // having a selected item in the edit list doesn't have
  739.                     // any meaning, but maybe someone will think of a way to
  740.                     // use it, so we might as well put the code in
  741.                     //
  742.                     foreach ($selected as $default{
  743.                         if ((string)$default == (string)$value{
  744.                             $result .= ' selected="selected"';
  745.                             break;
  746.                         }
  747.                     }
  748.  
  749.                     // Add the display value to our option string.
  750.                     //
  751.                     $result .= '>' sm_encode_html_special_chars($value"</option>\n";
  752.  
  753.                 }
  754.  
  755.                 $result .= '</select>';
  756.                 if (!empty($this->possible_values&& $this->use_delete_widget)
  757.                     $result .= '<br /><input type="checkbox" name="delete_' 
  758.                              . $this->name . '" id="delete_' $this->name 
  759.                              . '" value="1" />&nbsp;<label for="delete_'
  760.                              . $this->name . '">' _("Delete Selected")
  761.                              . '</label>';
  762.  
  763.                 break;
  764.  
  765.  
  766.  
  767.             case SMOPT_EDIT_LIST_LAYOUT_LIST:
  768.                 $result '<table width="80%" cellpadding="1" cellspacing="0" border="0" bgcolor="'
  769.                         . $color[0'"><tr><td>';
  770.                 if ($this->use_add_widget)
  771.                     $result .= _("Add"'&nbsp;<input name="add_' $this->name 
  772.                              . '" size="38" /><br />';
  773.                 $result .= '<table width="100%" cellpadding="1" cellspacing="0" border="0" bgcolor="' $color[5'">';
  774.  
  775.                 $bgcolor 4;
  776.                 if (!isset($color[12]))
  777.                     $color[12'#EAEAEA';
  778.                 $index 0;
  779.  
  780.                 foreach ($this->possible_values as $key => $value{
  781.  
  782.                     if ($bgcolor == 4$bgcolor 12;
  783.                     else $bgcolor 4;
  784.  
  785.                     $result .= '<tr bgcolor="' $color[$bgcolor'">'
  786.                              . '<td width="1%"><input type="checkbox" name="new_' $this->name . '[' ($index++']" id="' $this->name . '_list_item_' $key '" value="' sm_encode_html_special_chars($value'"></td>'
  787.                              . '<td><label for="' $this->name . '_list_item_' $key '">' sm_encode_html_special_chars($value'</label></td>'
  788.                              . "</tr>\n";
  789.  
  790.                 }
  791.  
  792.                 $result .= '</table>';
  793.  
  794.                 if (!empty($this->possible_values&& $this->use_delete_widget)
  795.                     $result .= '<input type="checkbox" name="delete_' 
  796.                         . $this->name . '" id="delete_' $this->name 
  797.                         . '" value="1" />&nbsp;<label for="delete_' $this->name . '">'
  798.                         . _("Delete Selected"'</label>';
  799.  
  800.                 $result .= '</td></tr></table>';
  801.  
  802.                 break;
  803.  
  804.  
  805.             default:
  806.                 $result '<font color="' $color[2'">'
  807.                         . sprintf(_("Edit List Layout Type '%s' Not Found")$this->layout_type)
  808.                         . '</font>';
  809.         }
  810.  
  811.         return $result;
  812.  
  813.     }
  814.  
  815.     /**
  816.      * Creates a submit button
  817.      *
  818.      * @return string html formated submit button widget
  819.      *
  820.      */
  821.     function createWidget_Submit({
  822.  
  823.         $result "<input type=\"submit\" name=\"$this->name\" value=\""
  824.                 . sm_encode_html_special_chars($this->comment)
  825.                 . "\" $this->script />
  826.                 . sm_encode_html_special_chars($this->trailing_text"\n";
  827.  
  828.         return $result;
  829.  
  830.     }
  831.  
  832.     function save({
  833.         $function $this->save_function;
  834.         $function($this);
  835.     }
  836.  
  837.     function changed({
  838.  
  839.         // edit lists have a lot going on, so we'll always process them
  840.         //
  841.         if ($this->type == SMOPT_TYPE_EDIT_LISTreturn TRUE;
  842.  
  843.         return ($this->value != $this->new_value);
  844.     }
  845. }
  846.  
  847. function save_option($option{
  848.  
  849.     // Can't save the pref if we don't have the username
  850.     //
  851.     if !sqgetGlobalVar('username'$usernameSQ_SESSION ) ) {
  852.         return;
  853.     }
  854.  
  855.     // if the widget is a selection list, make sure the new
  856.     // value is actually in the selection list and is not an
  857.     // injection attack
  858.     //
  859.     if ($option->type == SMOPT_TYPE_STRLIST
  860.      && !array_key_exists($option->new_value$option->possible_values))
  861.         return;
  862.  
  863.  
  864.     // all other widgets except TEXTAREAs should never be allowed to have newlines
  865.     //
  866.     else if ($option->type != SMOPT_TYPE_TEXTAREA)
  867.         $option->new_value str_replace(array("\r""\n")''$option->new_value);
  868.  
  869.  
  870.     global $data_dir;
  871.  
  872.     // edit lists: first add new elements to list, then
  873.     // remove any selected ones (note that we must add
  874.     // before deleting because the javascript that populates
  875.     // the "add" textbox when selecting items in the list
  876.     // (for deletion))
  877.     //
  878.     if ($option->type == SMOPT_TYPE_EDIT_LIST{
  879.  
  880.         if (empty($option->possible_values)) $option->possible_values array();
  881.         if (!is_array($option->possible_values)) $option->possible_values array($option->possible_values);
  882.  
  883.         // add element if given
  884.         //
  885.         if ((isset($option->use_add_widget&& $option->use_add_widget)
  886.          && sqGetGlobalVar('add_' $option->name$new_elementSQ_POST)) {
  887.             $new_element trim($new_element);
  888.             if (!empty($new_element)
  889.              && !in_array($new_element$option->possible_values))
  890.                 $option->possible_values[$new_element;
  891.         }
  892.  
  893.         // delete selected elements if needed
  894.         //
  895.         if ((isset($option->use_delete_widget&& $option->use_delete_widget)
  896.          && is_array($option->new_value)
  897.          && sqGetGlobalVar('delete_' $option->name$ignoreSQ_POST))
  898.             $option->possible_values array_diff($option->possible_values$option->new_value);
  899.  
  900.         // save full list (stored in "possible_values")
  901.         //
  902.         setPref($data_dir$username$option->nameserialize($option->possible_values));
  903.  
  904.     // Certain option types need to be serialized because
  905.     // they are not scalar
  906.     //
  907.     else if ($option->is_multiple_valued())
  908.         setPref($data_dir$username$option->nameserialize($option->new_value));
  909.  
  910.     // Checkboxes, when unchecked, don't submit anything in
  911.     // the POST, so set to SMPREF_OFF if not found
  912.     //
  913.     else if (($option->type == SMOPT_TYPE_BOOLEAN
  914.            || $option->type == SMOPT_TYPE_BOOLEAN_CHECKBOX)
  915.           && empty($option->new_value)) 
  916.         setPref($data_dir$username$option->nameSMPREF_OFF);
  917.  
  918.     // For integer fields, make sure we only have digits...
  919.     // We'll be nice and instead of just converting to an integer,
  920.     // we'll physically remove each non-digit in the string.
  921.     //
  922.     else if ($option->type == SMOPT_TYPE_INTEGER{
  923.         $option->new_value preg_replace('/[^0-9]/'''$option->new_value);
  924.         setPref($data_dir$username$option->name$option->new_value);
  925.     }
  926.  
  927.     else
  928.         setPref($data_dir$username$option->name$option->new_value);
  929.  
  930.  
  931.     // if a checkbox or multi select is zeroed/cleared out, it
  932.     // needs to have an empty value pushed into its "new_value" slot
  933.     //
  934.     if (($option->type == SMOPT_TYPE_STRLIST_MULTI
  935.       || $option->type == SMOPT_TYPE_BOOLEAN_CHECKBOX)
  936.      && is_null($option->new_value))
  937.         $option->new_value '';
  938.  
  939. }
  940.  
  941. function save_option_noop($option{
  942.     /* Do nothing here... */
  943. }
  944.  
  945. function create_optpage_element($optpage{
  946.     return create_hidden_element('optpage'$optpage);
  947. }
  948.  
  949. function create_optmode_element($optmode{
  950.     return create_hidden_element('optmode'$optmode);
  951. }
  952.  
  953. function create_hidden_element($name$value{
  954.     $result '<input type="hidden" '
  955.             . 'name="' $name '" '
  956.             . 'value="' sm_encode_html_special_chars($value'" />';
  957.     return ($result);
  958. }
  959.  
  960. function create_option_groups($optgrps$optvals{
  961.     /* Build a simple array with which to start. */
  962.     $result array();
  963.  
  964.     /* Create option group for each option group name. */
  965.     foreach ($optgrps as $grpkey => $grpname{
  966.         $result[$grpkeyarray();
  967.         $result[$grpkey]['name'$grpname;
  968.         $result[$grpkey]['options'array();
  969.     }
  970.  
  971.      /* Create a new SquirrelOption for each set of option values. */
  972.     foreach ($optvals as $grpkey => $grpopts{
  973.         foreach ($grpopts as $optset{
  974.             /* Create a new option with all values given. */
  975.             $next_option new SquirrelOption(
  976.                 $optset,
  977.                 $optset['name'],
  978.                 $optset['caption'],
  979.                 $optset['type'],
  980.                 (isset($optset['refresh']$optset['refresh'SMOPT_REFRESH_NONE),
  981.                 (isset($optset['initial_value']$optset['initial_value'''),
  982.                 (isset($optset['posvals']$optset['posvals'''),
  983.                 (isset($optset['htmlencoded']$optset['htmlencoded'false)
  984.                 );
  985.  
  986.             /* If provided, set if the caption is allowed to wrap for this option. */
  987.             if (isset($optset['caption_wrap'])) {
  988.                 $next_option->setCaptionWrap($optset['caption_wrap']);
  989.             }
  990.  
  991.             /* If provided, set the size for this option. */
  992.             if (isset($optset['size'])) {
  993.                 $next_option->setSize($optset['size']);
  994.             }
  995.  
  996.             /* If provided, set the trailing_text for this option. */
  997.             if (isset($optset['trailing_text'])) {
  998.                 $next_option->setTrailingText($optset['trailing_text']);
  999.             }
  1000.  
  1001.             /* If provided, set the yes_text for this option. */
  1002.             if (isset($optset['yes_text'])) {
  1003.                 $next_option->setYesText($optset['yes_text']);
  1004.             }
  1005.  
  1006.             /* If provided, set the no_text for this option. */
  1007.             if (isset($optset['no_text'])) {
  1008.                 $next_option->setNoText($optset['no_text']);
  1009.             }
  1010.  
  1011.             /* If provided, set the use_add_widget value for this option. */
  1012.             if (isset($optset['use_add_widget'])) {
  1013.                 $next_option->setUseAddWidget($optset['use_add_widget']);
  1014.             }
  1015.  
  1016.             /* If provided, set the use_delete_widget value for this option. */
  1017.             if (isset($optset['use_delete_widget'])) {
  1018.                 $next_option->setUseDeleteWidget($optset['use_delete_widget']);
  1019.             }
  1020.  
  1021.             /* If provided, set the layout type for this option. */
  1022.             if (isset($optset['layout_type'])) {
  1023.                 $next_option->setLayoutType($optset['layout_type']);
  1024.             }
  1025.  
  1026.             /* If provided, set the comment for this option. */
  1027.             if (isset($optset['comment'])) {
  1028.                 $next_option->setComment($optset['comment']);
  1029.             }
  1030.  
  1031.             /* If provided, set the save function for this option. */
  1032.             if (isset($optset['save'])) {
  1033.                 $next_option->setSaveFunction($optset['save']);
  1034.             }
  1035.  
  1036.             /* If provided, set the script for this option. */
  1037.             if (isset($optset['script'])) {
  1038.                 $next_option->setScript($optset['script']);
  1039.             }
  1040.  
  1041.             /* If provided, set the "post script" for this option. */
  1042.             if (isset($optset['post_script'])) {
  1043.                 $next_option->setPostScript($optset['post_script']);
  1044.             }
  1045.  
  1046.             /* Add this option to the option array. */
  1047.             $result[$grpkey]['options'][$next_option;
  1048.         }
  1049.     }
  1050.  
  1051.     /* Return our resulting array. */
  1052.     return ($result);
  1053. }
  1054.  
  1055. function print_option_groups($option_groups{
  1056.     /* Print each option group. */
  1057.     foreach ($option_groups as $next_optgrp{
  1058.         /* If it is not blank, print the name for this option group. */
  1059.         if ($next_optgrp['name'!= ''{
  1060.             echo html_tag'tr'"\n".
  1061.                         html_tag'td',
  1062.                             '<b>' $next_optgrp['name''</b>' ,
  1063.                         'center' ,'''valign="middle" colspan="2" nowrap' )
  1064.                     ."\n";
  1065.         }
  1066.  
  1067.         /* Print each option in this option group. */
  1068.         $hidden_options '';
  1069.         foreach ($next_optgrp['options'as $option{
  1070.             if ($option->type != SMOPT_TYPE_HIDDEN{
  1071.  
  1072.                 // although trailing_text will be a label for the checkbox,
  1073.                 // make the caption a label too - some widgets won't have
  1074.                 // trailing_text and having both as labels is perfectly fine
  1075.                 //
  1076.                 if ($option->type == SMOPT_TYPE_BOOLEAN_CHECKBOX
  1077.                  || $option->type == SMOPT_TYPE_BOOLEAN)
  1078.                     $option->caption '<label for="new_' $option->name '">'
  1079.                                      . $option->caption '</label>';
  1080.  
  1081.                 // text area trailing text just goes under the caption
  1082.                 //
  1083.                 if ($option->type == SMOPT_TYPE_TEXTAREA && !empty($option->trailing_text))
  1084.                     $option->caption .= '<br /><small>' $option->trailing_text '</small>';
  1085.  
  1086.                 global $color;
  1087.                 //$info_bgcolor = 0;
  1088.                 $info_bgcolor 4;
  1089.                 $info_width 80;
  1090.                 if ($option->type == SMOPT_TYPE_INFO)
  1091.                     echo html_tag('tr'"\n" html_tag('td'"\n" html_tag('table'"\n" html_tag('tr'"\n" html_tag('td'"\n" $option->createHTMLWidget()))''$color[$info_bgcolor]'width="' $info_width '%"')'center' ,'''colspan="2" valign="middle"')) ."\n";
  1092.                 else
  1093.                     echo html_tag'tr'"\n".
  1094.                                html_tag'td'$option->caption (!empty($option->caption':' '')'right' ,'''valign="middle"' ($option->caption_wrap '' ' style="white-space:nowrap"') ) .
  1095.                                html_tag'td'$option->createHTMLWidget()'left' )
  1096.                            ."\n";
  1097.             else {
  1098.                 $hidden_options .= $option->createHTMLWidget();
  1099.             }
  1100.         }
  1101.  
  1102.         /* Print an empty row after this option group. */
  1103.         echo html_tag'tr',
  1104.                    html_tag'td''&nbsp;' $hidden_options'left''''colspan="2"' )
  1105.                 "\n";
  1106.     }
  1107. }
  1108.  
  1109. function OptionSubmit$name {
  1110.         echo html_tag'tr',
  1111.                    html_tag'td''<input type="submit" value="' _("Submit"'" name="' $name '" />&nbsp;&nbsp;&nbsp;&nbsp;''right''''colspan="2"' )
  1112.                 "\n";
  1113. }

Documentation generated on Sun, 19 May 2013 04:22:37 +0200 by phpDocumentor 1.4.3