PageRenderTime 140ms CodeModel.GetById 79ms app.highlight 47ms RepoModel.GetById 0ms app.codeStats 1ms

/horde-3.3.13/lib/Horde/Form.php

#
PHP | 4908 lines | 3112 code | 652 blank | 1144 comment | 469 complexity | f4355879d9388b0d21ca68251e904d7e MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/**
   3 * @package Horde_Form
   4 */
   5
   6/** String */
   7include_once 'Horde/String.php';
   8
   9/**
  10 * Horde_Form Master Class.
  11 *
  12 * The Horde_Form:: package provides form rendering, validation, and
  13 * other functionality for the Horde Application Framework.
  14 *
  15 * $Horde: framework/Form/Form.php,v 1.306.2.81 2012/02/03 15:17:31 jan Exp $
  16 *
  17 * Copyright 2001-2007 Robert E. Coyle <robertecoyle@hotmail.com>
  18 * Copyright 2001-2009 The Horde Project (http://www.horde.org/)
  19 *
  20 * See the enclosed file COPYING for license information (LGPL). If you
  21 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  22 *
  23 * @author  Robert E. Coyle <robertecoyle@hotmail.com>
  24 * @author  Chuck Hagenbuch <chuck@horde.org>
  25 * @since   Horde 3.0
  26 * @package Horde_Form
  27 */
  28class Horde_Form {
  29
  30    var $_name = '';
  31    var $_title = '';
  32    var $_extra = '';
  33    var $_vars;
  34    var $_submit = array();
  35    var $_reset = false;
  36    var $_errors = array();
  37    var $_submitted = null;
  38    var $_sections = array();
  39    var $_open_section = null;
  40    var $_currentSection = array();
  41    var $_variables = array();
  42    var $_hiddenVariables = array();
  43    var $_useFormToken = true;
  44    var $_autofilled = false;
  45    var $_enctype = null;
  46    var $_help = false;
  47
  48    function Horde_Form(&$vars, $title = '', $name = null)
  49    {
  50        if (empty($name)) {
  51            $name = String::lower(get_class($this));
  52        }
  53
  54        $this->_vars = &$vars;
  55        $this->_title = $title;
  56        $this->_name = $name;
  57    }
  58
  59    function __construct($vars, $title = '', $name = null)
  60    {
  61        $this->Horde_Form($vars, $title, $name);
  62    }
  63
  64    function &singleton($form, &$vars, $title = '', $name = null)
  65    {
  66        static $instances = array();
  67
  68        $signature = serialize(array($form, $vars, $title, $name));
  69        if (!isset($instances[$signature])) {
  70            if (class_exists($form)) {
  71                $instances[$signature] = new $form($vars, $title, $name);
  72            } else {
  73                $instances[$signature] = new Horde_Form($vars, $title, $name);
  74            }
  75        }
  76
  77        return $instances[$signature];
  78    }
  79
  80    function setVars(&$vars)
  81    {
  82        $this->_vars = &$vars;
  83    }
  84
  85    function getTitle()
  86    {
  87        return $this->_title;
  88    }
  89
  90    function setTitle($title)
  91    {
  92        $this->_title = $title;
  93    }
  94
  95    function getExtra()
  96    {
  97        return $this->_extra;
  98    }
  99
 100    function setExtra($extra)
 101    {
 102        $this->_extra = $extra;
 103    }
 104
 105    function getName()
 106    {
 107        return $this->_name;
 108    }
 109
 110    /**
 111     * Sets or gets whether the form should be verified by tokens.
 112     * Tokens are used to verify that a form is only submitted once.
 113     *
 114     * @param boolean $token  If specified, sets whether to use form tokens.
 115     *
 116     * @return boolean  Whether form tokens are being used.
 117     */
 118    function useToken($token = null)
 119    {
 120        if (!is_null($token)) {
 121            $this->_useFormToken = $token;
 122        }
 123        return $this->_useFormToken;
 124    }
 125
 126    /**
 127     * Get the renderer for this form, either a custom renderer or the
 128     * standard one.
 129     *
 130     * To use a custom form renderer, your form class needs to
 131     * override this function:
 132     * <code>
 133     * function &getRenderer()
 134     * {
 135     *     $r = new CustomFormRenderer();
 136     *     return $r;
 137     * }
 138     * </code>
 139     *
 140     * ... where CustomFormRenderer is the classname of the custom
 141     * renderer class, which should extend Horde_Form_Renderer.
 142     *
 143     * @param array $params  A hash of renderer-specific parameters.
 144     *
 145     * @return object Horde_Form_Renderer  The form renderer.
 146     */
 147    function &getRenderer($params = array())
 148    {
 149        require_once 'Horde/Form/Renderer.php';
 150        $renderer = new Horde_Form_Renderer($params);
 151        return $renderer;
 152    }
 153
 154    function &getType($type, $params = array())
 155    {
 156        $type_class = 'Horde_Form_Type_' . $type;
 157        if (!class_exists($type_class)) {
 158            require_once 'PEAR.php';
 159            Horde::fatal(PEAR::raiseError(sprintf('Nonexistant class "%s" for field type "%s"', $type_class, $type)), __FILE__, __LINE__);
 160        }
 161        $type_ob = new $type_class();
 162        if (!$params) {
 163            $params = array();
 164        }
 165        call_user_func_array(array(&$type_ob, 'init'), $params);
 166        return $type_ob;
 167    }
 168
 169    function setSection($section = '', $desc = '', $image = '', $expanded = true)
 170    {
 171        $this->_currentSection = $section;
 172        if (!count($this->_sections) && !$this->getOpenSection()) {
 173            $this->setOpenSection($section);
 174        }
 175        $this->_sections[$section]['desc'] = $desc;
 176        $this->_sections[$section]['expanded'] = $expanded;
 177        $this->_sections[$section]['image'] = $image;
 178    }
 179
 180    function getSectionDesc($section)
 181    {
 182        return $this->_sections[$section]['desc'];
 183    }
 184
 185    function getSectionImage($section)
 186    {
 187        return $this->_sections[$section]['image'];
 188    }
 189
 190    function setOpenSection($section)
 191    {
 192        $this->_vars->set('__formOpenSection', $section);
 193    }
 194
 195    function getOpenSection()
 196    {
 197        return $this->_vars->get('__formOpenSection');
 198    }
 199
 200    function getSectionExpandedState($section, $boolean = false)
 201    {
 202        if ($boolean) {
 203            /* Only the boolean value is required. */
 204            return $this->_sections[$section]['expanded'];
 205        }
 206
 207        /* Need to return the values for use in styles. */
 208        if ($this->_sections[$section]['expanded']) {
 209            return 'block';
 210        } else {
 211            return 'none';
 212        }
 213    }
 214
 215    /**
 216     * TODO
 217     */
 218    function &addVariable($humanName, $varName, $type, $required,
 219                          $readonly = false, $description = null,
 220                          $params = array())
 221    {
 222        return $this->insertVariableBefore(null, $humanName, $varName, $type,
 223                                           $required, $readonly, $description,
 224                                           $params);
 225    }
 226
 227    /**
 228     * TODO
 229     */
 230    function &insertVariableBefore($before, $humanName, $varName, $type,
 231                                   $required, $readonly = false,
 232                                   $description = null, $params = array())
 233    {
 234        $type = &$this->getType($type, $params);
 235        $var = new Horde_Form_Variable($humanName, $varName, $type,
 236                                       $required, $readonly, $description);
 237
 238        /* Set the form object reference in the var. */
 239        $var->setFormOb($this);
 240
 241        if ($var->getTypeName() == 'enum' &&
 242            !strlen($type->getPrompt()) &&
 243            count($var->getValues()) == 1) {
 244            $vals = array_keys($var->getValues());
 245            $this->_vars->add($var->varName, $vals[0]);
 246            $var->_autofilled = true;
 247        } elseif ($var->getTypeName() == 'file' ||
 248                  $var->getTypeName() == 'image') {
 249            $this->_enctype = 'multipart/form-data';
 250        }
 251        if (empty($this->_currentSection)) {
 252            $this->_currentSection = '__base';
 253        }
 254
 255        if (is_null($before)) {
 256            $this->_variables[$this->_currentSection][] = &$var;
 257        } else {
 258            $num = 0;
 259            while (isset($this->_variables[$this->_currentSection][$num]) &&
 260                   $this->_variables[$this->_currentSection][$num]->getVarName() != $before) {
 261                $num++;
 262            }
 263            if (!isset($this->_variables[$this->_currentSection][$num])) {
 264                $this->_variables[$this->_currentSection][] = &$var;
 265            } else {
 266                $this->_variables[$this->_currentSection] = array_merge(
 267                    array_slice($this->_variables[$this->_currentSection], 0, $num),
 268                    array(&$var),
 269                    array_slice($this->_variables[$this->_currentSection], $num));
 270            }
 271        }
 272
 273        return $var;
 274    }
 275
 276    /**
 277     * Removes a variable from the form.
 278     *
 279     * As only variables can be passed by reference, you need to call this
 280     * method this way if want to pass a variable name:
 281     * <code>
 282     * $form->removeVariable($var = 'varname');
 283     * </code>
 284     *
 285     * @param Horde_Form_Variable|string $var  Either the variable's name or
 286     *                                         the variable to remove from the
 287     *                                         form.
 288     *
 289     * @return boolean  True if the variable was found (and deleted).
 290     */
 291    function removeVariable(&$var)
 292    {
 293        foreach (array_keys($this->_variables) as $section) {
 294            foreach (array_keys($this->_variables[$section]) as $i) {
 295                if ((is_a($var, 'Horde_Form_Variable') && $this->_variables[$section][$i] === $var) ||
 296                    ($this->_variables[$section][$i]->getVarName() == $var)) {
 297                    // Slice out the variable to be removed.
 298                    $this->_variables[$this->_currentSection] = array_merge(
 299                        array_slice($this->_variables[$this->_currentSection], 0, $i),
 300                        array_slice($this->_variables[$this->_currentSection], $i + 1));
 301
 302                    return true;
 303                }
 304            }
 305        }
 306
 307        return false;
 308    }
 309
 310    /**
 311     * TODO
 312     */
 313    function &addHidden($humanName, $varName, $type, $required,
 314                        $readonly = false, $description = null,
 315                        $params = array())
 316    {
 317        $type = &$this->getType($type, $params);
 318        $var = new Horde_Form_Variable($humanName, $varName, $type,
 319                                       $required, $readonly, $description);
 320        $var->hide();
 321        $this->_hiddenVariables[] = &$var;
 322        return $var;
 323    }
 324
 325    function &getVariables($flat = true, $withHidden = false)
 326    {
 327        if ($flat) {
 328            $vars = array();
 329            foreach ($this->_variables as $section) {
 330                foreach ($section as $var) {
 331                    $vars[] = $var;
 332                }
 333            }
 334            if ($withHidden) {
 335                foreach ($this->_hiddenVariables as $var) {
 336                    $vars[] = $var;
 337                }
 338            }
 339            return $vars;
 340        } else {
 341            return $this->_variables;
 342        }
 343    }
 344
 345    function setButtons($submit, $reset = false)
 346    {
 347        if ($submit === true || is_null($submit) || empty($submit)) {
 348            /* Default to 'Submit'. */
 349            $submit = array(_("Submit"));
 350        } elseif (!is_array($submit)) {
 351            /* Default to array if not passed. */
 352            $submit = array($submit);
 353        }
 354        /* Only if $reset is strictly true insert default 'Reset'. */
 355        if ($reset === true) {
 356            $reset = _("Reset");
 357        }
 358
 359        $this->_submit = $submit;
 360        $this->_reset = $reset;
 361    }
 362
 363    function appendButtons($submit)
 364    {
 365        if (!is_array($submit)) {
 366            $submit = array($submit);
 367        }
 368
 369        $this->_submit = array_merge($this->_submit, $submit);
 370    }
 371
 372    function preserveVarByPost(&$vars, $varname, $alt_varname = '')
 373    {
 374        $value = $vars->getExists($varname, $wasset);
 375
 376        /* If an alternate name is given under which to preserve use that. */
 377        if ($alt_varname) {
 378            $varname = $alt_varname;
 379        }
 380
 381        if ($wasset) {
 382            $this->_preserveVarByPost($varname, $value);
 383        }
 384    }
 385
 386    /**
 387     * @access private
 388     */
 389    function _preserveVarByPost($varname, $value)
 390    {
 391        if (is_array($value)) {
 392            foreach ($value as $id => $val) {
 393                $this->_preserveVarByPost($varname . '[' . $id . ']', $val);
 394            }
 395        } else {
 396            $varname = htmlspecialchars($varname);
 397            $value = htmlspecialchars($value);
 398            printf('<input type="hidden" name="%s" value="%s" />' . "\n",
 399                   $varname,
 400                   $value);
 401        }
 402    }
 403
 404    function open(&$renderer, &$vars, $action, $method = 'get', $enctype = null)
 405    {
 406        if (is_null($enctype) && !is_null($this->_enctype)) {
 407            $enctype = $this->_enctype;
 408        }
 409        $renderer->open($action, $method, $this->_name, $enctype);
 410        $renderer->listFormVars($this);
 411
 412        if (!empty($this->_name)) {
 413            $this->_preserveVarByPost('formname', $this->_name);
 414        }
 415
 416        if ($this->_useFormToken) {
 417            require_once 'Horde/Token.php';
 418            $token = Horde_Token::generateId($this->_name);
 419            $_SESSION['horde_form_secrets'][$token] = true;
 420            $this->_preserveVarByPost($this->_name . '_formToken', $token);
 421        }
 422
 423        /* Loop through vars and check for any special cases to preserve. */
 424        $variables = $this->getVariables();
 425        foreach ($variables as $var) {
 426            /* Preserve value if change has to be tracked. */
 427            if ($var->getOption('trackchange')) {
 428                $varname = $var->getVarName();
 429                $this->preserveVarByPost($vars, $varname, '__old_' . $varname);
 430            }
 431        }
 432
 433        foreach ($this->_hiddenVariables as $var) {
 434            $this->preserveVarByPost($vars, $var->getVarName());
 435        }
 436    }
 437
 438    function close($renderer)
 439    {
 440        $renderer->close();
 441    }
 442
 443    /**
 444     * Renders the form for editing.
 445     *
 446     * @param Horde_Form_Renderer $renderer  A renderer instance, optional
 447     *                                       since Horde 3.2.
 448     * @param Variables $vars                A Variables instance, optional
 449     *                                       since Horde 3.2.
 450     * @param string $action                 The form action (url).
 451     * @param string $method                 The form method, usually either
 452     *                                       'get' or 'post'.
 453     * @param string $enctype                The form encoding type. Determined
 454     *                                       automatically if null.
 455     * @param boolean $focus                 Focus the first form field?
 456     */
 457    function renderActive($renderer = null, $vars = null, $action = '',
 458                          $method = 'get', $enctype = null, $focus = true)
 459    {
 460        if (is_null($renderer)) {
 461            $renderer = $this->getRenderer();
 462        }
 463        if (is_null($vars)) {
 464            $vars = $this->_vars;
 465        }
 466
 467        if (is_null($enctype) && !is_null($this->_enctype)) {
 468            $enctype = $this->_enctype;
 469        }
 470        $renderer->open($action, $method, $this->getName(), $enctype);
 471        $renderer->listFormVars($this);
 472
 473        if (!empty($this->_name)) {
 474            $this->_preserveVarByPost('formname', $this->_name);
 475        }
 476
 477        if ($this->_useFormToken) {
 478            require_once 'Horde/Token.php';
 479            $token = Horde_Token::generateId($this->_name);
 480            $_SESSION['horde_form_secrets'][$token] = true;
 481            $this->_preserveVarByPost($this->_name . '_formToken', $token);
 482        }
 483
 484        if (count($this->_sections)) {
 485            $this->_preserveVarByPost('__formOpenSection', $this->getOpenSection());
 486        }
 487
 488        /* Loop through vars and check for any special cases to
 489         * preserve. */
 490        $variables = $this->getVariables();
 491        foreach ($variables as $var) {
 492            /* Preserve value if change has to be tracked. */
 493            if ($var->getOption('trackchange')) {
 494                $varname = $var->getVarName();
 495                $this->preserveVarByPost($vars, $varname, '__old_' . $varname);
 496            }
 497        }
 498
 499        foreach ($this->_hiddenVariables as $var) {
 500            $this->preserveVarByPost($vars, $var->getVarName());
 501        }
 502
 503        $renderer->beginActive($this->getTitle(), $this->getExtra());
 504        $renderer->renderFormActive($this, $vars);
 505        $renderer->submit($this->_submit, $this->_reset);
 506        $renderer->end();
 507        $renderer->close($focus);
 508    }
 509
 510    /**
 511     * Renders the form for displaying.
 512     *
 513     * @param Horde_Form_Renderer $renderer  A renderer instance, optional
 514     *                                       since Horde 3.2.
 515     * @param Variables $vars                A Variables instance, optional
 516     *                                       since Horde 3.2.
 517     */
 518    function renderInactive($renderer = null, $vars = null)
 519    {
 520        if (is_null($renderer)) {
 521            $renderer = $this->getRenderer();
 522        }
 523        if (is_null($vars)) {
 524            $vars = $this->_vars;
 525        }
 526
 527        $renderer->_name = $this->_name;
 528        $renderer->beginInactive($this->getTitle(), $this->getExtra());
 529        $renderer->renderFormInactive($this, $vars);
 530        $renderer->end();
 531    }
 532
 533    function preserve($vars)
 534    {
 535        if ($this->_useFormToken) {
 536            require_once 'Horde/Token.php';
 537            $token = Horde_Token::generateId($this->_name);
 538            $_SESSION['horde_form_secrets'][$token] = true;
 539            $this->_preserveVarByPost($this->_name . '_formToken', $token);
 540        }
 541
 542        $variables = $this->getVariables();
 543        foreach ($variables as $var) {
 544            $varname = $var->getVarName();
 545
 546            /* Save value of individual components. */
 547            switch ($var->getTypeName()) {
 548            case 'passwordconfirm':
 549            case 'emailconfirm':
 550                $this->preserveVarByPost($vars, $varname . '[original]');
 551                $this->preserveVarByPost($vars, $varname . '[confirm]');
 552                break;
 553
 554            case 'monthyear':
 555                $this->preserveVarByPost($vars, $varname . '[month]');
 556                $this->preserveVarByPost($vars, $varname . '[year]');
 557                break;
 558
 559            case 'monthdayyear':
 560                $this->preserveVarByPost($vars, $varname . '[month]');
 561                $this->preserveVarByPost($vars, $varname . '[day]');
 562                $this->preserveVarByPost($vars, $varname . '[year]');
 563                break;
 564            }
 565
 566            $this->preserveVarByPost($vars, $varname);
 567        }
 568        foreach ($this->_hiddenVariables as $var) {
 569            $this->preserveVarByPost($vars, $var->getVarName());
 570        }
 571    }
 572
 573    function unsetVars(&$vars)
 574    {
 575        foreach ($this->getVariables() as $var) {
 576            $vars->remove($var->getVarName());
 577        }
 578    }
 579
 580    /**
 581     * Validates the form, checking if it really has been submitted by calling
 582     * isSubmitted() and if true does any onSubmit() calls for variable types
 583     * in the form. The _submitted variable is then rechecked.
 584     *
 585     * @param Variables $vars       A Variables instance, optional since Horde
 586     *                              3.2.
 587     * @param boolean $canAutofill  Can the form be valid without being
 588     *                              submitted?
 589     *
 590     * @return boolean  True if the form is valid.
 591     */
 592    function validate($vars = null, $canAutoFill = false)
 593    {
 594        if (is_null($vars)) {
 595            $vars = $this->_vars;
 596        }
 597
 598        /* Get submitted status. */
 599        if ($this->isSubmitted() || $canAutoFill) {
 600            /* Form was submitted or can autofill; check for any variable
 601             * types' onSubmit(). */
 602            $this->onSubmit($vars);
 603
 604            /* Recheck submitted status. */
 605            if (!$this->isSubmitted() && !$canAutoFill) {
 606                return false;
 607            }
 608        } else {
 609            /* Form has not been submitted; return false. */
 610            return false;
 611        }
 612
 613        $message = '';
 614        $this->_autofilled = true;
 615
 616        if ($this->_useFormToken) {
 617            global $conf;
 618            require_once 'Horde/Token.php';
 619            if (isset($conf['token'])) {
 620                /* If there is a configured token system, set it up. */
 621                $tokenSource = &Horde_Token::singleton($conf['token']['driver'], Horde::getDriverConfig('token', $conf['token']['driver']));
 622            } else {
 623                /* Default to the file system if no config. */
 624                $tokenSource = &Horde_Token::singleton('file');
 625            }
 626            $passedToken = $vars->get($this->_name . '_formToken');
 627            if (!empty($passedToken) && !$tokenSource->verify($passedToken)) {
 628                $this->_errors['_formToken'] = _("This form has already been processed.");
 629            }
 630            if (empty($_SESSION['horde_form_secrets'][$passedToken])) {
 631                $this->_errors['_formSecret'] = _("Required secret is invalid - potentially malicious request.");
 632            }
 633        }
 634
 635        foreach ($this->getVariables() as $var) {
 636            $this->_autofilled = $var->_autofilled && $this->_autofilled;
 637            if (!$var->validate($vars, $message)) {
 638                $this->_errors[$var->getVarName()] = $message;
 639            }
 640        }
 641
 642        if ($this->_autofilled) {
 643            unset($this->_errors['_formToken']);
 644        }
 645
 646        foreach ($this->_hiddenVariables as $var) {
 647            if (!$var->validate($vars, $message)) {
 648                $this->_errors[$var->getVarName()] = $message;
 649            }
 650        }
 651
 652        return $this->isValid();
 653    }
 654
 655    function clearValidation()
 656    {
 657        $this->_errors = array();
 658    }
 659
 660    function getError($var)
 661    {
 662        if (is_a($var, 'Horde_Form_Variable')) {
 663            $name = $var->getVarName();
 664        } else {
 665            $name = $var;
 666        }
 667        return isset($this->_errors[$name]) ? $this->_errors[$name] : null;
 668    }
 669
 670    function setError($var, $message)
 671    {
 672        if (is_a($var, 'Horde_Form_Variable')) {
 673            $name = $var->getVarName();
 674        } else {
 675            $name = $var;
 676        }
 677        $this->_errors[$name] = $message;
 678    }
 679
 680    function clearError($var)
 681    {
 682        if (is_a($var, 'Horde_Form_Variable')) {
 683            $name = $var->getVarName();
 684        } else {
 685            $name = $var;
 686        }
 687        unset($this->_errors[$name]);
 688    }
 689
 690    function isValid()
 691    {
 692        return ($this->_autofilled || count($this->_errors) == 0);
 693    }
 694
 695    function execute()
 696    {
 697        Horde::logMessage('Warning: Horde_Form::execute() called, should be overridden', __FILE__, __LINE__, PEAR_LOG_DEBUG);
 698    }
 699
 700    /**
 701     * Fetch the field values of the submitted form.
 702     *
 703     * @param Variables $vars  A Variables instance, optional since Horde 3.2.
 704     * @param array $info      Array to be filled with the submitted field
 705     *                         values.
 706     */
 707    function getInfo($vars, &$info)
 708    {
 709        if (is_null($vars)) {
 710            $vars = $this->_vars;
 711        }
 712        $this->_getInfoFromVariables($this->getVariables(), $vars, $info);
 713        $this->_getInfoFromVariables($this->_hiddenVariables, $vars, $info);
 714    }
 715
 716    /**
 717     * Fetch the field values from a given array of variables.
 718     *
 719     * @access private
 720     *
 721     * @param array  $variables  An array of Horde_Form_Variable objects to
 722     *                           fetch from.
 723     * @param object $vars       The Variables object.
 724     * @param array  $info       The array to be filled with the submitted
 725     *                           field values.
 726     */
 727    function _getInfoFromVariables($variables, &$vars, &$info)
 728    {
 729        foreach ($variables as $var) {
 730            if ($var->isArrayVal()) {
 731                $var->getInfo($vars, $values);
 732                if (is_array($values)) {
 733                    $varName = str_replace('[]', '', $var->getVarName());
 734                    foreach ($values as $i => $val) {
 735                        $info[$i][$varName] = $val;
 736                    }
 737                }
 738            } else {
 739                require_once 'Horde/Array.php';
 740                if (Horde_Array::getArrayParts($var->getVarName(), $base, $keys)) {
 741                    if (!isset($info[$base])) {
 742                        $info[$base] = array();
 743                    }
 744                    $pointer = &$info[$base];
 745                    while (count($keys)) {
 746                        $key = array_shift($keys);
 747                        if (!isset($pointer[$key])) {
 748                            $pointer[$key] = array();
 749                        }
 750                        $pointer = &$pointer[$key];
 751                    }
 752                    $var->getInfo($vars, $pointer);
 753                } else {
 754                    $var->getInfo($vars, $info[$var->getVarName()]);
 755                }
 756            }
 757        }
 758    }
 759
 760    function hasHelp()
 761    {
 762        return $this->_help;
 763    }
 764
 765    /**
 766     * Determines if this form has been submitted or not. If the class
 767     * var _submitted is null then it will check for the presence of
 768     * the formname in the form variables.
 769     *
 770     * Other events can explicitly set the _submitted variable to
 771     * false to indicate a form submit but not for actual posting of
 772     * data (eg. onChange events to update the display of fields).
 773     *
 774     * @return boolean  True or false indicating if the form has been
 775     *                  submitted.
 776     */
 777    function isSubmitted()
 778    {
 779        if (is_null($this->_submitted)) {
 780            if ($this->_vars->get('formname') == $this->getName()) {
 781                $this->_submitted = true;
 782            } else {
 783                $this->_submitted = false;
 784            }
 785        }
 786
 787        return $this->_submitted;
 788    }
 789
 790    /**
 791     * Checks if there is anything to do on the submission of the form by
 792     * looping through each variable's onSubmit() function.
 793     *
 794     * @param Horde_Variables $vars
 795     */
 796    function onSubmit(&$vars)
 797    {
 798        /* Loop through all vars and check if there's anything to do on
 799         * submit. */
 800        $variables = $this->getVariables();
 801        foreach ($variables as $var) {
 802            $var->type->onSubmit($var, $vars);
 803            /* If changes to var being tracked don't register the form as
 804             * submitted if old value and new value differ. */
 805            if ($var->getOption('trackchange')) {
 806                $varname = $var->getVarName();
 807                if (!is_null($vars->get('formname')) &&
 808                    $vars->get($varname) != $vars->get('__old_' . $varname)) {
 809                    $this->_submitted = false;
 810                }
 811            }
 812        }
 813    }
 814
 815    /**
 816     * Explicitly sets the state of the form submit.
 817     *
 818     * An event can override the automatic determination of the submit state
 819     * in the isSubmitted() function.
 820     *
 821     * @param boolean $state  Whether to set the state of the form as being
 822     *                        submitted.
 823     */
 824    function setSubmitted($state = true)
 825    {
 826        $this->_submitted = $state;
 827    }
 828
 829}
 830
 831/**
 832 * Horde_Form_Type Class
 833 *
 834 * @author  Robert E. Coyle <robertecoyle@hotmail.com>
 835 * @package Horde_Form
 836 */
 837class Horde_Form_Type {
 838
 839    function Horde_Form_Type()
 840    {
 841    }
 842
 843    function getProperty($property)
 844    {
 845        $prop = '_' . $property;
 846        return isset($this->$prop) ? $this->$prop : null;
 847    }
 848
 849    function __get($property)
 850    {
 851        return $this->getProperty($property);
 852    }
 853
 854    function setProperty($property, $value)
 855    {
 856        $prop = '_' . $property;
 857        $this->$prop = $value;
 858    }
 859
 860    function __set($property, $value)
 861    {
 862        return $this->setProperty($property, $value);
 863    }
 864
 865    function init()
 866    {
 867    }
 868
 869    function onSubmit()
 870    {
 871    }
 872
 873    function isValid(&$var, &$vars, $value, &$message)
 874    {
 875        $message = '<strong>Error:</strong> Horde_Form_Type::isValid() called - should be overridden<br />';
 876        return false;
 877    }
 878
 879    function getTypeName()
 880    {
 881        return str_replace('horde_form_type_', '', String::lower(get_class($this)));
 882    }
 883
 884    function getValues()
 885    {
 886        return null;
 887    }
 888
 889    function getInfo(&$vars, &$var, &$info)
 890    {
 891        $info = $var->getValue($vars);
 892    }
 893
 894}
 895
 896class Horde_Form_Type_spacer extends Horde_Form_Type {
 897
 898    function isValid(&$var, &$vars, $value, &$message)
 899    {
 900        return true;
 901    }
 902
 903    /**
 904     * Return info about field type.
 905     */
 906    function about()
 907    {
 908        return array('name' => _("Spacer"));
 909    }
 910
 911}
 912
 913class Horde_Form_Type_header extends Horde_Form_Type {
 914
 915    function isValid(&$var, &$vars, $value, &$message)
 916    {
 917        return true;
 918    }
 919
 920    /**
 921     * Return info about field type.
 922     */
 923    function about()
 924    {
 925        return array('name' => _("Header"));
 926    }
 927
 928}
 929
 930class Horde_Form_Type_description extends Horde_Form_Type {
 931
 932    function isValid(&$var, &$vars, $value, &$message)
 933    {
 934        return true;
 935    }
 936
 937    /**
 938     * Return info about field type.
 939     */
 940    function about()
 941    {
 942        return array('name' => _("Description"));
 943    }
 944
 945}
 946
 947/**
 948 * Simply renders its raw value in both active and inactive rendering.
 949 */
 950class Horde_Form_Type_html extends Horde_Form_Type {
 951
 952    function isValid(&$var, &$vars, $value, &$message)
 953    {
 954        return true;
 955    }
 956
 957    /**
 958     * Return info about field type.
 959     */
 960    function about()
 961    {
 962        return array('name' => _("HTML"));
 963    }
 964
 965}
 966
 967class Horde_Form_Type_number extends Horde_Form_Type {
 968
 969    var $_fraction;
 970
 971    function init($fraction = null)
 972    {
 973        $this->_fraction = $fraction;
 974    }
 975
 976    function isValid(&$var, &$vars, $value, &$message)
 977    {
 978        if ($var->isRequired() && empty($value) && ((string)(double)$value !== $value)) {
 979            $message = _("This field is required.");
 980            return false;
 981        } elseif (empty($value)) {
 982            return true;
 983        }
 984
 985        /* If matched, then this is a correct numeric value. */
 986        if (preg_match($this->_getValidationPattern(), $value)) {
 987            return true;
 988        }
 989
 990        $message = _("This field must be a valid number.");
 991        return false;
 992    }
 993
 994    function _getValidationPattern()
 995    {
 996        static $pattern = '';
 997        if (!empty($pattern)) {
 998            return $pattern;
 999        }
1000
1001        /* Get current locale information. */
1002        $linfo = NLS::getLocaleInfo();
1003
1004        /* Build the pattern. */
1005        $pattern = '(-)?';
1006
1007        /* Only check thousands separators if locale has any. */
1008        if (!empty($linfo['mon_thousands_sep'])) {
1009            /* Regex to check for correct thousands separators (if any). */
1010            $pattern .= '((\d+)|((\d{0,3}?)([' . $linfo['mon_thousands_sep'] . ']\d{3})*?))';
1011        } else {
1012            /* No locale thousands separator, check for only digits. */
1013            $pattern .= '(\d+)';
1014        }
1015        /* If no decimal point specified default to dot. */
1016        if (empty($linfo['mon_decimal_point'])) {
1017            $linfo['mon_decimal_point'] = '.';
1018        }
1019        /* Regex to check for correct decimals (if any). */
1020        if (empty($this->_fraction)) {
1021            $fraction = '*';
1022        } else {
1023            $fraction = '{0,' . $this->_fraction . '}';
1024        }
1025        $pattern .= '([' . $linfo['mon_decimal_point'] . '](\d' . $fraction . '))?';
1026
1027        /* Put together the whole regex pattern. */
1028        $pattern = '/^' . $pattern . '$/';
1029
1030        return $pattern;
1031    }
1032
1033    function getInfo(&$vars, &$var, &$info)
1034    {
1035        $value = $vars->get($var->getVarName());
1036        $linfo = NLS::getLocaleInfo();
1037        $value = str_replace($linfo['mon_thousands_sep'], '', $value);
1038        $info = str_replace($linfo['mon_decimal_point'], '.', $value);
1039    }
1040
1041    /**
1042     * Return info about field type.
1043     */
1044    function about()
1045    {
1046        return array('name' => _("Number"));
1047    }
1048
1049}
1050
1051class Horde_Form_Type_int extends Horde_Form_Type {
1052
1053    function isValid(&$var, &$vars, $value, &$message)
1054    {
1055        if ($var->isRequired() && empty($value) && ((string)(int)$value !== $value)) {
1056            $message = _("This field is required.");
1057            return false;
1058        }
1059
1060        if (empty($value) || preg_match('/^[0-9]+$/', $value)) {
1061            return true;
1062        }
1063
1064        $message = _("This field may only contain integers.");
1065        return false;
1066    }
1067
1068    /**
1069     * Return info about field type.
1070     */
1071    function about()
1072    {
1073        return array('name' => _("Integer"));
1074    }
1075
1076}
1077
1078class Horde_Form_Type_octal extends Horde_Form_Type {
1079
1080    function isValid(&$var, &$vars, $value, &$message)
1081    {
1082        if ($var->isRequired() && empty($value) && ((string)(int)$value !== $value)) {
1083            $message = _("This field is required.");
1084            return false;
1085        }
1086
1087        if (empty($value) || preg_match('/^[0-7]+$/', $value)) {
1088            return true;
1089        }
1090
1091        $message = _("This field may only contain octal values.");
1092        return false;
1093    }
1094
1095    /**
1096     * Return info about field type.
1097     */
1098    function about()
1099    {
1100        return array('name' => _("Octal"));
1101    }
1102
1103}
1104
1105class Horde_Form_Type_intlist extends Horde_Form_Type {
1106
1107    function isValid(&$var, &$vars, $value, &$message)
1108    {
1109        if (empty($value) && $var->isRequired()) {
1110            $message = _("This field is required.");
1111            return false;
1112        }
1113
1114        if (empty($value) || preg_match('/^[0-9 ,]+$/', $value)) {
1115            return true;
1116        }
1117
1118        $message = _("This field must be a comma or space separated list of integers");
1119        return false;
1120    }
1121
1122    /**
1123     * Return info about field type.
1124     */
1125    function about()
1126    {
1127        return array('name' => _("Integer list"));
1128    }
1129
1130}
1131
1132class Horde_Form_Type_text extends Horde_Form_Type {
1133
1134    var $_regex;
1135    var $_size;
1136    var $_maxlength;
1137
1138    /**
1139     * The initialisation function for the text variable type.
1140     *
1141     * @access private
1142     *
1143     * @param string $regex       Any valid PHP PCRE pattern syntax that
1144     *                            needs to be matched for the field to be
1145     *                            considered valid. If left empty validity
1146     *                            will be checked only for required fields
1147     *                            whether they are empty or not.
1148     *                            If using this regex test it is advisable
1149     *                            to enter a description for this field to
1150     *                            warn the user what is expected, as the
1151     *                            generated error message is quite generic
1152     *                            and will not give any indication where
1153     *                            the regex failed.
1154     * @param integer $size       The size of the input field.
1155     * @param integer $maxlength  The max number of characters.
1156     */
1157    function init($regex = '', $size = 40, $maxlength = null)
1158    {
1159        $this->_regex     = $regex;
1160        $this->_size      = $size;
1161        $this->_maxlength = $maxlength;
1162    }
1163
1164    function isValid(&$var, &$vars, $value, &$message)
1165    {
1166        $valid = true;
1167
1168        if (!empty($this->_maxlength) && String::length($value) > $this->_maxlength) {
1169            $valid = false;
1170            $message = sprintf(_("Value is over the maximum length of %d."), $this->_maxlength);
1171        } elseif ($var->isRequired() && empty($this->_regex)) {
1172            $valid = strlen(trim($value)) > 0;
1173
1174            if (!$valid) {
1175                $message = _("This field is required.");
1176            }
1177        } elseif (!empty($this->_regex)) {
1178            $valid = preg_match($this->_regex, $value);
1179
1180            if (!$valid) {
1181                $message = _("You must enter a valid value.");
1182            }
1183        }
1184
1185        return $valid;
1186    }
1187
1188    function getSize()
1189    {
1190        return $this->_size;
1191    }
1192
1193    function getMaxLength()
1194    {
1195        return $this->_maxlength;
1196    }
1197
1198    /**
1199     * Return info about field type.
1200     */
1201    function about()
1202    {
1203        return array(
1204            'name' => _("Text"),
1205            'params' => array(
1206                'regex'     => array('label' => _("Regex"),
1207                                     'type'  => 'text'),
1208                'size'      => array('label' => _("Size"),
1209                                     'type'  => 'int'),
1210                'maxlength' => array('label' => _("Maximum length"),
1211                                     'type'  => 'int')));
1212    }
1213
1214}
1215
1216class Horde_Form_Type_stringlist extends Horde_Form_Type_text {
1217
1218    /**
1219     * Return info about field type.
1220     */
1221    function about()
1222    {
1223        return array(
1224            'name' => _("String list"),
1225            'params' => array(
1226                'regex'     => array('label' => _("Regex"),
1227                                     'type'  => 'text'),
1228                'size'      => array('label' => _("Size"),
1229                                     'type'  => 'int'),
1230                'maxlength' => array('label' => _("Maximum length"),
1231                                     'type'  => 'int')),
1232        );
1233    }
1234
1235}
1236
1237/**
1238 * @since Horde 3.3
1239 */
1240class Horde_Form_Type_stringarray extends Horde_Form_Type_stringlist {
1241
1242    function getInfo(&$vars, &$var, &$info)
1243    {
1244        $info = array_map('trim', explode(',', $vars->get($var->getVarName())));
1245    }
1246
1247    /**
1248     * Return info about field type.
1249     */
1250    function about()
1251    {
1252        return array(
1253            'name' => _("String list returning an array"),
1254            'params' => array(
1255                'regex'     => array('label' => _("Regex"),
1256                                     'type'  => 'text'),
1257                'size'      => array('label' => _("Size"),
1258                                     'type'  => 'int'),
1259                'maxlength' => array('label' => _("Maximum length"),
1260                                     'type'  => 'int')),
1261        );
1262    }
1263
1264}
1265
1266/**
1267 * @since Horde 3.2
1268 */
1269class Horde_Form_Type_phone extends Horde_Form_Type {
1270
1271    function isValid(&$var, &$vars, $value, &$message)
1272    {
1273        if (!strlen(trim($value))) {
1274            if ($var->isRequired()) {
1275                $message = _("This field is required.");
1276                return false;
1277            }
1278        } elseif (!preg_match('/^\+?[\d()\-\/. ]*$/', $value)) {
1279            $message = _("You must enter a valid phone number, digits only with an optional '+' for the international dialing prefix.");
1280            return false;
1281        }
1282
1283        return true;
1284    }
1285
1286    /**
1287     * Return info about field type.
1288     */
1289    function about()
1290    {
1291        return array('name' => _("Phone number"));
1292    }
1293
1294}
1295
1296class Horde_Form_Type_cellphone extends Horde_Form_Type_phone {
1297
1298    /**
1299     * Return info about field type.
1300     */
1301    function about()
1302    {
1303        return array('name' => _("Mobile phone number"));
1304    }
1305
1306}
1307
1308class Horde_Form_Type_ipaddress extends Horde_Form_Type_text {
1309
1310    function isValid(&$var, &$vars, $value, &$message)
1311    {
1312        $valid = true;
1313
1314        if (strlen(trim($value)) > 0) {
1315            $ip = explode('.', $value);
1316            $valid = (count($ip) == 4);
1317            if ($valid) {
1318                foreach ($ip as $part) {
1319                    if (!is_numeric($part) ||
1320                        $part > 255 ||
1321                        $part < 0) {
1322                        $valid = false;
1323                        break;
1324                    }
1325                }
1326            }
1327
1328            if (!$valid) {
1329                $message = _("Please enter a valid IP address.");
1330            }
1331        } elseif ($var->isRequired()) {
1332            $valid = false;
1333            $message = _("This field is required.");
1334        }
1335
1336        return $valid;
1337    }
1338
1339    /**
1340     * Return info about field type.
1341     */
1342    function about()
1343    {
1344        return array('name' => _("IP address"));
1345    }
1346
1347}
1348
1349class Horde_Form_Type_longtext extends Horde_Form_Type_text {
1350
1351    var $_rows;
1352    var $_cols;
1353    var $_helper = array();
1354
1355    function init($rows = 8, $cols = 80, $helper = array())
1356    {
1357        if (!is_array($helper)) {
1358            $helper = array($helper);
1359        }
1360
1361        $this->_rows = $rows;
1362        $this->_cols = $cols;
1363        $this->_helper = $helper;
1364    }
1365
1366    function getRows()
1367    {
1368        return $this->_rows;
1369    }
1370
1371    function getCols()
1372    {
1373        return $this->_cols;
1374    }
1375
1376    function hasHelper($option = '')
1377    {
1378        if (empty($option)) {
1379            /* No option specified, check if any helpers have been
1380             * activated. */
1381            return !empty($this->_helper);
1382        } elseif (empty($this->_helper)) {
1383            /* No helpers activated at all, return false. */
1384            return false;
1385        } else {
1386            /* Check if given helper has been activated. */
1387            return in_array($option, $this->_helper);
1388        }
1389    }
1390
1391    /**
1392     * Return info about field type.
1393     */
1394    function about()
1395    {
1396        return array(
1397            'name' => _("Long text"),
1398            'params' => array(
1399                'rows'   => array('label' => _("Number of rows"),
1400                                  'type'  => 'int'),
1401                'cols'   => array('label' => _("Number of columns"),
1402                                  'type'  => 'int'),
1403                'helper' => array('label' => _("Helpers"),
1404                                  'type'  => 'stringarray')));
1405    }
1406
1407}
1408
1409class Horde_Form_Type_countedtext extends Horde_Form_Type_longtext {
1410
1411    var $_chars;
1412
1413    function init($rows = null, $cols = null, $chars = 1000)
1414    {
1415        parent::init($rows, $cols);
1416        $this->_chars = $chars;
1417    }
1418
1419    function isValid(&$var, &$vars, $value, &$message)
1420    {
1421        $valid = true;
1422
1423        $length = String::length(trim($value));
1424
1425        if ($var->isRequired() && $length <= 0) {
1426            $valid = false;
1427            $message = _("This field is required.");
1428        } elseif ($length > $this->_chars) {
1429            $valid = false;
1430            $message = sprintf(ngettext("There are too many characters in this field. You have entered %d character; ", "There are too many characters in this field. You have entered %d characters; ", $length), $length)
1431                . sprintf(_("you must enter less than %d."), $this->_chars);
1432        }
1433
1434        return $valid;
1435    }
1436
1437    function getChars()
1438    {
1439        return $this->_chars;
1440    }
1441
1442    /**
1443     * Return info about field type.
1444     */
1445    function about()
1446    {
1447        return array(
1448            'name' => _("Counted text"),
1449            'params' => array(
1450                'rows'  => array('label' => _("Number of rows"),
1451                                 'type'  => 'int'),
1452                'cols'  => array('label' => _("Number of columns"),
1453                                 'type'  => 'int'),
1454                'chars' => array('label' => _("Number of characters"),
1455                                 'type'  => 'int')));
1456    }
1457
1458}
1459
1460class Horde_Form_Type_address extends Horde_Form_Type_longtext {
1461
1462    function parse($address)
1463    {
1464        $info = array();
1465        $aus_state_regex = '(?:ACT|NSW|NT|QLD|SA|TAS|VIC|WA)';
1466
1467        if (preg_match('/(?s)(.*?)(?-s)\r?\n(?:(.*?)\s+)?((?:A[BL]|B[ABDHLNRST]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[CHNX]?|F[KY]|G[LUY]?|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EKL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTWY]?|T[ADFNQRSW]|UB|W[ACDFNRSV]?|YO|ZE)\d(?:\d|[A-Z])? \d[A-Z]{2})/', $address, $addressParts)) {
1468            /* UK postcode detected. */
1469            $info = array('country' => 'uk', 'zip' => $addressParts[3]);
1470            if (!empty($addressParts[1])) {
1471                $info['street'] = $addressParts[1];
1472            }
1473            if (!empty($addressParts[2])) {
1474                $info['city'] = $addressParts[2];
1475            }
1476        } elseif (preg_match('/\b' . $aus_state_regex . '\b/', $address)) {
1477            /* Australian state detected. */
1478            /* Split out the address, line-by-line. */
1479            $addressLines = preg_split('/\r?\n/', $address);
1480            $info = array('country' => 'au');
1481            for ($i = 0; $i < count($addressLines); $i++) {
1482                /* See if it's the street number & name. */
1483                if (preg_match('/(\d+\s*\/\s*)?(\d+|\d+[a-zA-Z])\s+([a-zA-Z ]*)/', $addressLines[$i], $lineParts)) {
1484                    $info['street'] = $addressLines[$i];
1485                    $info['streetNumber'] = $lineParts[2];
1486                    $info['streetName'] = $lineParts[3];
1487                }
1488                /* Look for "Suburb, State". */
1489                if (preg_match('/([a-zA-Z ]*),?\s+(' . $aus_state_regex . ')/', $addressLines[$i], $lineParts)) {
1490                    $info['city'] = $lineParts[1];
1491                    $info['state'] = $lineParts[2];
1492                }
1493                /* Look for "State <4 digit postcode>". */
1494                if (preg_match('/(' . $aus_state_regex . ')\s+(\d{4})/', $addressLines[$i], $lineParts)) {
1495                    $info['state'] = $lineParts[1];
1496                    $info['zip'] = $lineParts[2];
1497                }
1498            }
1499        } elseif (preg_match('/(?s)(.*?)(?-s)\r?\n(.*)\s*,\s*(\w+)\.?\s+(\d+|[a-zA-Z]\d[a-zA-Z]\s?\d[a-zA-Z]\d)/', $address, $addressParts)) {
1500            /* American/Canadian address style. */
1501            $info = array('country' => 'us');
1502            if (!empty($addressParts[4]) &&
1503                preg_match('|[a-zA-Z]\d[a-zA-Z]\s?\d[a-zA-Z]\d|', $addressParts[4])) {
1504                $info['country'] = 'ca';
1505            }
1506            if (!empty($addressParts[1])) {
1507                $info['street'] = $addressParts[1];
1508            }
1509            if (!empty($addressParts[2])) {
1510                $info['city'] = $addressParts[2];
1511            }
1512            if (!empty($addressParts[3])) {
1513                $info['state'] = $addressParts[3];
1514            }
1515            if (!empty($addressParts[4])) {
1516                $info['zip'] = $addressParts[4];
1517            }
1518        } elseif (preg_match('/(?:(?s)(.*?)(?-s)(?:\r?\n|,\s*))?(?:([A-Z]{1,3})-)?(\d{4,5})\s+(.*)(?:\r?\n(.*))?/i', $address, $addressParts)) {
1519            /* European address style. */
1520            $info = array();
1521            if (!empty($addressParts[1])) {
1522                $info['street'] = $addressParts[1];
1523            }
1524            if (!empty($addressParts[2])) {
1525                include 'Horde/NLS/carsigns.php';
1526                $country = array_search(String::upper($addressParts[2]), $carsigns);
1527                if ($country) {
1528                    $info['country'] = $country;
1529                }
1530            }
1531            if (!empty($addressParts[5])) {
1532                include 'Horde/NLS/countries.php';
1533                $country = array_search($addressParts[5], $countries);
1534                if ($country) {
1535                    $info['country'] = String::lower($country);
1536                } elseif (!isset($info['street'])) {
1537                    $info['street'] = trim($addressParts[5]);
1538                } else {
1539                    $info['street'] .= "\n" . $addressParts[5];
1540                }
1541            }
1542            if (!empty($addressParts[3])) {
1543                $info['zip'] = $addressParts[3];
1544            }
1545            if (!empty($addressParts[4])) {
1546                $info['city'] = trim($addressParts[4]);
1547            }
1548        }
1549
1550        return $info;
1551    }
1552
1553    /**
1554     * Return info about field type.
1555     */
1556    function about()
1557    {
1558        return array(
1559            'name' => _("Address"),
1560            'params' => array(
1561                'rows' => array('label' => _("Number of rows"),
1562                                'type'  => 'int'),
1563                'cols' => array('label' => _("Number of columns"),
1564                                'type'  => 'int')));
1565    }
1566
1567}
1568
1569class Horde_Form_Type_addresslink extends Horde_Form_Type_address {
1570
1571    function isValid(&$var, &$vars, $value, &$message)
1572    {
1573        return true;
1574    }
1575
1576    /**
1577     * Return info about field type.
1578     */
1579    function about()
1580    {
1581        return array('name' => _("Address Link"));
1582    }
1583
1584}
1585
1586/**
1587 * @since Horde 3.3
1588 */
1589class Horde_Form_Type_pgp extends Horde_Form_Type_longtext {
1590
1591    /**
1592     * Path to the GnuPG binary.
1593     *
1594     * @var string
1595     */
1596    var $_gpg;
1597
1598    /**
1599     * A temporary directory.
1600     *
1601     * @var string
1602     */
1603    var $_temp;
1604
1605    function init($gpg, $temp_dir = null, $rows = null, $cols = null)
1606    {
1607        $this->_gpg = $gpg;
1608        $this->_temp = $temp_dir;
1609        parent::init($rows, $cols);
1610    }
1611
1612    /**
1613     * Returns a parameter hash for the Horde_Crypt_pgp constructor.
1614     *
1615     * @return array  A parameter hash.
1616     */
1617    function getPGPParams()
1618    {
1619        return array('program' => $this->_gpg, 'temp' => $this->_temp);
1620    }
1621
1622    /**
1623     * Return info about field type.
1624     */
1625    function about()
1626    {
1627        return array(
1628            'name' => _("PGP Key"),
1629            'params' => array(
1630                'gpg'      => array('label' => _("Path to the GnuPG binary"),
1631                                    'type'  => 'string'),
1632                'temp_dir' => array('label' => _("A temporary directory"),
1633                                    'type'  => 'string'),
1634                'rows'     => array('label' => _("Number of rows"),
1635                                    'type'  => 'int'),
1636                'cols'     => array('label' => _("Number of columns"),
1637                                    'type'  => 'int')));
1638    }
1639
1640}
1641
1642/**
1643 * @since Horde 3.3
1644 */
1645class Horde_Form_Type_smime extends Horde_Form_Type_longtext {
1646
1647    /**
1648     * A temporary directory.
1649     *
1650     * @var string
1651     */
1652    var $_temp;
1653
1654    function init($temp_dir = null, $rows = null, $cols = null)
1655    {
1656        $this->_temp = $temp_dir;
1657        parent::init($rows, $cols);
1658    }
1659
1660    /**
1661     * Returns a parameter hash for the Horde_Crypt_smime constructor.
1662     *
1663     * @return array  A parameter hash.
1664     */
1665    function getSMIMEParams()
1666    {
1667        return array('temp' => $this->_temp);
1668    }
1669
1670    /**
1671     * Return info about field type.
1672     */
1673    function about()
1674    {
1675        return array(
1676            'name' => _("S/MIME Key"),
1677            'params' => array(
1678                'temp_dir' => array('label' => _("A temporary directory"),
1679                                    'type'  => 'string'),
1680                'rows'     => array('label' => _("Number of rows"),
1681  

Large files files are truncated, but you can click here to view the full file