+++ /dev/null
-<?php
-/**
- * @package Horde_Form
- */
-
-/** String */
-include_once 'Horde/String.php';
-
-/**
- * Horde_Form Master Class.
- *
- * The Horde_Form:: package provides form rendering, validation, and
- * other functionality for the Horde Application Framework.
- *
- * $Horde: incubator/Horde_Form/Horde/Form.php,v 1.19 2008/08/26 15:32:55 selsky Exp $
- *
- * Copyright 2001-2007 Robert E. Coyle <robertecoyle@hotmail.com>
- * Copyright 2001-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @author Robert E. Coyle <robertecoyle@hotmail.com>
- * @author Chuck Hagenbuch <chuck@horde.org>
- * @since Horde 3.0
- * @package Horde_Form
- */
-class Horde_Form {
-
- protected $_name = '';
- protected $_title = '';
- protected $_vars;
- protected $_errors = array();
- protected $_submitted = null;
- protected $_sections = array();
- protected $_open_section = null;
- protected $_currentSection = array();
- protected $_variables = array();
- protected $_hiddenVariables = array();
- protected $_useFormToken = true;
- protected $_autofilled = false;
- protected $_help = false;
-
- public function __construct($vars, $title = '', $name = null)
- {
- if (is_null($name)) {
- $name = String::lower(get_class($this));
- }
-
- $this->_vars = $vars;
- $this->_title = $title;
- $this->_name = $name;
- }
-
- public function setVars($vars)
- {
- $this->_vars = $vars;
- }
-
- public function getVars()
- {
- return $this->_vars;
- }
-
- public function getTitle()
- {
- return $this->_title;
- }
-
- public function setTitle($title)
- {
- $this->_title = $title;
- }
-
- public function getName()
- {
- return $this->_name;
- }
-
- /**
- * Sets or gets whether the form should be verified by tokens.
- * Tokens are used to verify that a form is only submitted once.
- *
- * @param boolean $token If specified, sets whether to use form tokens.
- *
- * @return boolean Whether form tokens are being used.
- */
- public function useToken($token = null)
- {
- if (!is_null($token)) {
- $this->_useFormToken = $token;
- }
- return $this->_useFormToken;
- }
-
- /**
- * Get the renderer for this form, either a custom renderer or the
- * standard one.
- *
- * To use a custom form renderer, your form class needs to
- * override this function:
- * <code>
- * function getRenderer()
- * {
- * return new CustomFormRenderer();
- * }
- * </code>
- *
- * ... where CustomFormRenderer is the classname of the custom
- * renderer class, which should extend Horde_Form_Renderer.
- *
- * @param array $params A hash of renderer-specific parameters.
- *
- * @return object Horde_Form_Renderer The form renderer.
- */
- function getRenderer($params = array())
- {
- return new Horde_Form_Renderer_Xhtml($params);
- }
-
- function getType($type, $params = array())
- {
- $type_class = 'Horde_Form_Type_' . $type;
- if (!class_exists($type_class)) {
- Horde::fatal(PEAR::raiseError(sprintf('Nonexistant class "%s" for field type "%s"', $type_class, $type)), __FILE__, __LINE__);
- }
- $type_ob = new $type_class();
- call_user_func_array(array(&$type_ob, 'init'), $params);
- return $type_ob;
- }
-
- public function setSection($section = '', $desc = '', $image = '', $expanded = true)
- {
- $this->_currentSection = $section;
- if (!count($this->_sections) && !$this->getOpenSection()) {
- $this->setOpenSection($section);
- }
- $this->_sections[$section]['desc'] = $desc;
- $this->_sections[$section]['expanded'] = $expanded;
- $this->_sections[$section]['image'] = $image;
- }
-
- public function getSections()
- {
- return $this->_sections;
- }
-
- public function getSectionDesc($section)
- {
- return $this->_sections[$section]['desc'];
- }
-
- public function getSectionImage($section)
- {
- return $this->_sections[$section]['image'];
- }
-
- public function setOpenSection($section)
- {
- $this->_vars->set('__formOpenSection', $section);
- }
-
- public function getOpenSection()
- {
- return $this->_vars->get('__formOpenSection');
- }
-
- public function getSectionExpandedState($section, $boolean = false)
- {
- if ($boolean) {
- /* Only the boolean value is required. */
- return $this->_sections[$section]['expanded'];
- }
-
- /* Need to return the values for use in styles. */
- if ($this->_sections[$section]['expanded']) {
- return 'block';
- } else {
- return 'none';
- }
- }
-
- /**
- * TODO
- */
- public function addVariable($humanName, $varName, $type, $required,
- $readonly = false, $description = null,
- $params = array())
- {
- return $this->insertVariableBefore(null, $humanName, $varName, $type,
- $required, $readonly, $description,
- $params);
- }
-
- /**
- * TODO
- */
- public function insertVariableBefore($before, $humanName, $varName, $type,
- $required, $readonly = false,
- $description = null, $params = array())
- {
- $type = $this->getType($type, $params);
- $var = new Horde_Form_Variable($humanName, $varName, $type,
- $required, $readonly, $description);
-
- /* Set the form object reference in the var. */
- $var->setFormOb($this);
-
- if ($var->getType() instanceof Horde_Form_Type_enum &&
- count($var->getValues()) == 1) {
- $vals = array_keys($var->getValues());
- $this->_vars->add($var->varName, $vals[0]);
- $var->_autofilled = true;
- }
- if (empty($this->_currentSection)) {
- $this->_currentSection = '__base';
- }
-
- if (is_null($before)) {
- $this->_variables[$this->_currentSection][] = &$var;
- } else {
- $num = 0;
- while (isset($this->_variables[$this->_currentSection][$num]) &&
- $this->_variables[$this->_currentSection][$num]->getVarName() != $before) {
- $num++;
- }
- if (!isset($this->_variables[$this->_currentSection][$num])) {
- $this->_variables[$this->_currentSection][] = &$var;
- } else {
- $this->_variables[$this->_currentSection] = array_merge(
- array_slice($this->_variables[$this->_currentSection], 0, $num),
- array(&$var),
- array_slice($this->_variables[$this->_currentSection], $num));
- }
- }
-
- return $var;
- }
-
- /**
- * Removes a variable from the form.
- *
- * As only variables can be passed by reference, you need to call this
- * method this way if want to pass a variable name:
- * <code>
- * $form->removeVariable($var = 'varname');
- * </code>
- *
- * @param Horde_Form_Variable|string $var Either the variable's name or
- * the variable to remove from the
- * form.
- *
- * @return boolean True if the variable was found (and deleted).
- */
- public function removeVariable(&$var)
- {
- foreach (array_keys($this->_variables) as $section) {
- foreach (array_keys($this->_variables[$section]) as $i) {
- if ((is_a($var, 'Horde_Form_Variable') && $this->_variables[$section][$i] === $var) ||
- ($this->_variables[$section][$i]->getVarName() == $var)) {
- // Slice out the variable to be removed.
- $this->_variables[$this->_currentSection] = array_merge(
- array_slice($this->_variables[$this->_currentSection], 0, $i),
- array_slice($this->_variables[$this->_currentSection], $i + 1));
-
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * TODO
- */
- public function addHidden($varName, $type, $required, $params = array())
- {
- $type = $this->getType($type, $params);
- $var = new Horde_Form_Variable('', $varName, $type, $required);
- $var->hide();
- $this->_hiddenVariables[] = &$var;
- return $var;
- }
-
- public function getVariables($flat = true, $withHidden = false)
- {
- if ($flat) {
- $vars = array();
- foreach ($this->_variables as $section) {
- foreach ($section as $var) {
- $vars[] = $var;
- }
- }
- if ($withHidden) {
- foreach ($this->_hiddenVariables as $var) {
- $vars[] = $var;
- }
- }
- return $vars;
- } else {
- return $this->_variables;
- }
- }
-
- public function getHiddenVariables()
- {
- return $this->_hiddenVariables;
- }
-
- /**
- * Preserve the variables/values from another Horde_Form object.
- */
- public function preserve(Horde_Form $form)
- {
- /* OLD IMPLEMENTATION
- if ($this->_useFormToken) {
- $this->_preserveVarByPost($this->_name . '_formToken', Horde_Token::generateId($this->_name));
- }
-
- $variables = $this->getVariables();
- foreach ($variables as $var) {
- $varname = $var->getVarName();
-
- switch (get_class($var->getType()) {
- case 'passwordconfirm':
- case 'emailconfirm':
- $this->preserveVarByPost($this->_vars, $varname . '[original]');
- $this->preserveVarByPost($this->_vars, $varname . '[confirm]');
- break;
-
- case 'monthyear':
- $this->preserveVarByPost($this->_vars, $varname . '[month]');
- $this->preserveVarByPost($this->_vars, $varname . '[year]');
- break;
-
- case 'monthdayyear':
- $this->preserveVarByPost($this->_vars, $varname . '[month]');
- $this->preserveVarByPost($this->_vars, $varname . '[day]');
- $this->preserveVarByPost($this->_vars, $varname . '[year]');
- break;
- }
-
- $this->preserveVarByPost($this->_vars, $varname);
- }
- foreach ($this->_hiddenVariables as $var) {
- $this->preserveVarByPost($this->_vars, $var->getVarName());
- }
- */
- }
-
- /**
- * Does the action of validating the form, checking if it really has been
- * submitted by calling isSubmitted() and if true does any onSubmit()
- * calls for var types in the form. The _submitted var is then rechecked.
- *
- * @param boolean $canAutofill Can the form be valid without
- * being submitted?
- *
- * @return boolean True if the form is valid.
- */
- public function validate($canAutoFill = false)
- {
- /* Get submitted status. */
- if ($this->isSubmitted() || $canAutoFill) {
- /* Form was submitted or can autofill; check for any variable
- * types' onSubmit(). */
- $this->onSubmit($this->_vars);
-
- /* Recheck submitted status. */
- if (!$this->isSubmitted() && !$canAutoFill) {
- return false;
- }
- } else {
- /* Form has not been submitted; return false. */
- return false;
- }
-
- $message = '';
- $this->_autofilled = true;
-
- if ($this->_useFormToken) {
- global $conf;
- if (isset($conf['token'])) {
- /* If there is a configured token system, set it up. */
- $tokenSource = Horde_Token::factory($conf['token']['driver'], Horde::getDriverConfig('token', $conf['token']['driver']));
- } else {
- /* Default to the file system if no config. */
- $tokenSource = Horde_Token::factory('file');
- }
- if (!$tokenSource->verify($this->_vars->get($this->_name . '_formToken'))) {
- $this->_errors['_formToken'] = _("This form has already been processed.");
- }
- }
-
- foreach ($this->getVariables() as $var) {
- $this->_autofilled = $var->_autofilled && $this->_autofilled;
- if (!$var->validate($this->_vars, $message)) {
- $this->_errors[$var->getVarName()] = $message;
- }
- }
-
- if ($this->_autofilled) {
- unset($this->_errors['_formToken']);
- }
-
- foreach ($this->_hiddenVariables as $var) {
- if (!$var->validate($this->_vars, $message)) {
- $this->_errors[$var->getVarName()] = $message;
- }
- }
-
- return $this->isValid();
- }
-
- public function clearValidation()
- {
- $this->_errors = array();
- }
-
- public function getError($var)
- {
- if (is_a($var, 'Horde_Form_Variable')) {
- $name = $var->getVarName();
- } else {
- $name = $var;
- }
- return isset($this->_errors[$name]) ? $this->_errors[$name] : null;
- }
-
- public function setError($var, $message)
- {
- if (is_a($var, 'Horde_Form_Variable')) {
- $name = $var->getVarName();
- } else {
- $name = $var;
- }
- $this->_errors[$name] = $message;
- }
-
- public function clearError($var)
- {
- if (is_a($var, 'Horde_Form_Variable')) {
- $name = $var->getVarName();
- } else {
- $name = $var;
- }
- unset($this->_errors[$name]);
- }
-
- public function isValid()
- {
- return ($this->_autofilled || !count($this->_errors));
- }
-
- public function execute()
- {
- throw new Horde_Form_Exception('Subclass must overide execute()');
- }
-
- /**
- * Fetch the field values of the submitted form.
- *
- * @param array $info Array to be filled with the submitted field
- * values.
- */
- public function getInfo(&$info)
- {
- $this->_getInfoFromVariables($this->getVariables(), $info);
- $this->_getInfoFromVariables($this->_hiddenVariables, $info);
- }
-
- /**
- * Fetch the field values from a given array of variables.
- *
- * @access private
- *
- * @param array $variables An array of Horde_Form_Variable objects to
- * fetch from.
- * @param array $info The array to be filled with the submitted
- * field values.
- */
- protected function _getInfoFromVariables($variables, &$info)
- {
- foreach ($variables as $var) {
- if ($var->isArrayVal()) {
- $var->getInfo($this->_vars, $values);
- if (is_array($values)) {
- $varName = str_replace('[]', '', $var->getVarName());
- foreach ($values as $i => $val) {
- $info[$i][$varName] = $val;
- }
- }
- } else {
- if (Horde_Array::getArrayParts($var->getVarName(), $base, $keys)) {
- if (!isset($info[$base])) {
- $info[$base] = array();
- }
- $pointer = &$info[$base];
- while (count($keys)) {
- $key = array_shift($keys);
- if (!isset($pointer[$key])) {
- $pointer[$key] = array();
- }
- $pointer = &$pointer[$key];
- }
- $var->getInfo($this->_vars, $pointer);
- } else {
- $var->getInfo($this->_vars, $info[$var->getVarName()]);
- }
- }
- }
- }
-
- public function hasHelp()
- {
- return $this->_help;
- }
-
- /**
- * Determines if this form has been submitted or not. If the class
- * var _submitted is null then it will check for the presence of
- * the formname in the form variables.
- *
- * Other events can explicitly set the _submitted variable to
- * false to indicate a form submit but not for actual posting of
- * data (eg. onChange events to update the display of fields).
- *
- * @return boolean True or false indicating if the form has been
- * submitted.
- */
- public function isSubmitted()
- {
- if (is_null($this->_submitted)) {
- if ($this->_vars->get('formname') == $this->getName()) {
- $this->_submitted = true;
- } else {
- $this->_submitted = false;
- }
- }
-
- return $this->_submitted;
- }
-
- /**
- * Checks if there is anything to do on the submission of the form by
- * looping through each variable's onSubmit() function.
- */
- public function onSubmit()
- {
- /* Loop through all vars and check if there's anything to do on
- * submit. */
- $variables = $this->getVariables();
- foreach ($variables as $var) {
- $var->type->onSubmit($var, $this->_vars);
- /* If changes to var being tracked don't register the form as
- * submitted if old value and new value differ. */
- if ($var->getOption('trackchange')) {
- $varname = $var->getVarName();
- if (!is_null($this->_vars->get('formname')) &&
- $this->_vars->get($varname) != $this->_vars->get('__old_' . $varname)) {
- $this->_submitted = false;
- }
- }
- }
- }
-
- /**
- * Explicitly sets the state of the form submit.
- *
- * An event can override the automatic determination of the submit state
- * in the isSubmitted() function.
- *
- * @param boolean $state Whether to set the state of the form as being
- * submitted.
- */
- public function setSubmitted($state = true)
- {
- $this->_submitted = $state;
- }
-
-}
-
-/**
- * Horde_Form_Type Class
- *
- * @author Robert E. Coyle <robertecoyle@hotmail.com>
- * @package Horde_Form
- */
-class Horde_Form_Type {
-
- protected function __get($property)
- {
- $prop = '_' . $property;
- return isset($this->$prop) ? $this->$prop : null;
- }
-
- protected function __set($property, $value)
- {
- $prop = '_' . $property;
- $this->$prop = $value;
- }
-
- protected function __isset($property)
- {
- $prop = '_' . $property;
- return isset($this->$prop);
- }
-
- protected function __unset($property)
- {
- $prop = '_' . $property;
- unset($this->$prop);
- }
-
- public function init()
- {
- }
-
- public function onSubmit()
- {
- }
-
- public function isValid($var, $vars, $value, &$message)
- {
- $message = '<strong>Error:</strong> Horde_Form_Type::isValid() called - should be overridden<br />';
- return false;
- }
-
- function getInfo($vars, $var, &$info)
- {
- $info = $var->getValue($vars);
- }
-
-}
-
-class Horde_Form_Type_number extends Horde_Form_Type {
-
- var $_fraction;
-
- function init($fraction = null)
- {
- $this->_fraction = $fraction;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- if ($var->isRequired() && empty($value) && ((string)(double)$value !== $value)) {
- $message = _("This field is required.");
- return false;
- } elseif (empty($value)) {
- return true;
- }
-
- /* If matched, then this is a correct numeric value. */
- if (preg_match($this->_getValidationPattern(), $value)) {
- return true;
- }
-
- $message = _("This field must be a valid number.");
- return false;
- }
-
- function _getValidationPattern()
- {
- static $pattern = '';
- if (!empty($pattern)) {
- return $pattern;
- }
-
- /* Get current locale information. */
- $linfo = NLS::getLocaleInfo();
-
- /* Build the pattern. */
- $pattern = '(-)?';
-
- /* Only check thousands separators if locale has any. */
- if (!empty($linfo['mon_thousands_sep'])) {
- /* Regex to check for correct thousands separators (if any). */
- $pattern .= '((\d+)|((\d{0,3}?)([' . $linfo['mon_thousands_sep'] . ']\d{3})*?))';
- } else {
- /* No locale thousands separator, check for only digits. */
- $pattern .= '(\d+)';
- }
- /* If no decimal point specified default to dot. */
- if (empty($linfo['mon_decimal_point'])) {
- $linfo['mon_decimal_point'] = '.';
- }
- /* Regex to check for correct decimals (if any). */
- if (empty($this->_fraction)) {
- $fraction = '*';
- } else {
- $fraction = '{0,' . $this->_fraction . '}';
- }
- $pattern .= '([' . $linfo['mon_decimal_point'] . '](\d' . $fraction . '))?';
-
- /* Put together the whole regex pattern. */
- $pattern = '/^' . $pattern . '$/';
-
- return $pattern;
- }
-
- function getInfo($vars, $var, &$info)
- {
- $value = $vars->get($var->getVarName());
- $linfo = NLS::getLocaleInfo();
- $value = str_replace($linfo['mon_thousands_sep'], '', $value);
- $info = str_replace($linfo['mon_decimal_point'], '.', $value);
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Number"));
- }
-
-}
-
-class Horde_Form_Type_int extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- if ($var->isRequired() && empty($value) && ((string)(int)$value !== $value)) {
- $message = _("This field is required.");
- return false;
- }
-
- if (empty($value) || preg_match('/^[0-9]+$/', $value)) {
- return true;
- }
-
- $message = _("This field may only contain integers.");
- return false;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Integer"));
- }
-
-}
-
-class Horde_Form_Type_octal extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- if ($var->isRequired() && empty($value) && ((string)(int)$value !== $value)) {
- $message = _("This field is required.");
- return false;
- }
-
- if (empty($value) || preg_match('/^[0-7]+$/', $value)) {
- return true;
- }
-
- $message = _("This field may only contain octal values.");
- return false;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Octal"));
- }
-
-}
-
-class Horde_Form_Type_intlist extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- if (empty($value) && $var->isRequired()) {
- $message = _("This field is required.");
- return false;
- }
-
- if (empty($value) || preg_match('/^[0-9 ,]+$/', $value)) {
- return true;
- }
-
- $message = _("This field must be a comma or space separated list of integers");
- return false;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Integer list"));
- }
-
-}
-
-class Horde_Form_Type_text extends Horde_Form_Type {
-
- var $_regex;
- var $_size;
- var $_maxlength;
-
- /**
- * The initialisation function for the text variable type.
- *
- * @access private
- *
- * @param string $regex Any valid PHP PCRE pattern syntax that
- * needs to be matched for the field to be
- * considered valid. If left empty validity
- * will be checked only for required fields
- * whether they are empty or not.
- * If using this regex test it is advisable
- * to enter a description for this field to
- * warn the user what is expected, as the
- * generated error message is quite generic
- * and will not give any indication where
- * the regex failed.
- * @param integer $size The size of the input field.
- * @param integer $maxlength The max number of characters.
- */
- function init($regex = '', $size = 40, $maxlength = null)
- {
- $this->_regex = $regex;
- $this->_size = $size;
- $this->_maxlength = $maxlength;
- }
-
- public function isValid($var, $vars, $value, &$message)
- {
- $valid = true;
-
- if (!empty($this->_maxlength) && String::length($value) > $this->_maxlength) {
- $valid = false;
- $message = sprintf(_("Value is over the maximum length of %s."), $this->_maxlength);
- } elseif ($var->isRequired() && empty($this->_regex)) {
- if (!($valid = strlen(trim($value)) > 0)) {
- $message = _("This field is required.");
- }
- } elseif (strlen($this->_regex)) {
- if (!($valid = preg_match($this->_regex, $value))) {
- $message = _("You must enter a valid value.");
- }
- }
-
- return $valid;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Text"),
- 'params' => array(
- 'regex' => array('label' => _("Regex"),
- 'type' => 'text'),
- 'size' => array('label' => _("Size"),
- 'type' => 'int'),
- 'maxlength' => array('label' => _("Maximum length"),
- 'type' => 'int')));
- }
-
-}
-
-class Horde_Form_Type_stringlist extends Horde_Form_Type_text {
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("String list"),
- 'params' => array(
- 'regex' => array('label' => _("Regex"),
- 'type' => 'text'),
- 'size' => array('label' => _("Size"),
- 'type' => 'int'),
- 'maxlength' => array('label' => _("Maximum length"),
- 'type' => 'int')),
- );
- }
-
-}
-
-class Horde_Form_Type_phone extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- $valid = true;
-
- if ($var->isRequired()) {
- $valid = strlen(trim($value)) > 0;
- if (!$valid) {
- $message = _("This field is required.");
- }
- } else {
- $valid = preg_match('/^\+?[\d()\-\/ ]*$/', $value);
- if (!$valid) {
- $message = _("You must enter a valid phone number, digits only with an optional '+' for the international dialing prefix.");
- }
- }
-
- return $valid;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Phone number"));
- }
-
-}
-
-class Horde_Form_Type_cellphone extends Horde_Form_Type_phone {
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Mobile phone number"));
- }
-
-}
-
-class Horde_Form_Type_ipaddress extends Horde_Form_Type_text {
-
- function isValid($var, $vars, $value, &$message)
- {
- $valid = true;
-
- if (strlen(trim($value)) > 0) {
- $ip = explode('.', $value);
- $valid = (count($ip) == 4);
- if ($valid) {
- foreach ($ip as $part) {
- if (!is_numeric($part) ||
- $part > 255 ||
- $part < 0) {
- $valid = false;
- break;
- }
- }
- }
-
- if (!$valid) {
- $message = _("Please enter a valid IP address.");
- }
- } elseif ($var->isRequired()) {
- $valid = false;
- $message = _("This field is required.");
- }
-
- return $valid;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("IP address"));
- }
-
-}
-
-class Horde_Form_Type_longtext extends Horde_Form_Type_text {
-
- var $_rows;
- var $_cols;
- var $_helper = array();
-
- function init($rows = 8, $cols = 80, $helper = array())
- {
- if (!is_array($helper)) {
- $helper = array($helper);
- }
-
- $this->_rows = $rows;
- $this->_cols = $cols;
- $this->_helper = $helper;
- }
-
- function hasHelper($option = '')
- {
- if (empty($option)) {
- /* No option specified, check if any helpers have been
- * activated. */
- return !empty($this->_helper);
- } elseif (empty($this->_helper)) {
- /* No helpers activated at all, return false. */
- return false;
- } else {
- /* Check if given helper has been activated. */
- return in_array($option, $this->_helper);
- }
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Long text"),
- 'params' => array(
- 'rows' => array('label' => _("Number of rows"),
- 'type' => 'int'),
- 'cols' => array('label' => _("Number of columns"),
- 'type' => 'int'),
- 'helper' => array('label' => _("Helper?"),
- 'type' => 'boolean')));
- }
-
-}
-
-class Horde_Form_Type_countedtext extends Horde_Form_Type_longtext {
-
- var $_chars;
-
- function init($rows = null, $cols = null, $chars = 1000)
- {
- parent::init($rows, $cols);
- $this->_chars = $chars;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- $valid = true;
-
- $length = String::length(trim($value));
-
- if ($var->isRequired() && $length <= 0) {
- $valid = false;
- $message = _("This field is required.");
- } elseif ($length > $this->_chars) {
- $valid = false;
- $message = sprintf(_("There are too many characters in this field. You have entered %s characters; you must enter less than %s."), String::length(trim($value)), $this->_chars);
- }
-
- return $valid;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Counted text"),
- 'params' => array(
- 'rows' => array('label' => _("Number of rows"),
- 'type' => 'int'),
- 'cols' => array('label' => _("Number of columns"),
- 'type' => 'int'),
- 'chars' => array('label' => _("Number of characters"),
- 'type' => 'int')));
- }
-
-}
-
-class Horde_Form_Type_address extends Horde_Form_Type_longtext {
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Address"),
- 'params' => array(
- 'rows' => array('label' => _("Number of rows"),
- 'type' => 'int'),
- 'cols' => array('label' => _("Number of columns"),
- 'type' => 'int')));
- }
-
-}
-
-class Horde_Form_Type_addresslink extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- return true;
- }
-
-}
-
-class Horde_Form_Type_file extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- if ($var->isRequired()) {
- $uploaded = Horde_Browser::wasFileUploaded($var->getVarName());
- if (is_a($uploaded, 'PEAR_Error')) {
- $message = $uploaded->getMessage();
- return false;
- }
- }
-
- return true;
- }
-
- function getInfo($vars, $var, &$info)
- {
- $name = $var->getVarName();
- $uploaded = Horde_Browser::wasFileUploaded($name);
- if ($uploaded === true) {
- $info['name'] = $_FILES[$name]['name'];
- $info['type'] = $_FILES[$name]['type'];
- $info['tmp_name'] = $_FILES[$name]['tmp_name'];
- $info['file'] = $_FILES[$name]['tmp_name'];
- $info['error'] = $_FILES[$name]['error'];
- $info['size'] = $_FILES[$name]['size'];
- }
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("File upload"));
- }
-
-}
-
-class Horde_Form_Type_image extends Horde_Form_Type {
-
- /**
- * Has a file been uploaded on this form submit?
- *
- * @var boolean
- */
- var $_uploaded = null;
-
- /**
- * Show the upload button?
- *
- * @var boolean
- */
- var $_show_upload = true;
-
- /**
- * Show the option to upload also original non-modified image?
- *
- * @var boolean
- */
- var $_show_keeporig = false;
-
- /**
- * Limit the file size?
- *
- * @var integer
- */
- var $_max_filesize = null;
-
- /**
- * Hash containing the previously uploaded image info.
- *
- * @var array
- */
- var $_img = array();
-
- function init($show_upload = true, $show_keeporig = false, $max_filesize = null)
- {
- $this->_show_upload = $show_upload;
- $this->_show_keeporig = $show_keeporig;
- $this->_max_filesize = $max_filesize;
- }
-
- function onSubmit($var, $vars)
- {
- /* Get the upload. */
- $this->_getUpload($vars, $var);
-
- /* If this was done through the upload button override the submitted
- * value of the form. */
- if ($vars->get('_do_' . $var->getVarName())) {
- $var->form->setSubmitted(false);
- }
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- $field = $vars->get($var->getVarName());
-
- /* Get the upload. */
- $this->_getUpload($vars, $var);
-
- /* The upload generated a PEAR Error. */
- if (is_a($this->_uploaded, 'PEAR_Error')) {
- /* Not required and no image upload attempted. */
- if (!$var->isRequired() && empty($field['img']) &&
- $this->_uploaded->getCode() == UPLOAD_ERR_NO_FILE) {
- return true;
- }
-
- if (($this->_uploaded->getCode() == UPLOAD_ERR_NO_FILE) &&
- empty($field['img'])) {
- /* Nothing uploaded and no older upload. */
- $message = _("This field is required.");
- return false;
- } elseif (!empty($field['img'])) {
- /* Nothing uploaded but older upload present. */
- return true;
- } else {
- /* Some other error message. */
- $message = $this->_uploaded->getMessage();
- return false;
- }
- } elseif ($this->_max_filesize &&
- $this->_img['size'] > $this->_max_filesize) {
- $message = sprintf(_("The image file was larger than the maximum allowed size (%d bytes)."), $this->_max_filesize);
- return false;
- }
-
- return true;
- }
-
- function getInfo($vars, $var, &$info)
- {
- /* Get the upload. */
- $this->_getUpload($vars, $var);
-
- /* Get image params stored in the hidden field. */
- $value = $var->getValue($vars);
- $info = $this->_img;
- if (empty($info['file'])) {
- unset($info['file']);
- return;
- }
- if ($this->_show_keeporig) {
- $info['keep_orig'] = !empty($value['keep_orig']);
- }
-
- /* Set the uploaded value (either true or PEAR_Error). */
- $info['uploaded'] = &$this->_uploaded;
-
- /* If a modified file exists move it over the original. */
- if ($this->_show_keeporig && $info['keep_orig']) {
- /* Requested the saving of original file also. */
- $info['orig_file'] = Horde::getTempDir() . '/' . $info['file'];
- $info['file'] = Horde::getTempDir() . '/mod_' . $info['file'];
- /* Check if a modified file actually exists. */
- if (!file_exists($info['file'])) {
- $info['file'] = $info['orig_file'];
- unset($info['orig_file']);
- }
- } else {
- /* Saving of original not required. */
- $mod_file = Horde::getTempDir() . '/mod_' . $info['file'];
- $info['file'] = Horde::getTempDir() . '/' . $info['file'];
-
- if (file_exists($mod_file)) {
- /* Unlink first (has to be done on Windows machines?) */
- unlink($info['file']);
- rename($mod_file, $info['file']);
- }
- }
- }
-
- /**
- * Gets the upload and sets up the upload data array. Either
- * fetches an upload done with this submit or retries stored
- * upload info.
- */
- function _getUpload($vars, $var)
- {
- /* Don't bother with this function if already called and set
- * up vars. */
- if (!empty($this->_img)) {
- return true;
- }
-
- /* Check if file has been uploaded. */
- $varname = $var->getVarName();
- $this->_uploaded = Horde_Browser::wasFileUploaded($varname . '[new]');
-
- if ($this->_uploaded === true) {
- /* A file has been uploaded on this submit. Save to temp dir for
- * preview work. */
- $this->_img['type'] = $this->getUploadedFileType($varname . '[new]');
-
- /* Get the other parts of the upload. */
- Horde_Array::getArrayParts($varname . '[new]', $base, $keys);
-
- /* Get the temporary file name. */
- $keys_path = array_merge(array($base, 'tmp_name'), $keys);
- $this->_img['file'] = Horde_Array::getElement($_FILES, $keys_path);
-
- /* Get the actual file name. */
- $keys_path= array_merge(array($base, 'name'), $keys);
- $this->_img['name'] = Horde_Array::getElement($_FILES, $keys_path);
-
- /* Get the file size. */
- $keys_path= array_merge(array($base, 'size'), $keys);
- $this->_img['size'] = Horde_Array::getElement($_FILES, $keys_path);
-
- /* Get any existing values for the image upload field. */
- $upload = $vars->get($var->getVarName());
- $upload['img'] = @unserialize($upload['img']);
-
- /* Get the temp file if already one uploaded, otherwise create a
- * new temporary file. */
- if (!empty($upload['img']['file'])) {
- $tmp_file = Horde::getTempDir() . '/' . $upload['img']['file'];
- } else {
- $tmp_file = Horde::getTempFile('Horde', false);
- }
-
- /* Move the browser created temp file to the new temp file. */
- move_uploaded_file($this->_img['file'], $tmp_file);
- $this->_img['file'] = basename($tmp_file);
-
- /* Store the uploaded image file data to the hidden field. */
- $upload['img'] = serialize($this->_img);
- $vars->set($var->getVarName(), $upload);
- } elseif ($this->_uploaded) {
- /* File has not been uploaded. */
- $upload = $vars->get($var->getVarName());
- if ($this->_uploaded->getCode() == 4 && !empty($upload['img'])) {
- $this->_img = @unserialize($upload['img']);
- }
- }
- }
-
- function getUploadedFileType($field)
- {
- /* Get any index on the field name. */
- $index = Horde_Array::getArrayParts($field, $base, $keys);
-
- if ($index) {
- /* Index present, fetch the mime type var to check. */
- $keys_path = array_merge(array($base, 'type'), $keys);
- $type = Horde_Array::getElement($_FILES, $keys_path);
- $keys_path= array_merge(array($base, 'tmp_name'), $keys);
- $tmp_name = Horde_Array::getElement($_FILES, $keys_path);
- } else {
- /* No index, simple set up of vars to check. */
- $type = $_FILES[$field]['type'];
- $tmp_name = $_FILES[$field]['tmp_name'];
- }
-
- if (empty($type) || ($type == 'application/octet-stream')) {
- /* Type wasn't set on upload, try analising the upload. */
- global $conf;
- require_once 'Horde/MIME/Magic.php';
- if (!($type = MIME_Magic::analyzeFile($tmp_name, isset($conf['mime']['magic_db']) ? $conf['mime']['magic_db'] : null))) {
- if ($index) {
- /* Get the name value. */
- $keys_path = array_merge(array($base, 'name'), $keys);
- $name = Horde_Array::getElement($_FILES, $keys_path);
-
- /* Work out the type from the file name. */
- $type = MIME_Magic::filenameToMIME($name);
-
- /* Set the type. */
- $keys_path = array_merge(array($base, 'type'), $keys);
- Horde_Array::getElement($_FILES, $keys_path, $type);
- } else {
- /* Work out the type from the file name. */
- $type = MIME_Magic::filenameToMIME($_FILES[$field]['name']);
-
- /* Set the type. */
- $_FILES[$field]['type'] = MIME_Magic::filenameToMIME($_FILES[$field]['name']);
- }
- }
- }
-
- return $type;
- }
-
- /**
- * Loads any existing image data into the image field. Requires that the
- * array $image passed to it contains the structure:
- * $image['load']['file'] - the filename of the image;
- * $image['load']['data'] - the raw image data.
- *
- * @param array $image The image array.
- */
- function loadImageData(&$image)
- {
- /* No existing image data to load. */
- if (!isset($image['load'])) {
- return;
- }
-
- /* Save the data to the temp dir. */
- $tmp_file = Horde::getTempDir() . '/' . $image['load']['file'];
- if ($fd = fopen($tmp_file, 'w')) {
- fwrite($fd, $image['load']['data']);
- fclose($fd);
- }
-
- $image['img'] = serialize(array('file' => $image['load']['file']));
- unset($image['load']);
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Image upload"),
- 'params' => array(
- 'show_upload' => array('label' => _("Show upload?"),
- 'type' => 'boolean'),
- 'show_keeporig' => array('label' => _("Show option to keep original?"),
- 'type' => 'boolean'),
- 'max_filesize' => array('label' => _("Maximum file size in bytes"),
- 'type' => 'int')));
- }
-
-}
-
-class Horde_Form_Type_boolean extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- return true;
- }
-
- function getInfo($vars, $var, &$info)
- {
- $info = String::lower($vars->get($var->getVarName())) == 'on';
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("True or false"));
- }
-
-}
-
-class Horde_Form_Type_link extends Horde_Form_Type {
-
- /**
- * List of hashes containing link parameters. Possible keys: 'url', 'text',
- * 'target', 'onclick', 'title', 'accesskey'.
- *
- * @var array
- */
- var $values;
-
- function init($values)
- {
- $this->values = $values;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- return true;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Link"),
- 'params' => array(
- 'url' => array(
- 'label' => _("Link URL"),
- 'type' => 'text'),
- 'text' => array(
- 'label' => _("Link text"),
- 'type' => 'text'),
- 'target' => array(
- 'label' => _("Link target"),
- 'type' => 'text'),
- 'onclick' => array(
- 'label' => _("Onclick event"),
- 'type' => 'text'),
- 'title' => array(
- 'label' => _("Link title attribute"),
- 'type' => 'text'),
- 'accesskey' => array(
- 'label' => _("Link access key"),
- 'type' => 'text')));
- }
-
-}
-
-class Horde_Form_Type_email extends Horde_Form_Type {
-
- var $_allow_multi = false;
- var $_strip_domain = false;
- var $_link_compose = false;
- var $_check_smtp = false;
- var $_link_name;
-
- /**
- * A string containing valid delimiters (default is just comma).
- *
- * @var string
- */
- var $_delimiters = ',';
-
- function init($allow_multi = false, $strip_domain = false,
- $link_compose = false, $link_name = null,
- $delimiters = ',')
- {
- $this->_allow_multi = $allow_multi;
- $this->_strip_domain = $strip_domain;
- $this->_link_compose = $link_compose;
- $this->_link_name = $link_name;
- $this->_delimiters = $delimiters;
- }
-
- /**
- */
- function isValid($var, $vars, $value, &$message)
- {
- // Split into individual addresses.
- $emails = $this->splitEmailAddresses($value);
-
- // Check for too many.
- if (!$this->_allow_multi && count($emails) > 1) {
- $message = _("Only one email address is allowed.");
- return false;
- }
-
- // Check for all valid and at least one non-empty.
- $nonEmpty = 0;
- foreach ($emails as $email) {
- if (!strlen($email)) {
- continue;
- }
- if (!$this->validateEmailAddress($email)) {
- $message = sprintf(_("\"%s\" is not a valid email address."), $email);
- return false;
- }
- ++$nonEmpty;
- }
-
- if (!$nonEmpty && $var->isRequired()) {
- if ($this->_allow_multi) {
- $message = _("You must enter at least one email address.");
- } else {
- $message = _("You must enter an email address.");
- }
- return false;
- }
-
- return true;
- }
-
- /**
- * Explodes an RFC 2822 string, ignoring a delimiter if preceded
- * by a "\" character, or if the delimiter is inside single or
- * double quotes.
- *
- * @param string $string The RFC 822 string.
- *
- * @return array The exploded string in an array.
- */
- function splitEmailAddresses($string)
- {
- $quotes = array('"', "'");
- $emails = array();
- $pos = 0;
- $in_quote = null;
- $in_group = false;
- $prev = null;
-
- if (!strlen($string)) {
- return array();
- }
-
- $char = $string[0];
- if (in_array($char, $quotes)) {
- $in_quote = $char;
- } elseif ($char == ':') {
- $in_group = true;
- } elseif (strpos($this->_delimiters, $char) !== false) {
- $emails[] = '';
- $pos = 1;
- }
-
- for ($i = 1, $iMax = strlen($string); $i < $iMax; ++$i) {
- $char = $string[$i];
- if (in_array($char, $quotes)) {
- if ($prev !== '\\') {
- if ($in_quote === $char) {
- $in_quote = null;
- } elseif (is_null($in_quote)) {
- $in_quote = $char;
- }
- }
- } elseif ($in_group) {
- if ($char == ';') {
- $emails[] = substr($string, $pos, $i - $pos + 1);
- $pos = $i + 1;
- $in_group = false;
- }
- } elseif ($char == ':') {
- $in_group = true;
- } elseif (strpos($this->_delimiters, $char) !== false &&
- $prev !== '\\' &&
- is_null($in_quote)) {
- $emails[] = substr($string, $pos, $i - $pos);
- $pos = $i + 1;
- }
- $prev = $char;
- }
-
- if ($pos != $i) {
- /* The string ended without a delimiter. */
- $emails[] = substr($string, $pos, $i - $pos);
- }
-
- return $emails;
- }
-
- /**
- * RFC(2)822 Email Parser.
- *
- * By Cal Henderson <cal@iamcal.com>
- * This code is licensed under a Creative Commons Attribution-ShareAlike 2.5 License
- * http://creativecommons.org/licenses/by-sa/2.5/
- *
- * http://code.iamcal.com/php/rfc822/
- *
- * http://iamcal.com/publish/articles/php/parsing_email
- *
- * Revision 4
- *
- * @param string $email An individual email address to validate.
- *
- * @return boolean
- */
- function validateEmailAddress($email)
- {
- static $comment_regexp, $email_regexp;
- if ($comment_regexp === null) {
- $this->_defineValidationRegexps($comment_regexp, $email_regexp);
- }
-
- // We need to strip comments first (repeat until we can't find
- // any more).
- while (true) {
- $new = preg_replace("!$comment_regexp!", '', $email);
- if (strlen($new) == strlen($email)){
- break;
- }
- $email = $new;
- }
-
- // Now match what's left.
- $result = (bool)preg_match("!^$email_regexp$!", $email);
- if ($result && $this->_check_smtp) {
- $result = $this->validateEmailAddressSmtp($email);
- }
-
- return $result;
- }
-
- /**
- * Attempt partial delivery of mail to an address to validate it.
- *
- * @param string $email An individual email address to validate.
- *
- * @return boolean
- */
- function validateEmailAddressSmtp($email)
- {
- list(, $maildomain) = explode('@', $email, 2);
-
- // Try to get the real mailserver from MX records.
- if (function_exists('getmxrr') &&
- @getmxrr($maildomain, $mxhosts, $mxpriorities)) {
- // MX record found.
- array_multisort($mxpriorities, $mxhosts);
- $mailhost = $mxhosts[0];
- } else {
- // No MX record found, try the root domain as the mail
- // server.
- $mailhost = $maildomain;
- }
-
- $fp = @fsockopen($mailhost, 25, $errno, $errstr, 5);
- if (!$fp) {
- return false;
- }
-
- // Read initial response.
- fgets($fp, 4096);
-
- // HELO
- fputs($fp, "HELO $mailhost\r\n");
- fgets($fp, 4096);
-
- // MAIL FROM
- fputs($fp, "MAIL FROM: <root@example.com>\r\n");
- fgets($fp, 4096);
-
- // RCPT TO - gets the result we want.
- fputs($fp, "RCPT TO: <$email>\r\n");
- $result = trim(fgets($fp, 4096));
-
- // QUIT
- fputs($fp, "QUIT\r\n");
- fgets($fp, 4096);
- fclose($fp);
-
- return substr($result, 0, 1) == '2';
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Email"),
- 'params' => array(
- 'allow_multi' => array('label' => _("Allow multiple addresses?"),
- 'type' => 'boolean'),
- 'strip_domain' => array('label' => _("Protect address from spammers?"),
- 'type' => 'boolean'),
- 'link_compose' => array('label' => _("Link the email address to the compose page when displaying?"),
- 'type' => 'boolean'),
- 'link_name' => array('label' => _("The name to use when linking to the compose page"),
- 'type' => 'text'),
- 'delimiters' => array('label' => _("Character to split multiple addresses with"),
- 'type' => 'text'),
- ),
- );
- }
-
- /**
- * RFC(2)822 Email Parser.
- *
- * By Cal Henderson <cal@iamcal.com>
- * This code is licensed under a Creative Commons Attribution-ShareAlike 2.5 License
- * http://creativecommons.org/licenses/by-sa/2.5/
- *
- * http://code.iamcal.com/php/rfc822/
- *
- * http://iamcal.com/publish/articles/php/parsing_email
- *
- * Revision 4
- *
- * @param string &$comment The regexp for comments.
- * @param string &$addr_spec The regexp for email addresses.
- */
- function _defineValidationRegexps(&$comment, &$addr_spec)
- {
- /**
- * NO-WS-CTL = %d1-8 / ; US-ASCII control characters
- * %d11 / ; that do not include the
- * %d12 / ; carriage return, line feed,
- * %d14-31 / ; and white space characters
- * %d127
- * ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
- * DIGIT = %x30-39
- */
- $no_ws_ctl = "[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]";
- $alpha = "[\\x41-\\x5a\\x61-\\x7a]";
- $digit = "[\\x30-\\x39]";
- $cr = "\\x0d";
- $lf = "\\x0a";
- $crlf = "($cr$lf)";
-
- /**
- * obs-char = %d0-9 / %d11 / ; %d0-127 except CR and
- * %d12 / %d14-127 ; LF
- * obs-text = *LF *CR *(obs-char *LF *CR)
- * text = %d1-9 / ; Characters excluding CR and LF
- * %d11 /
- * %d12 /
- * %d14-127 /
- * obs-text
- * obs-qp = "\" (%d0-127)
- * quoted-pair = ("\" text) / obs-qp
- */
- $obs_char = "[\\x00-\\x09\\x0b\\x0c\\x0e-\\x7f]";
- $obs_text = "($lf*$cr*($obs_char$lf*$cr*)*)";
- $text = "([\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f]|$obs_text)";
- $obs_qp = "(\\x5c[\\x00-\\x7f])";
- $quoted_pair = "(\\x5c$text|$obs_qp)";
-
- /**
- * obs-FWS = 1*WSP *(CRLF 1*WSP)
- * FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
- * obs-FWS
- * ctext = NO-WS-CTL / ; Non white space controls
- * %d33-39 / ; The rest of the US-ASCII
- * %d42-91 / ; characters not including "(",
- * %d93-126 ; ")", or "\"
- * ccontent = ctext / quoted-pair / comment
- * comment = "(" *([FWS] ccontent) [FWS] ")"
- * CFWS = *([FWS] comment) (([FWS] comment) / FWS)
- *
- * @note: We translate ccontent only partially to avoid an
- * infinite loop. Instead, we'll recursively strip comments
- * before processing the input.
- */
- $wsp = "[\\x20\\x09]";
- $obs_fws = "($wsp+($crlf$wsp+)*)";
- $fws = "((($wsp*$crlf)?$wsp+)|$obs_fws)";
- $ctext = "($no_ws_ctl|[\\x21-\\x27\\x2A-\\x5b\\x5d-\\x7e])";
- $ccontent = "($ctext|$quoted_pair)";
- $comment = "(\\x28($fws?$ccontent)*$fws?\\x29)";
- $cfws = "(($fws?$comment)*($fws?$comment|$fws))";
- $cfws = "$fws*";
-
- /**
- * atext = ALPHA / DIGIT / ; Any character except controls,
- * "!" / "#" / ; SP, and specials.
- * "$" / "%" / ; Used for atoms
- * "&" / "'" /
- * "*" / "+" /
- * "-" / "/" /
- * "=" / "?" /
- * "^" / "_" /
- * "`" / "{" /
- * "|" / "}" /
- * "~"
- * atom = [CFWS] 1*atext [CFWS]
- */
- $atext = "($alpha|$digit|[\\x21\\x23-\\x27\\x2a\\x2b\\x2d\\x2e\\x3d\\x3f\\x5e\\x5f\\x60\\x7b-\\x7e])";
- $atom = "($cfws?$atext+$cfws?)";
-
- /**
- * qtext = NO-WS-CTL / ; Non white space controls
- * %d33 / ; The rest of the US-ASCII
- * %d35-91 / ; characters not including "\"
- * %d93-126 ; or the quote character
- * qcontent = qtext / quoted-pair
- * quoted-string = [CFWS]
- * DQUOTE *([FWS] qcontent) [FWS] DQUOTE
- * [CFWS]
- * word = atom / quoted-string
- */
- $qtext = "($no_ws_ctl|[\\x21\\x23-\\x5b\\x5d-\\x7e])";
- $qcontent = "($qtext|$quoted_pair)";
- $quoted_string = "($cfws?\\x22($fws?$qcontent)*$fws?\\x22$cfws?)";
- $word = "($atom|$quoted_string)";
-
- /**
- * obs-local-part = word *("." word)
- * obs-domain = atom *("." atom)
- */
- $obs_local_part = "($word(\\x2e$word)*)";
- $obs_domain = "($atom(\\x2e$atom)*)";
-
- /**
- * dot-atom-text = 1*atext *("." 1*atext)
- * dot-atom = [CFWS] dot-atom-text [CFWS]
- */
- $dot_atom_text = "($atext+(\\x2e$atext+)*)";
- $dot_atom = "($cfws?$dot_atom_text$cfws?)";
-
- /**
- * domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
- * dcontent = dtext / quoted-pair
- * dtext = NO-WS-CTL / ; Non white space controls
- *
- * %d33-90 / ; The rest of the US-ASCII
- * %d94-126 ; characters not including "[",
- * ; "]", or "\"
- */
- $dtext = "($no_ws_ctl|[\\x21-\\x5a\\x5e-\\x7e])";
- $dcontent = "($dtext|$quoted_pair)";
- $domain_literal = "($cfws?\\x5b($fws?$dcontent)*$fws?\\x5d$cfws?)";
-
- /**
- * local-part = dot-atom / quoted-string / obs-local-part
- * domain = dot-atom / domain-literal / obs-domain
- * addr-spec = local-part "@" domain
- */
- $local_part = "($dot_atom|$quoted_string|$obs_local_part)";
- $domain = "($dot_atom|$domain_literal|$obs_domain)";
- $addr_spec = "($local_part\\x40$domain)";
- }
-
-}
-
-class Horde_Form_Type_matrix extends Horde_Form_Type {
-
- var $_cols;
- var $_rows;
- var $_matrix;
- var $_new_input;
-
- /**
- * Initializes the variable.
- *
- * @example
- * init(array('Column A', 'Column B'),
- * array(1 => 'Row One', 2 => 'Row 2', 3 => 'Row 3'),
- * array(array(true, true, false),
- * array(true, false, true),
- * array(fasle, true, false)),
- * array('Row 4', 'Row 5'));
- *
- * @param array $cols A list of column headers.
- * @param array $rows A hash with row IDs as the keys and row
- * labels as the values.
- * @param array $matrix A two dimensional hash with the field
- * values.
- * @param boolean|array $new_input If true, a free text field to add a new
- * row is displayed on the top, a select
- * box if this parameter is a value.
- */
- function init($cols, $rows = array(), $matrix = array(), $new_input = false)
- {
- $this->_cols = $cols;
- $this->_rows = $rows;
- $this->_matrix = $matrix;
- $this->_new_input = $new_input;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- return true;
- }
-
- function getInfo($vars, $var, &$info)
- {
- $values = $vars->get($var->getVarName());
- if (!empty($values['n']['r']) && isset($values['n']['v'])) {
- $new_row = $values['n']['r'];
- $values['r'][$new_row] = $values['n']['v'];
- unset($values['n']);
- }
-
- $info = (isset($values['r']) ? $values['r'] : array());
- }
-
- function about()
- {
- return array(
- 'name' => _("Field matrix"),
- 'params' => array(
- 'cols' => array('label' => _("Column titles"),
- 'type' => 'stringlist')));
- }
-
-}
-
-class Horde_Form_Type_emailConfirm extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- if ($var->isRequired() && empty($value['original'])) {
- $message = _("This field is required.");
- return false;
- }
-
- if ($value['original'] != $value['confirm']) {
- $message = _("Email addresses must match.");
- return false;
- } else {
- $parser = new Mail_RFC822();
- $parsed_email = $parser->parseAddressList($value['original'], false, true);
-
- if (count($parsed_email) > 1) {
- $message = _("Only one email address allowed.");
- return false;
- }
- if (empty($parsed_email[0]->mailbox)) {
- $message = _("You did not enter a valid email address.");
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Email with confirmation"));
- }
-
-}
-
-class Horde_Form_Type_password extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- $valid = true;
-
- if ($var->isRequired()) {
- $valid = strlen(trim($value)) > 0;
-
- if (!$valid) {
- $message = _("This field is required.");
- }
- }
-
- return $valid;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Password"));
- }
-
-}
-
-class Horde_Form_Type_passwordconfirm extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- if ($var->isRequired() && empty($value['original'])) {
- $message = _("This field is required.");
- return false;
- }
-
- if ($value['original'] != $value['confirm']) {
- $message = _("Passwords must match.");
- return false;
- }
-
- return true;
- }
-
- function getInfo($vars, $var, &$info)
- {
- $value = $vars->get($var->getVarName());
- $info = $value['original'];
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Password with confirmation"));
- }
-
-}
-
-class Horde_Form_Type_enum extends Horde_Form_Type {
-
- var $_values;
- var $_prompt;
-
- function init($values, $prompt = null)
- {
- $this->_values = $values;
-
- if ($prompt === true) {
- $this->_prompt = _("-- select --");
- } else {
- $this->_prompt = $prompt;
- }
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- if ($var->isRequired() && $value == '' && !isset($this->_values[$value])) {
- $message = _("This field is required.");
- return false;
- }
-
- if (count($this->_values) == 0 || isset($this->_values[$value]) ||
- ($this->_prompt && empty($value))) {
- return true;
- }
-
- $message = _("Invalid data.");
- return false;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Drop down list"),
- 'params' => array(
- 'values' => array('label' => _("Values to select from"),
- 'type' => 'stringlist'),
- 'prompt' => array('label' => _("Prompt text"),
- 'type' => 'text')));
- }
-
-}
-
-class Horde_Form_Type_mlenum extends Horde_Form_Type {
-
- var $_values;
- var $_prompts;
-
- function init(&$values, $prompts = null)
- {
- $this->_values = &$values;
-
- if ($prompts === true) {
- $this->_prompts = array(_("-- select --"), _("-- select --"));
- } elseif (!is_array($prompts)) {
- $this->_prompts = array($prompts, $prompts);
- } else {
- $this->_prompts = $prompts;
- }
- }
-
- function onSubmit($var, $vars)
- {
- $varname = $var->getVarName();
- $value = $vars->get($varname);
-
- if ($value['1'] != $value['old']) {
- $var->form->setSubmitted(false);
- }
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- if ($var->isRequired() && (empty($value['1']) || empty($value['2']))) {
- $message = _("This field is required.");
- return false;
- }
-
- if (!count($this->_values) || isset($this->_values[$value['1']]) ||
- (!empty($this->_prompts) && empty($value['1']))) {
- return true;
- }
-
- $message = _("Invalid data.");
- return false;
- }
-
- function getInfo($vars, &$var, &$info)
- {
- $info = $vars->get($var->getVarName());
- return $info['2'];
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Multi-level drop down lists"),
- 'params' => array(
- 'values' => array('label' => _("Values to select from"),
- 'type' => 'stringlist'),
- 'prompt' => array('label' => _("Prompt text"),
- 'type' => 'text')));
- }
-
-}
-
-class Horde_Form_Type_multienum extends Horde_Form_Type_enum {
-
- var $size = 5;
-
- function init($values, $size = null)
- {
- if (!is_null($size)) {
- $this->size = (int)$size;
- }
-
- parent::init($values);
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- if (is_array($value)) {
- foreach ($value as $val) {
- if (!$this->isValid($var, $vars, $val, $message)) {
- return false;
- }
- }
- return true;
- }
-
- if (empty($value) && ((string)(int)$value !== $value)) {
- if ($var->isRequired()) {
- $message = _("This field is required.");
- return false;
- } else {
- return true;
- }
- }
-
- if (count($this->_values) == 0 || isset($this->_values[$value])) {
- return true;
- }
-
- $message = _("Invalid data.");
- return false;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Multiple selection"),
- 'params' => array(
- 'values' => array('label' => _("Values"),
- 'type' => 'stringlist'),
- 'size' => array('label' => _("Size"),
- 'type' => 'int'))
- );
- }
-
-}
-
-class Horde_Form_Type_keyval_multienum extends Horde_Form_Type_multienum {
-
- function getInfo($vars, $var, &$info)
- {
- $value = $vars->get($var->getVarName());
- $info = array();
- foreach ($value as $key) {
- $info[$key] = $this->_values[$key];
- }
- }
-
-}
-
-class Horde_Form_Type_radio extends Horde_Form_Type_enum {
-
- /* Entirely implemented by Horde_Form_Type_enum; just a different
- * view. */
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Radio selection"),
- 'params' => array(
- 'values' => array('label' => _("Values"),
- 'type' => 'stringlist')));
- }
-
-}
-
-class Horde_Form_Type_set extends Horde_Form_Type {
-
- var $_values;
- var $_checkAll = false;
-
- function init(&$values, $checkAll = false)
- {
- $this->_values = $values;
- $this->_checkAll = $checkAll;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- if (count($this->_values) == 0 || count($value) == 0) {
- return true;
- }
- foreach ($value as $item) {
- if (!isset($this->_values[$item])) {
- $error = true;
- break;
- }
- }
- if (!isset($error)) {
- return true;
- }
-
- $message = _("Invalid data.");
- return false;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Set"),
- 'params' => array(
- 'values' => array('label' => _("Values"),
- 'type' => 'stringlist')));
- }
-
-}
-
-class Horde_Form_Type_date extends Horde_Form_Type {
-
- var $_format;
-
- function init($format = '%a %d %B')
- {
- $this->_format = $format;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- $valid = true;
-
- if ($var->isRequired()) {
- $valid = strlen(trim($value)) > 0;
-
- if (!$valid) {
- $message = sprintf(_("%s is required"), $var->getHumanName());
- }
- }
-
- return $valid;
- }
-
- /**
- * @static
- */
- function getAgo($timestamp)
- {
- if ($timestamp === null) {
- return '';
- }
-
- $diffdays = Date_Calc::dateDiff(date('j', $timestamp),
- date('n', $timestamp),
- date('Y', $timestamp),
- date('j'), date('n'), date('Y'));
-
- /* An error occured. */
- if ($diffdays == -1) {
- return;
- }
-
- $ago = $diffdays * Date_Calc::compareDates(date('j', $timestamp),
- date('n', $timestamp),
- date('Y', $timestamp),
- date('j'), date('n'),
- date('Y'));
- if ($ago < -1) {
- return sprintf(_(" (%s days ago)"), $diffdays);
- } elseif ($ago == -1) {
- return _(" (yesterday)");
- } elseif ($ago == 0) {
- return _(" (today)");
- } elseif ($ago == 1) {
- return _(" (tomorrow)");
- } else {
- return sprintf(_(" (in %s days)"), $diffdays);
- }
- }
-
- function getFormattedTime($timestamp, $format = null, $showago = true)
- {
- if (empty($format)) {
- $format = $this->_format;
- }
- if (!empty($timestamp)) {
- return strftime($format, $timestamp) . ($showago ? Horde_Form_Type_date::getAgo($timestamp) : '');
- } else {
- return '';
- }
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Date"));
- }
-
-}
-
-class Horde_Form_Type_time extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- if ($var->isRequired() && empty($value) && ((string)(double)$value !== $value)) {
- $message = _("This field is required.");
- return false;
- }
-
- if (empty($value) || preg_match('/^[0-2]?[0-9]:[0-5][0-9]$/', $value)) {
- return true;
- }
-
- $message = _("This field may only contain numbers and the colon.");
- return false;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Time"));
- }
-
-}
-
-class Horde_Form_Type_hourminutesecond extends Horde_Form_Type {
-
- var $_show_seconds;
-
- function init($show_seconds = false)
- {
- $this->_show_seconds = $show_seconds;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- $time = $vars->get($var->getVarName());
- if (!$this->_show_seconds && !isset($time['second'])) {
- $time['second'] = 0;
- }
-
- if (!$this->emptyTimeArray($time) && !$this->checktime($time['hour'], $time['minute'], $time['second'])) {
- $message = _("Please enter a valid time.");
- return false;
- } elseif ($this->emptyTimeArray($time) && $var->isRequired()) {
- $message = _("This field is required.");
- return false;
- }
-
- return true;
- }
-
- function checktime($hour, $minute, $second)
- {
- if (!isset($hour) || $hour == '' || ($hour < 0 || $hour > 23)) {
- return false;
- }
- if (!isset($minute) || $minute == '' || ($minute < 0 || $minute > 60)) {
- return false;
- }
- if (!isset($second) || $second === '' || ($second < 0 || $second > 60)) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Return the time supplied as a Horde_Date object.
- *
- * @param string $time_in Date in one of the three formats supported by
- * Horde_Form and Horde_Date (ISO format
- * YYYY-MM-DD HH:MM:SS, timestamp YYYYMMDDHHMMSS and
- * UNIX epoch).
- *
- * @return Date The time object.
- */
- function getTimeOb($time_in)
- {
- if (is_array($time_in)) {
- if (!$this->emptyTimeArray($time_in)) {
- $time_in = sprintf('1970-01-01 %02d:%02d:%02d', $time_in['hour'], $time_in['minute'], $this->_show_seconds ? $time_in['second'] : 0);
- }
- }
-
- return new Horde_Date($time_in);
- }
-
- /**
- * Return the time supplied split up into an array.
- *
- * @param string $time_in Time in one of the three formats supported by
- * Horde_Form and Horde_Date (ISO format
- * YYYY-MM-DD HH:MM:SS, timestamp YYYYMMDDHHMMSS and
- * UNIX epoch).
- *
- * @return array Array with three elements - hour, minute and seconds.
- */
- function getTimeParts($time_in)
- {
- if (is_array($time_in)) {
- /* This is probably a failed isValid input so just return the
- * parts as they are. */
- return $time_in;
- } elseif (empty($time_in)) {
- /* This is just an empty field so return empty parts. */
- return array('hour' => '', 'minute' => '', 'second' => '');
- }
- $time = $this->getTimeOb($time_in);
- return array('hour' => $time->hour,
- 'minute' => $time->min,
- 'second' => $time->sec);
- }
-
- function emptyTimeArray($time)
- {
- return (is_array($time) && empty($time['hour']) && empty($time['minute']) && empty($time['second']));
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Time selection"),
- 'params' => array(
- 'seconds' => array('label' => _("Show seconds?"),
- 'type' => 'boolean')));
- }
-
-}
-
-class Horde_Form_Type_monthyear extends Horde_Form_Type {
-
- var $_start_year;
- var $_end_year;
-
- function init($start_year = null, $end_year = null)
- {
- if (empty($start_year)) {
- $start_year = 1920;
- }
- if (empty($end_year)) {
- $end_year = date('Y');
- }
-
- $this->_start_year = $start_year;
- $this->_end_year = $end_year;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- if (!$var->isRequired()) {
- return true;
- }
-
- if (!$vars->get($this->getMonthVar($var)) ||
- !$vars->get($this->getYearVar($var))) {
- $message = _("Please enter a month and a year.");
- return false;
- }
-
- return true;
- }
-
- function getMonthVar($var)
- {
- return $var->getVarName() . '[month]';
- }
-
- function getYearVar($var)
- {
- return $var->getVarName() . '[year]';
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Month and year"),
- 'params' => array(
- 'start_year' => array('label' => _("Start year"),
- 'type' => 'int'),
- 'end_year' => array('label' => _("End year"),
- 'type' => 'int')));
- }
-
-}
-
-class Horde_Form_Type_monthdayyear extends Horde_Form_Type {
-
- var $_start_year;
- var $_end_year;
- var $_picker;
- var $_format_in = null;
- var $_format_out = '%x';
-
- /**
- * Return the date supplied as a Horde_Date object.
- *
- * @param integer $start_year The first available year for input.
- * @param integer $end_year The last available year for input.
- * @param boolean $picker Do we show the DHTML calendar?
- * @param integer $format_in The format to use when sending the date
- * for storage. Defaults to Unix epoch.
- * Similar to the strftime() function.
- * @param integer $format_out The format to use when displaying the
- * date. Similar to the strftime() function.
- */
- function init($start_year = '', $end_year = '', $picker = true,
- $format_in = null, $format_out = '%x')
- {
- if (empty($start_year)) {
- $start_year = date('Y');
- }
- if (empty($end_year)) {
- $end_year = date('Y') + 10;
- }
-
- $this->_start_year = $start_year;
- $this->_end_year = $end_year;
- $this->_picker = $picker;
- $this->_format_in = $format_in;
- $this->_format_out = $format_out;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- $date = $vars->get($var->getVarName());
- $empty = $this->emptyDateArray($date);
-
- if ($empty == 1 && $var->isRequired()) {
- $message = _("This field is required.");
- return false;
- } elseif ($empty == 0 && !checkdate($date['month'], $date['day'], $date['year'])) {
- $message = _("Please enter a valid date, check the number of days in the month.");
- return false;
- } elseif ($empty == -1) {
- $message = _("Select all date components.");
- return false;
- }
-
- return true;
- }
-
- function emptyDateArray($date)
- {
- if (!is_array($date)) {
- return empty($date);
- }
-
- $empty = 0;
- /* Check each date array component. */
- foreach ($date as $key => $val) {
- if (empty($val)) {
- $empty++;
- }
- }
-
- /* Check state of empty. */
- if ($empty == 0) {
- /* If no empty parts return 0. */
- return 0;
- } elseif ($empty == count($date)) {
- /* If all empty parts return 1. */
- return 1;
- } else {
- /* If some empty parts return -1. */
- return -1;
- }
- }
-
- /**
- * Return the date supplied split up into an array.
- *
- * @param string $date_in Date in one of the three formats supported by
- * Horde_Form and Horde_Date (ISO format
- * YYYY-MM-DD HH:MM:SS, timestamp YYYYMMDDHHMMSS
- * and UNIX epoch) plus the fourth YYYY-MM-DD.
- *
- * @return array Array with three elements - year, month and day.
- */
- function getDateParts($date_in)
- {
- if (is_array($date_in)) {
- /* This is probably a failed isValid input so just return
- * the parts as they are. */
- return $date_in;
- } elseif (empty($date_in)) {
- /* This is just an empty field so return empty parts. */
- return array('year' => '', 'month' => '', 'day' => '');
- }
-
- $date = $this->getDateOb($date_in);
- return array('year' => $date->year,
- 'month' => $date->month,
- 'day' => $date->mday);
- }
-
- /**
- * Return the date supplied as a Horde_Date object.
- *
- * @param string $date_in Date in one of the three formats supported by
- * Horde_Form and Horde_Date (ISO format
- * YYYY-MM-DD HH:MM:SS, timestamp YYYYMMDDHHMMSS
- * and UNIX epoch) plus the fourth YYYY-MM-DD.
- *
- * @return Date The date object.
- */
- function getDateOb($date_in)
- {
- if (is_array($date_in)) {
- /* If passed an array change it to the ISO format. */
- if ($this->emptyDateArray($date_in) == 0) {
- $date_in = sprintf('%04d-%02d-%02d 00:00:00',
- $date_in['year'],
- $date_in['month'],
- $date_in['day']);
- }
- } elseif (preg_match('/^\d{4}-?\d{2}-?\d{2}$/', $date_in)) {
- /* Fix the date if it is the shortened ISO. */
- $date_in = $date_in . ' 00:00:00';
- }
-
- return new Horde_Date($date_in);
- }
-
- /**
- * Return the date supplied as a Horde_Date object.
- *
- * @param string $date Either an already set up Horde_Date object or a
- * string date in one of the three formats supported
- * by Horde_Form and Horde_Date (ISO format
- * YYYY-MM-DD HH:MM:SS, timestamp YYYYMMDDHHMMSS and
- * UNIX epoch) plus the fourth YYYY-MM-DD.
- *
- * @return string The date formatted according to the $format_out
- * parameter when setting up the monthdayyear field.
- */
- function formatDate($date)
- {
- if (!is_a($date, 'Date')) {
- $date = $this->getDateOb($date);
- }
-
- return $date->strftime($this->_format_out);
- }
-
- /**
- * Insert the date input through the form into $info array, in the format
- * specified by the $format_in parameter when setting up monthdayyear
- * field.
- */
- function getInfo($vars, &$var, &$info)
- {
- $info = $this->_validateAndFormat($var->getValue($vars), $var);
- }
-
- /**
- * Validate/format a date submission.
- */
- function _validateAndFormat($value, $var)
- {
- /* If any component is empty consider it a bad date and return the
- * default. */
- if ($this->emptyDateArray($value) == 1) {
- return $var->getDefault();
- } else {
- $date = $this->getDateOb($value);
- if ($this->_format_in === null) {
- return $date->timestamp();
- } else {
- return $date->strftime($this->_format_in);
- }
- }
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Date selection"),
- 'params' => array(
- 'start_year' => array('label' => _("Start year"),
- 'type' => 'int'),
- 'end_year' => array('label' => _("End year"),
- 'type' => 'int'),
- 'picker' => array('label' => _("Show picker?"),
- 'type' => 'boolean'),
- 'format_in' => array('label' => _("Storage format"),
- 'type' => 'text'),
- 'format_out' => array('label' => _("Display format"),
- 'type' => 'text')));
- }
-
-}
-
-/**
- * @since Horde 3.2
- */
-class Horde_Form_Type_datetime extends Horde_Form_Type {
-
- var $_mdy;
- var $_hms;
-
- /**
- * Return the date supplied as a Horde_Date object.
- *
- * @param integer $start_year The first available year for input.
- * @param integer $end_year The last available year for input.
- * @param boolean $picker Do we show the DHTML calendar?
- * @param integer $format_in The format to use when sending the date
- * for storage. Defaults to Unix epoch.
- * Similar to the strftime() function.
- * @param integer $format_out The format to use when displaying the
- * date. Similar to the strftime() function.
- * @param boolean $show_seconds Include a form input for seconds.
- */
- function init($start_year = '', $end_year = '', $picker = true,
- $format_in = null, $format_out = '%x', $show_seconds = false)
- {
- $this->_mdy = new Horde_Form_Type_monthdayyear();
- $this->_mdy->init($start_year, $end_year, $picker, $format_in, $format_out);
-
- $this->_hms = new Horde_Form_Type_hourminutesecond();
- $this->_hms->init($show_seconds);
- }
-
- function isValid(&$var, &$vars, $value, &$message)
- {
- if ($var->isRequired()) {
- return $this->_mdy->isValid($var, $vars, $value, $message) &&
- $this->_hms->isValid($var, $vars, $value, $message);
- }
- return true;
- }
-
- function getInfo(&$vars, &$var, &$info)
- {
- /* If any component is empty consider it a bad date and return the
- * default. */
- $value = $var->getValue($vars);
- if ($this->emptyDateArray($value) == 1 || $this->emptyTimeArray($value)) {
- $info = $var->getDefault();
- return;
- }
-
- $date = $this->getDateOb($value);
- $time = $this->getTimeOb($value);
- $date->hour = $time->hour;
- $date->min = $time->min;
- $date->sec = $time->sec;
- if (is_null($this->format_in)) {
- $info = $date->timestamp();
- } else {
- $info = $date->strftime($this->format_in);
- }
- }
-
- function __get($property)
- {
- if ($property == 'show_seconds') {
- return $this->_hms->$property;
- } else {
- return $this->_mdy->$property;
- }
- }
-
- function __set($property, $value)
- {
- if ($property == 'show_seconds') {
- $this->_hms->$property = $value;
- } else {
- $this->_mdy->$property = $value;
- }
- }
-
- function checktime($hour, $minute, $second)
- {
- return $this->_hms->checktime($hour, $minute, $second);
- }
-
- function getTimeOb($time_in)
- {
- return $this->_hms->getTimeOb($time_in);
- }
-
- function getTimeParts($time_in)
- {
- return $this->_hms->getTimeParts($time_in);
- }
-
- function emptyTimeArray($time)
- {
- return $this->_hms->emptyTimeArray($time);
- }
-
- function emptyDateArray($date)
- {
- return $this->_mdy->emptyDateArray($date);
- }
-
- function getDateParts($date_in)
- {
- return $this->_mdy->getDateParts($date_in);
- }
-
- function getDateOb($date_in)
- {
- return $this->_mdy->getDateOb($date_in);
- }
-
- function formatDate($date)
- {
- if ($date === null) {
- return '';
- }
- return $this->_mdy->formatDate($date);
- }
-
- function about()
- {
- return array(
- 'name' => _("Date and time selection"),
- 'params' => array(
- 'start_year' => array('label' => _("Start year"),
- 'type' => 'int'),
- 'end_year' => array('label' => _("End year"),
- 'type' => 'int'),
- 'picker' => array('label' => _("Show picker?"),
- 'type' => 'boolean'),
- 'format_in' => array('label' => _("Storage format"),
- 'type' => 'text'),
- 'format_out' => array('label' => _("Display format"),
- 'type' => 'text'),
- 'seconds' => array('label' => _("Show seconds?"),
- 'type' => 'boolean')));
- }
-
-}
-
-class Horde_Form_Type_colorpicker extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- if ($var->isRequired() && empty($value)) {
- $message = _("This field is required.");
- return false;
- }
-
- if (empty($value) || preg_match('/^#([0-9a-z]){6}$/i', $value)) {
- return true;
- }
-
- $message = _("This field must contain a color code in the RGB Hex format, for example '#1234af'.");
- return false;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Colour selection"));
- }
-
-}
-
-class Horde_Form_Type_sorter extends Horde_Form_Type {
-
- var $_instance;
- var $_values;
- var $_size;
- var $_header;
-
- function init($values, $size = 8, $header = '')
- {
- static $horde_sorter_instance = 0;
-
- /* Get the next progressive instance count for the horde
- * sorter so that multiple sorters can be used on one page. */
- $horde_sorter_instance++;
- $this->_instance = 'horde_sorter_' . $horde_sorter_instance;
- $this->_values = $values;
- $this->_size = $size;
- $this->_header = $header;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- return true;
- }
-
- function getOptions($keys = null)
- {
- $html = '';
- if ($this->_header) {
- $html .= '<option value="">' . htmlspecialchars($this->_header) . '</option>';
- }
-
- if (empty($keys)) {
- $keys = array_keys($this->_values);
- } else {
- $keys = explode("\t", $keys['array']);
- }
- foreach ($keys as $sl_key) {
- $html .= '<option value="' . $sl_key . '">' . htmlspecialchars($this->_values[$sl_key]) . '</option>';
- }
-
- return $html;
- }
-
- function getInfo($vars, &$var, &$info)
- {
- $value = $vars->get($var->getVarName());
- $info = explode("\t", $value['array']);
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Sort order selection"),
- 'params' => array(
- 'values' => array('label' => _("Values"),
- 'type' => 'stringlist'),
- 'size' => array('label' => _("Size"),
- 'type' => 'int'),
- 'header' => array('label' => _("Header"),
- 'type' => 'text')));
- }
-
-}
-
-class Horde_Form_Type_selectfiles extends Horde_Form_Type {
-
- /**
- * The text to use in the link.
- *
- * @var string
- */
- var $_link_text;
-
- /**
- * The style to use for the link.
- *
- * @var string
- */
- var $_link_style;
-
- /**
- * Create the link with an icon instead of text?
- *
- * @var boolean
- */
- var $_icon;
-
- /**
- * Contains gollem selectfile selectionID
- *
- * @var string
- */
- var $_selectid;
-
- function init($selectid, $link_text = null, $link_style = '',
- $icon = false)
- {
- $this->_selectid = $selectid;
- if (is_null($link_text)) {
- $link_text = _("Select Files");
- }
- $this->_link_text = $link_text;
- $this->_link_style = $link_style;
- $this->_icon = $icon;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- return true;
- }
-
- function getInfo($var, &$vars, &$info)
- {
- $value = $vars->getValue($var);
- $info = $GLOBALS['registry']->call('files/selectlistResults', array($value));
- }
-
- function about()
- {
- return array(
- 'name' => _("File selection"),
- 'params' => array(
- 'selectid' => array('label' => _("Id"),
- 'type' => 'text'),
- 'link_text' => array('label' => _("Link text"),
- 'type' => 'text'),
- 'link_style' => array('label' => _("Link style"),
- 'type' => 'text'),
- 'icon' => array('label' => _("Show icon?"),
- 'type' => 'boolean')));
- }
-
-}
-
-class Horde_Form_Type_assign extends Horde_Form_Type {
-
- var $_leftValues;
- var $_rightValues;
- var $_leftHeader;
- var $_rightHeader;
- var $_size;
- var $_width;
-
- function init($leftValues, $rightValues, $leftHeader = '',
- $rightHeader = '', $size = 8, $width = '200px')
- {
- $this->_leftValues = $leftValues;
- $this->_rightValues = $rightValues;
- $this->_leftHeader = $leftHeader;
- $this->_rightHeader = $rightHeader;
- $this->_size = $size;
- $this->_width = $width;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- return true;
- }
-
- function setValues($side, $values)
- {
- if ($side) {
- $this->_rightValues = $values;
- } else {
- $this->_leftValues = $values;
- }
- }
-
- function getHeader($side)
- {
- return $side ? $this->_rightHeader : $this->_leftHeader;
- }
-
- function getOptions($side, $formname, $varname)
- {
- $html = '';
- $headers = false;
- if ($side) {
- $values = $this->_rightValues;
- if (!empty($this->_rightHeader)) {
- $values = array('' => $this->_rightHeader) + $values;
- $headers = true;
- }
- } else {
- $values = $this->_leftValues;
- if (!empty($this->_leftHeader)) {
- $values = array('' => $this->_leftHeader) + $values;
- $headers = true;
- }
- }
-
- foreach ($values as $key => $val) {
- $html .= '<option value="' . htmlspecialchars($key) . '"';
- if ($headers) {
- $headers = false;
- } else {
- $html .= ' ondblclick="Horde_Form_Assign.move(\'' . $formname . '\', \'' . $varname . '\', ' . (int)$side . ');"';
- }
- $html .= '>' . htmlspecialchars($val) . '</option>';
- }
-
- return $html;
- }
-
- function getInfo($vars, &$var, &$info)
- {
- $value = $vars->get($var->getVarName() . '__values');
- if (strpos($value, "\t\t") === false) {
- $left = $value;
- $right = '';
- } else {
- list($left, $right) = explode("\t\t", $value);
- }
- if (empty($left)) {
- $info['left'] = array();
- } else {
- $info['left'] = explode("\t", $left);
- }
- if (empty($right)) {
- $info['right'] = array();
- } else {
- $info['right'] = explode("\t", $right);
- }
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Assignment columns"),
- 'params' => array(
- 'leftValues' => array('label' => _("Left values"),
- 'type' => 'stringlist'),
- 'rightValues' => array('label' => _("Right values"),
- 'type' => 'stringlist'),
- 'leftHeader' => array('label' => _("Left header"),
- 'type' => 'text'),
- 'rightHeader' => array('label' => _("Right header"),
- 'type' => 'text'),
- 'size' => array('label' => _("Size"),
- 'type' => 'int'),
- 'width' => array('label' => _("Width in CSS units"),
- 'type' => 'text')));
- }
-
-}
-
-class Horde_Form_Type_creditcard extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- if (empty($value) && $var->isRequired()) {
- $message = _("This field is required.");
- return false;
- }
-
- if (!empty($value)) {
- /* getCardType() will also verify the checksum. */
- $type = $this->getCardType($value);
- if ($type === false || $type == 'unknown') {
- $message = _("This does not seem to be a valid card number.");
- return false;
- }
- }
-
- return true;
- }
-
- function getChecksum($ccnum)
- {
- $len = strlen($ccnum);
- if (!is_long($len / 2)) {
- $weight = 2;
- $digit = $ccnum[0];
- } elseif (is_long($len / 2)) {
- $weight = 1;
- $digit = $ccnum[0] * 2;
- }
- if ($digit > 9) {
- $digit = $digit - 9;
- }
- $i = 1;
- $checksum = $digit;
- while ($i < $len) {
- if ($ccnum[$i] != ' ') {
- $digit = $ccnum[$i] * $weight;
- $weight = ($weight == 1) ? 2 : 1;
- if ($digit > 9) {
- $digit = $digit - 9;
- }
- $checksum += $digit;
- }
- $i++;
- }
-
- return $checksum;
- }
-
- function getCardType($ccnum)
- {
- $sum = $this->getChecksum($ccnum);
- $l = strlen($ccnum);
-
- // Screen checksum.
- if (($sum % 10) != 0) {
- return false;
- }
-
- // Check for Visa.
- if ((($l == 16) || ($l == 13)) &&
- ($ccnum[0] == 4)) {
- return 'visa';
- }
-
- // Check for MasterCard.
- if (($l == 16) &&
- ($ccnum[0] == 5) &&
- ($ccnum[1] >= 1) &&
- ($ccnum[1] <= 5)) {
- return 'mastercard';
- }
-
- // Check for Amex.
- if (($l == 15) &&
- ($ccnum[0] == 3) &&
- (($ccnum[1] == 4) || ($ccnum[1] == 7))) {
- return 'amex';
- }
-
- // Check for Discover (Novus).
- if (strlen($ccnum) == 16 &&
- substr($ccnum, 0, 4) == '6011') {
- return 'discover';
- }
-
- // If we got this far, then no card matched.
- return 'unknown';
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Credit card number"));
- }
-
-}
-
-class Horde_Form_Type_obrowser extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- return true;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Relationship browser"));
- }
-
-}
-
-class Horde_Form_Type_dblookup extends Horde_Form_Type_enum {
-
- function init($dsn, $sql, $prompt = null)
- {
- $values = array();
- $db = DB::connect($dsn);
- if (!is_a($db, 'PEAR_Error')) {
- // Set DB portability options.
- switch ($db->phptype) {
- case 'mssql':
- $db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM);
- break;
- default:
- $db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS);
- }
-
- $col = $db->getCol($sql);
- if (!is_a($col, 'PEAR_Error')) {
- $values = Horde_Array::combine($col, $col);
- }
- }
- parent::init($values, $prompt);
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Database lookup"),
- 'params' => array(
- 'dsn' => array('label' => _("DSN (see http://pear.php.net/manual/en/package.database.db.intro-dsn.php)"),
- 'type' => 'text'),
- 'sql' => array('label' => _("SQL statement for value lookups"),
- 'type' => 'text'),
- 'prompt' => array('label' => _("Prompt text"),
- 'type' => 'text'))
- );
- }
-
-}
-
-class Horde_Form_Type_figlet extends Horde_Form_Type {
-
- var $_text;
- var $_font;
-
- function init($text, $font)
- {
- $this->_text = $text;
- $this->_font = $font;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- if (empty($value) && $var->isRequired()) {
- $message = _("This field is required.");
- return false;
- }
-
- if (String::lower($value) != String::lower($this->_text)) {
- $message = _("The text you entered did not match the text on the screen.");
- return false;
- }
-
- return true;
- }
-
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Figlet CAPTCHA"),
- 'params' => array(
- 'text' => array('label' => _("Text"),
- 'type' => 'text'),
- 'font' => array('label' => _("Figlet font"),
- 'type' => 'text'))
- );
- }
-
-}
-
-class Horde_Form_Type_invalid extends Horde_Form_Type {
-
- var $message;
-
- function init($message)
- {
- $this->message = $message;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- return false;
- }
-
-}
-
-/**
- * This class represents a single form variable that may be rendered as one or
- * more form fields.
- *
- * @author Robert E. Coyle <robertecoyle@hotmail.com>
- * @package Horde_Form
- */
-class Horde_Form_Variable {
-
- /**
- * The form instance this variable is assigned to.
- *
- * @var Horde_Form
- */
- var $form;
-
- /**
- * A short description of this variable's purpose.
- *
- * @var string
- */
- var $humanName;
-
- /**
- * The internally used name.
- *
- * @var string
- */
- var $varName;
-
- /**
- * A {@link Horde_Form_Type} instance.
- *
- * @var Horde_Form_Type
- */
- var $type;
-
- /**
- * Whether this is a required variable.
- *
- * @var boolean
- */
- var $required;
-
- /**
- * Whether this is a readonly variable.
- *
- * @var boolean
- */
- var $readonly;
-
- /**
- * A long description of the variable's purpose, special instructions, etc.
- *
- * @var string
- */
- var $description;
-
- /**
- * The variable help text.
- *
- * @var string
- */
- var $help;
-
- /**
- * Whether this is an array variable.
- *
- * @var boolean
- */
- var $_arrayVal;
-
- /**
- * The default value.
- *
- * @var mixed
- */
- var $_defValue = null;
-
- /**
- * A {@link Horde_Form_Action} instance.
- *
- * @var Horde_Form_Action
- */
- var $_action;
-
- /**
- * Whether this variable is disabled.
- *
- * @var boolean
- */
- var $_disabled = false;
-
- /**
- * TODO
- *
- * @var boolean
- */
- var $_autofilled = false;
-
- /**
- * Whether this is a hidden variable.
- *
- * @var boolean
- */
- var $_hidden = false;
-
- /**
- * TODO
- *
- * @var array
- */
- var $_options = array();
-
- /**
- * Variable constructor.
- *
- * @param string $humanName A short description of the variable's
- * purpose.
- * @param string $varName The internally used name.
- * @param Horde_Form_Type $type A {@link Horde_Form_Type} instance.
- * @param boolean $required Whether this is a required variable.
- * @param boolean $readonly Whether this is a readonly variable.
- * @param string $description A long description of the variable's
- * purpose, special instructions, etc.
- */
- function Horde_Form_Variable($humanName, $varName, $type, $required,
- $readonly = false, $description = null)
- {
- $this->humanName = $humanName;
- $this->varName = $varName;
- $this->type = $type;
- $this->required = $required;
- $this->readonly = $readonly;
- $this->description = $description;
- $this->_arrayVal = (strpos($varName, '[]') !== false);
- }
-
- /**
- * Assign this variable to the specified form.
- *
- * @param Horde_Form $form The form instance to assign this variable to.
- */
- function setFormOb($form)
- {
- $this->form = $form;
- }
-
- /**
- * Sets a default value for this variable.
- *
- * @param mixed $value A variable value.
- */
- function setDefault($value)
- {
- $this->_defValue = $value;
- }
-
- /**
- * Returns this variable's default value.
- *
- * @return mixed This variable's default value.
- */
- function getDefault()
- {
- return $this->_defValue;
- }
-
- /**
- * Assigns an action to this variable.
- *
- * Example:
- * <code>
- * $v = $form->addVariable('My Variable', 'var1', 'text', false);
- * $action = new Horde_Form_Action_submit;
- * $v->setAction($action);
- * </code>
- *
- * @param Horde_Form_Action $action A {@link Horde_Form_Action} instance.
- */
- function setAction($action)
- {
- $this->_action = $action;
- }
-
- /**
- * Returns whether this variable has an attached action.
- *
- * @return boolean True if this variable has an attached action.
- */
- function hasAction()
- {
- return !is_null($this->_action);
- }
-
- /**
- * Makes this a hidden variable.
- */
- function hide()
- {
- $this->_hidden = true;
- }
-
- /**
- * Returns whether this is a hidden variable.
- *
- * @return boolean True if this a hidden variable.
- */
- function isHidden()
- {
- return $this->_hidden;
- }
-
- /**
- * Disables this variable.
- */
- function disable()
- {
- $this->_disabled = true;
- }
-
- /**
- * Returns whether this variable is disabled.
- *
- * @return boolean True if this variable is disabled.
- */
- function isDisabled()
- {
- return $this->_disabled;
- }
-
- /**
- * Return the short description of this variable.
- *
- * @return string A short description
- */
- function getHumanName()
- {
- return $this->humanName;
- }
-
- /**
- * Returns the internally used variable name.
- *
- * @return string This variable's internal name.
- */
- function getVarName()
- {
- return $this->varName;
- }
-
- /**
- * Returns this variable's type.
- *
- * @return Horde_Form_Type This variable's {@link Horde_Form_Type}
- * instance.
- */
- function getType()
- {
- return $this->type;
- }
-
- /**
- * Returns whether this is a required variable.
- *
- * @return boolean True if this is a required variable.
- */
- function isRequired()
- {
- return $this->required;
- }
-
- /**
- * Returns whether this is a readonly variable.
- *
- * @return boolean True if this a readonly variable.
- */
- function isReadonly()
- {
- return $this->readonly;
- }
-
- /**
- * Returns the possible values of this variable.
- *
- * @return array The possible values of this variable or null.
- */
- function getValues()
- {
- return $this->type->values;
- }
-
- /**
- * Returns whether this variable has a long description.
- *
- * @return boolean True if this variable has a long description.
- */
- function hasDescription()
- {
- return !empty($this->description);
- }
-
- /**
- * Returns this variable's long description.
- *
- * @return string This variable's long description.
- */
- function getDescription()
- {
- return $this->description;
- }
-
- /**
- * Returns whether this is an array variable.
- *
- * @return boolean True if this an array variable.
- */
- function isArrayVal()
- {
- return $this->_arrayVal;
- }
-
- /**
- * Returns whether this variable is to upload a file.
- *
- * @return boolean True if variable is to upload a file.
- */
- function isUpload()
- {
- return ($this->type instanceof Horde_Form_Type_file);
- }
-
- /**
- * Assigns a help text to this variable.
- *
- * @param string $help The variable help text.
- */
- function setHelp($help)
- {
- $this->form->_help = true;
- $this->help = $help;
- }
-
- /**
- * Returns whether this variable has some help text assigned.
- *
- * @return boolean True if this variable has a help text.
- */
- function hasHelp()
- {
- return !empty($this->help);
- }
-
- /**
- * Returns the help text of this variable.
- *
- * @return string This variable's help text.
- */
- function getHelp()
- {
- return $this->help;
- }
-
- /**
- * Sets a variable option.
- *
- * @param string $option The option name.
- * @param mixed $val The option's value.
- */
- function setOption($option, $val)
- {
- $this->_options[$option] = $val;
- }
-
- /**
- * Returns a variable option's value.
- *
- * @param string $option The option name.
- *
- * @return mixed The option's value.
- */
- function getOption($option)
- {
- return isset($this->_options[$option]) ? $this->_options[$option] : null;
- }
-
- /**
- * Processes the submitted value of this variable according to the rules of
- * the variable type.
- *
- * @param Variables $vars The {@link Variables} instance of the submitted
- * form.
- * @param mixed $info A variable passed by reference that will be
- * assigned the processed value of the submitted
- * variable value.
- *
- * @return mixed Depending on the variable type.
- */
- function getInfo($vars, &$info)
- {
- return $this->type->getInfo($vars, $this, $info);
- }
-
- /**
- * Returns whether this variable if it had the "trackchange" option set
- * has actually been changed.
- *
- * @param Variables $vars The {@link Variables} instance of the submitted
- * form.
- *
- * @return boolean Null if this variable doesn't have the "trackchange"
- * option set or the form wasn't submitted yet. A boolean
- * indicating whether the variable was changed otherwise.
- */
- function wasChanged($vars)
- {
- if (!$this->getOption('trackchange')) {
- return null;
- }
- $old = $vars->get('__old_' . $this->getVarName());
- if (is_null($old)) {
- return null;
- }
- return $old != $vars->get($this->getVarName());
- }
-
- /**
- * Validates this variable.
- *
- * @param Variables $vars The {@link Variables} instance of the submitted
- * form.
- * @param string $message A variable passed by reference that will be
- * assigned a descriptive error message if
- * validation failed.
- *
- * @return boolean True if the variable validated.
- */
- function validate($vars, &$message)
- {
- if ($this->_arrayVal) {
- $vals = $this->getValue($vars);
- if (!is_array($vals)) {
- if ($this->required) {
- $message = _("This field is required.");
- return false;
- } else {
- return true;
- }
- }
- foreach ($vals as $i => $value) {
- if ($value === null && $this->required) {
- $message = _("This field is required.");
- return false;
- } else {
- if (!$this->type->isValid($this, $vars, $value, $message)) {
- return false;
- }
- }
- }
- } else {
- $value = $this->getValue($vars);
- return $this->type->isValid($this, $vars, $value, $message);
- }
-
- return true;
- }
-
- /**
- * Returns the submitted or default value of this variable.
- * If an action is attached to this variable, the value will get passed to
- * the action object.
- *
- * @param Variables $vars The {@link Variables} instance of the submitted
- * form.
- * @param integer $index If the variable is an array variable, this
- * specifies the array element to return.
- *
- * @return mixed The variable or element value.
- */
- function getValue($vars, $index = null)
- {
- if ($this->_arrayVal) {
- $name = str_replace('[]', '', $this->varName);
- } else {
- $name = $this->varName;
- }
- $value = $vars->getExists($name, $wasset);
-
- if (!$wasset) {
- $value = $this->getDefault();
- }
-
- if ($this->_arrayVal && !is_null($index)) {
- if (!$wasset && !is_array($value)) {
- $return = $value;
- } else {
- $return = isset($value[$index]) ? $value[$index] : null;
- }
- } else {
- $return = $value;
- }
-
- if ($this->hasAction()) {
- $this->_action->setValues($vars, $return, $this->_arrayVal);
- }
-
- return $return;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * @package Horde_Form
- */
-
-/**
- * The Horde_Form_Renderer class provides HTML and other renderings of
- * forms for the Horde_Form:: package.
- *
- * $Horde: incubator/Horde_Form/Horde/Form/Renderer.php,v 1.7 2007/09/16 19:51:08 chuck Exp $
- *
- * Copyright 2001-2007 Robert E. Coyle <robertecoyle@hotmail.com>
- * Copyright 2005-2007 Matt Warden <mwarden@gmail.com>
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @author Robert E. Coyle <robertecoyle@hotmail.com>
- * @author Matt Warden <mwarden@gmail.com>
- * @package Horde_Form
- */
-abstract class Horde_Form_Renderer {
-
- var $_name;
- var $_requiredLegend = false;
- var $_helpMarker = '?';
- var $_onLoadJS = array();
- var $_showHeader = true;
- var $_cols = 2;
- var $_varRenderer = null;
- var $_firstField = null;
- var $_stripedRows = true;
-
- protected $_submit = array();
- protected $_reset = false;
-
- /**
- * Does the title of the form contain HTML? If so, you are responsible for
- * doing any needed escaping/sanitization yourself. Otherwise the title
- * will be run through htmlspecialchars() before being output.
- *
- * @var boolean
- */
- var $_encodeTitle = true;
-
- /**
- * Construct a new Horde_Form_Renderer::.
- *
- * @param array $params This is a hash of renderer-specific parameters.
- * Possible keys:<code>
- * 'encode_title': @see $_encodeTitle</code>
- */
- function __construct($params = array())
- {
- if (isset($params['encode_title'])) {
- $this->encodeTitle($params['encode_title']);
- }
-
- $this->_varRenderer = new Horde_Form_VarRenderer_Xhtml;
- }
-
- abstract public function renderActive($form, $action, $method = 'get', $enctype = null, $focus = true);
-
- public function setButtons($submit, $reset = false)
- {
- if ($submit === true || is_null($submit) || empty($submit)) {
- /* Default to 'Submit'. */
- $submit = array(_("Submit"));
- } elseif (!is_array($submit)) {
- /* Default to array if not passed. */
- $submit = array($submit);
- }
- /* Only if $reset is strictly true insert default 'Reset'. */
- if ($reset === true) {
- $reset = _("Reset");
- }
-
- $this->_submit = $submit;
- $this->_reset = $reset;
-
- return $this;
- }
-
- public function addButtons($buttons)
- {
- if (!is_array($buttons)) {
- $buttons = array($buttons);
- }
-
- $this->_submit = array_merge($this->_submit, $buttons);
- }
-
- public function showHeader($bool)
- {
- $this->_showHeader = $bool;
- }
-
- /**
- * Sets or returns whether the form title should be encoded with
- * htmlspecialchars().
- *
- * @param boolean $encode If true, the form title gets encoded. If false
- * the title can contain HTML, but the class user
- * is responsible to encode any special characters.
- *
- * @return boolean Whether the form title should be encoded.
- */
- function encodeTitle($encode = null)
- {
- if (!is_null($encode)) {
- $this->_encodeTitle = $encode;
- }
- return $this->_encodeTitle = $encode;
- }
-
-}
+++ /dev/null
-<?php
-/**
- */
-class Horde_Form_Renderer_Xhtml extends Horde_Form_Renderer {
-
- protected $_enctype = 'multipart/form-data';
-
- function _renderSectionTabs($form)
- {
- /* If javascript is not available, do not render tabs. */
- if (!$GLOBALS['browser']->hasFeature('javascript')) {
- return;
- }
-
- $open_section = $form->getOpenSection();
-
- /* Add the javascript for the toggling the sections. */
- Horde::addScriptFile('form_sections.js', 'horde', true);
- echo '<script type="text/javascript">' . "\n" .
- sprintf('var sections_%1$s = new Horde_Form_Sections(\'%1$s\', \'%2$s\');',
- $form->getName(),
- $open_section) .
- '</script>';
-
- /* Loop through the sections and print out a tab for each. */
- echo "<div class=\"tabset\">\n";
- $js = array();
- foreach ($form->_sections as $section => $val) {
- $class = ($section == $open_section) ? ' class="activeTab"' : '';
- $tabid = htmlspecialchars($form->getName() . '_tab_' . $section);
- $js[$linkid] = sprintf('sections_%s.toggle(\'%s\'); return false;"',
- $form->getName(),
- $section);
- printf('<div%s id="%s"><a href="#" id="%s">%s%s</a></div>' . "\n",
- $class,
- $tabid,
- '_tablink_' . $section,
- $form->getSectionImage($section),
- $form->getSectionDesc($section));
- }
- echo "</div>\n";
-
- // This doesn't help a whole lot now, but if there is a way to
- // buffer output of JS, then we can keep JS separated from
- // markup, whereas before the onclicks were assigned as an
- // HTML attribute.
- echo '<script type="text/javascript">' . "\n";
- echo 'if (document.getElementById) {' . "\n";
- echo ' addEvent(window, \'load\', function() {' . "\n";
- foreach ($js as $id => $onclick) {
- $line = '
-if (document.getElementById(%1$s)){
- document.getElementById(%1$s).onclick = function() {
- %2$s
- };
-}';
- printf($line, $id, $onclick);
- }
- echo ' });}</script>' . "\n";
- }
-
- function _renderSectionBegin($form, $section)
- {
- // Stripe alternate rows if that option is turned on.
- if ($this->_stripedRows) {
- Horde::addScriptFile('stripe.js', 'horde', true);
- $class = 'striped';
- } else {
- $class = '';
- }
-
- $open_section = $form->getOpenSection();
- if (empty($open_section)) {
- $open_section = '__base';
- }
-
- // include a general class name for styling purposes. also helps select
- // ULs, which only get a className currently if they are striped.
- printf('<fieldset id="%s" class="%s form-section %s">',
- htmlspecialchars($form->getName() . '_section_' . $section),
- ($open_section == $section ? 'form-sectionshown' : 'form-sectionhidden'),
- $class);
- }
-
- function _renderSectionEnd()
- {
- echo '</fieldset>';
- }
-
- function preserveVarByPost($vars, $varname, $alt_varname = '')
- {
- $value = $vars->getExists($varname, $wasset);
-
- if ($alt_varname) {
- $varname = $alt_varname;
- }
-
- if ($wasset) {
- $this->_preserveVarByPost($varname, $value);
- }
- }
-
- function _preserveVarByPost($varname, $value)
- {
- if (is_array($value)) {
- foreach ($value as $id => $val) {
- $this->_preserveVarByPost($varname . '[' . $id . ']', $val);
- }
- } else {
- $varname = htmlspecialchars($varname);
- $value = htmlspecialchars($value);
- printf('<input type="hidden" id="%1$s" name="%1$s" value="%2$s" />'."\n",
- $varname,
- $value);
- }
- }
-
- function listFormVars($form)
- {
- $variables = $form->getVariables(true, true);
- $vars = array();
- if ($variables) {
- foreach ($variables as $var) {
- if (is_object($var)) {
- if (!$var->isReadonly()) {
- $vars[$var->getVarName()] = 1;
- }
- } else {
- $vars[$var] = 1;
- }
- }
- }
- require_once 'Horde/NLS.php';
- echo '<input type="hidden" name="_formvars" value="'
- . htmlspecialchars(serialize($vars), ENT_QUOTES, NLS::getCharset())
- . '" />';
- }
-
- public function renderActive($form, $action, $method = 'get', $enctype = null, $focus = true)
- {
- $this->_name = $form->getName();
-
- echo "<form class=\"horde-form\" action=\"$action\" method=\"$method\""
- . (empty($this->_name) ? '' : ' id="' . $this->_name. '"')
- . (is_null($this->_enctype) ? '' : ' enctype="' . $this->_enctype . '"')
- . ">\n";
- echo Util::formInput();
-
- $this->listFormVars($form);
-
- if (!empty($this->_name)) {
- $this->_preserveVarByPost('formname', $this->_name);
- }
-
- if ($form->useToken()) {
- $this->_preserveVarByPost($this->_name . '_formToken', Horde_Token::generateId($this->_name));
- }
-
- if (count($form->getSections())) {
- $this->_preserveVarByPost('__formOpenSection', $form->getOpenSection());
- }
-
- $vars = $form->getVars();
-
- $variables = $form->getVariables();
- foreach ($variables as $var) {
- if ($var->getOption('trackchange')) {
- $varname = $var->getVarName();
- $this->preserveVarByPost($vars, $varname, '__old_' . $varname);
- }
- }
-
- foreach ($form->getHiddenVariables() as $var) {
- $this->preserveVarByPost($vars, $var->getVarName());
- }
-
- $this->_renderBeginActive($form->getTitle());
- $this->_renderForm($form, true);
- $this->submit($this->_submit, $this->_reset);
-
- echo "\n</fieldset>\n</form>\n";
- if ($focus && !empty($this->_firstField)) {
- echo '<script type="text/javascript">
-try {
- document.getElementById("'. $this->_firstField .'").focus();
-} catch (e) {}
-</script>
-';
- }
- }
-
- function renderInactive($form)
- {
- $this->_name = $form->getName();
- $this->_renderBeginInactive($form->getTitle());
- $this->_renderForm($form, false);
- }
-
- function _renderForm($form, $active)
- {
- $vars = $form->getVars();
-
- /* If help is present 3 columns are needed. */
- $this->_cols = $form->hasHelp() ? 3 : 2;
-
- $variables = $form->getVariables(false);
-
- /* Check for a form token error. */
- if (($tokenError = $form->getError('_formToken')) !== null) {
- printf('<p class="form-error">%s</p>'."\n", $tokenError);
- }
-
- $error_section = null;
- reset($variables);
- if (count($variables) > 1 || key($variables) != '__base') {
- $this->_renderSectionTabs($form);
- }
-
- foreach ($variables as $section_id => $section) {
- $this->_renderSectionBegin($form, $section_id);
- foreach ($section as $var) {
- switch (get_class($var->type)) {
- case 'Horde_Form_Type_header':
- $this->_renderHeader($var->getHumanName(), $form->getError($var->getVarName()));
- break;
-
- case 'Horde_Form_Type_description':
- $this->_renderDescription($var->getHumanName());
- break;
-
- case 'Horde_Form_Type_spacer':
- $this->_renderSpacer();
- break;
-
- default:
- $isInput = ($active && !$var->isReadonly());
- $format = $isInput ? 'Input' : 'Display';
- $begin = "_renderVar${format}Begin";
- $end = "_renderVar${format}End";
-
- $this->$begin($form, $var);
- echo $this->_varRenderer->render($form, $var, $vars, $isInput);
- $this->$end($form, $var);
-
- /* Print any javascript if actions present. */
- if ($var->hasAction()) {
- $var->_action->printJavaScript();
- }
-
- /* Keep first field. */
- if ($active && empty($this->_firstField) && !$var->isReadonly()
- && !$var->isHidden()) {
- $this->_firstField = $var->getVarName();
- }
-
- /* Keep section with first error. */
- if (is_null($error_section) && $form->getError($var)) {
- $error_section = $section_id;
- }
- }
- }
-
- $this->_renderSectionEnd();
- }
-
- if (!is_null($error_section)) {
- echo '<script type="text/javascript">' .
- "\n" . sprintf('sections_%s.toggle(\'%s\');',
- $form->getName(),
- $error_section) .
- "\n</script>\n";
- }
-
- echo '</fieldset>' . $this->_varRenderer->renderEnd();
- }
-
- function submit($submit = null, $reset = false)
- {
- if (is_null($submit) || empty($submit)) {
- $submit = _("Submit");
- }
- if ($reset === true) {
- $reset = _("Reset");
- }
- $this->_renderSubmit($submit, $reset);
- }
-
- /**
- * Implementation specific begin function.
- */
- function _renderBeginActive($name)
- {
- echo '<fieldset class="horde-form" id="fieldset_' . htmlspecialchars($this->_name) . '">'."\n";
- if ($this->_showHeader) {
- $this->_renderSectionHeader($name);
- }
- if ($this->_requiredLegend) {
- echo '<div class="form-error-example">' . $this->_requiredMarker
- . ' = ' . _("Required Field") . '</div>'."\n";
- }
- }
-
- /**
- * Implementation specific begin function.
- */
- function _renderBeginInactive($name)
- {
- echo '<fieldset class="horde-form" id="fieldset_' . htmlspecialchars($this->_name) . '">';
- if ($this->_showHeader) {
- $this->_renderSectionHeader($name);
- }
- }
-
- function _renderHeader($header, $error = '')
- {
- echo '<div class="form-header">'. $header . '</div>';
- if (!empty($error)) {
- echo '<div class="form-error">'. $error . '</div>';
- }
- }
-
- function _renderDescription($description)
- {
- echo '<div class="form-description">'. $description . '</div>';
- }
-
- function _renderSpacer()
- {
- // TODO: fix this later so we're not inserting nonsemantic elements just for spacing
- // ... maybe append form-spacer to class of next or previous element
- echo '<div class="form-spacer"> </div>';
- }
-
- function _renderSubmit($submit, $reset)
- {
- echo '<fieldset class="form-buttons">'."\n";
- if (!is_array($submit)) $submit = array($submit);
- foreach ($submit as $submitbutton) {
- echo '<input class="button" name="submitbutton" type="submit"';
- // allow for default-value submit buttons (e.g. _renderSubmit(""))
- if (!empty($submitbutton)) {
- echo ' value="'. $submitbutton .'"';
- }
- echo ' />'."\n";
- }
- if (!empty($reset)) {
- echo '<input class="button" name="resetbutton" type="reset"
- value="'. $reset .'" />'."\n";
- }
- }
-
- /**
- * Renders the beginning of an writeable form entry, including the label
- * and any form error related to this variable.
- *
- * @access private
- * @author Matt Warden <mwarden@gmail.com>
- * @author Robert E. Coyle <robertecoyle@hotmail.com>
- */
- function _renderVarInputBegin($form, $var, $readonly = false)
- {
- // get error message for variable, if any
- $message = $form->getError($var);
- // if no message, then no error
- $isvalid = empty($message);
-
- $classnames = 'form-input'
- . (!$isvalid ? ' form-error' : '')
- . ($var->isRequired() ? ' form-required' : '');
-
- echo '<div class="', $classnames, '">';
-
- if (!$isvalid) {
- echo '<p class="form-error">', $message, '</p>', "\n";
- }
-
- printf('<label%s>%s</label>',
- ($readonly ? '' : ' for="'. $var->getVarName() .'"'),
- $var->getHumanName());
- }
-
- /**
- * Renders the end of an writeable form entry, including any form notes
- * and help info.
- *
- * @access private
- * @author Matt Warden <mwarden@gmail.com>
- * @author Robert E. Coyle <robertecoyle@hotmail.com>
- */
- function _renderVarInputEnd($form, $var)
- {
- /* Display any help for the field. */
- if ($var->hasHelp()) {
- global $registry;
- if (isset($registry) && is_a($registry, 'Registry')) {
- $help = Help::link($GLOBALS['registry']->getApp(), $var->getHelp());
- } else {
- $help = @htmlspecialchars($var->getHelp());
- }
- echo '<p class="form-hint">', $help, '</p>';
- }
-
- /* Display any description for the field. */
- if ($var->hasDescription()) {
- echo '<div class="form-note"><p>', $var->getDescription(), '</p></div>';
- } else {
- echo '<br class="clear" />';
- }
-
- echo '</div>';
- }
-
- /**
- * Renders the beginning of a readonly form entry.
- *
- * @access private
- * @author Matt Warden <mwarden@gmail.com>
- * @author Robert E. Coyle <robertecoyle@hotmail.com>
- */
- function _renderVarDisplayBegin($form, $var)
- {
- return $this->_renderVarInputBegin($form, $var, true);
- }
-
- /**
- * Renders the end of a readonly form entry. Help and notes are not
- * applicable.
- *
- * @access private
- * @author Matt Warden <mwarden@gmail.com>
- * @author Robert E. Coyle <robertecoyle@hotmail.com>
- */
- function _renderVarDisplayEnd()
- {
- echo '</div>';
- }
-
- /**
- * Renders the header for the section.
- *
- * @access private
- * @author Matt Warden <mwarden@gmail.com>
- * @author Robert E. Coyle <robertecoyle@hotmail.com>
- * @param string $title section header title
- */
- function _renderSectionHeader($title)
- {
- if (!empty($title)) {
- echo "\n".'<legend>';
- echo $this->_encodeTitle ? htmlspecialchars($title) : $title;
- echo '</legend>'."\n";
- }
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Horde_Form_Type Class
- *
- * @author Robert E. Coyle <robertecoyle@hotmail.com>
- * @package Horde_Form
- */
-abstract class Horde_Form_Type {
-
- protected $_properties = array();
-
- /**
- * Type constructor. Takes a hash of key/value parameters.
- *
- * @param array $properties Any type properties to initialize.
- */
- public function __construct($properties = array())
- {
- $this->_properties = array();
- $vars = array_keys(get_object_vars($this));
- foreach ($vars as $var) {
- $this->_properties[] = substr($var, 1);
- }
-
- if ($this->_properties && $properties) {
- $properties = array_combine(array_slice($this->_properties, 0, count($properties)), $properties);
- foreach ($properties as $property => $value) {
- $this->__set($property, $value);
- }
- }
- }
-
- /**
- */
- abstract public function isValid($var, $vars, $value, &$message);
-
- /**
- */
- function getInfo($vars, $var, &$info)
- {
- $info = $var->getValue($vars);
- }
-
- /**
- */
- public function onSubmit()
- {
- }
-
- /**
- * To get the 'escape' property of a type:
- * $escape = $type->escape;
- * If the property is not set this will return null.
- *
- * @param string $property The property to retrieve.
- */
- protected function __get($property)
- {
- if (in_array($property, $this->_properties)) {
- $prop = '_' . $property;
- return $this->$prop;
- }
-
- return null;
- }
-
- /**
- * To set the 'escape' property of a type to true:
- * $type->escape = true;
- *
- * @param string $property The property name to set.
- * @param mixed $value The property value.
- */
- protected function __set($property, $value)
- {
- if (in_array($property, $this->_properties)) {
- $prop = '_' . $property;
- $this->$prop = $value;
- }
- }
-
- /**
- * To check if a type has a property named 'escape':
- * if (isset($type->escape)) { ... }
- *
- * @param string $property Property name to check existance of.
- */
- protected function __isset($property)
- {
- $prop = '_' . $property;
- return isset($this->$prop);
- }
-
- /**
- * To unset a Type property named 'escape':
- * unset($type->escape);
- *
- * @param string $property Property name to unset.
- */
- protected function __unset($property)
- {
- $prop = '_' . $property;
- unset($this->$prop);
- }
-
-}
+++ /dev/null
-<?php
-/**
- * An on/off value
- */
-class Horde_Form_Type_Boolean extends Horde_Form_Type {
-
- public function isValid($var, $vars, $value, &$message)
- {
- return true;
- }
-
- public function getInfo($vars, $var, &$info)
- {
- $info = String::lower($vars->get($var->name)) == 'on';
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Color
- */
-class Horde_Form_Type_Color extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- if ($var->required && empty($value)) {
- $message = _("This field is required.");
- return false;
- }
-
- if (empty($value) || preg_match('/^#([0-9a-z]){6}$/i', $value)) {
- return true;
- }
-
- $message = _("This field must contain a color code in the RGB Hex format, for example '#1234af'.");
- return false;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Credit card number
- */
-class Horde_Form_Type_creditcard extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- if (empty($value) && $var->required) {
- $message = _("This field is required.");
- return false;
- }
-
- if (!empty($value)) {
- /* getCardType() will also verify the checksum. */
- $type = $this->getCardType($value);
- if ($type === false || $type == 'unknown') {
- $message = _("This does not seem to be a valid card number.");
- return false;
- }
- }
-
- return true;
- }
-
- function getChecksum($ccnum)
- {
- $len = strlen($ccnum);
- if (!is_long($len / 2)) {
- $weight = 2;
- $digit = $ccnum[0];
- } elseif (is_long($len / 2)) {
- $weight = 1;
- $digit = $ccnum[0] * 2;
- }
- if ($digit > 9) {
- $digit = $digit - 9;
- }
- $i = 1;
- $checksum = $digit;
- while ($i < $len) {
- if ($ccnum[$i] != ' ') {
- $digit = $ccnum[$i] * $weight;
- $weight = ($weight == 1) ? 2 : 1;
- if ($digit > 9) {
- $digit = $digit - 9;
- }
- $checksum += $digit;
- }
- $i++;
- }
-
- return $checksum;
- }
-
- function getCardType($ccnum)
- {
- $sum = $this->getChecksum($ccnum);
- $l = strlen($ccnum);
-
- // Screen checksum.
- if (($sum % 10) != 0) {
- return false;
- }
-
- // Check for Visa.
- if ((($l == 16) || ($l == 13)) &&
- ($ccnum[0] == 4)) {
- return 'visa';
- }
-
- // Check for MasterCard.
- if (($l == 16) &&
- ($ccnum[0] == 5) &&
- ($ccnum[1] >= 1) &&
- ($ccnum[1] <= 5)) {
- return 'mastercard';
- }
-
- // Check for Amex.
- if (($l == 15) &&
- ($ccnum[0] == 3) &&
- (($ccnum[1] == 4) || ($ccnum[1] == 7))) {
- return 'amex';
- }
-
- // Check for Discover (Novus).
- if (strlen($ccnum) == 16 &&
- substr($ccnum, 0, 4) == '6011') {
- return 'discover';
- }
-
- // If we got this far, then no card matched.
- return 'unknown';
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Date
- */
-class Horde_Form_Type_Date extends Horde_Form_Type {
-
- var $_format = '%a %d %B';
-
- public function isValid($var, $vars, $value, &$message)
- {
- $valid = true;
-
- if ($var->required) {
- $valid = strlen(trim($value)) > 0;
-
- if (!$valid) {
- $message = _("This field is required.");
- }
- }
-
- return $valid;
- }
-
- public static function getAgo($timestamp)
- {
- if ($timestamp === null) {
- return '';
- }
-
- $diffdays = Date_Calc::dateDiff(date('j', $timestamp),
- date('n', $timestamp),
- date('Y', $timestamp),
- date('j'), date('n'), date('Y'));
-
- /* An error occured. */
- if ($diffdays == -1) {
- return;
- }
-
- $ago = $diffdays * Date_Calc::compareDates(date('j', $timestamp),
- date('n', $timestamp),
- date('Y', $timestamp),
- date('j'), date('n'),
- date('Y'));
- if ($ago < -1) {
- return sprintf(_(" (%s days ago)"), $diffdays);
- } elseif ($ago == -1) {
- return _(" (yesterday)");
- } elseif ($ago == 0) {
- return _(" (today)");
- } elseif ($ago == 1) {
- return _(" (tomorrow)");
- } else {
- return sprintf(_(" (in %s days)"), $diffdays);
- }
- }
-
- public function getFormattedTime($timestamp, $format = null, $showago = true)
- {
- if (empty($format)) {
- $format = $this->_format;
- }
- if (!empty($timestamp)) {
- return strftime($format, $timestamp) . ($showago ? self::getAgo($timestamp) : '');
- } else {
- return '';
- }
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Date and time selection
- */
-class Horde_Form_Type_DateTime extends Horde_Form_Type {
-
- var $_date;
- var $_time;
-
- /**
- * Return the date supplied as a Horde_Date object.
- *
- * @param integer $start_year The first available year for input.
- * @param integer $end_year The last available year for input.
- * @param boolean $picker Do we show the DHTML calendar?
- * @param integer $format_in The format to use when sending the date
- * for storage. Defaults to Unix epoch.
- * Similar to the strftime() function.
- * @param integer $format_out The format to use when displaying the
- * date. Similar to the strftime() function.
- * @param boolean $show_seconds Include a form input for seconds.
- */
- function init($start_year = '', $end_year = '', $picker = true,
- $format_in = null, $format_out = '%x', $show_seconds = false)
- {
- $this->_date = new Horde_Form_Type_Date();
- $this->_date->init($start_year, $end_year, $picker, $format_in, $format_out);
-
- $this->_time = new Horde_Form_Type_Time();
- $this->_time->init($show_seconds);
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- if ($var->required) {
- return $this->_date->isValid($var, $vars, $value, $message) &&
- $this->_time->isValid($var, $vars, $value, $message);
- }
- return true;
- }
-
- function getInfo(&$vars, &$var, &$info)
- {
- /* If any component is empty consider it a bad date and return the
- * default. */
- $value = $var->getValue($vars);
- if ($this->emptyDateArray($value) == 1 || $this->emptyTimeArray($value)) {
- $info = $var->getDefault();
- return;
- }
-
- $date = $this->getDateOb($value);
- $time = $this->getTimeOb($value);
- $date->hour = $time->hour;
- $date->min = $time->min;
- $date->sec = $time->sec;
- if (is_null($this->format_in)) {
- $info = $date->timestamp();
- } else {
- $info = $date->strftime($this->format_in);
- }
- }
-
- function __get($property)
- {
- if ($property == 'show_seconds') {
- return $this->_time->$property;
- } else {
- return $this->_date->$property;
- }
- }
-
- function __set($property, $value)
- {
- if ($property == 'show_seconds') {
- $this->_time->$property = $value;
- } else {
- $this->_date->$property = $value;
- }
- }
-
- function checktime($hour, $minute, $second)
- {
- return $this->_time->checktime($hour, $minute, $second);
- }
-
- function getTimeOb($time_in)
- {
- return $this->_time->getTimeOb($time_in);
- }
-
- function getTimeParts($time_in)
- {
- return $this->_time->getTimeParts($time_in);
- }
-
- function emptyTimeArray($time)
- {
- return $this->_time->emptyTimeArray($time);
- }
-
- function emptyDateArray($date)
- {
- return $this->_date->emptyDateArray($date);
- }
-
- function getDateParts($date_in)
- {
- return $this->_date->getDateParts($date_in);
- }
-
- function getDateOb($date_in)
- {
- return $this->_date->getDateOb($date_in);
- }
-
- function formatDate($date)
- {
- if ($date === null) {
- return '';
- }
- return $this->_date->formatDate($date);
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Email
- */
-class Horde_Form_Type_Email extends Horde_Form_Type {
-
- /**
- * Allow multiple addresses?
- *
- * @type boolean
- * @var boolean
- */
- var $_allow_multi = false;
-
- /**
- * Strip domain from the address?
- *
- * @type boolean
- * @var boolean
- */
- var $_strip_domain = false;
-
- /**
- * Make displayed email addresses clickable?
- *
- * @type boolean
- * @var boolean
- */
- var $_link_compose = false;
-
- /**
- * The compose name to use
- *
- * @type text
- * @var boolean
- */
- var $_link_name;
-
- /**
- * The character to separate multiple email addresses
- *
- * @type text
- * @var string
- */
- var $_delimiters = ',';
-
- /**
- * Contact the target mail server to see if the email address is deliverable?
- *
- * @type boolean
- * @var boolean
- */
- var $_check_smtp = false;
-
- /**
- */
- public function init($allow_multi = false, $strip_domain = false,
- $link_compose = false, $link_name = null,
- $delimiters = ',')
- {
- $this->_allow_multi = $allow_multi;
- $this->_strip_domain = $strip_domain;
- $this->_link_compose = $link_compose;
- $this->_link_name = $link_name;
- $this->_delimiters = $delimiters;
- }
-
- /**
- */
- public function isValid($var, $vars, $value, &$message)
- {
- // Split into individual addresses.
- $emails = $this->splitEmailAddresses($value);
-
- // Check for too many.
- if (!$this->_allow_multi && count($emails) > 1) {
- $message = _("Only one email address is allowed.");
- return false;
- }
-
- // Check for all valid and at least one non-empty.
- $nonEmpty = 0;
- foreach ($emails as $email) {
- if (!strlen($email)) {
- continue;
- }
- if (!$this->validateEmailAddress($email)) {
- $message = sprintf(_("\"%s\" is not a valid email address."), $email);
- return false;
- }
- ++$nonEmpty;
- }
-
- if (!$nonEmpty && $var->required) {
- if ($this->_allow_multi) {
- $message = _("You must enter at least one email address.");
- } else {
- $message = _("You must enter an email address.");
- }
- return false;
- }
-
- return true;
- }
-
- /**
- * Explodes an RFC 2822 string, ignoring a delimiter if preceded
- * by a "\" character, or if the delimiter is inside single or
- * double quotes.
- *
- * @param string $string The RFC 822 string.
- *
- * @return array The exploded string in an array.
- */
- public function splitEmailAddresses($string)
- {
- $quotes = array('"', "'");
- $emails = array();
- $pos = 0;
- $in_quote = null;
- $in_group = false;
- $prev = null;
-
- if (!strlen($string)) {
- return array();
- }
-
- $char = $string[0];
- if (in_array($char, $quotes)) {
- $in_quote = $char;
- } elseif ($char == ':') {
- $in_group = true;
- } elseif (strpos($this->_delimiters, $char) !== false) {
- $emails[] = '';
- $pos = 1;
- }
-
- for ($i = 1, $iMax = strlen($string); $i < $iMax; ++$i) {
- $char = $string[$i];
- if (in_array($char, $quotes)) {
- if ($prev !== '\\') {
- if ($in_quote === $char) {
- $in_quote = null;
- } elseif (is_null($in_quote)) {
- $in_quote = $char;
- }
- }
- } elseif ($in_group) {
- if ($char == ';') {
- $emails[] = substr($string, $pos, $i - $pos + 1);
- $pos = $i + 1;
- $in_group = false;
- }
- } elseif ($char == ':') {
- $in_group = true;
- } elseif (strpos($this->_delimiters, $char) !== false &&
- $prev !== '\\' &&
- is_null($in_quote)) {
- $emails[] = substr($string, $pos, $i - $pos);
- $pos = $i + 1;
- }
- $prev = $char;
- }
-
- if ($pos != $i) {
- /* The string ended without a delimiter. */
- $emails[] = substr($string, $pos, $i - $pos);
- }
-
- return $emails;
- }
-
- /**
- * RFC(2)822 Email Parser.
- *
- * By Cal Henderson <cal@iamcal.com>
- * This code is licensed under a Creative Commons Attribution-ShareAlike 2.5 License
- * http://creativecommons.org/licenses/by-sa/2.5/
- *
- * http://code.iamcal.com/php/rfc822/
- *
- * http://iamcal.com/publish/articles/php/parsing_email
- *
- * Revision 4
- *
- * @param string $email An individual email address to validate.
- *
- * @return boolean
- */
- public function validateEmailAddress($email)
- {
- static $comment_regexp, $email_regexp;
- if ($comment_regexp === null) {
- $this->_defineValidationRegexps($comment_regexp, $email_regexp);
- }
-
- // We need to strip comments first (repeat until we can't find
- // any more).
- while (true) {
- $new = preg_replace("!$comment_regexp!", '', $email);
- if (strlen($new) == strlen($email)){
- break;
- }
- $email = $new;
- }
-
- // Now match what's left.
- $result = (bool)preg_match("!^$email_regexp$!", $email);
- if ($result && $this->_check_smtp) {
- $result = $this->validateEmailAddressSmtp($email);
- }
-
- return $result;
- }
-
- /**
- * Attempt partial delivery of mail to an address to validate it.
- *
- * @param string $email An individual email address to validate.
- *
- * @return boolean
- */
- public function validateEmailAddressSmtp($email)
- {
- list(, $maildomain) = explode('@', $email, 2);
-
- // Try to get the real mailserver from MX records.
- if (function_exists('getmxrr') &&
- @getmxrr($maildomain, $mxhosts, $mxpriorities)) {
- // MX record found.
- array_multisort($mxpriorities, $mxhosts);
- $mailhost = $mxhosts[0];
- } else {
- // No MX record found, try the root domain as the mail
- // server.
- $mailhost = $maildomain;
- }
-
- $fp = @fsockopen($mailhost, 25, $errno, $errstr, 5);
- if (!$fp) {
- return false;
- }
-
- // Read initial response.
- fgets($fp, 4096);
-
- // HELO
- fputs($fp, "HELO $mailhost\r\n");
- fgets($fp, 4096);
-
- // MAIL FROM
- fputs($fp, "MAIL FROM: <root@example.com>\r\n");
- fgets($fp, 4096);
-
- // RCPT TO - gets the result we want.
- fputs($fp, "RCPT TO: <$email>\r\n");
- $result = trim(fgets($fp, 4096));
-
- // QUIT
- fputs($fp, "QUIT\r\n");
- fgets($fp, 4096);
- fclose($fp);
-
- return substr($result, 0, 1) == '2';
- }
-
- /**
- * RFC(2)822 Email Parser.
- *
- * By Cal Henderson <cal@iamcal.com>
- * This code is licensed under a Creative Commons Attribution-ShareAlike 2.5 License
- * http://creativecommons.org/licenses/by-sa/2.5/
- *
- * http://code.iamcal.com/php/rfc822/
- *
- * http://iamcal.com/publish/articles/php/parsing_email
- *
- * Revision 4
- *
- * @param string &$comment The regexp for comments.
- * @param string &$addr_spec The regexp for email addresses.
- */
- protected function _defineValidationRegexps(&$comment, &$addr_spec)
- {
- /**
- * NO-WS-CTL = %d1-8 / ; US-ASCII control characters
- * %d11 / ; that do not include the
- * %d12 / ; carriage return, line feed,
- * %d14-31 / ; and white space characters
- * %d127
- * ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
- * DIGIT = %x30-39
- */
- $no_ws_ctl = "[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]";
- $alpha = "[\\x41-\\x5a\\x61-\\x7a]";
- $digit = "[\\x30-\\x39]";
- $cr = "\\x0d";
- $lf = "\\x0a";
- $crlf = "($cr$lf)";
-
- /**
- * obs-char = %d0-9 / %d11 / ; %d0-127 except CR and
- * %d12 / %d14-127 ; LF
- * obs-text = *LF *CR *(obs-char *LF *CR)
- * text = %d1-9 / ; Characters excluding CR and LF
- * %d11 /
- * %d12 /
- * %d14-127 /
- * obs-text
- * obs-qp = "\" (%d0-127)
- * quoted-pair = ("\" text) / obs-qp
- */
- $obs_char = "[\\x00-\\x09\\x0b\\x0c\\x0e-\\x7f]";
- $obs_text = "($lf*$cr*($obs_char$lf*$cr*)*)";
- $text = "([\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f]|$obs_text)";
- $obs_qp = "(\\x5c[\\x00-\\x7f])";
- $quoted_pair = "(\\x5c$text|$obs_qp)";
-
- /**
- * obs-FWS = 1*WSP *(CRLF 1*WSP)
- * FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
- * obs-FWS
- * ctext = NO-WS-CTL / ; Non white space controls
- * %d33-39 / ; The rest of the US-ASCII
- * %d42-91 / ; characters not including "(",
- * %d93-126 ; ")", or "\"
- * ccontent = ctext / quoted-pair / comment
- * comment = "(" *([FWS] ccontent) [FWS] ")"
- * CFWS = *([FWS] comment) (([FWS] comment) / FWS)
- *
- * @note: We translate ccontent only partially to avoid an
- * infinite loop. Instead, we'll recursively strip comments
- * before processing the input.
- */
- $wsp = "[\\x20\\x09]";
- $obs_fws = "($wsp+($crlf$wsp+)*)";
- $fws = "((($wsp*$crlf)?$wsp+)|$obs_fws)";
- $ctext = "($no_ws_ctl|[\\x21-\\x27\\x2A-\\x5b\\x5d-\\x7e])";
- $ccontent = "($ctext|$quoted_pair)";
- $comment = "(\\x28($fws?$ccontent)*$fws?\\x29)";
- $cfws = "(($fws?$comment)*($fws?$comment|$fws))";
- $cfws = "$fws*";
-
- /**
- * atext = ALPHA / DIGIT / ; Any character except controls,
- * "!" / "#" / ; SP, and specials.
- * "$" / "%" / ; Used for atoms
- * "&" / "'" /
- * "*" / "+" /
- * "-" / "/" /
- * "=" / "?" /
- * "^" / "_" /
- * "`" / "{" /
- * "|" / "}" /
- * "~"
- * atom = [CFWS] 1*atext [CFWS]
- */
- $atext = "($alpha|$digit|[\\x21\\x23-\\x27\\x2a\\x2b\\x2d\\x2e\\x3d\\x3f\\x5e\\x5f\\x60\\x7b-\\x7e])";
- $atom = "($cfws?$atext+$cfws?)";
-
- /**
- * qtext = NO-WS-CTL / ; Non white space controls
- * %d33 / ; The rest of the US-ASCII
- * %d35-91 / ; characters not including "\"
- * %d93-126 ; or the quote character
- * qcontent = qtext / quoted-pair
- * quoted-string = [CFWS]
- * DQUOTE *([FWS] qcontent) [FWS] DQUOTE
- * [CFWS]
- * word = atom / quoted-string
- */
- $qtext = "($no_ws_ctl|[\\x21\\x23-\\x5b\\x5d-\\x7e])";
- $qcontent = "($qtext|$quoted_pair)";
- $quoted_string = "($cfws?\\x22($fws?$qcontent)*$fws?\\x22$cfws?)";
- $word = "($atom|$quoted_string)";
-
- /**
- * obs-local-part = word *("." word)
- * obs-domain = atom *("." atom)
- */
- $obs_local_part = "($word(\\x2e$word)*)";
- $obs_domain = "($atom(\\x2e$atom)*)";
-
- /**
- * dot-atom-text = 1*atext *("." 1*atext)
- * dot-atom = [CFWS] dot-atom-text [CFWS]
- */
- $dot_atom_text = "($atext+(\\x2e$atext+)*)";
- $dot_atom = "($cfws?$dot_atom_text$cfws?)";
-
- /**
- * domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
- * dcontent = dtext / quoted-pair
- * dtext = NO-WS-CTL / ; Non white space controls
- *
- * %d33-90 / ; The rest of the US-ASCII
- * %d94-126 ; characters not including "[",
- * ; "]", or "\"
- */
- $dtext = "($no_ws_ctl|[\\x21-\\x5a\\x5e-\\x7e])";
- $dcontent = "($dtext|$quoted_pair)";
- $domain_literal = "($cfws?\\x5b($fws?$dcontent)*$fws?\\x5d$cfws?)";
-
- /**
- * local-part = dot-atom / quoted-string / obs-local-part
- * domain = dot-atom / domain-literal / obs-domain
- * addr-spec = local-part "@" domain
- */
- $local_part = "($dot_atom|$quoted_string|$obs_local_part)";
- $domain = "($dot_atom|$domain_literal|$obs_domain)";
- $addr_spec = "($local_part\\x40$domain)";
- }
-
-}
-
-/**
- * Email with confirmation
- */
-class Horde_Form_Type_EmailConfirm extends Horde_Form_Type {
-
- public function isValid($var, $vars, $value, &$message)
- {
- if ($var->required && empty($value['original'])) {
- $message = _("This field is required.");
- return false;
- }
-
- if ($value['original'] != $value['confirm']) {
- $message = _("Email addresses must match.");
- return false;
- } else {
- require_once 'Horde/MIME.php';
- $parsed_email = MIME::parseAddressList($value['original'], false,
- true);
- if (is_a($parsed_email, 'PEAR_Error')) {
- $message = $parsed_email->getMessage();
- return false;
- }
- if (count($parsed_email) > 1) {
- $message = _("Only one email address allowed.");
- return false;
- }
- if (empty($parsed_email[0]->mailbox)) {
- $message = _("You did not enter a valid email address.");
- return false;
- }
- }
-
- return true;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Choose one from a list of values
- */
-class Horde_Form_Type_Enum extends Horde_Form_Type {
-
- /**
- * List of values to choose from
- *
- * @type stringlist
- * @var array
- */
- protected $_values = array();
-
- /**
- * Initial prompt value, if any
- *
- * @type text
- * @var string
- */
- protected $_prompt;
-
- /**
- */
- public function isValid($var, $vars, $value, &$message)
- {
- if ($var->required && $value == '' && !isset($this->_values[$value])) {
- $message = _("This field is required.");
- return false;
- }
-
- if (count($this->_values) == 0 || isset($this->_values[$value]) ||
- ($this->_prompt && empty($value))) {
- return true;
- }
-
- $message = _("Invalid data.");
- return false;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Integer
- */
-class Horde_Form_Type_Int extends Horde_Form_Type {
-
- public function isValid($var, $vars, $value, &$message)
- {
- if ($var->required && empty($value) && ((string)(int)$value !== $value)) {
- $message = _("This field is required.");
- return false;
- }
-
- if (empty($value) || preg_match('/^[0-9]+$/', $value)) {
- return true;
- }
-
- $message = _("This field may only contain integers.");
- return false;
- }
-
-}
+++ /dev/null
-<?php
-class Horde_Form_Type_invalid extends Horde_Form_Type {
-
- var $message;
-
- function init($message)
- {
- $this->message = $message;
- }
-
- function isValid($var, $vars, $value, &$message)
- {
- return false;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Number
- */
-class Horde_Form_Type_Number extends Horde_Form_Type {
-
- /**
- */
- protected $_fraction;
-
- public function isValid($var, $vars, $value, &$message)
- {
- if ($var->required && empty($value) && ((string)(double)$value !== $value)) {
- $message = _("This field is required.");
- return false;
- } elseif (empty($value)) {
- return true;
- }
-
- /* If matched, then this is a correct numeric value. */
- if (preg_match($this->_getValidationPattern(), $value)) {
- return true;
- }
-
- $message = _("This field must be a valid number.");
- return false;
- }
-
- /**
- */
- public function getInfo($vars, $var, &$info)
- {
- $value = $vars->get($var->name);
- $linfo = NLS::getLocaleInfo();
- $value = str_replace($linfo['mon_thousands_sep'], '', $value);
- $info = str_replace($linfo['mon_decimal_point'], '.', $value);
- }
-
- /**
- */
- protected function _getValidationPattern()
- {
- static $pattern = '';
- if (!empty($pattern)) {
- return $pattern;
- }
-
- /* Get current locale information. */
- $linfo = NLS::getLocaleInfo();
-
- /* Build the pattern. */
- $pattern = '(-)?';
-
- /* Only check thousands separators if locale has any. */
- if (!empty($linfo['mon_thousands_sep'])) {
- /* Regex to check for correct thousands separators (if any). */
- $pattern .= '((\d+)|((\d{0,3}?)([' . $linfo['mon_thousands_sep'] . ']\d{3})*?))';
- } else {
- /* No locale thousands separator, check for only digits. */
- $pattern .= '(\d+)';
- }
- /* If no decimal point specified default to dot. */
- if (empty($linfo['mon_decimal_point'])) {
- $linfo['mon_decimal_point'] = '.';
- }
- /* Regex to check for correct decimals (if any). */
- if (empty($this->_fraction)) {
- $fraction = '*';
- } else {
- $fraction = '{0,' . $this->_fraction . '}';
- }
- $pattern .= '([' . $linfo['mon_decimal_point'] . '](\d' . $fraction . '))?';
-
- /* Put together the whole regex pattern. */
- $pattern = '/^' . $pattern . '$/';
-
- return $pattern;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Octal
- */
-class Horde_Form_Type_Octal extends Horde_Form_Type {
-
- function isValid($var, $vars, $value, &$message)
- {
- if ($var->required && empty($value) && ((string)(int)$value !== $value)) {
- $message = _("This field is required.");
- return false;
- }
-
- if (empty($value) || preg_match('/^[0-7]+$/', $value)) {
- return true;
- }
-
- $message = _("This field may only contain octal values.");
- return false;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Password
- */
-class Horde_Form_Type_Password extends Horde_Form_Type {
-
- public function isValid($var, $vars, $value, &$message)
- {
- $valid = true;
-
- if ($var->required) {
- $valid = strlen(trim($value)) > 0;
-
- if (!$valid) {
- $message = _("This field is required.");
- }
- }
-
- return $valid;
- }
-
-}
-
-
-/**
- * Password with confirmation
- */
-class Horde_Form_Type_passwordConfirm extends Horde_Form_Type {
-
- public function isValid($var, $vars, $value, &$message)
- {
- if ($var->required && empty($value['original'])) {
- $message = _("This field is required.");
- return false;
- }
-
- if ($value['original'] != $value['confirm']) {
- $message = _("Passwords must match.");
- return false;
- }
-
- return true;
- }
-
- function getInfo($vars, $var, &$info)
- {
- $value = $vars->get($var->name);
- $info = $value['original'];
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Phone number
- */
-class Horde_Form_Type_Phone extends Horde_Form_Type {
-
- public function isValid($var, $vars, $value, &$message)
- {
- $valid = true;
-
- if ($var->required) {
- $valid = strlen(trim($value)) > 0;
- if (!$valid) {
- $message = _("This field is required.");
- }
- } else {
- $valid = preg_match('/^\+?[\d()\-\/ ]*$/', $value);
- if (!$valid) {
- $message = _("You must enter a valid phone number, digits only with an optional '+' for the international dialing prefix.");
- }
- }
-
- return $valid;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Mobile Phone Number
- */
-class Horde_Form_Type_Phone_Mobile extends Horde_Form_Type_Phone {}
+++ /dev/null
-<?php
-/**
- * Set of values
- */
-class Horde_Form_Type_Set extends Horde_Form_Type {
-
- /**
- * Values
- *
- * @type stringlist
- * @var string
- */
- protected $_values;
-
- public function isValid($var, $vars, $value, &$message)
- {
- if (count($this->_values) == 0 || count($value) == 0) {
- return true;
- }
- foreach ($value as $item) {
- if (!isset($this->_values[$item])) {
- $error = true;
- break;
- }
- }
- if (!isset($error)) {
- return true;
- }
-
- $message = _("Invalid data.");
- return false;
- }
-
-}
-
-class Horde_Form_Type_multienum extends Horde_Form_Type_enum {
-
- public function isValid($var, $vars, $value, &$message)
- {
- if (is_array($value)) {
- foreach ($value as $val) {
- if (!$this->isValid($var, $vars, $val, $message)) {
- return false;
- }
- }
- return true;
- }
-
- if (empty($value) && ((string)(int)$value !== $value)) {
- if ($var->required) {
- $message = _("This field is required.");
- return false;
- } else {
- return true;
- }
- }
-
- if (count($this->_values) == 0 || isset($this->_values[$value])) {
- return true;
- }
-
- $message = _("Invalid data.");
- return false;
- }
-
-}
-
-class Horde_Form_Type_keyval_multienum extends Horde_Form_Type_multienum {
-
- function getInfo($vars, $var, &$info)
- {
- $value = $vars->get($var->name);
- $info = array();
- foreach ($value as $key) {
- $info[$key] = $this->_values[$key];
- }
- }
-
-}
+++ /dev/null
-<?php
-/**
- * String
- */
-class Horde_Form_Type_String extends Horde_Form_Type {
-
- /**
- * Validation regex
- *
- * @type string
- * @var string
- */
- protected $_regex;
-
- /**
- * Maximum length
- *
- * @type int
- * @var integer
- */
- protected $_maxlength;
-
- public function isValid($var, $vars, $value, &$message)
- {
- $valid = true;
-
- if (!empty($this->_maxlength) && String::length($value) > $this->_maxlength) {
- $valid = false;
- $message = sprintf(_("Value is over the maximum length of %s."), $this->_maxlength);
- } elseif ($var->required && empty($this->_regex)) {
- if (!($valid = strlen(trim($value)) > 0)) {
- $message = _("This field is required.");
- }
- } elseif (strlen($this->_regex)) {
- if (!($valid = preg_match($this->_regex, $value))) {
- $message = _("You must enter a valid value.");
- }
- }
-
- return $valid;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Time
- */
-class Horde_Form_Type_Time extends Horde_Form_Type {
-
- public function isValid($var, $vars, $value, &$message)
- {
- if ($var->required && empty($value) && ((string)(double)$value !== $value)) {
- $message = _("This field is required.");
- return false;
- }
-
- if (empty($value) || preg_match('/^[0-2]?[0-9]:[0-5][0-9]$/', $value)) {
- return true;
- }
-
- $message = _("This field may only contain numbers and the colon.");
- return false;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * The Horde_Form_VarRenderer:: class provides base functionality for
- * other Horde_Form elements.
- *
- * $Horde: incubator/Horde_Form/Horde/Form/VarRenderer.php,v 1.8 2008/01/02 11:12:48 jan Exp $
- *
- * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
- * Copyright 2005-2007 Matt Warden <mwarden@gmail.com>
- *
- * See the enclosed file LICENSE for license information (LGPL).
- *
- * @author Jason M. Felice <jason.m.felice@gmail.com>
- * @package Horde_Form
- */
-class Horde_Form_VarRenderer {
-
- /**
- * Renders a variable.
- *
- * @param Horde_Form $form Reference to a Horde_Form instance,
- * or null if none is available.
- * @param Horde_Form_Variable $var Reference to a Horde_Form_Variable.
- * @param Variables $vars A Variables instance.
- * @param boolean $isInput Whether this is an input field.
- */
- public function render($form, $var, $vars, $isInput = false)
- {
- if ($isInput) {
- $state = 'Input';
- } else {
- $state = 'Display';
- }
- $method = "_renderVar${state}_" . str_replace('Horde_Form_Type_', '', get_class($var->type));
- if (!method_exists($this, $method)) {
- $method = "_renderVar${state}Default";
- }
- return $this->$method($form, $var, $vars);
- }
-
- /**
- * Finishes rendering after all fields are output.
- */
- public function renderEnd()
- {
- return '';
- }
-
-}
+++ /dev/null
-<?php
-/**
- * The Horde_Form_VarRenderer_Xhtml:: class renders variables as Xhtml.
- *
- * $Horde: incubator/Horde_Form/Horde/Form/VarRenderer/Xhtml.php,v 1.14 2008/01/02 11:12:48 jan Exp $
- *
- * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
- * Copyright 2005 Matt Warden <mwarden@gmail.com>
- *
- * See the enclosed file LICENSE for license information (LGPL).
- *
- * @author Jason M. Felice <jason.m.felice@gmail.com>
- * @package Horde_Form
- */
-class Horde_Form_VarRenderer_Xhtml extends Horde_Form_VarRenderer {
-
- protected $_onLoadJS = array();
-
- /**
- * Handles the end of rendering of variables; writes onload JavaScript.
- *
- * @access public
- * @author ?
- * @return string the javascript to execute, and its container script tags,
- * or and empty string if there is nothing to execute onload
- */
- public function renderEnd()
- {
- if (count($this->_onLoadJS)) {
- return "<script type=\"text/javascript\">" .
- "<!--\n" . implode("\n", $this->_onLoadJS) . "\n// -->\n" .
- "</script>";
- } else {
- return '';
- }
- }
-
- function _renderVarInputDefault($form, $var, $vars)
- {
- throw new Horde_Form_Exception('Unknown variable type:' . get_class($var->type));
- }
-
- function _renderVarInput_number($form, $var, $vars)
- {
- $value = $var->getValue($vars);
- if ($var->type->fraction) {
- $value = sprintf('%01.' . $var->type->fraction . 'f', $value);
- }
- $linfo = NLS::getLocaleInfo();
- /* Only if there is a mon_decimal_point do the
- * substitution. */
- if (!empty($linfo['mon_decimal_point'])) {
- $value = str_replace('.', $linfo['mon_decimal_point'], $value);
- }
- return sprintf(' <input type="text" class="form-input-number" name="%1$s" id="%1$s" value="%2$s"%3$s />',
- $var->getVarName(),
- $value,
- $this->_getActionScripts($form, $var)
- );
- }
-
- function _renderVarInput_int($form, $var, $vars)
- {
- return sprintf(' <input type="text" class="form-input-int" name="%1$s" id="%1$s" value="%2$s"%3$s />',
- $var->getVarName(),
- $value = $var->getValue($vars),
- $this->_getActionScripts($form, $var)
- );
- }
-
- function _renderVarInput_octal($form, $var, $vars)
- {
- return sprintf('<input type="text" class="form-input-octal" name="%1$s" id="%1$s" value="%2$s"%3$s />',
- $var->getVarName(),
- sprintf('0%o', octdec($var->getValue($vars))),
- $this->_getActionScripts($form, $var)
- );
- }
-
- function _renderVarInput_intlist($form, $var, $vars)
- {
- return sprintf('<input type="text" class="form-input-intlist" name="%1$s" id="%1$s" value="%2$s"%3$s />',
- $var->getVarName(),
- $value = $var->getValue($vars),
- $this->_getActionScripts($form, $var)
- );
- }
-
- function _renderVarInput_text($form, $var, $vars)
- {
- return sprintf(
- '<input type="text" class="form-input-text%1$s" name="%2$s" '
- . 'id="%2$s" value="%3$s"%4$s%5$s%6$s />',
- ($var->isDisabled() ? ' form-input-disabled" ' : ''),
- $var->getVarName(),
- htmlspecialchars($var->getValue($vars), ENT_QUOTES, NLS::getCharset()),
- ($var->isDisabled() ? ' disabled="disabled" ' : ''),
- ($var->type->maxlength ? ' maxlength="' . $var->type->maxlength . '"' : ''),
- $this->_getActionScripts($form, $var)
- );
- }
-
- function _renderVarInput_stringlist($form, $var, $vars)
- {
- return sprintf(
- '<input type="text" class="form-input-stringlist" name="%s" value="%s"%s />',
- $var->getVarName(),
- $value = $var->getValue($vars),
- $this->_getActionScripts($form, $var)
- );
- }
-
- function _renderVarInput_phone($form, $var, $vars)
- {
- return sprintf(
- '<input type="text" class="form-input-phone" name="%1$s" id="%1$s" value="%2$s" %3$s%4$s />',
- $var->getVarName(),
- htmlspecialchars($var->getValue($vars), ENT_QUOTES, NLS::getCharset()),
- ($var->isDisabled() ? ' disabled="disabled" ' : ''),
- $this->_getActionScripts($form, $var)
- );
- }
-
- function _renderVarInput_cellphone($form, $var, $vars)
- {
- return $this->_renderVarInput_phone($form, $var, $vars);
- }
-
- function _renderVarInput_ipaddress($form, $var, $vars)
- {
- return sprintf(' <input type="text" class="form-input-ipaddress" name="%1$s" id="%1$s" value="%2$s" %3$s%4$s />',
- $var->getVarName(),
- htmlspecialchars($var->getValue($vars), ENT_QUOTES, NLS::getCharset()),
- $var->isDisabled() ? ' disabled="disabled" ' : '',
- $this->_getActionScripts($form, $var)
- );
- }
-
- function _renderVarInput_file($form, $var, $vars)
- {
- $file = $var->getValue($vars);
- return sprintf(' <input type="file" class="form-input-file" name="%1$s" id="%1$s"%2$s />',
- $var->getVarName(),
- $this->_getActionScripts($form, $var));
- }
-
- /**
- * @todo Show image dimensions in the width/height boxes.
- */
- function _renderVarInput_image($form, $var, $vars)
- {
- $varname = $var->getVarName();
- $image = $var->getValue($vars);
-
- /* Check if existing image data is being loaded. */
- $var->type->loadImageData($image);
-
- Horde::addScriptFile('image.js', 'horde', true);
- $graphics_dir = $GLOBALS['registry']->getImageDir('horde');
- $img_dir = $graphics_dir . '/image';
-
- $html = '';
-
- /* Check if there is existing img information stored. */
- if (isset($image['img'])) {
- /* Hidden tag to store the preview image filename. */
- $html = sprintf(' <input type="hidden" name="%1$s" id="%1$s" value="%2$s" />',
- $varname . '[img]',
- htmlspecialchars($image['img'], ENT_QUOTES, NLS::getCharset()));
-
- /* Unserialize the img information to get the full array. */
- $image['img'] = @unserialize($image['img']);
- }
-
- /* Output the input tag. */
- if (empty($image['img'])) {
- $js = "
-var p = document.getElementById('" . $varname . "[preview]');
-o = '\\\\'; a = '/';
-tmp = '' + document.getElementById('" . $varname . "[new]').value;
-if (tmp) {
- while (tmp.indexOf(o) > -1) {
- pos = tmp.indexOf(o);
- tmp = '' + (tmp.substring(0, pos) + a + tmp.substring((pos + o.length), tmp.length));
- }
- p.src = 'file:///' + tmp;
- p.alt = '" . addslashes(_("If you see this message but no image, the image you want to upload can't be displayed by your browser.")) . "';
-}";
- $browser = Horde_Browser::singleton();
- if ($browser->isBrowser('msie')) {
- $html .= sprintf(' <input type="file" class="form-input-file" name="%1$s" id="%1$s" onchange="%2$s" />',
- $varname . '[new]',
- $js);
- } else {
- $html .= sprintf(' <input type="file" class="form-input-file" name="%1$s" id="%1$s"
- onclick="window.setTimeout(\'document.getElementById(\\\'%1$s\\\').blur();\', 5);"
- onblur="%2$s" />',
- $varname . '[new]',
- $js);
- }
- } else {
- $html .= sprintf(' <input type="file" class="form-input-file" name="%1$s" id="%1$s" />',
- $varname . '[new]');
- }
-
- /* Output the button to upload/reset the image. */
- if ($var->type->show_upload) {
- $html .= ' ';
- $html .= sprintf(' <input class="form-button-upload" name="%1$s" id="%1$s" type="submit" value="%2$s" /> ',
- '_do_' . $varname,
- _("Upload"));
- }
-
- if (empty($image['img'])) {
- /* No image information stored yet, show a blank
- * preview. */
- $html .= Horde::img('tree/blank.png', _("Preview"),
- 'class="form-image-preview-blank" id="' . $varname . '[preview]"',
- $graphics_dir);
- } else {
- /* Image information stored, show preview, add buttons for
- * image manipulation. */
- $html .= '<br />';
- $img = Horde::url($GLOBALS['registry']->get('webroot', 'horde') . '/services/images/view.php');
- if (isset($image['img']['vfs_id'])) {
- /* Calling an image from VFS. */
- $img = Util::addParameter($img, array('f' => $image['img']['vfs_id'],
- 's' => 'vfs',
- 'p' => $image['img']['vfs_path']));
- } else {
- /* Calling an image from a tmp directory (uploads). */
- $img = Util::addParameter($img, 'f', $image['img']['file']);
- }
-
- // TODO: possible to change to unobtrusive JS?
- /* Rotate 270. */
- $html .= Horde::link('#', '', '', '', 'showImage(\'' . Util::addParameter($img, array('a' => 'rotate', 'v' => '270')) . '\', \'_p_' . $varname . '\', true);') . Horde::img('rotate-270.png', _("Rotate Left"), '', $img_dir) . '</a>';
-
- /* Rotate 180. */
- $html .= Horde::link('#', '', '', '', 'showImage(\'' . Util::addParameter($img, array('a' => 'rotate', 'v' => '180')) . '\', \'_p_' . $varname . '\', true);') . Horde::img('rotate-180.png', _("Rotate 180"), '', $img_dir) . '</a>';
-
- /* Rotate 90. */
- $html .= Horde::link('#', '', '', '', 'showImage(\'' . Util::addParameter($img, array('a' => 'rotate', 'v' => '90')) . '\', \'_p_' . $varname . '\', true);') . Horde::img('rotate-90.png', _("Rotate Right"), '', $img_dir) . '</a>';
-
- /* Flip image. */
- $html .= Horde::link('#', '', '', '', 'showImage(\'' . Util::addParameter($img, 'a', 'flip') . '\', \'_p_' . $varname . '\', true);') . Horde::img('flip.png', _("Flip"), '', $img_dir) . '</a>';
-
- /* Mirror image. */
- $html .= Horde::link('#', '', '', '', 'showImage(\'' . Util::addParameter($img, 'a', 'mirror') . '\', \'_p_' . $varname . '\', true);') . Horde::img('mirror.png', _("Mirror"), '', $img_dir) . '</a>';
-
- /* Apply grayscale. */
- $html .= Horde::link('#', '', '', '', 'showImage(\'' . Util::addParameter($img, 'a', 'grayscale') . '\', \'_p_' . $varname . '\', true);') . Horde::img('grayscale.png', _("Grayscale"), '', $img_dir) . '</a>';
-
- /* Resize width. */
- $html .= sprintf('%s <input type="text" class="form-input-resize" onchange="src=getResizeSrc(\'%s\', \'%s\');showImage(src, \'_p_%s\', true);" %s />',
- _("w:"),
- Util::addParameter($img, 'a', 'resize'),
- $varname,
- $varname,
- '_w_'. $varname);
-
- /* Resize height. */
- $html .= sprintf('%s <input type="text" class="form-input-resize" onchange="src=getResizeSrc(\'%s\', \'%s\');showImage(src, \'_p_%s\', true);" %s />',
- _("h:"),
- Util::addParameter($img, 'a', 'resize'),
- $varname,
- $varname,
- '_h_'. $varname);
-
- /* Apply fixed ratio resize. */
- $html .= Horde::link('#', '', '', '', 'src=getResizeSrc(\'' . Util::addParameter($img, 'a', 'resize') . '\', \'' . $varname . '\', \'1\');showImage(src, \'_p_' . $varname . '\', true);') . Horde::img('ratio.png', _("Fix ratio"), '', $img_dir) . '</a>';
-
- /* Keep also original if it has been requested. */
- if ($var->type->show_keeporig) {
- $html .= sprintf(' <input type="checkbox" class="form-input-checkbox" name="%s"%s />%s' . "\n",
- $varname . '[keep_orig]',
- !empty($image['keep_orig']) ? ' checked="checked"' : '',
- _("Keep original?"));
- }
-
- /* The preview image element. */
- $html .= '<br /><img src="' . $img . '" id="_p_' . $varname .'" />'."\n";
- }
-
- return $html;
- }
-
- function _renderVarInput_longtext($form, $var, $vars)
- {
- global $browser;
-
- $html = sprintf('<textarea class="form-input-longtext" id="%1$s" name="%1$s" '
- .'cols="%2$s" rows="%3$s"%4$s%5$s>%6$s</textarea>',
- $var->getVarName(),
- $var->type->cols,
- $var->type->rows,
- $this->_getActionScripts($form, $var),
- $var->isDisabled() ? ' disabled="disabled"' : '',
- htmlspecialchars($var->getValue($vars)));
-
- if ($var->type->hasHelper('rte') && $browser->hasFeature('rte')) {
- $editor = Horde_Editor::factory('Xinha', array('id' => $var->getVarName()));
- }
-
- if ($var->type->hasHelper() && $browser->hasFeature('javascript')) {
- $html .= '<div class="form-html-helper">';
- Horde::addScriptFile('open_html_helper.js', 'horde');
- $imgId = $var->getVarName() . 'ehelper';
- if ($var->type->hasHelper('emoticons')) {
- $html .= Horde::link('#', _("Emoticons"), '', '', 'openHtmlHelper(\'emoticons\', \'' . $var->getVarName() . '\'); return false;')
- . Horde::img('smile.png', _("Emoticons"), 'id="' . $imgId . '" align="middle"', $GLOBALS['registry']->getImageDir('horde') . '/emoticons')
- . '</a>'."\n";
- }
- $html .= '</div><div id="htmlhelper_' . $var->getVarName()
- . '" class="form-control"></div>'."\n";
- }
-
- return $html;
- }
-
- function _renderVarInput_countedtext($form, $var, $vars)
- {
- return sprintf('<textarea class="form-input-countedtext" id="%1$s" name="%1$s" '
- .'cols="%2$s" rows="%3$s"%4$s%5$s>%6$s</textarea>',
- $var->getVarName(),
- $var->type->cols,
- $var->type->rows,
- $this->_getActionScripts($form, $var),
- $var->isDisabled() ? ' disabled="disabled"' : '',
- $var->getValue($vars));
- }
-
- function _renderVarInput_address($form, $var, $vars)
- {
- return sprintf('<textarea class="form-input-address" id="%1$s" name="%1$s" '
- .'cols="%2$s" rows="%3$s"%4$s%5$s>%6$s</textarea>',
- $var->getVarName(),
- $var->type->cols,
- $var->type->rows,
- $this->_getActionScripts($form, $var),
- $var->isDisabled() ? ' disabled="disabled"' : '',
- $var->getValue($vars));
- }
-
- function _renderVarInput_date($form, $var, $vars)
- {
- return sprintf(' <input type="text" class="form-input-date" name="%1$s" id="%1$s" '
- .'value="%2$s"%3$s />',
- $var->getVarName(),
- $value = $var->getValue($vars),
- $this->_getActionScripts($form, $var));
- }
-
- function _renderVarInput_time($form, $var, $vars)
- {
- return sprintf(' <input type="text" class="form-input-time" name="%1$s" id="%1$s" '
- .'value="%2$s"%3$s />',
- $var->getVarName(),
- $value = $var->getValue($vars),
- $this->_getActionScripts($form, $var));
- }
-
- function _renderVarInput_hourminutesecond($form, $var, $vars)
- {
- $varname = $var->getVarName();
- $time = $var->type->getTimeParts($var->getValue($vars));
-
- /* Output hours. */
- $hours = array('' => _("hh"));
- for ($i = 0; $i <= 23; $i++) {
- $hours[sprintf('%02d', $i)] = $i;
- }
- $html = sprintf('<select name="%1$s[hour]" id="%1$s[hour]"%2$s>%3$s </select>',
- $varname,
- $this->_selectOptions($hours, $time['hour']),
- $this->_getActionScripts($form, $var));
-
- /* Output minutes. */
- $minutes = array('' => _("mm"));
- for ($i = 0; $i <= 59; $i++) {
- $minutes[sprintf('%02d', $i)] = $i;
- }
- $html .= sprintf('<select name="%1$s[minute]" id="%1$s[minute]"%2$s>%3$s </select>',
- $varname,
- $this->_selectOptions($minutes, $time['minute']),
- $this->_getActionScripts($form, $var));
-
- /* Return if seconds are not required. */
- if ($var->type->show_seconds) {
- /* Output seconds. */
- $seconds = array('' => _("ss"));
- for ($i = 0; $i <= 59; $i++) {
- $seconds[sprintf('%02d', $i)] = $i;
- }
- $html .= sprintf('<select name="%1$s[second]" id="%1$s[second]"%2$s>%3$s </select>',
- $varname,
- $this->_getActionScripts($form, $var),
- $this->_selectOptions($seconds, $time['second']));
- }
-
- return $html;
- }
-
- function _renderVarInput_monthyear($form, $var, $vars)
- {
- $dates = array();
- $dates['month'] = array('' => _("MM"),
- 1 => _("January"),
- 2 => _("February"),
- 3 => _("March"),
- 4 => _("April"),
- 5 => _("May"),
- 6 => _("June"),
- 7 => _("July"),
- 8 => _("August"),
- 9 => _("September"),
- 10 => _("October"),
- 11 => _("November"),
- 12 => _("December"));
- $dates['year'] = array('' => _("YYYY"));
- if ($var->type->start_year > $var->type->end_year) {
- for ($i = $var->type->start_year; $i >= $var->type->end_year; $i--) {
- $dates['year'][$i] = $i;
- }
- } else {
- for ($i = $var->type->start_year; $i <= $var->type->end_year; $i++) {
- $dates['year'][$i] = $i;
- }
- }
- $html = sprintf('<select name="%1$s" id="%1$s"%2$s>%3$s </select>',
- $var->type->getMonthVar($var),
- $this->_getActionScripts($form, $var),
- $this->_selectOptions($dates['month'], $vars->get($var->type->getMonthVar($var))));
-
- $html .= sprintf('<select name="%1$s" id="%1$s"%2$s>%3$s </select>',
- $var->type->getYearVar($var),
- $this->_getActionScripts($form, $var),
- $this->_selectOptions($dates['year'], $vars->get($var->type->getYearVar($var))));
-
- return $html;
- }
-
- function _renderVarInput_monthdayyear($form, $var, $vars)
- {
- $dates = array();
- $dates['month'] = array('' => _("MM"),
- '1' => _("January"),
- '2' => _("February"),
- '3' => _("March"),
- '4' => _("April"),
- '5' => _("May"),
- '6' => _("June"),
- '7' => _("July"),
- '8' => _("August"),
- '9' => _("September"),
- '10' => _("October"),
- '11' => _("November"),
- '12' => _("December"));
- $dates['day'] = array('' => _("DD"));
- for ($i = 1; $i <= 31; $i++) {
- $dates['day'][$i] = $i;
- }
- $dates['year'] = array('' => _("YYYY"));
- if ($var->type->start_year > $var->type->end_year) {
- for ($i = $var->type->start_year; $i >= $var->type->end_year; $i--) {
- $dates['year'][$i] = $i;
- }
- } else {
- for ($i = $var->type->start_year; $i <= $var->type->end_year; $i++) {
- $dates['year'][$i] = $i;
- }
- }
- $date = $var->type->getDateParts($var->getValue($vars));
-
- // TODO: use NLS to get the order right for the Rest Of The
- // World.
- $html = '';
- $date_parts = array('month', 'day', 'year');
- foreach ($date_parts as $part) {
- $varname = $var->getVarName() . '[' . $part . ']';
- $html .= sprintf('<select name="%1$s" id="%1$s"%2$s>%3$s </select>',
- $varname,
- $this->_getActionScripts($form, $var),
- $this->_selectOptions($dates[$part], $date[$part]));
- }
-
- if ($var->type->picker && $GLOBALS['browser']->hasFeature('javascript')) {
- Horde::addScriptFile('open_calendar.js', 'horde');
- $imgId = $var->getVarName() .'goto';
- $html .= '<div id="goto"></div>';
- $html .= Horde::link('#', _("Select a date"), '', '', 'openCalendar(\'' . $imgId . '\', \'' . $var->getVarName() . '\'); return false;')
- . Horde::img('calendar.png', _("Calendar"), 'id="' . $imgId . '" ', $GLOBALS['registry']->getImageDir('horde'))
- . '</a>';
- }
-
- return $html;
- }
-
- function _renderVarInput_datetime($form, $var, $vars)
- {
- return parent::_renderVarInput_monthdayyear($form, $var, $vars) .
- parent::_renderVarInput_hourminutesecond($form, $var, $vars);
- }
-
- function _renderVarInput_colorpicker($form, $var, $vars)
- {
- $html = '<div class="form-colorpicker">'
- . '<input type="text" maxlength="7" name="'
- . $var->getVarName() . '" id="' . $var->getVarName()
- . '" value="' . $var->getValue($vars) . '" />';
-
- if ($GLOBALS['browser']->hasFeature('javascript')) {
- Horde::addScriptFile('open_colorpicker.js', 'horde', true);
- $html .= Horde::img('blank.gif', '', array('class' => 'form-colorpicker-preview',
- 'id' => 'colordemo_' . $var->getVarName(),
- 'style' => 'background:' . $var->getValue($vars)), $GLOBALS['registry']->getImageDir('horde'))
- . Horde::link('#', _("Color Picker"), '', '', 'openColorPicker(\''. $var->getVarName() .'\'); return false;')
- . Horde::img('colorpicker.png', _("Color Picker"), '', $GLOBALS['registry']->getImageDir('horde')) . '</a>'
- . '<div id="colorpicker_' . $var->getVarName() . '" class="form-colorpicker-palette"></div>';
- }
-
- return $html . '</div>';
- }
-
- function _renderVarInput_sorter($form, $var, $vars)
- {
- global $registry;
-
- $varname = $var->getVarName();
- $instance = $var->type->instance;
-
- Horde::addScriptFile('sorter.js', 'horde', true);
-
- return ' <input type="hidden" name="'. $varname
- . '[array]" value="" id="'. $varname .'-array-" />'."\n"
- . ' <select class="leftFloat" multiple="multiple" size="'
- . $var->type->size . '" name="' . $varname
- . '[list]" onchange="' . $instance . '.deselectHeader();" '
- . ' id="'. $varname . '-list-">'
- . $var->type->getOptions($var->getValue($vars)) . ' </select><div class="leftFloat">'
- . Horde::link('#', _("Move up"), '', '', $instance . '.moveColumnUp(); return false;')
- . Horde::img('nav/up.png', _("Move up"), '', $registry->getImageDir('horde'))
- . '</a><br />'
- . Horde::link('#', _("Move up"), '', '', $instance . '.moveColumnDown(); return false;')
- . Horde::img('nav/down.png', _("Move down"), '', $registry->getImageDir('horde'))
- . '</a></div>'
- . '<script type="text/javascript">' . "\n"
- . sprintf('%1$s = new Horde_Form_Sorter(\'%1$s\', \'%2$s\', \'%3$s\');' . "\n",
- $instance, $varname, $var->type->header)
- . sprintf("%s.setHidden();\n</script>\n", $instance);
- }
-
- function _renderVarInput_assign($form, $var, $vars)
- {
- global $registry;
-
- Horde::addScriptFile('form_assign.js', 'horde', true);
-
- $name = $var->getVarName();
- $fname = $form->getName() . '.' . $name;
- $width = $var->type->width;
- $lhdr = (bool)$var->type->getHeader(0);
- $rhdr = (bool)$var->type->getHeader(1);
- $this->_onLoadJS[] = 'Horde_Form_Assign.setField(\'' . $fname . '\');';
-
- $html = '<div class="form-input-assign">'
- . ' <input type="hidden" name="' . $name . '__values" id="' . $name . '__values" />'
- . sprintf(' <select name="%1$s__left" id="%1$s__left" multiple="multiple" '
- .'size="%2$d" style="width:%3$s"%4$s>',
- $name, $var->type->size, $width,
- $lhdr ? ' onchange="Horde_Form_Assign.deselectHeaders(\'' . $fname . '\', 0);"' : '')
- . $var->type->getOptions(0, $fname)
- . ' </select>'
- . '<div><a href="" onclick="Horde_Form_Assign.move(\''. $fname .'\', 0); return false;">'
- . Horde::img('rhand.png', _("Add column"), null, $registry->getImageDir('horde'))
- . '</a><br /><a href="" onclick="Horde_Form_Assign.move(\''
- . $fname . '\', 1); return false;">'
- . Horde::img('lhand.png', _("Remove column"), null, $registry->getImageDir('horde'))
- . '</a></div>'
- . sprintf(' <select name="%s__right" multiple="multiple" size="%d" style="width:%s"%s>',
- $name, $size, $width,
- $rhdr ? ' onchange="Horde_Form_Assign.deselectHeaders(\'' . $fname . '\', 1);"' : '')
- . $var->type->getOptions(1, $fname)
- . ' </select></div>';
-
- return $html;
- }
-
- function _renderVarInput_invalid($form, $var, $vars)
- {
- return $this->_renderVarDisplay_invalid($form, $var, $vars);
- }
-
- function _renderVarInput_enum($form, $var, $vars)
- {
- $values = $var->getValues();
- $prompt = $var->type->prompt;
- $htmlchars = $var->getOption('htmlchars');
- if ($prompt) {
- $prompt = '<option value="">' . ($htmlchars ? htmlspecialchars($prompt, ENT_QUOTES, NLS::getCharset()) : $prompt) . '</option>';
- }
- return sprintf(' <select name="%1$s" id="%1$s"%2$s>%3$s%4$s </select>',
- $var->getVarName(),
- $this->_getActionScripts($form, $var),
- $prompt,
- $this->_selectOptions($values, $var->getValue($vars), $htmlchars));
- }
-
- function _renderVarInput_mlenum($form, $var, $vars)
- {
- $varname = $var->getVarName();
- $values = $var->getValues();
- $prompts = $var->type->prompts;
- $selected = $var->getValue($vars);
-
- /* If passing a non-array value need to get the keys. */
- if (!is_array($selected)) {
- foreach ($values as $key_1 => $values_2) {
- if (isset($values_2[$selected])) {
- $selected = array('1' => $key_1, '2' => $selected);
- break;
- }
- }
- }
-
- /* Hidden tag to store the current first level. */
- $html = sprintf(' <input type="hidden" name="%1$s[old]" id="%1$s[old]" value="%2$s" />',
- $varname,
- htmlspecialchars($selected['1'], ENT_QUOTES, NLS::getCharset()));
-
- /* First level. */
- $values_1 = Horde_Array::valuesToKeys(array_keys($values));
- $html .= sprintf(' <select id="%1$s[1]" name="%1$s[1]" onchange="%2$s"%3$s>',
- $varname,
- 'if (this.value) { document.' . $form->getName() . '.formname.value=\'\';' . 'document.' . $form->getName() . '.submit() }',
- ($var->hasAction() ? ' ' . $this->_genActionScript($form, $var->_action, $varname) : ''));
- if (!empty($prompts)) {
- $html .= '<option value="">' . htmlspecialchars($prompts[0], ENT_QUOTES, NLS::getCharset()) . '</option>';
- }
- $html .= $this->_selectOptions($values_1, $selected['1']);
- $html .= ' </select>';
-
- /* Second level. */
- $html .= sprintf(' <select id="%1$s[2]" name="%1$s[2]"%2$s>',
- $varname,
- ($var->hasAction() ? ' ' . $this->_genActionScript($form, $var->_action, $varname) : ''));
- if (!empty($prompts)) {
- $html .= '<option value="">' . htmlspecialchars($prompts[1], ENT_QUOTES, NLS::getCharset()) . '</option>';
- }
- $values_2 = array();
- if (!empty($selected['1'])) {
- $values_2 = $values[$selected['1']];
- }
- return $html . $this->_selectOptions($values_2, $selected['2']) . ' </select>';
- }
-
- function _renderVarInput_multienum($form, $var, $vars)
- {
- $values = $var->getValues();
- $selected = $vars->getExists($var->getVarName(), $wasset);
- if (!$wasset) {
- $selected = $var->getDefault();
- }
- $html = sprintf(' <select multiple="multiple" size="%1$s" name="%2$s[]" id="%2$s[]" %3$s>%4$s </select>',
- $var->type->size,
- $var->getVarName(),
- $this->_getActionScripts($form, $var),
- $this->_multiSelectOptions($values, $selected));
- return $html . '<p class="form-hint">'
- . _("To select multiple items, hold down the Control (PC) or Command (Mac) key while clicking.")
- . "</p>\n";
- }
-
- function _renderVarInput_keyval_multienum($form, $var, $vars)
- {
- return $this->_renderVarInput_multienum($form, $var, $vars);
- }
-
- function _renderVarInput_radio($form, $var, $vars)
- {
- return $this->_radioButtons($var->getVarName(),
- $var->getValues(),
- $var->getValue($vars),
- $this->_getActionScripts($form, $var));
- }
-
- function _renderVarInput_set($form, $var, $vars)
- {
- $html = $this->_checkBoxes($var->getVarName(),
- $var->getValues(),
- $var->getValue($vars),
- $this->_getActionScripts($form, $var));
-
- if ($var->type->checkAll) {
- $form_name = $form->getName();
- $var_name = $var->getVarName() . '[]';
- $function_name = 'select' . $form_name . $var->getVarName();
- $enable = _("Select all");
- $disable = _("Select none");
- $invert = _("Invert selection");
- $html .= <<<EOT
-<script type="text/javascript">
-function $function_name()
-{
- for (var i = 0; i < document.$form_name.elements.length; i++) {
- f = document.$form_name.elements[i];
- if (f.name != '$var_name') {
- continue;
- }
- if (arguments.length) {
- f.checked = arguments[0];
- } else {
- f.checked = !f.checked;
- }
- }
-}
-</script>
-<a href="#" onclick="$function_name(true); return false;">$enable</a>,
-<a href="#" onclick="$function_name(false); return false;">$disable</a>,
-<a href="#" onclick="$function_name(); return false;">$invert</a>
-EOT;
- }
-
- return $html;
- }
-
- function _renderVarInput_link($form, $var, $vars)
- {
- return $this->_renderVarDisplay_link($form, $var, $vars);
- }
-
- function _renderVarInput_html($form, $var, $vars)
- {
- return $this->_renderVarDisplay_html($form, $var, $vars);
- }
-
- function _renderVarInput_email($form, $var, $vars)
- {
- return sprintf(' <input type="text" id="%1$s" name="%1$s" value="%2$s"%3$s />',
- $var->getVarName(),
- $value = $var->getValue($vars),
- $this->_getActionScripts($form, $var));
- }
-
- function _renderVarInput_matrix($form, $var, $vars)
- {
- $varname = $var->getVarName();
- $var_array = $var->getValue($vars);
- $cols = $var->type->cols;
- $rows = $var->type->rows;
- $matrix = $var->type->matrix;
- $new_input = $var->type->new_input;
-
- $html = '<table cellspacing="0"><tr>';
-
- $html .= '<td align="right" width="20%"></td>';
- foreach ($cols as $col_title) {
- $html .= sprintf('<td align="center" width="1%%">%s</td>', $col_title);
- }
- $html .= '<td align="right" width="60%"></td></tr>';
-
- /* Offer a new row of data to be added to the matrix? */
- if ($new_input) {
- $html .= '<tr><td>'."\n";
- if (is_array($new_input)) {
- $html .= sprintf(' <select%s name="%s[n][r]"><option value="">%s</option>%s </select><br />'."\n",
- ' id="'. $varname .'-n--r-"',
- $varname,
- _("-- select --"),
- $this->_selectOptions($new_input, $var_array['n']['r']));
- } elseif ($new_input == true) {
- $html .= sprintf(' <input%s type="text" name="%s[n][r]" value="%s" />',
- ' id="'. $varname .'-n--r-',
- $varname,
- $var_array['n']['r']);
- }
- $html .= ' </td>';
- foreach ($cols as $col_id => $col_title) {
- $html .= sprintf('<td align="center"><input type="checkbox" class="checkbox" name="%s[n][v][%s]" /></td>', $varname, $col_id);
- }
- $html .= '<td> </td></tr>'."\n";
- }
-
- /* Loop through the rows and create checkboxes for each column. */
- foreach ($rows as $row_id => $row_title) {
- $html .= sprintf('<tr><td>%s</td>', $row_title);
- foreach ($cols as $col_id => $col_title) {
- $html .= sprintf('<td align="center"><input type="checkbox" class="checkbox" name="%s[r][%s][%s]"%s /></td>', $varname, $row_id, $col_id, (!empty($matrix[$row_id][$col_id]) ? ' checked="checked"' : ''));
- }
- $html .= '<td> </td></tr>'."\n";
- }
-
- $html .= '</table>'."\n";
- return $html;
- }
-
- function _renderVarInput_password($form, $var, $vars)
- {
- return sprintf('<input type="password" id="%1$s" name="%1$s" value="%2$s"%3$s />',
- $var->getVarName(),
- $value = $var->getValue($vars),
- $this->_getActionScripts($form, $var));
- }
-
- function _renderVarInput_emailconfirm($form, $var, $vars)
- {
- $email = $var->getValue($vars);
- return '<ul><li>' . sprintf('<input type="text" class="form-input-emailconfirm"' .
- ' id="%1$s" name="%1$s[original]" value="%2$s"%3$s />',
- $var->getVarName(),
- $value = $email['original'],
- $this->_getActionScripts($form, $var)) . '</li><li>' .
- sprintf('<input type="text" class="form-input-emailconfirm"' .
- ' id="%1$s-confirm-" name="%1$s[confirm]" value="%2$s"%3$s />',
- $var->getVarName(),
- $value = $email['confirm'],
- $this->_getActionScripts($form, $var)) . '</li></ul>';
- }
-
- function _renderVarInput_passwordconfirm($form, $var, $vars)
- {
- $password = $var->getValue($vars);
- return '<ul><li>' . sprintf('<input type="password" class="form-input-passwordconfirm"'
- .' id="%1$s" name="%1$s[original]" value="%2$s"%3$s />',
- $var->getVarName(),
- $value = $password['original'],
- $this->_getActionScripts($form, $var)) . '</li><li>' .
- sprintf('<input type="password" class="form-input-passwordconfirm"'
- .' id="%1$s-confirm-" name="%1$s[confirm]" value="%2$s"%3$s />',
- $var->getVarName(),
- $value = $password['confirm'],
- $this->_getActionScripts($form, $var)) . '</li></ul>';
- }
-
- function _renderVarInput_boolean($form, $var, $vars)
- {
- $varName = $var->getVarName();
-
- $html = ' <input type="checkbox" class="form-input-checkbox" id="' . $varName . '"'
- . ' name="' . $varName . '"'
- . ($var->getValue($vars) ? ' checked="checked"' : '');
- if ($var->hasAction()) {
- $html .= $this->_genActionScript($form, $var->_action,
- $var->getVarName());
- }
- $html .= ' />';
- return $html;
- }
-
- function _renderVarInput_creditcard($form, $var, $vars)
- {
- $varName = $var->getVarName();
-
- $html = ' <input type="text" class="form-input-creditcard" id="' . $varName . '"'
- . ' name="' . $varName . '"'
- .$var->getValue($vars);
- if ($var->hasAction()) {
- $html .= $this->_genActionScript($form, $var->_action,
- $var->getVarName());
- }
-
- return $html . ' />';
- }
-
- function _renderVarInput_obrowser($form, $var, $vars)
- {
- $varname = $var->getVarName();
- $varvalue = $vars->get($varname);
- $fieldId = 'obrowser_' . hash('md5', uniqid(rand(), true));
- $html = '
- <script type="text/javascript">
- var obrowserWindowName;
- function obrowserCallback(name, oid)
- {
- if (name == obrowserWindowName) {
- document.getElementById(\'' . $fieldId . '\').value = oid;
- return false;
- } else {
- return "Invalid window name supplied";
- }
- }
- </script>
- ';
- $html .= sprintf('<input type="hidden" name="%s" id="%s"%s value="%s" />',
- $varname,
- $fieldId,
- $this->_getActionScripts($form, $var),
- $varvalue);
- if (!empty($varvalue)) {
- $html .= $varvalue;
- }
-
- if ($GLOBALS['browser']->hasFeature('javascript')) {
- Horde::addScriptFile('popup.js', 'horde', true);
- $imgId = $varname .'goto';
- $html .= '<div id="goto" class="headerbox"
- style="position:absolute;visibility:hidden;padding:0"></div>';
- $html .= Horde::link('#', _("Select an object"), '', '', 'obrowserWindow = popup(\'' . $GLOBALS['registry']->get('webroot', 'horde') . '/services/obrowser/' . '\'); obrowserWindowName = obrowserWindow.name; return false;') . Horde::img('tree/leaf.png', _("Object"), 'id="' . $imgId . '" align="middle"', $GLOBALS['registry']->getImageDir('horde')) . "</a>\n";
- }
-
- return $html;
- }
-
- function _renderVarInput_dblookup($form, $var, $vars)
- {
- return $this->_renderVarInput_enum($form, $var, $vars);
- }
-
- function _renderVarInput_figlet($form, $var, $vars)
- {
- return sprintf(' <input type="text" class="form-input-figlet" id="%1$s" name="%1$s" size="%2$s" value="%3$s" />',
- $var->getVarName(),
- strlen($var->type->text),
- htmlspecialchars($var->getValue($vars))) .
- '<p class="form-input-figlet">' . _("Enter the letters below:") . '</p>' .
- $this->_renderVarDisplay_figlet($form, $var, $vars);
- }
-
- function _renderVarDisplayDefault($form, $var, $vars)
- {
- return nl2br(htmlspecialchars($var->getValue($vars), ENT_QUOTES,
- NLS::getCharset()));
- }
-
- function _renderVarDisplay_html($form, $var, $vars)
- {
- return $var->getValue($vars);
- }
-
- function _renderVarDisplay_email($form, $var, $vars)
- {
- $display_email = $email = $var->getValue($vars);
-
- if ($var->type->strip_domain && strpos($email, '@') !== false) {
- $display_email = str_replace(array('@', '.'),
- array(' (at) ', ' (dot) '),
- $email);
- }
-
- if ($var->type->link_compose) {
- $email_val = trim($email);
-
- // Format the address according to RFC822.
- $mailbox_host = explode('@', $email_val);
- if (!isset($mailbox_host[1])) {
- $mailbox_host[1] = '';
- }
-
- $name = $var->type->link_name;
-
- require_once 'Horde/MIME.php';
- $address = MIME::rfc822WriteAddress($mailbox_host[0], $mailbox_host[1], $name);
-
- // Get rid of the trailing @ (when no host is included in
- // the email address).
- $address = str_replace('@>', '>', $address);
- $mail_link = $GLOBALS['registry']->call('mail/compose', array(array('to' => addslashes($address))));
- if (is_a($mail_link, 'PEAR_Error')) {
- $mail_link = 'mailto:' . urlencode($address);
- }
-
- return Horde::link($mail_link, $email_val)
- . htmlspecialchars($display_email) . '</a>';
- } else {
- return nl2br(htmlspecialchars($display_email, ENT_QUOTES, NLS::getCharset()));
- }
- }
-
- function _renderVarDisplay_password($form, $var, $vars)
- {
- return '********';
- }
-
- function _renderVarDisplay_passwordconfirm($form, $var, $vars)
- {
- return '********';
- }
-
- function _renderVarDisplay_octal($form, $var, $vars)
- {
- return sprintf('0%o', octdec($var->getValue($vars)));
- }
-
- function _renderVarDisplay_boolean($form, $var, $vars)
- {
- return $var->getValue($vars) ? _("Yes") : _("No");
- }
-
- function _renderVarDisplay_enum($form, $var, $vars)
- {
- $values = $var->getValues();
- $value = $var->getValue($vars);
- if (count($values) == 0) {
- return _("No values");
- } elseif (isset($values[$value]) && $value != '') {
- return htmlspecialchars($values[$value], ENT_QUOTES, NLS::getCharset());
- }
- }
-
- function _renderVarDisplay_radio($form, $var, $vars)
- {
- $values = $var->getValues();
- if (count($values) == 0) {
- return _("No values");
- } elseif (isset($values[$var->getValue($vars)])) {
- return htmlspecialchars($values[$var->getValue($vars)], ENT_QUOTES, NLS::getCharset());
- }
- }
-
- function _renderVarDisplay_multienum($form, $var, $vars)
- {
- $values = $var->getValues();
- $on = $var->getValue($vars);
- if (!count($values) || !count($on)) {
- return _("No values");
- } else {
- $display = array();
- foreach ($values as $value => $name) {
- if (in_array($value, $on)) {
- $display[] = $name;
- }
- }
- return htmlspecialchars(implode(', ', $display), ENT_QUOTES, NLS::getCharset());
- }
- }
-
- function _renderVarDisplay_set($form, $var, $vars)
- {
- $values = $var->getValues();
- $on = $var->getValue($vars);
- if (!count($values) || !count($on)) {
- return _("No values");
- } else {
- $display = array();
- foreach ($values as $value => $name) {
- if (in_array($value, $on)) {
- $display[] = $name;
- }
- }
- return htmlspecialchars(implode(', ', $display), ENT_QUOTES, NLS::getCharset());
- }
- }
-
- function _renderVarDisplay_image($form, $var, $vars)
- {
- $img_params = $var->getValue($vars);
- $img_url = Horde::url($GLOBALS['registry']->get('webroot', 'horde') . '/services/images/view.php');
- $img_url = Util::addParameter($img_url, $img_params);
-
- return Horde::img($img_url, isset($img_params['f']) ? $img_params['f'] : '', '', '');
- }
-
- function _renderVarDisplay_phone($form, &$var, &$vars)
- {
- global $registry;
-
- $number = $var->getValue($vars);
- $html = htmlspecialchars($number, ENT_QUOTES, $this->_charset);
-
- if ($number && $registry->hasMethod('telephony/dial')) {
- $url = $registry->call('telephony/dial', array($number));
- $label = sprintf(_("Dial %s"), $number);
- $html .= ' ' . Horde::link($url, $label) . Horde::img('phone.png', $label, '', $registry->getImageDir('horde')) . '</a>';
- }
-
- return $html;
- }
-
- function _renderVarDisplay_cellphone($form, &$var, &$vars)
- {
- global $registry;
-
- $html = $this->_renderVarDisplay_phone($form, $var, $vars);
-
- $number = $var->getValue($vars);
- if ($number && $registry->hasMethod('sms/compose')) {
- $url = $registry->link('sms/compose', array('to' => $number));
- $html .= ' ' . Horde::link($url, _("Send SMS")) . Horde::img('mobile.png', _("Send SMS"), '', $registry->getImageDir('horde')) . '</a>';
- }
-
- return $html;
- }
-
- function _renderVarDisplay_address($form, $var, $vars)
- {
- global $registry;
-
- $address = $var->getValue($vars);
-
- if (preg_match('/((?: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, $postcode)) {
- /* UK postcode detected. */
- /* Multimap.co.uk generated map */
- $mapurl = 'http://www.multimap.com/map/browse.cgi?pc=' . urlencode($postcode[1]);
- $desc = _("Multimap UK map");
- $icon = 'map.png';
- } elseif (preg_match('/ACT|NSW|NT|QLD|SA|TAS|VIC|WA/', $address)) {
- /* Australian state detected. */
- /* Whereis.com.au generated map */
- $mapurl = 'http://www.whereis.com.au/whereis/mapping/geocodeAddress.do?';
- $desc = _("Whereis Australia map");
- $icon = 'map.png';
- /* Split out the address, line-by-line. */
- $addressLines = explode("\n", $address);
- for ($i = 0; $i < count($addressLines); $i++) {
- /* See if it's the street number & name. */
- if (preg_match('/(\d+\s*\/\s*)?(\d+|\d+[a-zA-Z])\s+([a-zA-Z ]*)/', $addressLines[$i], $lineParts)) {
- $mapurl .= '&streetNumber=' . urlencode($lineParts[2]);
- $mapurl .= '&streetName=' . urlencode($lineParts[3]);
- }
- /* Look for "Suburb, State". */
- if (preg_match('/([a-zA-Z ]*),?\s+' . $aus_state_regexp . '/', $addressLines[$i], $lineParts)) {
- $mapurl .= '&suburb=' . urlencode($lineParts[1]);
- }
- /* Look for "State <4 digit postcode>". */
- if (preg_match('/(' . $aus_state_regexp . ')\s+(\d{4})/', $addressLines[$i], $lineParts)) {
- $mapurl .= '&state=' . urlencode($lineParts[1]);
- }
- }
- } elseif (preg_match('/(.*)\n(.*)\s*,\s*(\w+)\.?\s+(\d+|[a-zA-Z]\d[a-zA-Z]\s?\d[a-zA-Z]\d)/', $address, $addressParts)) {
- /* American/Canadian address style. */
- /* Mapquest generated map */
- $mapurl = 'http://www.mapquest.com/maps/map.adp?size=big&zoom=7';
- $desc = _("MapQuest map");
- $icon = 'map.png';
- $country = null;
- if (!empty($addressParts[4]) && preg_match('|[a-zA-Z]\d[a-zA-Z]\s?\d[a-zA-Z]\d|', $addressParts[4])) {
- $country = 'CA';
- }
- if (!empty($addressParts[1])) {
- $mapurl .= '&address=' . urlencode($addressParts[1]);
- }
- if (!empty($addressParts[2])) {
- $mapurl .= '&city=' . urlencode($addressParts[2]);
- }
- if (!empty($addressParts[3])) {
- $mapurl .= '&state=' . urlencode($addressParts[3]);
- }
- if (!empty($addressParts[4])) {
- if ($country == 'CA') {
- $mapurl .= '&country=CA';
- }
- $mapurl .= '&zipcode=' . urlencode($addressParts[4]);
- }
-
- /* Yahoo! generated map. */
- $mapurl2 = 'http://us.rd.yahoo.com/maps/home/submit_a/*-http://maps.yahoo.com/maps?srchtype=a&getmap=Get+Map&';
- $desc2 = _("Yahoo! map");
- $icon2 = 'map.png';
- if (!empty($addressParts[1])) {
- $mapurl2 .= '&addr=' . urlencode($addressParts[1]);
- }
- /* Give precedence to zipcode over city/state */
- if (empty($addressParts[4]) && !empty($addressParts[2]) && !empty($addressParts[3])) {
- $mapurl2 .= '&csz=' . urlencode($addressParts[2] . ' ' . $addressParts[3]);
- }
- if (!empty($addressParts[4])) {
- if (preg_match('|([a-zA-Z]\d[a-zA-Z])\s?(\d[a-zA-Z]\d)|', $addressParts[4], $pcParts)) {
- $mapurl2 .= '&country=ca';
- /* make sure the postal-code has a space */
- $addressParts[4] = $pcParts[1] . ' ' . $pcParts[2];
- }
- $mapurl2 .= '&csz=' . urlencode($addressParts[4]);
- }
-
- /* Google generated map. */
- $mapurl3 = 'http://maps.google.com/maps?q=' . urlencode($addressParts[0]) . '&hl=en';
- $desc3 = _("Google Maps");
- $icon3 = 'map.png';
-
- } elseif (preg_match('/(.*?)\r?\n([A-Z]{1,3})-(\d{5})\s+(.*)/i', $address, $addressParts)) {
- /* European address style. */
- include 'Horde/NLS/carsigns.php';
- $country = array_search(String::upper($addressParts[2]), $carsigns);
-
- /* Map24 generated map. */
- if (in_array($country, array('al', 'ad', 'am', 'az', 'be', 'ba',
- 'bg', 'de', 'dk', 'ee', 'fo', 'fi',
- 'fr', 'ge', 'gr', 'gb', 'ie', 'is',
- 'it', 'hr', 'lv', 'li', 'lt', 'lu',
- 'mt', 'mk', 'md', 'mc', 'nl', 'no',
- 'pl', 'pt', 'ro', 'ru', 'se', 'ch',
- 'cs', 'sk', 'si', 'es', 'cz', 'tr',
- 'ua', 'hu', 'by', 'cy', 'at'))) {
- if (in_array($country, array('at', 'be', 'ch', 'de', 'dk',
- 'es', 'fi', 'fr', 'it', 'nl',
- 'no', 'se'))) {
- $mirror = $country;
- } else {
- $mirror = 'uk';
- }
- $mapurl = 'http://www.' . $mirror . '.map24.com/source/address/v2.0.0/cnt_nav_maplet.php?cid=validateaddr&country=' . $country;
- $desc = _("Map24 map");
- $icon = 'map_eu.png';
- if (!empty($addressParts[1])) {
- $mapurl .= '&street=' . urlencode($addressParts[1]);
- }
- if (!empty($addressParts[3])) {
- $mapurl .= '&zip=' . urlencode($addressParts[3]);
- }
- if (!empty($addressParts[4])) {
- $mapurl .= '&city=' . urlencode($addressParts[4]);
- }
- }
-
- /* Mapquest generated map. */
- $mapurl2 = 'http://www.mapquest.com/maps/map.adp?country=' . String::upper($country);
- $desc2 = _("MapQuest map");
- $icon2 = 'map_eu.png';
- if (!empty($addressParts[1])) {
- $mapurl2 .= '&address=' . urlencode($addressParts[1]);
- }
- if (!empty($addressParts[3])) {
- $mapurl2 .= '&zipcode=' . urlencode($addressParts[3]);
- }
- if (!empty($addressParts[4])) {
- $mapurl2 .= '&city=' . urlencode($addressParts[4]);
- }
- }
-
- $html = nl2br(htmlspecialchars($var->getValue($vars), ENT_QUOTES, NLS::getCharset()));
- if (!empty($mapurl)) {
- $html .= ' ' . Horde::link(Horde::externalUrl($mapurl), $desc, null, '_blank') . Horde::img($icon, $desc, '', $registry->getImageDir('horde')) . '</a>';
- }
- if (!empty($mapurl2)) {
- $html .= ' ' . Horde::link(Horde::externalUrl($mapurl2), $desc2, null, '_blank') . Horde::img($icon2, $desc2, '', $registry->getImageDir('horde')) . '</a>';
- }
- if (!empty($mapurl3)) {
- $html .= ' ' . Horde::link(Horde::externalUrl($mapurl3), $desc3, null, '_blank') . Horde::img($icon3, $desc3, '', $registry->getImageDir('horde')) . '</a>';
- }
-
- return $html;
- }
-
- function _renderVarDisplay_date($form, $var, $vars)
- {
- return $var->type->getFormattedTime($var->getValue($vars));
- }
-
- function _renderVarDisplay_monthyear($form, $var, $vars)
- {
- return $vars->get($var->getVarName() . '[month]') . ', ' . $vars->get($var->getVarName() . '[year]');
- }
-
- function _renderVarDisplay_monthdayyear($form, $var, $vars)
- {
- $date = $var->getValue($vars);
- if ((is_array($date) && !empty($date['year']) &&
- !empty($date['month']) && !empty($date['day']))
- || (!is_array($date) && !empty($date))) {
- return $var->type->formatDate($date);
- }
- return '';
- }
-
- function _renderVarDisplay_invalid($form, $var, $vars)
- {
- return '<p class="form-error form-inline">'
- . htmlspecialchars($var->type->message, ENT_QUOTES, NLS::getCharset())
- . '</p>';
- }
-
- function _renderVarDisplay_link($form, $var, $vars)
- {
- $values = $var->getValues();
- if (!isset($values[0])) {
- $values = array($values);
- }
-
-
- $count = count($values);
- $html = '';
- for ($i = 0; $i < $count; $i++) {
- if (empty($values[$i]['url']) || empty($values[$i]['text'])) {
- continue;
- }
- if (!isset($values[$i]['target'])) {
- $values[$i]['target'] = '';
- }
- if (!isset($values[$i]['onclick'])) {
- $values[$i]['onclick'] = '';
- }
- if (!isset($values[$i]['title'])) {
- $values[$i]['title'] = '';
- }
- if (!isset($values[$i]['accesskey'])) {
- $values[$i]['accesskey'] = '';
- }
- if ($i > 0) {
- $html .= ' | ';
- }
- $html .= Horde::link($values[$i]['url'], $values[$i]['text'],
- 'widget', $values[$i]['target'], $values[$i]['onclick'],
- $values[$i]['title'], $values[$i]['accesskey'])
- . $values[$i]['text'] . '</a>';
- }
-
- return $html;
- }
-
- function _renderVarDisplay_dblookup($form, $var, $vars)
- {
- return $this->_renderVarDisplay_enum($form, $var, $vars);
- }
-
- function _renderVarDisplay_figlet($form, $var, $vars)
- {
- $figlet = new Text_Figlet();
- $result = $figlet->loadFont($var->type->font);
- if (is_a($result, 'PEAR_Error')) {
- return $result->getMessage();
- }
-
- return '<pre>' . $figlet->lineEcho($var->type->text) . '</pre>';
- }
-
- function _renderVarInput_selectFiles($form, $var, $vars)
- {
- /* Needed for gollem js calls */
- $html = sprintf('<input type="hidden" id="%1$s" name="%1$s" value="%2$s" />',
- 'selectlist_selectid',
- $var->type->selectid)
- . sprintf('<input type="hidden" id="%1$s" name="%1$s" />', 'actionID');
-
- /* Form field. */
- $html .= sprintf('<input type="hidden" id="%1$s" name="%1$s" value="%2$s" />',
- $var->getVarName(),
- $var->type->selectid);
-
- /* Open window link. */
- $param = array($var->type->link_text,
- $var->type->link_style,
- $form->getName(),
- $var->type->icon,
- $var->type->selectid);
- $html .= "<p>\n" . $GLOBALS['registry']->call('files/selectlistLink', $param) . "</p>\n";
-
- if ($var->type->selectid) {
- $param = array($var->type->selectid);
- $files = $GLOBALS['registry']->call('files/selectlistResults', $param);
- if ($files) {
- $html .= '<ol>';
- foreach ($files as $id => $file) {
- $dir = key($file);
- $filename = current($file);
- if ($GLOBALS['registry']->hasMethod('files/getViewLink')) {
- $filename = basename($filename);
- $url = $GLOBALS['registry']->call('files/getViewLink', array($dir, $filename));
- $filename = Horde::link($url, _("Preview"), null, 'form_file_view') . htmlspecialchars(Util::realPath($dir . '/' . $filename), ENT_QUOTES, $this->_charset) . '</a>';
- } else {
- if (!empty($dir) && ($dir != '.')) {
- $filename = $dir . '/' . $filename;
- }
- $filename = htmlspecialchars($filename, ENT_QUOTES, $this->_charset);
- }
- $html .= '<li>' . $filename . "</li>\n";
- }
- $html .= '</ol>';
- }
- }
-
- return $html;
- }
-
- function _selectOptions($values, $selectedValue = false, $htmlchars = true)
- {
- $result = '';
- $sel = false;
- foreach ($values as $value => $display) {
- if (!is_null($selectedValue) && !$sel && $value == $selectedValue
- && strlen($value) == strlen($selectedValue)) {
- $selected = ' selected="selected"';
- $sel = true;
- } else {
- $selected = '';
- }
- $result .= ' <option value="';
- $result .= ($htmlchars) ? htmlspecialchars($value, ENT_QUOTES, NLS::getCharset()) : $value;
- $result .= '"' . $selected . '>';
- $result .= ($htmlchars) ? htmlspecialchars($display) : $display;
- $result .= "</option>\n";
- }
-
- return $result;
- }
-
- function _multiSelectOptions($values, $selectedValues)
- {
- $result = '';
- $sel = false;
- foreach ($values as $value => $display) {
- if (@in_array($value, $selectedValues)) {
- $selected = ' selected="selected"';
- } else {
- $selected = '';
- }
- $result .= " <option value=\""
- . htmlspecialchars($value, ENT_QUOTES, NLS::getCharset())
- . "\"$selected>" . htmlspecialchars($display) . "</option>\n";
- }
-
- return $result;
- }
-
- function _checkBoxes($name, $values, $checkedValues, $actions = '')
- {
- $result = '';
- if (!is_array($checkedValues)) {
- $checkedValues = array();
- }
-
- if (count($values) > 0) {
- $result .= " <ul>\n";
- }
-
- $i = 0;
- foreach ($values as $value => $display) {
- $checked = in_array($value, $checkedValues) ? ' checked="checked"' : '';
- $result .= sprintf(' <li>'
- .'<input id="%1$s%2$s" type="checkbox"'
- .' class="form-input-checkbox" name="%1$s[]"'
- .' value="%3$s"%4$s%5$s />'
- .' <label class="form-inline" for="%1$s%2$s">'
- .'%6$s</label></li>'."\n",
- $name,
- $i,
- $value,
- $checked,
- $actions,
- $display);
- $i++;
- }
-
- if (count($values) > 0) {
- $result .= " </ul>";
- }
-
-
- return $result;
- }
-
- function _radioButtons($name, $values, $checkedValue = null, $actions = '')
- {
- $result = '';
-
- if (count($values) > 0) {
- $result .= " <ul>\n";
- }
-
- $i = 0;
- foreach ($values as $value => $display) {
- $checked = (!is_null($checkedValue) && $value == $checkedValue) ? ' checked="checked"' : '';
- $result .= sprintf(' <li>'
- .'<input id="%1$s%2$s" type="radio"'
- .' class="form-input-checkbox" name="%1$s"'
- .' value="%3$s"%4$s%5$s />'
- .' <label class="form-inline" for="%1$s%2$s">'
- .'%6$s</label></li>'."\n",
- $name,
- $i,
- $value,
- $checked,
- $actions,
- $display);
- $i++;
- }
-
- if (count($values) > 0) {
- $result .= " </ul>";
- }
-
- return $result;
- }
-
- /**
- *
- * @access private
- * @author ?
- * @deprecated
- */
- function _genID($name, $fulltag = true)
- {
- return $fulltag ? 'id="' . htmlspecialchars($name) . '"' : $name;
- }
-
- /**
- * Returns script for an rendered variable. TODO: make this unobtrusive.
- *
- * @access private
- * @author ?
- * @return string html representing an attribute with action script as value,
- * or and empty string, if the action is to happen window.onload
- */
- function _genActionScript($form, $action, $varname)
- {
- $html = '';
- $triggers = $action->getTrigger();
- if (!is_array($triggers)) {
- $triggers = array($triggers);
- }
- $js = $action->getActionScript($form, $this, $varname);
- foreach ($triggers as $trigger) {
- if ($trigger == 'onload') {
- $this->_onLoadJS[] = $js;
- } else {
- $html .= ' ' . $trigger . '="' . $js . '"';
- }
- }
- return $html;
- }
-
- /**
- * Returns scripts for an rendered variable. TODO: make this unobtrusive.
- *
- * @access private
- * @author ?
- * @return string html representing attributes with action script as values,
- * or and empty string, if the actions are all to happen window.onload
- */
- function _getActionScripts($form, $var)
- {
- $actions = '';
- if ($var->hasAction()) {
- $varname = $var->getVarName();
- $action = &$var->_action;
- $triggers = $action->getTrigger();
- if (!is_array($triggers)) {
- $triggers = array($triggers);
- }
- $js = $action->getActionScript($form, $this, $varname);
- foreach ($triggers as $trigger) {
- if ($trigger == 'onload') {
- $this->_onLoadJS[] = $js;
- } else {
- $actions .= ' ' . $trigger . '="' . $js . '"';
- }
- }
- }
- return $actions;
- }
-
-}
+++ /dev/null
-/* http://www.quirksmode.org/dom/maxlength.html */
-
-/*
-<textarea id="text" name="text" maxlength="1500"></textarea>
-*/
-
-
-function setMaxLength()
-{
- var x = document.getElementsByTagName('textarea');
- var counter = document.createElement('div');
- counter.className = 'counter';
- for (var i=0;i<x.length;i++)
- {
- if (x[i].getAttribute('maxlength'))
- {
- var counterClone = counter.cloneNode(true);
- counterClone.relatedElement = x[i];
- counterClone.innerHTML = '<span>0</span>/'+x[i].getAttribute('maxlength');
- x[i].parentNode.insertBefore(counterClone,x[i].nextSibling);
- x[i].relatedElement = counterClone.getElementsByTagName('span')[0];
-
- x[i].onkeyup = x[i].onchange = checkMaxLength;
- x[i].onkeyup();
- }
- }
-}
-
-function checkMaxLength()
-{
- var maxLength = this.getAttribute('maxlength');
- var currentLength = this.value.length;
- if (currentLength > maxLength)
- this.relatedElement.className = 'toomuch';
- else
- this.relatedElement.className = '';
- this.relatedElement.firstChild.nodeValue = currentLength;
- // not innerHTML
-}
+++ /dev/null
-<?php
-/**
- * Incubator Horde_Form rewrite example page.
- *
- * The initial Horde_Form xhtml rewrite was supported by Google SoC
- * 2005.
- *
- * $Horde: incubator/Horde_Form/test.php,v 1.25 2008/09/02 17:43:09 chuck Exp $
- */
-
-@define('HORDE_BASE', dirname(__FILE__) . '/../..');
-@define('INCUBATOR_BASE', dirname(__FILE__));
-
-require_once HORDE_BASE . '/lib/core.php';
-require_once 'Horde/Variables.php';
-require_once 'Horde/Autoloader.php';
-Horde_Autoloader::addClassPath(dirname(__FILE__));
-$registry = Registry::singleton();
-$vars = Variables::getDefaultVariables();
-
-$vars->set('example_bar', 'text with a beginning and an end');
-$form = new Horde_Form($vars, 'Horde_Form Test');
-
-$choices = array('big' => 'BIG',
- 'small' => 'small',
- 'other' => 'Other');
-$form->add('condchoices', 'Enum', _("Select something"), '', true, false, array($choices, true));
-
-$o = $form->add('other_text', 'String', _("If other, please describe"), '', false);
-$params = array('target' => 'condchoices',
- 'enabled' => true,
- 'values' => array('other'));
-$o->setAction(new Horde_Form_Action_ConditionalEnable($params));
-
-$form->add('color', 'Color', _("Color"), null, false);
-
-$vars->set('form', 'add');
-$enum = array('' => _("Select:"),
- 1 => _("Yes"),
- 0 => _("No"));
-$form->add('opciones', 'Enum', _("Simple description"), '', true, false, array($enum));
-$form->add('bool', 'Boolean', _("Boolean"));
-$form->add('number', 'Int', _("Integer"));
-$form->add('mybday', 'date', _("A Date"), '', false);
-$form->addHidden('form', 'String', true);
-$unamevar = $form->add('user_name', 'String', _("Username"));
-$form->add('password', 'password', _("Password"));
-$form->addHidden('example_hidden', 'int', false);
-$form->add('some_text', 'String', _("Insert some text"), _("Insert some text in this box"), false);
-$choices = array('big' => 'BIG',
- 'small' => 'small',
- 'mixed' => 'mIxED');
-$form->add('choices', 'enum', _("Select something2"), 'Use the selection box to make your choice', true, false, array($choices, true));
-$form->add('email_address', 'email', _("Email"));
-$form->add('email_address2', 'emailconfirm', _("Email2"));
-$form->add('a_creditcard', 'creditcard', _("Credit Card"));
-$form->add('a_password', 'password', _("Password"));
-$form->add('a_password2', 'passwordconfirm', _("Password with confirmation"), _("type the password twice to confirm"));
-$form->add('a_octal', 'Octal', _("Octal"), false);
-$form->add('a_radiogroup', 'set', _("Radio Group"), '', true, false, array($choices));
-
-$t = $form->add('example_bar', 'String', _("Bar field"), _("You have to fill in some long text here"), true, false, array(4, 40));
-$t->setAction(new Horde_Form_Action_setcursorpos(array(4)));
-
-$form->add('a_checkboxgroup', 'set', _("Checkbox Group"), '', false, false, array($choices));
-//$form->add('a_obrowser', 'obrowser', _("obrowser"));
-
-?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html>
-<head>
-<title>Incubator Horde_Form Test</title>
-<link rel="stylesheet" type="text/css" href="themes/form.css" />
-<script type="text/javascript" src="<?=$registry->get('jsuri', 'horde')?>/horde.js"></script>
-<script type="text/javascript" src="<?=$registry->get('jsuri', 'horde')?>/form_helpers.js"></script>
-</head>
-<body>
-<?php
-if ($form->validate()) {
- $form->getInfo($info);
- echo 'You have submitted:<br /><pre>';
- var_dump($info);
- echo '</pre>';
-}
-
-/* Render the form. */
-$renderer = new Horde_Form_Renderer_Xhtml;
-$renderer->setButtons(_("Add user"), _("Reset"));
-$renderer->renderActive($form, 'test.php', 'post');
-
-?>
-</body>
-</html>
+++ /dev/null
-form.horde-form {
- font-size: 100%;
- font-weight: normal;
-}
-
-form.horde-form input[type="text"], form.horde-form input[type="password"],
-form.horde-form select, form.horde-form textarea {
- width: 130px;
- margin: .2em 0 .1em .1em;
-}
-
-form.horde-form input[type="text"], form.horde-form input[type="password"], form.horde-form textarea {
- padding: .1em;
-}
-
-.clear {
- clear: both;
-}
-
-.horde-form fieldset {
- padding: .5em;
- margin: 0;
- border: 1px solid #ccc;
-}
-
-.horde-form fieldset.form-buttons {
- color: #000;
- background: #ccc;
- border: 1px solid #aaa;
-}
-
-fieldset legend {
- color: #000;
- background: #ccc;
- padding: .5em;
- margin-bottom: -1em;
- border: 1px solid #999;
- border-bottom: none;
- font-weight: bold;
-}
-
-fieldset.form-section {
- padding: .5em;
- margin: .5em 0;
-}
-
-.form-button, .form-button-upload {
- font-size: 90%;
-}
-
-.form-colorpicker {
- float: left;
-}
-.form-colorpicker img {
- border: 0;
- padding: 0;
- margin: 2px;
- height: 16px;
- width: 16px;
-}
-.form-colorpicker input {
- width: 100px;
- clear: none;
-}
-.form-colorpicker-palette {
- display: none;
- margin: 2px;
-}
-
-.form-description {
- padding: 8px;
-}
-
-.form-error, .form-error-example {
- color: #f00;
-}
-
-p.form-error {
- background-color: #f00;
- color: #fff;
- padding: 3px;
- border: 1px solid #000;
- margin: auto 70px;
-}
-
-div.form-error {
- background-color: #ffffe1;
- background-image: url("graphics/required.png");
- background-repeat: no-repeat;
- background-position: top left;
- color: #000;
-}
-
-.form-hint {
- display: block;
- margin: 0 0 5px 142px;
- padding: 1px 3px;
- font-size: 88%;
-}
-
-.form-header {
- vertical-align: bottom;
- font-weight: bold;
-}
-
-.form-image-preview-blank {
- width: 50px;
- height: 40px;
- vertical-align: top;
-}
-
-.form-inline {
- display: inline;
-}
-
-.form-input {
- vertical-align: top;
- clear: both;
- padding: 4px;
- margin: 2px 0;
-}
-
-.form-input label {
- vertical-align: top;
- text-align: right;
- float: left;
- clear: left;
- display: block;
- width: 10em;
- padding: 0.3em;
-}
-
-.form-input label.form-inline {
- float: none;
- width: auto;
- display: inline;
-}
-
-.form-input ul, .form-input ol {
- list-style-type: none;
- display: block;
- float: left;
-}
-
-.form-input ul, .form-input ol, .form-input li {
- margin-top: 0;
- margin-left: 0;
- padding-top: 0;
- padding-left: 0;
-}
-.form-input ul {
- margin-bottom: .5em;
-}
-
-.form-input-address {
-}
-
-.form-input-assign {
-}
-
-.form-input-assign select, .form-input-assign div {
- display: inline;
- clear: none;
-}
-
-.form-input-checkbox {
- border: 0;
- height: 14px;
- width: 14px;
- background: transparent;
-}
-
-.form-input-text, .form-input-intlist, .form-input-octal, .form-input-int,
-.form-input-number, .form-input-phone, .form-input-file {
- width: 100px;
-}
-
-.form-input-resize {
- width: 25px;
-}
-
-.form-input-stringlist {
- width: 150px;
-}
-
-.form-input-time {
- width: 30px;
-}
-
-.form-note {
- clear: left;
- width: 130px;
- height: auto;
- padding: .3em;
- margin: 0 0 0 10.7em;
- border: 1px solid #666;
- background-color: #ffc;
-}
-.form-note p {
- margin: 0;
- padding: 0;
- font-style: italic;
- font-size: 70%;
-}
-
-.form-required {
- background: url("graphics/required.png") .5em .5em no-repeat;
-}
-
-.form-required label {
- font-weight: bold;
-}
-
-.form-sectionhidden {
- position: absolute;
- left: 0;
- top: -500px;
- width: 1px;
- height: 1px;
- overflow: hidden;
- display: block;
-}
-
-.form-sectionshown {
- display: block;
-}
-
-.form-spacer {
- padding: .9em;
-}
-
-.rowEven {
- background-color: #eef;
-}
-.rowOdd {
- background-color: #fff;
-}
-
-/* Form styles. */
-.htmlarea .statusBar .statusBarTree a {
- font: inherit;
-}
-.htmlarea table {
- width: auto;
-}
-input, select {
-}
-input {
- padding: 1px;
-}
-option {
- padding: 0 5px 0 3px;
-}
-
-.button {
- font-size: 90%;
-}
-a.button {
- padding: 2px;
- font-weight: normal;
- text-decoration: none;
-}
--- /dev/null
+<?php
+/**
+ * @package Horde_Form
+ */
+
+/** String */
+include_once 'Horde/String.php';
+
+/**
+ * Horde_Form Master Class.
+ *
+ * The Horde_Form:: package provides form rendering, validation, and
+ * other functionality for the Horde Application Framework.
+ *
+ * $Horde: incubator/Horde_Form/Horde/Form.php,v 1.19 2008/08/26 15:32:55 selsky Exp $
+ *
+ * Copyright 2001-2007 Robert E. Coyle <robertecoyle@hotmail.com>
+ * Copyright 2001-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author Robert E. Coyle <robertecoyle@hotmail.com>
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @since Horde 3.0
+ * @package Horde_Form
+ */
+class Horde_Form {
+
+ protected $_name = '';
+ protected $_title = '';
+ protected $_vars;
+ protected $_errors = array();
+ protected $_submitted = null;
+ protected $_sections = array();
+ protected $_open_section = null;
+ protected $_currentSection = array();
+ protected $_variables = array();
+ protected $_hiddenVariables = array();
+ protected $_useFormToken = true;
+ protected $_autofilled = false;
+ protected $_help = false;
+
+ public function __construct($vars, $title = '', $name = null)
+ {
+ if (is_null($name)) {
+ $name = String::lower(get_class($this));
+ }
+
+ $this->_vars = $vars;
+ $this->_title = $title;
+ $this->_name = $name;
+ }
+
+ public function setVars($vars)
+ {
+ $this->_vars = $vars;
+ }
+
+ public function getVars()
+ {
+ return $this->_vars;
+ }
+
+ public function getTitle()
+ {
+ return $this->_title;
+ }
+
+ public function setTitle($title)
+ {
+ $this->_title = $title;
+ }
+
+ public function getName()
+ {
+ return $this->_name;
+ }
+
+ /**
+ * Sets or gets whether the form should be verified by tokens.
+ * Tokens are used to verify that a form is only submitted once.
+ *
+ * @param boolean $token If specified, sets whether to use form tokens.
+ *
+ * @return boolean Whether form tokens are being used.
+ */
+ public function useToken($token = null)
+ {
+ if (!is_null($token)) {
+ $this->_useFormToken = $token;
+ }
+ return $this->_useFormToken;
+ }
+
+ /**
+ * Get the renderer for this form, either a custom renderer or the
+ * standard one.
+ *
+ * To use a custom form renderer, your form class needs to
+ * override this function:
+ * <code>
+ * function getRenderer()
+ * {
+ * return new CustomFormRenderer();
+ * }
+ * </code>
+ *
+ * ... where CustomFormRenderer is the classname of the custom
+ * renderer class, which should extend Horde_Form_Renderer.
+ *
+ * @param array $params A hash of renderer-specific parameters.
+ *
+ * @return object Horde_Form_Renderer The form renderer.
+ */
+ function getRenderer($params = array())
+ {
+ return new Horde_Form_Renderer_Xhtml($params);
+ }
+
+ function getType($type, $params = array())
+ {
+ $type_class = 'Horde_Form_Type_' . $type;
+ if (!class_exists($type_class)) {
+ Horde::fatal(PEAR::raiseError(sprintf('Nonexistant class "%s" for field type "%s"', $type_class, $type)), __FILE__, __LINE__);
+ }
+ $type_ob = new $type_class();
+ call_user_func_array(array(&$type_ob, 'init'), $params);
+ return $type_ob;
+ }
+
+ public function setSection($section = '', $desc = '', $image = '', $expanded = true)
+ {
+ $this->_currentSection = $section;
+ if (!count($this->_sections) && !$this->getOpenSection()) {
+ $this->setOpenSection($section);
+ }
+ $this->_sections[$section]['desc'] = $desc;
+ $this->_sections[$section]['expanded'] = $expanded;
+ $this->_sections[$section]['image'] = $image;
+ }
+
+ public function getSections()
+ {
+ return $this->_sections;
+ }
+
+ public function getSectionDesc($section)
+ {
+ return $this->_sections[$section]['desc'];
+ }
+
+ public function getSectionImage($section)
+ {
+ return $this->_sections[$section]['image'];
+ }
+
+ public function setOpenSection($section)
+ {
+ $this->_vars->set('__formOpenSection', $section);
+ }
+
+ public function getOpenSection()
+ {
+ return $this->_vars->get('__formOpenSection');
+ }
+
+ public function getSectionExpandedState($section, $boolean = false)
+ {
+ if ($boolean) {
+ /* Only the boolean value is required. */
+ return $this->_sections[$section]['expanded'];
+ }
+
+ /* Need to return the values for use in styles. */
+ if ($this->_sections[$section]['expanded']) {
+ return 'block';
+ } else {
+ return 'none';
+ }
+ }
+
+ /**
+ * TODO
+ */
+ public function addVariable($humanName, $varName, $type, $required,
+ $readonly = false, $description = null,
+ $params = array())
+ {
+ return $this->insertVariableBefore(null, $humanName, $varName, $type,
+ $required, $readonly, $description,
+ $params);
+ }
+
+ /**
+ * TODO
+ */
+ public function insertVariableBefore($before, $humanName, $varName, $type,
+ $required, $readonly = false,
+ $description = null, $params = array())
+ {
+ $type = $this->getType($type, $params);
+ $var = new Horde_Form_Variable($humanName, $varName, $type,
+ $required, $readonly, $description);
+
+ /* Set the form object reference in the var. */
+ $var->setFormOb($this);
+
+ if ($var->getType() instanceof Horde_Form_Type_enum &&
+ count($var->getValues()) == 1) {
+ $vals = array_keys($var->getValues());
+ $this->_vars->add($var->varName, $vals[0]);
+ $var->_autofilled = true;
+ }
+ if (empty($this->_currentSection)) {
+ $this->_currentSection = '__base';
+ }
+
+ if (is_null($before)) {
+ $this->_variables[$this->_currentSection][] = &$var;
+ } else {
+ $num = 0;
+ while (isset($this->_variables[$this->_currentSection][$num]) &&
+ $this->_variables[$this->_currentSection][$num]->getVarName() != $before) {
+ $num++;
+ }
+ if (!isset($this->_variables[$this->_currentSection][$num])) {
+ $this->_variables[$this->_currentSection][] = &$var;
+ } else {
+ $this->_variables[$this->_currentSection] = array_merge(
+ array_slice($this->_variables[$this->_currentSection], 0, $num),
+ array(&$var),
+ array_slice($this->_variables[$this->_currentSection], $num));
+ }
+ }
+
+ return $var;
+ }
+
+ /**
+ * Removes a variable from the form.
+ *
+ * As only variables can be passed by reference, you need to call this
+ * method this way if want to pass a variable name:
+ * <code>
+ * $form->removeVariable($var = 'varname');
+ * </code>
+ *
+ * @param Horde_Form_Variable|string $var Either the variable's name or
+ * the variable to remove from the
+ * form.
+ *
+ * @return boolean True if the variable was found (and deleted).
+ */
+ public function removeVariable(&$var)
+ {
+ foreach (array_keys($this->_variables) as $section) {
+ foreach (array_keys($this->_variables[$section]) as $i) {
+ if ((is_a($var, 'Horde_Form_Variable') && $this->_variables[$section][$i] === $var) ||
+ ($this->_variables[$section][$i]->getVarName() == $var)) {
+ // Slice out the variable to be removed.
+ $this->_variables[$this->_currentSection] = array_merge(
+ array_slice($this->_variables[$this->_currentSection], 0, $i),
+ array_slice($this->_variables[$this->_currentSection], $i + 1));
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * TODO
+ */
+ public function addHidden($varName, $type, $required, $params = array())
+ {
+ $type = $this->getType($type, $params);
+ $var = new Horde_Form_Variable('', $varName, $type, $required);
+ $var->hide();
+ $this->_hiddenVariables[] = &$var;
+ return $var;
+ }
+
+ public function getVariables($flat = true, $withHidden = false)
+ {
+ if ($flat) {
+ $vars = array();
+ foreach ($this->_variables as $section) {
+ foreach ($section as $var) {
+ $vars[] = $var;
+ }
+ }
+ if ($withHidden) {
+ foreach ($this->_hiddenVariables as $var) {
+ $vars[] = $var;
+ }
+ }
+ return $vars;
+ } else {
+ return $this->_variables;
+ }
+ }
+
+ public function getHiddenVariables()
+ {
+ return $this->_hiddenVariables;
+ }
+
+ /**
+ * Preserve the variables/values from another Horde_Form object.
+ */
+ public function preserve(Horde_Form $form)
+ {
+ /* OLD IMPLEMENTATION
+ if ($this->_useFormToken) {
+ $this->_preserveVarByPost($this->_name . '_formToken', Horde_Token::generateId($this->_name));
+ }
+
+ $variables = $this->getVariables();
+ foreach ($variables as $var) {
+ $varname = $var->getVarName();
+
+ switch (get_class($var->getType()) {
+ case 'passwordconfirm':
+ case 'emailconfirm':
+ $this->preserveVarByPost($this->_vars, $varname . '[original]');
+ $this->preserveVarByPost($this->_vars, $varname . '[confirm]');
+ break;
+
+ case 'monthyear':
+ $this->preserveVarByPost($this->_vars, $varname . '[month]');
+ $this->preserveVarByPost($this->_vars, $varname . '[year]');
+ break;
+
+ case 'monthdayyear':
+ $this->preserveVarByPost($this->_vars, $varname . '[month]');
+ $this->preserveVarByPost($this->_vars, $varname . '[day]');
+ $this->preserveVarByPost($this->_vars, $varname . '[year]');
+ break;
+ }
+
+ $this->preserveVarByPost($this->_vars, $varname);
+ }
+ foreach ($this->_hiddenVariables as $var) {
+ $this->preserveVarByPost($this->_vars, $var->getVarName());
+ }
+ */
+ }
+
+ /**
+ * Does the action of validating the form, checking if it really has been
+ * submitted by calling isSubmitted() and if true does any onSubmit()
+ * calls for var types in the form. The _submitted var is then rechecked.
+ *
+ * @param boolean $canAutofill Can the form be valid without
+ * being submitted?
+ *
+ * @return boolean True if the form is valid.
+ */
+ public function validate($canAutoFill = false)
+ {
+ /* Get submitted status. */
+ if ($this->isSubmitted() || $canAutoFill) {
+ /* Form was submitted or can autofill; check for any variable
+ * types' onSubmit(). */
+ $this->onSubmit($this->_vars);
+
+ /* Recheck submitted status. */
+ if (!$this->isSubmitted() && !$canAutoFill) {
+ return false;
+ }
+ } else {
+ /* Form has not been submitted; return false. */
+ return false;
+ }
+
+ $message = '';
+ $this->_autofilled = true;
+
+ if ($this->_useFormToken) {
+ global $conf;
+ if (isset($conf['token'])) {
+ /* If there is a configured token system, set it up. */
+ $tokenSource = Horde_Token::factory($conf['token']['driver'], Horde::getDriverConfig('token', $conf['token']['driver']));
+ } else {
+ /* Default to the file system if no config. */
+ $tokenSource = Horde_Token::factory('file');
+ }
+ if (!$tokenSource->verify($this->_vars->get($this->_name . '_formToken'))) {
+ $this->_errors['_formToken'] = _("This form has already been processed.");
+ }
+ }
+
+ foreach ($this->getVariables() as $var) {
+ $this->_autofilled = $var->_autofilled && $this->_autofilled;
+ if (!$var->validate($this->_vars, $message)) {
+ $this->_errors[$var->getVarName()] = $message;
+ }
+ }
+
+ if ($this->_autofilled) {
+ unset($this->_errors['_formToken']);
+ }
+
+ foreach ($this->_hiddenVariables as $var) {
+ if (!$var->validate($this->_vars, $message)) {
+ $this->_errors[$var->getVarName()] = $message;
+ }
+ }
+
+ return $this->isValid();
+ }
+
+ public function clearValidation()
+ {
+ $this->_errors = array();
+ }
+
+ public function getError($var)
+ {
+ if (is_a($var, 'Horde_Form_Variable')) {
+ $name = $var->getVarName();
+ } else {
+ $name = $var;
+ }
+ return isset($this->_errors[$name]) ? $this->_errors[$name] : null;
+ }
+
+ public function setError($var, $message)
+ {
+ if (is_a($var, 'Horde_Form_Variable')) {
+ $name = $var->getVarName();
+ } else {
+ $name = $var;
+ }
+ $this->_errors[$name] = $message;
+ }
+
+ public function clearError($var)
+ {
+ if (is_a($var, 'Horde_Form_Variable')) {
+ $name = $var->getVarName();
+ } else {
+ $name = $var;
+ }
+ unset($this->_errors[$name]);
+ }
+
+ public function isValid()
+ {
+ return ($this->_autofilled || !count($this->_errors));
+ }
+
+ public function execute()
+ {
+ throw new Horde_Form_Exception('Subclass must overide execute()');
+ }
+
+ /**
+ * Fetch the field values of the submitted form.
+ *
+ * @param array $info Array to be filled with the submitted field
+ * values.
+ */
+ public function getInfo(&$info)
+ {
+ $this->_getInfoFromVariables($this->getVariables(), $info);
+ $this->_getInfoFromVariables($this->_hiddenVariables, $info);
+ }
+
+ /**
+ * Fetch the field values from a given array of variables.
+ *
+ * @access private
+ *
+ * @param array $variables An array of Horde_Form_Variable objects to
+ * fetch from.
+ * @param array $info The array to be filled with the submitted
+ * field values.
+ */
+ protected function _getInfoFromVariables($variables, &$info)
+ {
+ foreach ($variables as $var) {
+ if ($var->isArrayVal()) {
+ $var->getInfo($this->_vars, $values);
+ if (is_array($values)) {
+ $varName = str_replace('[]', '', $var->getVarName());
+ foreach ($values as $i => $val) {
+ $info[$i][$varName] = $val;
+ }
+ }
+ } else {
+ if (Horde_Array::getArrayParts($var->getVarName(), $base, $keys)) {
+ if (!isset($info[$base])) {
+ $info[$base] = array();
+ }
+ $pointer = &$info[$base];
+ while (count($keys)) {
+ $key = array_shift($keys);
+ if (!isset($pointer[$key])) {
+ $pointer[$key] = array();
+ }
+ $pointer = &$pointer[$key];
+ }
+ $var->getInfo($this->_vars, $pointer);
+ } else {
+ $var->getInfo($this->_vars, $info[$var->getVarName()]);
+ }
+ }
+ }
+ }
+
+ public function hasHelp()
+ {
+ return $this->_help;
+ }
+
+ /**
+ * Determines if this form has been submitted or not. If the class
+ * var _submitted is null then it will check for the presence of
+ * the formname in the form variables.
+ *
+ * Other events can explicitly set the _submitted variable to
+ * false to indicate a form submit but not for actual posting of
+ * data (eg. onChange events to update the display of fields).
+ *
+ * @return boolean True or false indicating if the form has been
+ * submitted.
+ */
+ public function isSubmitted()
+ {
+ if (is_null($this->_submitted)) {
+ if ($this->_vars->get('formname') == $this->getName()) {
+ $this->_submitted = true;
+ } else {
+ $this->_submitted = false;
+ }
+ }
+
+ return $this->_submitted;
+ }
+
+ /**
+ * Checks if there is anything to do on the submission of the form by
+ * looping through each variable's onSubmit() function.
+ */
+ public function onSubmit()
+ {
+ /* Loop through all vars and check if there's anything to do on
+ * submit. */
+ $variables = $this->getVariables();
+ foreach ($variables as $var) {
+ $var->type->onSubmit($var, $this->_vars);
+ /* If changes to var being tracked don't register the form as
+ * submitted if old value and new value differ. */
+ if ($var->getOption('trackchange')) {
+ $varname = $var->getVarName();
+ if (!is_null($this->_vars->get('formname')) &&
+ $this->_vars->get($varname) != $this->_vars->get('__old_' . $varname)) {
+ $this->_submitted = false;
+ }
+ }
+ }
+ }
+
+ /**
+ * Explicitly sets the state of the form submit.
+ *
+ * An event can override the automatic determination of the submit state
+ * in the isSubmitted() function.
+ *
+ * @param boolean $state Whether to set the state of the form as being
+ * submitted.
+ */
+ public function setSubmitted($state = true)
+ {
+ $this->_submitted = $state;
+ }
+
+}
+
+/**
+ * Horde_Form_Type Class
+ *
+ * @author Robert E. Coyle <robertecoyle@hotmail.com>
+ * @package Horde_Form
+ */
+class Horde_Form_Type {
+
+ protected function __get($property)
+ {
+ $prop = '_' . $property;
+ return isset($this->$prop) ? $this->$prop : null;
+ }
+
+ protected function __set($property, $value)
+ {
+ $prop = '_' . $property;
+ $this->$prop = $value;
+ }
+
+ protected function __isset($property)
+ {
+ $prop = '_' . $property;
+ return isset($this->$prop);
+ }
+
+ protected function __unset($property)
+ {
+ $prop = '_' . $property;
+ unset($this->$prop);
+ }
+
+ public function init()
+ {
+ }
+
+ public function onSubmit()
+ {
+ }
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ $message = '<strong>Error:</strong> Horde_Form_Type::isValid() called - should be overridden<br />';
+ return false;
+ }
+
+ function getInfo($vars, $var, &$info)
+ {
+ $info = $var->getValue($vars);
+ }
+
+}
+
+class Horde_Form_Type_number extends Horde_Form_Type {
+
+ var $_fraction;
+
+ function init($fraction = null)
+ {
+ $this->_fraction = $fraction;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->isRequired() && empty($value) && ((string)(double)$value !== $value)) {
+ $message = _("This field is required.");
+ return false;
+ } elseif (empty($value)) {
+ return true;
+ }
+
+ /* If matched, then this is a correct numeric value. */
+ if (preg_match($this->_getValidationPattern(), $value)) {
+ return true;
+ }
+
+ $message = _("This field must be a valid number.");
+ return false;
+ }
+
+ function _getValidationPattern()
+ {
+ static $pattern = '';
+ if (!empty($pattern)) {
+ return $pattern;
+ }
+
+ /* Get current locale information. */
+ $linfo = NLS::getLocaleInfo();
+
+ /* Build the pattern. */
+ $pattern = '(-)?';
+
+ /* Only check thousands separators if locale has any. */
+ if (!empty($linfo['mon_thousands_sep'])) {
+ /* Regex to check for correct thousands separators (if any). */
+ $pattern .= '((\d+)|((\d{0,3}?)([' . $linfo['mon_thousands_sep'] . ']\d{3})*?))';
+ } else {
+ /* No locale thousands separator, check for only digits. */
+ $pattern .= '(\d+)';
+ }
+ /* If no decimal point specified default to dot. */
+ if (empty($linfo['mon_decimal_point'])) {
+ $linfo['mon_decimal_point'] = '.';
+ }
+ /* Regex to check for correct decimals (if any). */
+ if (empty($this->_fraction)) {
+ $fraction = '*';
+ } else {
+ $fraction = '{0,' . $this->_fraction . '}';
+ }
+ $pattern .= '([' . $linfo['mon_decimal_point'] . '](\d' . $fraction . '))?';
+
+ /* Put together the whole regex pattern. */
+ $pattern = '/^' . $pattern . '$/';
+
+ return $pattern;
+ }
+
+ function getInfo($vars, $var, &$info)
+ {
+ $value = $vars->get($var->getVarName());
+ $linfo = NLS::getLocaleInfo();
+ $value = str_replace($linfo['mon_thousands_sep'], '', $value);
+ $info = str_replace($linfo['mon_decimal_point'], '.', $value);
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Number"));
+ }
+
+}
+
+class Horde_Form_Type_int extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->isRequired() && empty($value) && ((string)(int)$value !== $value)) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (empty($value) || preg_match('/^[0-9]+$/', $value)) {
+ return true;
+ }
+
+ $message = _("This field may only contain integers.");
+ return false;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Integer"));
+ }
+
+}
+
+class Horde_Form_Type_octal extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->isRequired() && empty($value) && ((string)(int)$value !== $value)) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (empty($value) || preg_match('/^[0-7]+$/', $value)) {
+ return true;
+ }
+
+ $message = _("This field may only contain octal values.");
+ return false;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Octal"));
+ }
+
+}
+
+class Horde_Form_Type_intlist extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if (empty($value) && $var->isRequired()) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (empty($value) || preg_match('/^[0-9 ,]+$/', $value)) {
+ return true;
+ }
+
+ $message = _("This field must be a comma or space separated list of integers");
+ return false;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Integer list"));
+ }
+
+}
+
+class Horde_Form_Type_text extends Horde_Form_Type {
+
+ var $_regex;
+ var $_size;
+ var $_maxlength;
+
+ /**
+ * The initialisation function for the text variable type.
+ *
+ * @access private
+ *
+ * @param string $regex Any valid PHP PCRE pattern syntax that
+ * needs to be matched for the field to be
+ * considered valid. If left empty validity
+ * will be checked only for required fields
+ * whether they are empty or not.
+ * If using this regex test it is advisable
+ * to enter a description for this field to
+ * warn the user what is expected, as the
+ * generated error message is quite generic
+ * and will not give any indication where
+ * the regex failed.
+ * @param integer $size The size of the input field.
+ * @param integer $maxlength The max number of characters.
+ */
+ function init($regex = '', $size = 40, $maxlength = null)
+ {
+ $this->_regex = $regex;
+ $this->_size = $size;
+ $this->_maxlength = $maxlength;
+ }
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ $valid = true;
+
+ if (!empty($this->_maxlength) && String::length($value) > $this->_maxlength) {
+ $valid = false;
+ $message = sprintf(_("Value is over the maximum length of %s."), $this->_maxlength);
+ } elseif ($var->isRequired() && empty($this->_regex)) {
+ if (!($valid = strlen(trim($value)) > 0)) {
+ $message = _("This field is required.");
+ }
+ } elseif (strlen($this->_regex)) {
+ if (!($valid = preg_match($this->_regex, $value))) {
+ $message = _("You must enter a valid value.");
+ }
+ }
+
+ return $valid;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Text"),
+ 'params' => array(
+ 'regex' => array('label' => _("Regex"),
+ 'type' => 'text'),
+ 'size' => array('label' => _("Size"),
+ 'type' => 'int'),
+ 'maxlength' => array('label' => _("Maximum length"),
+ 'type' => 'int')));
+ }
+
+}
+
+class Horde_Form_Type_stringlist extends Horde_Form_Type_text {
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("String list"),
+ 'params' => array(
+ 'regex' => array('label' => _("Regex"),
+ 'type' => 'text'),
+ 'size' => array('label' => _("Size"),
+ 'type' => 'int'),
+ 'maxlength' => array('label' => _("Maximum length"),
+ 'type' => 'int')),
+ );
+ }
+
+}
+
+class Horde_Form_Type_phone extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ $valid = true;
+
+ if ($var->isRequired()) {
+ $valid = strlen(trim($value)) > 0;
+ if (!$valid) {
+ $message = _("This field is required.");
+ }
+ } else {
+ $valid = preg_match('/^\+?[\d()\-\/ ]*$/', $value);
+ if (!$valid) {
+ $message = _("You must enter a valid phone number, digits only with an optional '+' for the international dialing prefix.");
+ }
+ }
+
+ return $valid;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Phone number"));
+ }
+
+}
+
+class Horde_Form_Type_cellphone extends Horde_Form_Type_phone {
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Mobile phone number"));
+ }
+
+}
+
+class Horde_Form_Type_ipaddress extends Horde_Form_Type_text {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ $valid = true;
+
+ if (strlen(trim($value)) > 0) {
+ $ip = explode('.', $value);
+ $valid = (count($ip) == 4);
+ if ($valid) {
+ foreach ($ip as $part) {
+ if (!is_numeric($part) ||
+ $part > 255 ||
+ $part < 0) {
+ $valid = false;
+ break;
+ }
+ }
+ }
+
+ if (!$valid) {
+ $message = _("Please enter a valid IP address.");
+ }
+ } elseif ($var->isRequired()) {
+ $valid = false;
+ $message = _("This field is required.");
+ }
+
+ return $valid;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("IP address"));
+ }
+
+}
+
+class Horde_Form_Type_longtext extends Horde_Form_Type_text {
+
+ var $_rows;
+ var $_cols;
+ var $_helper = array();
+
+ function init($rows = 8, $cols = 80, $helper = array())
+ {
+ if (!is_array($helper)) {
+ $helper = array($helper);
+ }
+
+ $this->_rows = $rows;
+ $this->_cols = $cols;
+ $this->_helper = $helper;
+ }
+
+ function hasHelper($option = '')
+ {
+ if (empty($option)) {
+ /* No option specified, check if any helpers have been
+ * activated. */
+ return !empty($this->_helper);
+ } elseif (empty($this->_helper)) {
+ /* No helpers activated at all, return false. */
+ return false;
+ } else {
+ /* Check if given helper has been activated. */
+ return in_array($option, $this->_helper);
+ }
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Long text"),
+ 'params' => array(
+ 'rows' => array('label' => _("Number of rows"),
+ 'type' => 'int'),
+ 'cols' => array('label' => _("Number of columns"),
+ 'type' => 'int'),
+ 'helper' => array('label' => _("Helper?"),
+ 'type' => 'boolean')));
+ }
+
+}
+
+class Horde_Form_Type_countedtext extends Horde_Form_Type_longtext {
+
+ var $_chars;
+
+ function init($rows = null, $cols = null, $chars = 1000)
+ {
+ parent::init($rows, $cols);
+ $this->_chars = $chars;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ $valid = true;
+
+ $length = String::length(trim($value));
+
+ if ($var->isRequired() && $length <= 0) {
+ $valid = false;
+ $message = _("This field is required.");
+ } elseif ($length > $this->_chars) {
+ $valid = false;
+ $message = sprintf(_("There are too many characters in this field. You have entered %s characters; you must enter less than %s."), String::length(trim($value)), $this->_chars);
+ }
+
+ return $valid;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Counted text"),
+ 'params' => array(
+ 'rows' => array('label' => _("Number of rows"),
+ 'type' => 'int'),
+ 'cols' => array('label' => _("Number of columns"),
+ 'type' => 'int'),
+ 'chars' => array('label' => _("Number of characters"),
+ 'type' => 'int')));
+ }
+
+}
+
+class Horde_Form_Type_address extends Horde_Form_Type_longtext {
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Address"),
+ 'params' => array(
+ 'rows' => array('label' => _("Number of rows"),
+ 'type' => 'int'),
+ 'cols' => array('label' => _("Number of columns"),
+ 'type' => 'int')));
+ }
+
+}
+
+class Horde_Form_Type_addresslink extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ return true;
+ }
+
+}
+
+class Horde_Form_Type_file extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->isRequired()) {
+ $uploaded = Horde_Browser::wasFileUploaded($var->getVarName());
+ if (is_a($uploaded, 'PEAR_Error')) {
+ $message = $uploaded->getMessage();
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function getInfo($vars, $var, &$info)
+ {
+ $name = $var->getVarName();
+ $uploaded = Horde_Browser::wasFileUploaded($name);
+ if ($uploaded === true) {
+ $info['name'] = $_FILES[$name]['name'];
+ $info['type'] = $_FILES[$name]['type'];
+ $info['tmp_name'] = $_FILES[$name]['tmp_name'];
+ $info['file'] = $_FILES[$name]['tmp_name'];
+ $info['error'] = $_FILES[$name]['error'];
+ $info['size'] = $_FILES[$name]['size'];
+ }
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("File upload"));
+ }
+
+}
+
+class Horde_Form_Type_image extends Horde_Form_Type {
+
+ /**
+ * Has a file been uploaded on this form submit?
+ *
+ * @var boolean
+ */
+ var $_uploaded = null;
+
+ /**
+ * Show the upload button?
+ *
+ * @var boolean
+ */
+ var $_show_upload = true;
+
+ /**
+ * Show the option to upload also original non-modified image?
+ *
+ * @var boolean
+ */
+ var $_show_keeporig = false;
+
+ /**
+ * Limit the file size?
+ *
+ * @var integer
+ */
+ var $_max_filesize = null;
+
+ /**
+ * Hash containing the previously uploaded image info.
+ *
+ * @var array
+ */
+ var $_img = array();
+
+ function init($show_upload = true, $show_keeporig = false, $max_filesize = null)
+ {
+ $this->_show_upload = $show_upload;
+ $this->_show_keeporig = $show_keeporig;
+ $this->_max_filesize = $max_filesize;
+ }
+
+ function onSubmit($var, $vars)
+ {
+ /* Get the upload. */
+ $this->_getUpload($vars, $var);
+
+ /* If this was done through the upload button override the submitted
+ * value of the form. */
+ if ($vars->get('_do_' . $var->getVarName())) {
+ $var->form->setSubmitted(false);
+ }
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ $field = $vars->get($var->getVarName());
+
+ /* Get the upload. */
+ $this->_getUpload($vars, $var);
+
+ /* The upload generated a PEAR Error. */
+ if (is_a($this->_uploaded, 'PEAR_Error')) {
+ /* Not required and no image upload attempted. */
+ if (!$var->isRequired() && empty($field['img']) &&
+ $this->_uploaded->getCode() == UPLOAD_ERR_NO_FILE) {
+ return true;
+ }
+
+ if (($this->_uploaded->getCode() == UPLOAD_ERR_NO_FILE) &&
+ empty($field['img'])) {
+ /* Nothing uploaded and no older upload. */
+ $message = _("This field is required.");
+ return false;
+ } elseif (!empty($field['img'])) {
+ /* Nothing uploaded but older upload present. */
+ return true;
+ } else {
+ /* Some other error message. */
+ $message = $this->_uploaded->getMessage();
+ return false;
+ }
+ } elseif ($this->_max_filesize &&
+ $this->_img['size'] > $this->_max_filesize) {
+ $message = sprintf(_("The image file was larger than the maximum allowed size (%d bytes)."), $this->_max_filesize);
+ return false;
+ }
+
+ return true;
+ }
+
+ function getInfo($vars, $var, &$info)
+ {
+ /* Get the upload. */
+ $this->_getUpload($vars, $var);
+
+ /* Get image params stored in the hidden field. */
+ $value = $var->getValue($vars);
+ $info = $this->_img;
+ if (empty($info['file'])) {
+ unset($info['file']);
+ return;
+ }
+ if ($this->_show_keeporig) {
+ $info['keep_orig'] = !empty($value['keep_orig']);
+ }
+
+ /* Set the uploaded value (either true or PEAR_Error). */
+ $info['uploaded'] = &$this->_uploaded;
+
+ /* If a modified file exists move it over the original. */
+ if ($this->_show_keeporig && $info['keep_orig']) {
+ /* Requested the saving of original file also. */
+ $info['orig_file'] = Horde::getTempDir() . '/' . $info['file'];
+ $info['file'] = Horde::getTempDir() . '/mod_' . $info['file'];
+ /* Check if a modified file actually exists. */
+ if (!file_exists($info['file'])) {
+ $info['file'] = $info['orig_file'];
+ unset($info['orig_file']);
+ }
+ } else {
+ /* Saving of original not required. */
+ $mod_file = Horde::getTempDir() . '/mod_' . $info['file'];
+ $info['file'] = Horde::getTempDir() . '/' . $info['file'];
+
+ if (file_exists($mod_file)) {
+ /* Unlink first (has to be done on Windows machines?) */
+ unlink($info['file']);
+ rename($mod_file, $info['file']);
+ }
+ }
+ }
+
+ /**
+ * Gets the upload and sets up the upload data array. Either
+ * fetches an upload done with this submit or retries stored
+ * upload info.
+ */
+ function _getUpload($vars, $var)
+ {
+ /* Don't bother with this function if already called and set
+ * up vars. */
+ if (!empty($this->_img)) {
+ return true;
+ }
+
+ /* Check if file has been uploaded. */
+ $varname = $var->getVarName();
+ $this->_uploaded = Horde_Browser::wasFileUploaded($varname . '[new]');
+
+ if ($this->_uploaded === true) {
+ /* A file has been uploaded on this submit. Save to temp dir for
+ * preview work. */
+ $this->_img['type'] = $this->getUploadedFileType($varname . '[new]');
+
+ /* Get the other parts of the upload. */
+ Horde_Array::getArrayParts($varname . '[new]', $base, $keys);
+
+ /* Get the temporary file name. */
+ $keys_path = array_merge(array($base, 'tmp_name'), $keys);
+ $this->_img['file'] = Horde_Array::getElement($_FILES, $keys_path);
+
+ /* Get the actual file name. */
+ $keys_path= array_merge(array($base, 'name'), $keys);
+ $this->_img['name'] = Horde_Array::getElement($_FILES, $keys_path);
+
+ /* Get the file size. */
+ $keys_path= array_merge(array($base, 'size'), $keys);
+ $this->_img['size'] = Horde_Array::getElement($_FILES, $keys_path);
+
+ /* Get any existing values for the image upload field. */
+ $upload = $vars->get($var->getVarName());
+ $upload['img'] = @unserialize($upload['img']);
+
+ /* Get the temp file if already one uploaded, otherwise create a
+ * new temporary file. */
+ if (!empty($upload['img']['file'])) {
+ $tmp_file = Horde::getTempDir() . '/' . $upload['img']['file'];
+ } else {
+ $tmp_file = Horde::getTempFile('Horde', false);
+ }
+
+ /* Move the browser created temp file to the new temp file. */
+ move_uploaded_file($this->_img['file'], $tmp_file);
+ $this->_img['file'] = basename($tmp_file);
+
+ /* Store the uploaded image file data to the hidden field. */
+ $upload['img'] = serialize($this->_img);
+ $vars->set($var->getVarName(), $upload);
+ } elseif ($this->_uploaded) {
+ /* File has not been uploaded. */
+ $upload = $vars->get($var->getVarName());
+ if ($this->_uploaded->getCode() == 4 && !empty($upload['img'])) {
+ $this->_img = @unserialize($upload['img']);
+ }
+ }
+ }
+
+ function getUploadedFileType($field)
+ {
+ /* Get any index on the field name. */
+ $index = Horde_Array::getArrayParts($field, $base, $keys);
+
+ if ($index) {
+ /* Index present, fetch the mime type var to check. */
+ $keys_path = array_merge(array($base, 'type'), $keys);
+ $type = Horde_Array::getElement($_FILES, $keys_path);
+ $keys_path= array_merge(array($base, 'tmp_name'), $keys);
+ $tmp_name = Horde_Array::getElement($_FILES, $keys_path);
+ } else {
+ /* No index, simple set up of vars to check. */
+ $type = $_FILES[$field]['type'];
+ $tmp_name = $_FILES[$field]['tmp_name'];
+ }
+
+ if (empty($type) || ($type == 'application/octet-stream')) {
+ /* Type wasn't set on upload, try analising the upload. */
+ global $conf;
+ require_once 'Horde/MIME/Magic.php';
+ if (!($type = MIME_Magic::analyzeFile($tmp_name, isset($conf['mime']['magic_db']) ? $conf['mime']['magic_db'] : null))) {
+ if ($index) {
+ /* Get the name value. */
+ $keys_path = array_merge(array($base, 'name'), $keys);
+ $name = Horde_Array::getElement($_FILES, $keys_path);
+
+ /* Work out the type from the file name. */
+ $type = MIME_Magic::filenameToMIME($name);
+
+ /* Set the type. */
+ $keys_path = array_merge(array($base, 'type'), $keys);
+ Horde_Array::getElement($_FILES, $keys_path, $type);
+ } else {
+ /* Work out the type from the file name. */
+ $type = MIME_Magic::filenameToMIME($_FILES[$field]['name']);
+
+ /* Set the type. */
+ $_FILES[$field]['type'] = MIME_Magic::filenameToMIME($_FILES[$field]['name']);
+ }
+ }
+ }
+
+ return $type;
+ }
+
+ /**
+ * Loads any existing image data into the image field. Requires that the
+ * array $image passed to it contains the structure:
+ * $image['load']['file'] - the filename of the image;
+ * $image['load']['data'] - the raw image data.
+ *
+ * @param array $image The image array.
+ */
+ function loadImageData(&$image)
+ {
+ /* No existing image data to load. */
+ if (!isset($image['load'])) {
+ return;
+ }
+
+ /* Save the data to the temp dir. */
+ $tmp_file = Horde::getTempDir() . '/' . $image['load']['file'];
+ if ($fd = fopen($tmp_file, 'w')) {
+ fwrite($fd, $image['load']['data']);
+ fclose($fd);
+ }
+
+ $image['img'] = serialize(array('file' => $image['load']['file']));
+ unset($image['load']);
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Image upload"),
+ 'params' => array(
+ 'show_upload' => array('label' => _("Show upload?"),
+ 'type' => 'boolean'),
+ 'show_keeporig' => array('label' => _("Show option to keep original?"),
+ 'type' => 'boolean'),
+ 'max_filesize' => array('label' => _("Maximum file size in bytes"),
+ 'type' => 'int')));
+ }
+
+}
+
+class Horde_Form_Type_boolean extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ return true;
+ }
+
+ function getInfo($vars, $var, &$info)
+ {
+ $info = String::lower($vars->get($var->getVarName())) == 'on';
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("True or false"));
+ }
+
+}
+
+class Horde_Form_Type_link extends Horde_Form_Type {
+
+ /**
+ * List of hashes containing link parameters. Possible keys: 'url', 'text',
+ * 'target', 'onclick', 'title', 'accesskey'.
+ *
+ * @var array
+ */
+ var $values;
+
+ function init($values)
+ {
+ $this->values = $values;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ return true;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Link"),
+ 'params' => array(
+ 'url' => array(
+ 'label' => _("Link URL"),
+ 'type' => 'text'),
+ 'text' => array(
+ 'label' => _("Link text"),
+ 'type' => 'text'),
+ 'target' => array(
+ 'label' => _("Link target"),
+ 'type' => 'text'),
+ 'onclick' => array(
+ 'label' => _("Onclick event"),
+ 'type' => 'text'),
+ 'title' => array(
+ 'label' => _("Link title attribute"),
+ 'type' => 'text'),
+ 'accesskey' => array(
+ 'label' => _("Link access key"),
+ 'type' => 'text')));
+ }
+
+}
+
+class Horde_Form_Type_email extends Horde_Form_Type {
+
+ var $_allow_multi = false;
+ var $_strip_domain = false;
+ var $_link_compose = false;
+ var $_check_smtp = false;
+ var $_link_name;
+
+ /**
+ * A string containing valid delimiters (default is just comma).
+ *
+ * @var string
+ */
+ var $_delimiters = ',';
+
+ function init($allow_multi = false, $strip_domain = false,
+ $link_compose = false, $link_name = null,
+ $delimiters = ',')
+ {
+ $this->_allow_multi = $allow_multi;
+ $this->_strip_domain = $strip_domain;
+ $this->_link_compose = $link_compose;
+ $this->_link_name = $link_name;
+ $this->_delimiters = $delimiters;
+ }
+
+ /**
+ */
+ function isValid($var, $vars, $value, &$message)
+ {
+ // Split into individual addresses.
+ $emails = $this->splitEmailAddresses($value);
+
+ // Check for too many.
+ if (!$this->_allow_multi && count($emails) > 1) {
+ $message = _("Only one email address is allowed.");
+ return false;
+ }
+
+ // Check for all valid and at least one non-empty.
+ $nonEmpty = 0;
+ foreach ($emails as $email) {
+ if (!strlen($email)) {
+ continue;
+ }
+ if (!$this->validateEmailAddress($email)) {
+ $message = sprintf(_("\"%s\" is not a valid email address."), $email);
+ return false;
+ }
+ ++$nonEmpty;
+ }
+
+ if (!$nonEmpty && $var->isRequired()) {
+ if ($this->_allow_multi) {
+ $message = _("You must enter at least one email address.");
+ } else {
+ $message = _("You must enter an email address.");
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Explodes an RFC 2822 string, ignoring a delimiter if preceded
+ * by a "\" character, or if the delimiter is inside single or
+ * double quotes.
+ *
+ * @param string $string The RFC 822 string.
+ *
+ * @return array The exploded string in an array.
+ */
+ function splitEmailAddresses($string)
+ {
+ $quotes = array('"', "'");
+ $emails = array();
+ $pos = 0;
+ $in_quote = null;
+ $in_group = false;
+ $prev = null;
+
+ if (!strlen($string)) {
+ return array();
+ }
+
+ $char = $string[0];
+ if (in_array($char, $quotes)) {
+ $in_quote = $char;
+ } elseif ($char == ':') {
+ $in_group = true;
+ } elseif (strpos($this->_delimiters, $char) !== false) {
+ $emails[] = '';
+ $pos = 1;
+ }
+
+ for ($i = 1, $iMax = strlen($string); $i < $iMax; ++$i) {
+ $char = $string[$i];
+ if (in_array($char, $quotes)) {
+ if ($prev !== '\\') {
+ if ($in_quote === $char) {
+ $in_quote = null;
+ } elseif (is_null($in_quote)) {
+ $in_quote = $char;
+ }
+ }
+ } elseif ($in_group) {
+ if ($char == ';') {
+ $emails[] = substr($string, $pos, $i - $pos + 1);
+ $pos = $i + 1;
+ $in_group = false;
+ }
+ } elseif ($char == ':') {
+ $in_group = true;
+ } elseif (strpos($this->_delimiters, $char) !== false &&
+ $prev !== '\\' &&
+ is_null($in_quote)) {
+ $emails[] = substr($string, $pos, $i - $pos);
+ $pos = $i + 1;
+ }
+ $prev = $char;
+ }
+
+ if ($pos != $i) {
+ /* The string ended without a delimiter. */
+ $emails[] = substr($string, $pos, $i - $pos);
+ }
+
+ return $emails;
+ }
+
+ /**
+ * RFC(2)822 Email Parser.
+ *
+ * By Cal Henderson <cal@iamcal.com>
+ * This code is licensed under a Creative Commons Attribution-ShareAlike 2.5 License
+ * http://creativecommons.org/licenses/by-sa/2.5/
+ *
+ * http://code.iamcal.com/php/rfc822/
+ *
+ * http://iamcal.com/publish/articles/php/parsing_email
+ *
+ * Revision 4
+ *
+ * @param string $email An individual email address to validate.
+ *
+ * @return boolean
+ */
+ function validateEmailAddress($email)
+ {
+ static $comment_regexp, $email_regexp;
+ if ($comment_regexp === null) {
+ $this->_defineValidationRegexps($comment_regexp, $email_regexp);
+ }
+
+ // We need to strip comments first (repeat until we can't find
+ // any more).
+ while (true) {
+ $new = preg_replace("!$comment_regexp!", '', $email);
+ if (strlen($new) == strlen($email)){
+ break;
+ }
+ $email = $new;
+ }
+
+ // Now match what's left.
+ $result = (bool)preg_match("!^$email_regexp$!", $email);
+ if ($result && $this->_check_smtp) {
+ $result = $this->validateEmailAddressSmtp($email);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Attempt partial delivery of mail to an address to validate it.
+ *
+ * @param string $email An individual email address to validate.
+ *
+ * @return boolean
+ */
+ function validateEmailAddressSmtp($email)
+ {
+ list(, $maildomain) = explode('@', $email, 2);
+
+ // Try to get the real mailserver from MX records.
+ if (function_exists('getmxrr') &&
+ @getmxrr($maildomain, $mxhosts, $mxpriorities)) {
+ // MX record found.
+ array_multisort($mxpriorities, $mxhosts);
+ $mailhost = $mxhosts[0];
+ } else {
+ // No MX record found, try the root domain as the mail
+ // server.
+ $mailhost = $maildomain;
+ }
+
+ $fp = @fsockopen($mailhost, 25, $errno, $errstr, 5);
+ if (!$fp) {
+ return false;
+ }
+
+ // Read initial response.
+ fgets($fp, 4096);
+
+ // HELO
+ fputs($fp, "HELO $mailhost\r\n");
+ fgets($fp, 4096);
+
+ // MAIL FROM
+ fputs($fp, "MAIL FROM: <root@example.com>\r\n");
+ fgets($fp, 4096);
+
+ // RCPT TO - gets the result we want.
+ fputs($fp, "RCPT TO: <$email>\r\n");
+ $result = trim(fgets($fp, 4096));
+
+ // QUIT
+ fputs($fp, "QUIT\r\n");
+ fgets($fp, 4096);
+ fclose($fp);
+
+ return substr($result, 0, 1) == '2';
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Email"),
+ 'params' => array(
+ 'allow_multi' => array('label' => _("Allow multiple addresses?"),
+ 'type' => 'boolean'),
+ 'strip_domain' => array('label' => _("Protect address from spammers?"),
+ 'type' => 'boolean'),
+ 'link_compose' => array('label' => _("Link the email address to the compose page when displaying?"),
+ 'type' => 'boolean'),
+ 'link_name' => array('label' => _("The name to use when linking to the compose page"),
+ 'type' => 'text'),
+ 'delimiters' => array('label' => _("Character to split multiple addresses with"),
+ 'type' => 'text'),
+ ),
+ );
+ }
+
+ /**
+ * RFC(2)822 Email Parser.
+ *
+ * By Cal Henderson <cal@iamcal.com>
+ * This code is licensed under a Creative Commons Attribution-ShareAlike 2.5 License
+ * http://creativecommons.org/licenses/by-sa/2.5/
+ *
+ * http://code.iamcal.com/php/rfc822/
+ *
+ * http://iamcal.com/publish/articles/php/parsing_email
+ *
+ * Revision 4
+ *
+ * @param string &$comment The regexp for comments.
+ * @param string &$addr_spec The regexp for email addresses.
+ */
+ function _defineValidationRegexps(&$comment, &$addr_spec)
+ {
+ /**
+ * NO-WS-CTL = %d1-8 / ; US-ASCII control characters
+ * %d11 / ; that do not include the
+ * %d12 / ; carriage return, line feed,
+ * %d14-31 / ; and white space characters
+ * %d127
+ * ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
+ * DIGIT = %x30-39
+ */
+ $no_ws_ctl = "[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]";
+ $alpha = "[\\x41-\\x5a\\x61-\\x7a]";
+ $digit = "[\\x30-\\x39]";
+ $cr = "\\x0d";
+ $lf = "\\x0a";
+ $crlf = "($cr$lf)";
+
+ /**
+ * obs-char = %d0-9 / %d11 / ; %d0-127 except CR and
+ * %d12 / %d14-127 ; LF
+ * obs-text = *LF *CR *(obs-char *LF *CR)
+ * text = %d1-9 / ; Characters excluding CR and LF
+ * %d11 /
+ * %d12 /
+ * %d14-127 /
+ * obs-text
+ * obs-qp = "\" (%d0-127)
+ * quoted-pair = ("\" text) / obs-qp
+ */
+ $obs_char = "[\\x00-\\x09\\x0b\\x0c\\x0e-\\x7f]";
+ $obs_text = "($lf*$cr*($obs_char$lf*$cr*)*)";
+ $text = "([\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f]|$obs_text)";
+ $obs_qp = "(\\x5c[\\x00-\\x7f])";
+ $quoted_pair = "(\\x5c$text|$obs_qp)";
+
+ /**
+ * obs-FWS = 1*WSP *(CRLF 1*WSP)
+ * FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
+ * obs-FWS
+ * ctext = NO-WS-CTL / ; Non white space controls
+ * %d33-39 / ; The rest of the US-ASCII
+ * %d42-91 / ; characters not including "(",
+ * %d93-126 ; ")", or "\"
+ * ccontent = ctext / quoted-pair / comment
+ * comment = "(" *([FWS] ccontent) [FWS] ")"
+ * CFWS = *([FWS] comment) (([FWS] comment) / FWS)
+ *
+ * @note: We translate ccontent only partially to avoid an
+ * infinite loop. Instead, we'll recursively strip comments
+ * before processing the input.
+ */
+ $wsp = "[\\x20\\x09]";
+ $obs_fws = "($wsp+($crlf$wsp+)*)";
+ $fws = "((($wsp*$crlf)?$wsp+)|$obs_fws)";
+ $ctext = "($no_ws_ctl|[\\x21-\\x27\\x2A-\\x5b\\x5d-\\x7e])";
+ $ccontent = "($ctext|$quoted_pair)";
+ $comment = "(\\x28($fws?$ccontent)*$fws?\\x29)";
+ $cfws = "(($fws?$comment)*($fws?$comment|$fws))";
+ $cfws = "$fws*";
+
+ /**
+ * atext = ALPHA / DIGIT / ; Any character except controls,
+ * "!" / "#" / ; SP, and specials.
+ * "$" / "%" / ; Used for atoms
+ * "&" / "'" /
+ * "*" / "+" /
+ * "-" / "/" /
+ * "=" / "?" /
+ * "^" / "_" /
+ * "`" / "{" /
+ * "|" / "}" /
+ * "~"
+ * atom = [CFWS] 1*atext [CFWS]
+ */
+ $atext = "($alpha|$digit|[\\x21\\x23-\\x27\\x2a\\x2b\\x2d\\x2e\\x3d\\x3f\\x5e\\x5f\\x60\\x7b-\\x7e])";
+ $atom = "($cfws?$atext+$cfws?)";
+
+ /**
+ * qtext = NO-WS-CTL / ; Non white space controls
+ * %d33 / ; The rest of the US-ASCII
+ * %d35-91 / ; characters not including "\"
+ * %d93-126 ; or the quote character
+ * qcontent = qtext / quoted-pair
+ * quoted-string = [CFWS]
+ * DQUOTE *([FWS] qcontent) [FWS] DQUOTE
+ * [CFWS]
+ * word = atom / quoted-string
+ */
+ $qtext = "($no_ws_ctl|[\\x21\\x23-\\x5b\\x5d-\\x7e])";
+ $qcontent = "($qtext|$quoted_pair)";
+ $quoted_string = "($cfws?\\x22($fws?$qcontent)*$fws?\\x22$cfws?)";
+ $word = "($atom|$quoted_string)";
+
+ /**
+ * obs-local-part = word *("." word)
+ * obs-domain = atom *("." atom)
+ */
+ $obs_local_part = "($word(\\x2e$word)*)";
+ $obs_domain = "($atom(\\x2e$atom)*)";
+
+ /**
+ * dot-atom-text = 1*atext *("." 1*atext)
+ * dot-atom = [CFWS] dot-atom-text [CFWS]
+ */
+ $dot_atom_text = "($atext+(\\x2e$atext+)*)";
+ $dot_atom = "($cfws?$dot_atom_text$cfws?)";
+
+ /**
+ * domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
+ * dcontent = dtext / quoted-pair
+ * dtext = NO-WS-CTL / ; Non white space controls
+ *
+ * %d33-90 / ; The rest of the US-ASCII
+ * %d94-126 ; characters not including "[",
+ * ; "]", or "\"
+ */
+ $dtext = "($no_ws_ctl|[\\x21-\\x5a\\x5e-\\x7e])";
+ $dcontent = "($dtext|$quoted_pair)";
+ $domain_literal = "($cfws?\\x5b($fws?$dcontent)*$fws?\\x5d$cfws?)";
+
+ /**
+ * local-part = dot-atom / quoted-string / obs-local-part
+ * domain = dot-atom / domain-literal / obs-domain
+ * addr-spec = local-part "@" domain
+ */
+ $local_part = "($dot_atom|$quoted_string|$obs_local_part)";
+ $domain = "($dot_atom|$domain_literal|$obs_domain)";
+ $addr_spec = "($local_part\\x40$domain)";
+ }
+
+}
+
+class Horde_Form_Type_matrix extends Horde_Form_Type {
+
+ var $_cols;
+ var $_rows;
+ var $_matrix;
+ var $_new_input;
+
+ /**
+ * Initializes the variable.
+ *
+ * @example
+ * init(array('Column A', 'Column B'),
+ * array(1 => 'Row One', 2 => 'Row 2', 3 => 'Row 3'),
+ * array(array(true, true, false),
+ * array(true, false, true),
+ * array(fasle, true, false)),
+ * array('Row 4', 'Row 5'));
+ *
+ * @param array $cols A list of column headers.
+ * @param array $rows A hash with row IDs as the keys and row
+ * labels as the values.
+ * @param array $matrix A two dimensional hash with the field
+ * values.
+ * @param boolean|array $new_input If true, a free text field to add a new
+ * row is displayed on the top, a select
+ * box if this parameter is a value.
+ */
+ function init($cols, $rows = array(), $matrix = array(), $new_input = false)
+ {
+ $this->_cols = $cols;
+ $this->_rows = $rows;
+ $this->_matrix = $matrix;
+ $this->_new_input = $new_input;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ return true;
+ }
+
+ function getInfo($vars, $var, &$info)
+ {
+ $values = $vars->get($var->getVarName());
+ if (!empty($values['n']['r']) && isset($values['n']['v'])) {
+ $new_row = $values['n']['r'];
+ $values['r'][$new_row] = $values['n']['v'];
+ unset($values['n']);
+ }
+
+ $info = (isset($values['r']) ? $values['r'] : array());
+ }
+
+ function about()
+ {
+ return array(
+ 'name' => _("Field matrix"),
+ 'params' => array(
+ 'cols' => array('label' => _("Column titles"),
+ 'type' => 'stringlist')));
+ }
+
+}
+
+class Horde_Form_Type_emailConfirm extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->isRequired() && empty($value['original'])) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if ($value['original'] != $value['confirm']) {
+ $message = _("Email addresses must match.");
+ return false;
+ } else {
+ $parser = new Mail_RFC822();
+ $parsed_email = $parser->parseAddressList($value['original'], false, true);
+
+ if (count($parsed_email) > 1) {
+ $message = _("Only one email address allowed.");
+ return false;
+ }
+ if (empty($parsed_email[0]->mailbox)) {
+ $message = _("You did not enter a valid email address.");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Email with confirmation"));
+ }
+
+}
+
+class Horde_Form_Type_password extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ $valid = true;
+
+ if ($var->isRequired()) {
+ $valid = strlen(trim($value)) > 0;
+
+ if (!$valid) {
+ $message = _("This field is required.");
+ }
+ }
+
+ return $valid;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Password"));
+ }
+
+}
+
+class Horde_Form_Type_passwordconfirm extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->isRequired() && empty($value['original'])) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if ($value['original'] != $value['confirm']) {
+ $message = _("Passwords must match.");
+ return false;
+ }
+
+ return true;
+ }
+
+ function getInfo($vars, $var, &$info)
+ {
+ $value = $vars->get($var->getVarName());
+ $info = $value['original'];
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Password with confirmation"));
+ }
+
+}
+
+class Horde_Form_Type_enum extends Horde_Form_Type {
+
+ var $_values;
+ var $_prompt;
+
+ function init($values, $prompt = null)
+ {
+ $this->_values = $values;
+
+ if ($prompt === true) {
+ $this->_prompt = _("-- select --");
+ } else {
+ $this->_prompt = $prompt;
+ }
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->isRequired() && $value == '' && !isset($this->_values[$value])) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (count($this->_values) == 0 || isset($this->_values[$value]) ||
+ ($this->_prompt && empty($value))) {
+ return true;
+ }
+
+ $message = _("Invalid data.");
+ return false;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Drop down list"),
+ 'params' => array(
+ 'values' => array('label' => _("Values to select from"),
+ 'type' => 'stringlist'),
+ 'prompt' => array('label' => _("Prompt text"),
+ 'type' => 'text')));
+ }
+
+}
+
+class Horde_Form_Type_mlenum extends Horde_Form_Type {
+
+ var $_values;
+ var $_prompts;
+
+ function init(&$values, $prompts = null)
+ {
+ $this->_values = &$values;
+
+ if ($prompts === true) {
+ $this->_prompts = array(_("-- select --"), _("-- select --"));
+ } elseif (!is_array($prompts)) {
+ $this->_prompts = array($prompts, $prompts);
+ } else {
+ $this->_prompts = $prompts;
+ }
+ }
+
+ function onSubmit($var, $vars)
+ {
+ $varname = $var->getVarName();
+ $value = $vars->get($varname);
+
+ if ($value['1'] != $value['old']) {
+ $var->form->setSubmitted(false);
+ }
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->isRequired() && (empty($value['1']) || empty($value['2']))) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (!count($this->_values) || isset($this->_values[$value['1']]) ||
+ (!empty($this->_prompts) && empty($value['1']))) {
+ return true;
+ }
+
+ $message = _("Invalid data.");
+ return false;
+ }
+
+ function getInfo($vars, &$var, &$info)
+ {
+ $info = $vars->get($var->getVarName());
+ return $info['2'];
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Multi-level drop down lists"),
+ 'params' => array(
+ 'values' => array('label' => _("Values to select from"),
+ 'type' => 'stringlist'),
+ 'prompt' => array('label' => _("Prompt text"),
+ 'type' => 'text')));
+ }
+
+}
+
+class Horde_Form_Type_multienum extends Horde_Form_Type_enum {
+
+ var $size = 5;
+
+ function init($values, $size = null)
+ {
+ if (!is_null($size)) {
+ $this->size = (int)$size;
+ }
+
+ parent::init($values);
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if (is_array($value)) {
+ foreach ($value as $val) {
+ if (!$this->isValid($var, $vars, $val, $message)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ if (empty($value) && ((string)(int)$value !== $value)) {
+ if ($var->isRequired()) {
+ $message = _("This field is required.");
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ if (count($this->_values) == 0 || isset($this->_values[$value])) {
+ return true;
+ }
+
+ $message = _("Invalid data.");
+ return false;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Multiple selection"),
+ 'params' => array(
+ 'values' => array('label' => _("Values"),
+ 'type' => 'stringlist'),
+ 'size' => array('label' => _("Size"),
+ 'type' => 'int'))
+ );
+ }
+
+}
+
+class Horde_Form_Type_keyval_multienum extends Horde_Form_Type_multienum {
+
+ function getInfo($vars, $var, &$info)
+ {
+ $value = $vars->get($var->getVarName());
+ $info = array();
+ foreach ($value as $key) {
+ $info[$key] = $this->_values[$key];
+ }
+ }
+
+}
+
+class Horde_Form_Type_radio extends Horde_Form_Type_enum {
+
+ /* Entirely implemented by Horde_Form_Type_enum; just a different
+ * view. */
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Radio selection"),
+ 'params' => array(
+ 'values' => array('label' => _("Values"),
+ 'type' => 'stringlist')));
+ }
+
+}
+
+class Horde_Form_Type_set extends Horde_Form_Type {
+
+ var $_values;
+ var $_checkAll = false;
+
+ function init(&$values, $checkAll = false)
+ {
+ $this->_values = $values;
+ $this->_checkAll = $checkAll;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if (count($this->_values) == 0 || count($value) == 0) {
+ return true;
+ }
+ foreach ($value as $item) {
+ if (!isset($this->_values[$item])) {
+ $error = true;
+ break;
+ }
+ }
+ if (!isset($error)) {
+ return true;
+ }
+
+ $message = _("Invalid data.");
+ return false;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Set"),
+ 'params' => array(
+ 'values' => array('label' => _("Values"),
+ 'type' => 'stringlist')));
+ }
+
+}
+
+class Horde_Form_Type_date extends Horde_Form_Type {
+
+ var $_format;
+
+ function init($format = '%a %d %B')
+ {
+ $this->_format = $format;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ $valid = true;
+
+ if ($var->isRequired()) {
+ $valid = strlen(trim($value)) > 0;
+
+ if (!$valid) {
+ $message = sprintf(_("%s is required"), $var->getHumanName());
+ }
+ }
+
+ return $valid;
+ }
+
+ /**
+ * @static
+ */
+ function getAgo($timestamp)
+ {
+ if ($timestamp === null) {
+ return '';
+ }
+
+ $diffdays = Date_Calc::dateDiff(date('j', $timestamp),
+ date('n', $timestamp),
+ date('Y', $timestamp),
+ date('j'), date('n'), date('Y'));
+
+ /* An error occured. */
+ if ($diffdays == -1) {
+ return;
+ }
+
+ $ago = $diffdays * Date_Calc::compareDates(date('j', $timestamp),
+ date('n', $timestamp),
+ date('Y', $timestamp),
+ date('j'), date('n'),
+ date('Y'));
+ if ($ago < -1) {
+ return sprintf(_(" (%s days ago)"), $diffdays);
+ } elseif ($ago == -1) {
+ return _(" (yesterday)");
+ } elseif ($ago == 0) {
+ return _(" (today)");
+ } elseif ($ago == 1) {
+ return _(" (tomorrow)");
+ } else {
+ return sprintf(_(" (in %s days)"), $diffdays);
+ }
+ }
+
+ function getFormattedTime($timestamp, $format = null, $showago = true)
+ {
+ if (empty($format)) {
+ $format = $this->_format;
+ }
+ if (!empty($timestamp)) {
+ return strftime($format, $timestamp) . ($showago ? Horde_Form_Type_date::getAgo($timestamp) : '');
+ } else {
+ return '';
+ }
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Date"));
+ }
+
+}
+
+class Horde_Form_Type_time extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->isRequired() && empty($value) && ((string)(double)$value !== $value)) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (empty($value) || preg_match('/^[0-2]?[0-9]:[0-5][0-9]$/', $value)) {
+ return true;
+ }
+
+ $message = _("This field may only contain numbers and the colon.");
+ return false;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Time"));
+ }
+
+}
+
+class Horde_Form_Type_hourminutesecond extends Horde_Form_Type {
+
+ var $_show_seconds;
+
+ function init($show_seconds = false)
+ {
+ $this->_show_seconds = $show_seconds;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ $time = $vars->get($var->getVarName());
+ if (!$this->_show_seconds && !isset($time['second'])) {
+ $time['second'] = 0;
+ }
+
+ if (!$this->emptyTimeArray($time) && !$this->checktime($time['hour'], $time['minute'], $time['second'])) {
+ $message = _("Please enter a valid time.");
+ return false;
+ } elseif ($this->emptyTimeArray($time) && $var->isRequired()) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ return true;
+ }
+
+ function checktime($hour, $minute, $second)
+ {
+ if (!isset($hour) || $hour == '' || ($hour < 0 || $hour > 23)) {
+ return false;
+ }
+ if (!isset($minute) || $minute == '' || ($minute < 0 || $minute > 60)) {
+ return false;
+ }
+ if (!isset($second) || $second === '' || ($second < 0 || $second > 60)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Return the time supplied as a Horde_Date object.
+ *
+ * @param string $time_in Date in one of the three formats supported by
+ * Horde_Form and Horde_Date (ISO format
+ * YYYY-MM-DD HH:MM:SS, timestamp YYYYMMDDHHMMSS and
+ * UNIX epoch).
+ *
+ * @return Date The time object.
+ */
+ function getTimeOb($time_in)
+ {
+ if (is_array($time_in)) {
+ if (!$this->emptyTimeArray($time_in)) {
+ $time_in = sprintf('1970-01-01 %02d:%02d:%02d', $time_in['hour'], $time_in['minute'], $this->_show_seconds ? $time_in['second'] : 0);
+ }
+ }
+
+ return new Horde_Date($time_in);
+ }
+
+ /**
+ * Return the time supplied split up into an array.
+ *
+ * @param string $time_in Time in one of the three formats supported by
+ * Horde_Form and Horde_Date (ISO format
+ * YYYY-MM-DD HH:MM:SS, timestamp YYYYMMDDHHMMSS and
+ * UNIX epoch).
+ *
+ * @return array Array with three elements - hour, minute and seconds.
+ */
+ function getTimeParts($time_in)
+ {
+ if (is_array($time_in)) {
+ /* This is probably a failed isValid input so just return the
+ * parts as they are. */
+ return $time_in;
+ } elseif (empty($time_in)) {
+ /* This is just an empty field so return empty parts. */
+ return array('hour' => '', 'minute' => '', 'second' => '');
+ }
+ $time = $this->getTimeOb($time_in);
+ return array('hour' => $time->hour,
+ 'minute' => $time->min,
+ 'second' => $time->sec);
+ }
+
+ function emptyTimeArray($time)
+ {
+ return (is_array($time) && empty($time['hour']) && empty($time['minute']) && empty($time['second']));
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Time selection"),
+ 'params' => array(
+ 'seconds' => array('label' => _("Show seconds?"),
+ 'type' => 'boolean')));
+ }
+
+}
+
+class Horde_Form_Type_monthyear extends Horde_Form_Type {
+
+ var $_start_year;
+ var $_end_year;
+
+ function init($start_year = null, $end_year = null)
+ {
+ if (empty($start_year)) {
+ $start_year = 1920;
+ }
+ if (empty($end_year)) {
+ $end_year = date('Y');
+ }
+
+ $this->_start_year = $start_year;
+ $this->_end_year = $end_year;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if (!$var->isRequired()) {
+ return true;
+ }
+
+ if (!$vars->get($this->getMonthVar($var)) ||
+ !$vars->get($this->getYearVar($var))) {
+ $message = _("Please enter a month and a year.");
+ return false;
+ }
+
+ return true;
+ }
+
+ function getMonthVar($var)
+ {
+ return $var->getVarName() . '[month]';
+ }
+
+ function getYearVar($var)
+ {
+ return $var->getVarName() . '[year]';
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Month and year"),
+ 'params' => array(
+ 'start_year' => array('label' => _("Start year"),
+ 'type' => 'int'),
+ 'end_year' => array('label' => _("End year"),
+ 'type' => 'int')));
+ }
+
+}
+
+class Horde_Form_Type_monthdayyear extends Horde_Form_Type {
+
+ var $_start_year;
+ var $_end_year;
+ var $_picker;
+ var $_format_in = null;
+ var $_format_out = '%x';
+
+ /**
+ * Return the date supplied as a Horde_Date object.
+ *
+ * @param integer $start_year The first available year for input.
+ * @param integer $end_year The last available year for input.
+ * @param boolean $picker Do we show the DHTML calendar?
+ * @param integer $format_in The format to use when sending the date
+ * for storage. Defaults to Unix epoch.
+ * Similar to the strftime() function.
+ * @param integer $format_out The format to use when displaying the
+ * date. Similar to the strftime() function.
+ */
+ function init($start_year = '', $end_year = '', $picker = true,
+ $format_in = null, $format_out = '%x')
+ {
+ if (empty($start_year)) {
+ $start_year = date('Y');
+ }
+ if (empty($end_year)) {
+ $end_year = date('Y') + 10;
+ }
+
+ $this->_start_year = $start_year;
+ $this->_end_year = $end_year;
+ $this->_picker = $picker;
+ $this->_format_in = $format_in;
+ $this->_format_out = $format_out;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ $date = $vars->get($var->getVarName());
+ $empty = $this->emptyDateArray($date);
+
+ if ($empty == 1 && $var->isRequired()) {
+ $message = _("This field is required.");
+ return false;
+ } elseif ($empty == 0 && !checkdate($date['month'], $date['day'], $date['year'])) {
+ $message = _("Please enter a valid date, check the number of days in the month.");
+ return false;
+ } elseif ($empty == -1) {
+ $message = _("Select all date components.");
+ return false;
+ }
+
+ return true;
+ }
+
+ function emptyDateArray($date)
+ {
+ if (!is_array($date)) {
+ return empty($date);
+ }
+
+ $empty = 0;
+ /* Check each date array component. */
+ foreach ($date as $key => $val) {
+ if (empty($val)) {
+ $empty++;
+ }
+ }
+
+ /* Check state of empty. */
+ if ($empty == 0) {
+ /* If no empty parts return 0. */
+ return 0;
+ } elseif ($empty == count($date)) {
+ /* If all empty parts return 1. */
+ return 1;
+ } else {
+ /* If some empty parts return -1. */
+ return -1;
+ }
+ }
+
+ /**
+ * Return the date supplied split up into an array.
+ *
+ * @param string $date_in Date in one of the three formats supported by
+ * Horde_Form and Horde_Date (ISO format
+ * YYYY-MM-DD HH:MM:SS, timestamp YYYYMMDDHHMMSS
+ * and UNIX epoch) plus the fourth YYYY-MM-DD.
+ *
+ * @return array Array with three elements - year, month and day.
+ */
+ function getDateParts($date_in)
+ {
+ if (is_array($date_in)) {
+ /* This is probably a failed isValid input so just return
+ * the parts as they are. */
+ return $date_in;
+ } elseif (empty($date_in)) {
+ /* This is just an empty field so return empty parts. */
+ return array('year' => '', 'month' => '', 'day' => '');
+ }
+
+ $date = $this->getDateOb($date_in);
+ return array('year' => $date->year,
+ 'month' => $date->month,
+ 'day' => $date->mday);
+ }
+
+ /**
+ * Return the date supplied as a Horde_Date object.
+ *
+ * @param string $date_in Date in one of the three formats supported by
+ * Horde_Form and Horde_Date (ISO format
+ * YYYY-MM-DD HH:MM:SS, timestamp YYYYMMDDHHMMSS
+ * and UNIX epoch) plus the fourth YYYY-MM-DD.
+ *
+ * @return Date The date object.
+ */
+ function getDateOb($date_in)
+ {
+ if (is_array($date_in)) {
+ /* If passed an array change it to the ISO format. */
+ if ($this->emptyDateArray($date_in) == 0) {
+ $date_in = sprintf('%04d-%02d-%02d 00:00:00',
+ $date_in['year'],
+ $date_in['month'],
+ $date_in['day']);
+ }
+ } elseif (preg_match('/^\d{4}-?\d{2}-?\d{2}$/', $date_in)) {
+ /* Fix the date if it is the shortened ISO. */
+ $date_in = $date_in . ' 00:00:00';
+ }
+
+ return new Horde_Date($date_in);
+ }
+
+ /**
+ * Return the date supplied as a Horde_Date object.
+ *
+ * @param string $date Either an already set up Horde_Date object or a
+ * string date in one of the three formats supported
+ * by Horde_Form and Horde_Date (ISO format
+ * YYYY-MM-DD HH:MM:SS, timestamp YYYYMMDDHHMMSS and
+ * UNIX epoch) plus the fourth YYYY-MM-DD.
+ *
+ * @return string The date formatted according to the $format_out
+ * parameter when setting up the monthdayyear field.
+ */
+ function formatDate($date)
+ {
+ if (!is_a($date, 'Date')) {
+ $date = $this->getDateOb($date);
+ }
+
+ return $date->strftime($this->_format_out);
+ }
+
+ /**
+ * Insert the date input through the form into $info array, in the format
+ * specified by the $format_in parameter when setting up monthdayyear
+ * field.
+ */
+ function getInfo($vars, &$var, &$info)
+ {
+ $info = $this->_validateAndFormat($var->getValue($vars), $var);
+ }
+
+ /**
+ * Validate/format a date submission.
+ */
+ function _validateAndFormat($value, $var)
+ {
+ /* If any component is empty consider it a bad date and return the
+ * default. */
+ if ($this->emptyDateArray($value) == 1) {
+ return $var->getDefault();
+ } else {
+ $date = $this->getDateOb($value);
+ if ($this->_format_in === null) {
+ return $date->timestamp();
+ } else {
+ return $date->strftime($this->_format_in);
+ }
+ }
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Date selection"),
+ 'params' => array(
+ 'start_year' => array('label' => _("Start year"),
+ 'type' => 'int'),
+ 'end_year' => array('label' => _("End year"),
+ 'type' => 'int'),
+ 'picker' => array('label' => _("Show picker?"),
+ 'type' => 'boolean'),
+ 'format_in' => array('label' => _("Storage format"),
+ 'type' => 'text'),
+ 'format_out' => array('label' => _("Display format"),
+ 'type' => 'text')));
+ }
+
+}
+
+/**
+ * @since Horde 3.2
+ */
+class Horde_Form_Type_datetime extends Horde_Form_Type {
+
+ var $_mdy;
+ var $_hms;
+
+ /**
+ * Return the date supplied as a Horde_Date object.
+ *
+ * @param integer $start_year The first available year for input.
+ * @param integer $end_year The last available year for input.
+ * @param boolean $picker Do we show the DHTML calendar?
+ * @param integer $format_in The format to use when sending the date
+ * for storage. Defaults to Unix epoch.
+ * Similar to the strftime() function.
+ * @param integer $format_out The format to use when displaying the
+ * date. Similar to the strftime() function.
+ * @param boolean $show_seconds Include a form input for seconds.
+ */
+ function init($start_year = '', $end_year = '', $picker = true,
+ $format_in = null, $format_out = '%x', $show_seconds = false)
+ {
+ $this->_mdy = new Horde_Form_Type_monthdayyear();
+ $this->_mdy->init($start_year, $end_year, $picker, $format_in, $format_out);
+
+ $this->_hms = new Horde_Form_Type_hourminutesecond();
+ $this->_hms->init($show_seconds);
+ }
+
+ function isValid(&$var, &$vars, $value, &$message)
+ {
+ if ($var->isRequired()) {
+ return $this->_mdy->isValid($var, $vars, $value, $message) &&
+ $this->_hms->isValid($var, $vars, $value, $message);
+ }
+ return true;
+ }
+
+ function getInfo(&$vars, &$var, &$info)
+ {
+ /* If any component is empty consider it a bad date and return the
+ * default. */
+ $value = $var->getValue($vars);
+ if ($this->emptyDateArray($value) == 1 || $this->emptyTimeArray($value)) {
+ $info = $var->getDefault();
+ return;
+ }
+
+ $date = $this->getDateOb($value);
+ $time = $this->getTimeOb($value);
+ $date->hour = $time->hour;
+ $date->min = $time->min;
+ $date->sec = $time->sec;
+ if (is_null($this->format_in)) {
+ $info = $date->timestamp();
+ } else {
+ $info = $date->strftime($this->format_in);
+ }
+ }
+
+ function __get($property)
+ {
+ if ($property == 'show_seconds') {
+ return $this->_hms->$property;
+ } else {
+ return $this->_mdy->$property;
+ }
+ }
+
+ function __set($property, $value)
+ {
+ if ($property == 'show_seconds') {
+ $this->_hms->$property = $value;
+ } else {
+ $this->_mdy->$property = $value;
+ }
+ }
+
+ function checktime($hour, $minute, $second)
+ {
+ return $this->_hms->checktime($hour, $minute, $second);
+ }
+
+ function getTimeOb($time_in)
+ {
+ return $this->_hms->getTimeOb($time_in);
+ }
+
+ function getTimeParts($time_in)
+ {
+ return $this->_hms->getTimeParts($time_in);
+ }
+
+ function emptyTimeArray($time)
+ {
+ return $this->_hms->emptyTimeArray($time);
+ }
+
+ function emptyDateArray($date)
+ {
+ return $this->_mdy->emptyDateArray($date);
+ }
+
+ function getDateParts($date_in)
+ {
+ return $this->_mdy->getDateParts($date_in);
+ }
+
+ function getDateOb($date_in)
+ {
+ return $this->_mdy->getDateOb($date_in);
+ }
+
+ function formatDate($date)
+ {
+ if ($date === null) {
+ return '';
+ }
+ return $this->_mdy->formatDate($date);
+ }
+
+ function about()
+ {
+ return array(
+ 'name' => _("Date and time selection"),
+ 'params' => array(
+ 'start_year' => array('label' => _("Start year"),
+ 'type' => 'int'),
+ 'end_year' => array('label' => _("End year"),
+ 'type' => 'int'),
+ 'picker' => array('label' => _("Show picker?"),
+ 'type' => 'boolean'),
+ 'format_in' => array('label' => _("Storage format"),
+ 'type' => 'text'),
+ 'format_out' => array('label' => _("Display format"),
+ 'type' => 'text'),
+ 'seconds' => array('label' => _("Show seconds?"),
+ 'type' => 'boolean')));
+ }
+
+}
+
+class Horde_Form_Type_colorpicker extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->isRequired() && empty($value)) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (empty($value) || preg_match('/^#([0-9a-z]){6}$/i', $value)) {
+ return true;
+ }
+
+ $message = _("This field must contain a color code in the RGB Hex format, for example '#1234af'.");
+ return false;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Colour selection"));
+ }
+
+}
+
+class Horde_Form_Type_sorter extends Horde_Form_Type {
+
+ var $_instance;
+ var $_values;
+ var $_size;
+ var $_header;
+
+ function init($values, $size = 8, $header = '')
+ {
+ static $horde_sorter_instance = 0;
+
+ /* Get the next progressive instance count for the horde
+ * sorter so that multiple sorters can be used on one page. */
+ $horde_sorter_instance++;
+ $this->_instance = 'horde_sorter_' . $horde_sorter_instance;
+ $this->_values = $values;
+ $this->_size = $size;
+ $this->_header = $header;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ return true;
+ }
+
+ function getOptions($keys = null)
+ {
+ $html = '';
+ if ($this->_header) {
+ $html .= '<option value="">' . htmlspecialchars($this->_header) . '</option>';
+ }
+
+ if (empty($keys)) {
+ $keys = array_keys($this->_values);
+ } else {
+ $keys = explode("\t", $keys['array']);
+ }
+ foreach ($keys as $sl_key) {
+ $html .= '<option value="' . $sl_key . '">' . htmlspecialchars($this->_values[$sl_key]) . '</option>';
+ }
+
+ return $html;
+ }
+
+ function getInfo($vars, &$var, &$info)
+ {
+ $value = $vars->get($var->getVarName());
+ $info = explode("\t", $value['array']);
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Sort order selection"),
+ 'params' => array(
+ 'values' => array('label' => _("Values"),
+ 'type' => 'stringlist'),
+ 'size' => array('label' => _("Size"),
+ 'type' => 'int'),
+ 'header' => array('label' => _("Header"),
+ 'type' => 'text')));
+ }
+
+}
+
+class Horde_Form_Type_selectfiles extends Horde_Form_Type {
+
+ /**
+ * The text to use in the link.
+ *
+ * @var string
+ */
+ var $_link_text;
+
+ /**
+ * The style to use for the link.
+ *
+ * @var string
+ */
+ var $_link_style;
+
+ /**
+ * Create the link with an icon instead of text?
+ *
+ * @var boolean
+ */
+ var $_icon;
+
+ /**
+ * Contains gollem selectfile selectionID
+ *
+ * @var string
+ */
+ var $_selectid;
+
+ function init($selectid, $link_text = null, $link_style = '',
+ $icon = false)
+ {
+ $this->_selectid = $selectid;
+ if (is_null($link_text)) {
+ $link_text = _("Select Files");
+ }
+ $this->_link_text = $link_text;
+ $this->_link_style = $link_style;
+ $this->_icon = $icon;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ return true;
+ }
+
+ function getInfo($var, &$vars, &$info)
+ {
+ $value = $vars->getValue($var);
+ $info = $GLOBALS['registry']->call('files/selectlistResults', array($value));
+ }
+
+ function about()
+ {
+ return array(
+ 'name' => _("File selection"),
+ 'params' => array(
+ 'selectid' => array('label' => _("Id"),
+ 'type' => 'text'),
+ 'link_text' => array('label' => _("Link text"),
+ 'type' => 'text'),
+ 'link_style' => array('label' => _("Link style"),
+ 'type' => 'text'),
+ 'icon' => array('label' => _("Show icon?"),
+ 'type' => 'boolean')));
+ }
+
+}
+
+class Horde_Form_Type_assign extends Horde_Form_Type {
+
+ var $_leftValues;
+ var $_rightValues;
+ var $_leftHeader;
+ var $_rightHeader;
+ var $_size;
+ var $_width;
+
+ function init($leftValues, $rightValues, $leftHeader = '',
+ $rightHeader = '', $size = 8, $width = '200px')
+ {
+ $this->_leftValues = $leftValues;
+ $this->_rightValues = $rightValues;
+ $this->_leftHeader = $leftHeader;
+ $this->_rightHeader = $rightHeader;
+ $this->_size = $size;
+ $this->_width = $width;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ return true;
+ }
+
+ function setValues($side, $values)
+ {
+ if ($side) {
+ $this->_rightValues = $values;
+ } else {
+ $this->_leftValues = $values;
+ }
+ }
+
+ function getHeader($side)
+ {
+ return $side ? $this->_rightHeader : $this->_leftHeader;
+ }
+
+ function getOptions($side, $formname, $varname)
+ {
+ $html = '';
+ $headers = false;
+ if ($side) {
+ $values = $this->_rightValues;
+ if (!empty($this->_rightHeader)) {
+ $values = array('' => $this->_rightHeader) + $values;
+ $headers = true;
+ }
+ } else {
+ $values = $this->_leftValues;
+ if (!empty($this->_leftHeader)) {
+ $values = array('' => $this->_leftHeader) + $values;
+ $headers = true;
+ }
+ }
+
+ foreach ($values as $key => $val) {
+ $html .= '<option value="' . htmlspecialchars($key) . '"';
+ if ($headers) {
+ $headers = false;
+ } else {
+ $html .= ' ondblclick="Horde_Form_Assign.move(\'' . $formname . '\', \'' . $varname . '\', ' . (int)$side . ');"';
+ }
+ $html .= '>' . htmlspecialchars($val) . '</option>';
+ }
+
+ return $html;
+ }
+
+ function getInfo($vars, &$var, &$info)
+ {
+ $value = $vars->get($var->getVarName() . '__values');
+ if (strpos($value, "\t\t") === false) {
+ $left = $value;
+ $right = '';
+ } else {
+ list($left, $right) = explode("\t\t", $value);
+ }
+ if (empty($left)) {
+ $info['left'] = array();
+ } else {
+ $info['left'] = explode("\t", $left);
+ }
+ if (empty($right)) {
+ $info['right'] = array();
+ } else {
+ $info['right'] = explode("\t", $right);
+ }
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Assignment columns"),
+ 'params' => array(
+ 'leftValues' => array('label' => _("Left values"),
+ 'type' => 'stringlist'),
+ 'rightValues' => array('label' => _("Right values"),
+ 'type' => 'stringlist'),
+ 'leftHeader' => array('label' => _("Left header"),
+ 'type' => 'text'),
+ 'rightHeader' => array('label' => _("Right header"),
+ 'type' => 'text'),
+ 'size' => array('label' => _("Size"),
+ 'type' => 'int'),
+ 'width' => array('label' => _("Width in CSS units"),
+ 'type' => 'text')));
+ }
+
+}
+
+class Horde_Form_Type_creditcard extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if (empty($value) && $var->isRequired()) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (!empty($value)) {
+ /* getCardType() will also verify the checksum. */
+ $type = $this->getCardType($value);
+ if ($type === false || $type == 'unknown') {
+ $message = _("This does not seem to be a valid card number.");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function getChecksum($ccnum)
+ {
+ $len = strlen($ccnum);
+ if (!is_long($len / 2)) {
+ $weight = 2;
+ $digit = $ccnum[0];
+ } elseif (is_long($len / 2)) {
+ $weight = 1;
+ $digit = $ccnum[0] * 2;
+ }
+ if ($digit > 9) {
+ $digit = $digit - 9;
+ }
+ $i = 1;
+ $checksum = $digit;
+ while ($i < $len) {
+ if ($ccnum[$i] != ' ') {
+ $digit = $ccnum[$i] * $weight;
+ $weight = ($weight == 1) ? 2 : 1;
+ if ($digit > 9) {
+ $digit = $digit - 9;
+ }
+ $checksum += $digit;
+ }
+ $i++;
+ }
+
+ return $checksum;
+ }
+
+ function getCardType($ccnum)
+ {
+ $sum = $this->getChecksum($ccnum);
+ $l = strlen($ccnum);
+
+ // Screen checksum.
+ if (($sum % 10) != 0) {
+ return false;
+ }
+
+ // Check for Visa.
+ if ((($l == 16) || ($l == 13)) &&
+ ($ccnum[0] == 4)) {
+ return 'visa';
+ }
+
+ // Check for MasterCard.
+ if (($l == 16) &&
+ ($ccnum[0] == 5) &&
+ ($ccnum[1] >= 1) &&
+ ($ccnum[1] <= 5)) {
+ return 'mastercard';
+ }
+
+ // Check for Amex.
+ if (($l == 15) &&
+ ($ccnum[0] == 3) &&
+ (($ccnum[1] == 4) || ($ccnum[1] == 7))) {
+ return 'amex';
+ }
+
+ // Check for Discover (Novus).
+ if (strlen($ccnum) == 16 &&
+ substr($ccnum, 0, 4) == '6011') {
+ return 'discover';
+ }
+
+ // If we got this far, then no card matched.
+ return 'unknown';
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Credit card number"));
+ }
+
+}
+
+class Horde_Form_Type_obrowser extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ return true;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array('name' => _("Relationship browser"));
+ }
+
+}
+
+class Horde_Form_Type_dblookup extends Horde_Form_Type_enum {
+
+ function init($dsn, $sql, $prompt = null)
+ {
+ $values = array();
+ $db = DB::connect($dsn);
+ if (!is_a($db, 'PEAR_Error')) {
+ // Set DB portability options.
+ switch ($db->phptype) {
+ case 'mssql':
+ $db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM);
+ break;
+ default:
+ $db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS);
+ }
+
+ $col = $db->getCol($sql);
+ if (!is_a($col, 'PEAR_Error')) {
+ $values = Horde_Array::combine($col, $col);
+ }
+ }
+ parent::init($values, $prompt);
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Database lookup"),
+ 'params' => array(
+ 'dsn' => array('label' => _("DSN (see http://pear.php.net/manual/en/package.database.db.intro-dsn.php)"),
+ 'type' => 'text'),
+ 'sql' => array('label' => _("SQL statement for value lookups"),
+ 'type' => 'text'),
+ 'prompt' => array('label' => _("Prompt text"),
+ 'type' => 'text'))
+ );
+ }
+
+}
+
+class Horde_Form_Type_figlet extends Horde_Form_Type {
+
+ var $_text;
+ var $_font;
+
+ function init($text, $font)
+ {
+ $this->_text = $text;
+ $this->_font = $font;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if (empty($value) && $var->isRequired()) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (String::lower($value) != String::lower($this->_text)) {
+ $message = _("The text you entered did not match the text on the screen.");
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Return info about field type.
+ */
+ function about()
+ {
+ return array(
+ 'name' => _("Figlet CAPTCHA"),
+ 'params' => array(
+ 'text' => array('label' => _("Text"),
+ 'type' => 'text'),
+ 'font' => array('label' => _("Figlet font"),
+ 'type' => 'text'))
+ );
+ }
+
+}
+
+class Horde_Form_Type_invalid extends Horde_Form_Type {
+
+ var $message;
+
+ function init($message)
+ {
+ $this->message = $message;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ return false;
+ }
+
+}
+
+/**
+ * This class represents a single form variable that may be rendered as one or
+ * more form fields.
+ *
+ * @author Robert E. Coyle <robertecoyle@hotmail.com>
+ * @package Horde_Form
+ */
+class Horde_Form_Variable {
+
+ /**
+ * The form instance this variable is assigned to.
+ *
+ * @var Horde_Form
+ */
+ var $form;
+
+ /**
+ * A short description of this variable's purpose.
+ *
+ * @var string
+ */
+ var $humanName;
+
+ /**
+ * The internally used name.
+ *
+ * @var string
+ */
+ var $varName;
+
+ /**
+ * A {@link Horde_Form_Type} instance.
+ *
+ * @var Horde_Form_Type
+ */
+ var $type;
+
+ /**
+ * Whether this is a required variable.
+ *
+ * @var boolean
+ */
+ var $required;
+
+ /**
+ * Whether this is a readonly variable.
+ *
+ * @var boolean
+ */
+ var $readonly;
+
+ /**
+ * A long description of the variable's purpose, special instructions, etc.
+ *
+ * @var string
+ */
+ var $description;
+
+ /**
+ * The variable help text.
+ *
+ * @var string
+ */
+ var $help;
+
+ /**
+ * Whether this is an array variable.
+ *
+ * @var boolean
+ */
+ var $_arrayVal;
+
+ /**
+ * The default value.
+ *
+ * @var mixed
+ */
+ var $_defValue = null;
+
+ /**
+ * A {@link Horde_Form_Action} instance.
+ *
+ * @var Horde_Form_Action
+ */
+ var $_action;
+
+ /**
+ * Whether this variable is disabled.
+ *
+ * @var boolean
+ */
+ var $_disabled = false;
+
+ /**
+ * TODO
+ *
+ * @var boolean
+ */
+ var $_autofilled = false;
+
+ /**
+ * Whether this is a hidden variable.
+ *
+ * @var boolean
+ */
+ var $_hidden = false;
+
+ /**
+ * TODO
+ *
+ * @var array
+ */
+ var $_options = array();
+
+ /**
+ * Variable constructor.
+ *
+ * @param string $humanName A short description of the variable's
+ * purpose.
+ * @param string $varName The internally used name.
+ * @param Horde_Form_Type $type A {@link Horde_Form_Type} instance.
+ * @param boolean $required Whether this is a required variable.
+ * @param boolean $readonly Whether this is a readonly variable.
+ * @param string $description A long description of the variable's
+ * purpose, special instructions, etc.
+ */
+ function Horde_Form_Variable($humanName, $varName, $type, $required,
+ $readonly = false, $description = null)
+ {
+ $this->humanName = $humanName;
+ $this->varName = $varName;
+ $this->type = $type;
+ $this->required = $required;
+ $this->readonly = $readonly;
+ $this->description = $description;
+ $this->_arrayVal = (strpos($varName, '[]') !== false);
+ }
+
+ /**
+ * Assign this variable to the specified form.
+ *
+ * @param Horde_Form $form The form instance to assign this variable to.
+ */
+ function setFormOb($form)
+ {
+ $this->form = $form;
+ }
+
+ /**
+ * Sets a default value for this variable.
+ *
+ * @param mixed $value A variable value.
+ */
+ function setDefault($value)
+ {
+ $this->_defValue = $value;
+ }
+
+ /**
+ * Returns this variable's default value.
+ *
+ * @return mixed This variable's default value.
+ */
+ function getDefault()
+ {
+ return $this->_defValue;
+ }
+
+ /**
+ * Assigns an action to this variable.
+ *
+ * Example:
+ * <code>
+ * $v = $form->addVariable('My Variable', 'var1', 'text', false);
+ * $action = new Horde_Form_Action_submit;
+ * $v->setAction($action);
+ * </code>
+ *
+ * @param Horde_Form_Action $action A {@link Horde_Form_Action} instance.
+ */
+ function setAction($action)
+ {
+ $this->_action = $action;
+ }
+
+ /**
+ * Returns whether this variable has an attached action.
+ *
+ * @return boolean True if this variable has an attached action.
+ */
+ function hasAction()
+ {
+ return !is_null($this->_action);
+ }
+
+ /**
+ * Makes this a hidden variable.
+ */
+ function hide()
+ {
+ $this->_hidden = true;
+ }
+
+ /**
+ * Returns whether this is a hidden variable.
+ *
+ * @return boolean True if this a hidden variable.
+ */
+ function isHidden()
+ {
+ return $this->_hidden;
+ }
+
+ /**
+ * Disables this variable.
+ */
+ function disable()
+ {
+ $this->_disabled = true;
+ }
+
+ /**
+ * Returns whether this variable is disabled.
+ *
+ * @return boolean True if this variable is disabled.
+ */
+ function isDisabled()
+ {
+ return $this->_disabled;
+ }
+
+ /**
+ * Return the short description of this variable.
+ *
+ * @return string A short description
+ */
+ function getHumanName()
+ {
+ return $this->humanName;
+ }
+
+ /**
+ * Returns the internally used variable name.
+ *
+ * @return string This variable's internal name.
+ */
+ function getVarName()
+ {
+ return $this->varName;
+ }
+
+ /**
+ * Returns this variable's type.
+ *
+ * @return Horde_Form_Type This variable's {@link Horde_Form_Type}
+ * instance.
+ */
+ function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * Returns whether this is a required variable.
+ *
+ * @return boolean True if this is a required variable.
+ */
+ function isRequired()
+ {
+ return $this->required;
+ }
+
+ /**
+ * Returns whether this is a readonly variable.
+ *
+ * @return boolean True if this a readonly variable.
+ */
+ function isReadonly()
+ {
+ return $this->readonly;
+ }
+
+ /**
+ * Returns the possible values of this variable.
+ *
+ * @return array The possible values of this variable or null.
+ */
+ function getValues()
+ {
+ return $this->type->values;
+ }
+
+ /**
+ * Returns whether this variable has a long description.
+ *
+ * @return boolean True if this variable has a long description.
+ */
+ function hasDescription()
+ {
+ return !empty($this->description);
+ }
+
+ /**
+ * Returns this variable's long description.
+ *
+ * @return string This variable's long description.
+ */
+ function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Returns whether this is an array variable.
+ *
+ * @return boolean True if this an array variable.
+ */
+ function isArrayVal()
+ {
+ return $this->_arrayVal;
+ }
+
+ /**
+ * Returns whether this variable is to upload a file.
+ *
+ * @return boolean True if variable is to upload a file.
+ */
+ function isUpload()
+ {
+ return ($this->type instanceof Horde_Form_Type_file);
+ }
+
+ /**
+ * Assigns a help text to this variable.
+ *
+ * @param string $help The variable help text.
+ */
+ function setHelp($help)
+ {
+ $this->form->_help = true;
+ $this->help = $help;
+ }
+
+ /**
+ * Returns whether this variable has some help text assigned.
+ *
+ * @return boolean True if this variable has a help text.
+ */
+ function hasHelp()
+ {
+ return !empty($this->help);
+ }
+
+ /**
+ * Returns the help text of this variable.
+ *
+ * @return string This variable's help text.
+ */
+ function getHelp()
+ {
+ return $this->help;
+ }
+
+ /**
+ * Sets a variable option.
+ *
+ * @param string $option The option name.
+ * @param mixed $val The option's value.
+ */
+ function setOption($option, $val)
+ {
+ $this->_options[$option] = $val;
+ }
+
+ /**
+ * Returns a variable option's value.
+ *
+ * @param string $option The option name.
+ *
+ * @return mixed The option's value.
+ */
+ function getOption($option)
+ {
+ return isset($this->_options[$option]) ? $this->_options[$option] : null;
+ }
+
+ /**
+ * Processes the submitted value of this variable according to the rules of
+ * the variable type.
+ *
+ * @param Variables $vars The {@link Variables} instance of the submitted
+ * form.
+ * @param mixed $info A variable passed by reference that will be
+ * assigned the processed value of the submitted
+ * variable value.
+ *
+ * @return mixed Depending on the variable type.
+ */
+ function getInfo($vars, &$info)
+ {
+ return $this->type->getInfo($vars, $this, $info);
+ }
+
+ /**
+ * Returns whether this variable if it had the "trackchange" option set
+ * has actually been changed.
+ *
+ * @param Variables $vars The {@link Variables} instance of the submitted
+ * form.
+ *
+ * @return boolean Null if this variable doesn't have the "trackchange"
+ * option set or the form wasn't submitted yet. A boolean
+ * indicating whether the variable was changed otherwise.
+ */
+ function wasChanged($vars)
+ {
+ if (!$this->getOption('trackchange')) {
+ return null;
+ }
+ $old = $vars->get('__old_' . $this->getVarName());
+ if (is_null($old)) {
+ return null;
+ }
+ return $old != $vars->get($this->getVarName());
+ }
+
+ /**
+ * Validates this variable.
+ *
+ * @param Variables $vars The {@link Variables} instance of the submitted
+ * form.
+ * @param string $message A variable passed by reference that will be
+ * assigned a descriptive error message if
+ * validation failed.
+ *
+ * @return boolean True if the variable validated.
+ */
+ function validate($vars, &$message)
+ {
+ if ($this->_arrayVal) {
+ $vals = $this->getValue($vars);
+ if (!is_array($vals)) {
+ if ($this->required) {
+ $message = _("This field is required.");
+ return false;
+ } else {
+ return true;
+ }
+ }
+ foreach ($vals as $i => $value) {
+ if ($value === null && $this->required) {
+ $message = _("This field is required.");
+ return false;
+ } else {
+ if (!$this->type->isValid($this, $vars, $value, $message)) {
+ return false;
+ }
+ }
+ }
+ } else {
+ $value = $this->getValue($vars);
+ return $this->type->isValid($this, $vars, $value, $message);
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the submitted or default value of this variable.
+ * If an action is attached to this variable, the value will get passed to
+ * the action object.
+ *
+ * @param Variables $vars The {@link Variables} instance of the submitted
+ * form.
+ * @param integer $index If the variable is an array variable, this
+ * specifies the array element to return.
+ *
+ * @return mixed The variable or element value.
+ */
+ function getValue($vars, $index = null)
+ {
+ if ($this->_arrayVal) {
+ $name = str_replace('[]', '', $this->varName);
+ } else {
+ $name = $this->varName;
+ }
+ $value = $vars->getExists($name, $wasset);
+
+ if (!$wasset) {
+ $value = $this->getDefault();
+ }
+
+ if ($this->_arrayVal && !is_null($index)) {
+ if (!$wasset && !is_array($value)) {
+ $return = $value;
+ } else {
+ $return = isset($value[$index]) ? $value[$index] : null;
+ }
+ } else {
+ $return = $value;
+ }
+
+ if ($this->hasAction()) {
+ $this->_action->setValues($vars, $return, $this->_arrayVal);
+ }
+
+ return $return;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * @package Horde_Form
+ */
+
+/**
+ * The Horde_Form_Renderer class provides HTML and other renderings of
+ * forms for the Horde_Form:: package.
+ *
+ * $Horde: incubator/Horde_Form/Horde/Form/Renderer.php,v 1.7 2007/09/16 19:51:08 chuck Exp $
+ *
+ * Copyright 2001-2007 Robert E. Coyle <robertecoyle@hotmail.com>
+ * Copyright 2005-2007 Matt Warden <mwarden@gmail.com>
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author Robert E. Coyle <robertecoyle@hotmail.com>
+ * @author Matt Warden <mwarden@gmail.com>
+ * @package Horde_Form
+ */
+abstract class Horde_Form_Renderer {
+
+ var $_name;
+ var $_requiredLegend = false;
+ var $_helpMarker = '?';
+ var $_onLoadJS = array();
+ var $_showHeader = true;
+ var $_cols = 2;
+ var $_varRenderer = null;
+ var $_firstField = null;
+ var $_stripedRows = true;
+
+ protected $_submit = array();
+ protected $_reset = false;
+
+ /**
+ * Does the title of the form contain HTML? If so, you are responsible for
+ * doing any needed escaping/sanitization yourself. Otherwise the title
+ * will be run through htmlspecialchars() before being output.
+ *
+ * @var boolean
+ */
+ var $_encodeTitle = true;
+
+ /**
+ * Construct a new Horde_Form_Renderer::.
+ *
+ * @param array $params This is a hash of renderer-specific parameters.
+ * Possible keys:<code>
+ * 'encode_title': @see $_encodeTitle</code>
+ */
+ function __construct($params = array())
+ {
+ if (isset($params['encode_title'])) {
+ $this->encodeTitle($params['encode_title']);
+ }
+
+ $this->_varRenderer = new Horde_Form_VarRenderer_Xhtml;
+ }
+
+ abstract public function renderActive($form, $action, $method = 'get', $enctype = null, $focus = true);
+
+ public function setButtons($submit, $reset = false)
+ {
+ if ($submit === true || is_null($submit) || empty($submit)) {
+ /* Default to 'Submit'. */
+ $submit = array(_("Submit"));
+ } elseif (!is_array($submit)) {
+ /* Default to array if not passed. */
+ $submit = array($submit);
+ }
+ /* Only if $reset is strictly true insert default 'Reset'. */
+ if ($reset === true) {
+ $reset = _("Reset");
+ }
+
+ $this->_submit = $submit;
+ $this->_reset = $reset;
+
+ return $this;
+ }
+
+ public function addButtons($buttons)
+ {
+ if (!is_array($buttons)) {
+ $buttons = array($buttons);
+ }
+
+ $this->_submit = array_merge($this->_submit, $buttons);
+ }
+
+ public function showHeader($bool)
+ {
+ $this->_showHeader = $bool;
+ }
+
+ /**
+ * Sets or returns whether the form title should be encoded with
+ * htmlspecialchars().
+ *
+ * @param boolean $encode If true, the form title gets encoded. If false
+ * the title can contain HTML, but the class user
+ * is responsible to encode any special characters.
+ *
+ * @return boolean Whether the form title should be encoded.
+ */
+ function encodeTitle($encode = null)
+ {
+ if (!is_null($encode)) {
+ $this->_encodeTitle = $encode;
+ }
+ return $this->_encodeTitle = $encode;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ */
+class Horde_Form_Renderer_Xhtml extends Horde_Form_Renderer {
+
+ protected $_enctype = 'multipart/form-data';
+
+ function _renderSectionTabs($form)
+ {
+ /* If javascript is not available, do not render tabs. */
+ if (!$GLOBALS['browser']->hasFeature('javascript')) {
+ return;
+ }
+
+ $open_section = $form->getOpenSection();
+
+ /* Add the javascript for the toggling the sections. */
+ Horde::addScriptFile('form_sections.js', 'horde', true);
+ echo '<script type="text/javascript">' . "\n" .
+ sprintf('var sections_%1$s = new Horde_Form_Sections(\'%1$s\', \'%2$s\');',
+ $form->getName(),
+ $open_section) .
+ '</script>';
+
+ /* Loop through the sections and print out a tab for each. */
+ echo "<div class=\"tabset\">\n";
+ $js = array();
+ foreach ($form->_sections as $section => $val) {
+ $class = ($section == $open_section) ? ' class="activeTab"' : '';
+ $tabid = htmlspecialchars($form->getName() . '_tab_' . $section);
+ $js[$linkid] = sprintf('sections_%s.toggle(\'%s\'); return false;"',
+ $form->getName(),
+ $section);
+ printf('<div%s id="%s"><a href="#" id="%s">%s%s</a></div>' . "\n",
+ $class,
+ $tabid,
+ '_tablink_' . $section,
+ $form->getSectionImage($section),
+ $form->getSectionDesc($section));
+ }
+ echo "</div>\n";
+
+ // This doesn't help a whole lot now, but if there is a way to
+ // buffer output of JS, then we can keep JS separated from
+ // markup, whereas before the onclicks were assigned as an
+ // HTML attribute.
+ echo '<script type="text/javascript">' . "\n";
+ echo 'if (document.getElementById) {' . "\n";
+ echo ' addEvent(window, \'load\', function() {' . "\n";
+ foreach ($js as $id => $onclick) {
+ $line = '
+if (document.getElementById(%1$s)){
+ document.getElementById(%1$s).onclick = function() {
+ %2$s
+ };
+}';
+ printf($line, $id, $onclick);
+ }
+ echo ' });}</script>' . "\n";
+ }
+
+ function _renderSectionBegin($form, $section)
+ {
+ // Stripe alternate rows if that option is turned on.
+ if ($this->_stripedRows) {
+ Horde::addScriptFile('stripe.js', 'horde', true);
+ $class = 'striped';
+ } else {
+ $class = '';
+ }
+
+ $open_section = $form->getOpenSection();
+ if (empty($open_section)) {
+ $open_section = '__base';
+ }
+
+ // include a general class name for styling purposes. also helps select
+ // ULs, which only get a className currently if they are striped.
+ printf('<fieldset id="%s" class="%s form-section %s">',
+ htmlspecialchars($form->getName() . '_section_' . $section),
+ ($open_section == $section ? 'form-sectionshown' : 'form-sectionhidden'),
+ $class);
+ }
+
+ function _renderSectionEnd()
+ {
+ echo '</fieldset>';
+ }
+
+ function preserveVarByPost($vars, $varname, $alt_varname = '')
+ {
+ $value = $vars->getExists($varname, $wasset);
+
+ if ($alt_varname) {
+ $varname = $alt_varname;
+ }
+
+ if ($wasset) {
+ $this->_preserveVarByPost($varname, $value);
+ }
+ }
+
+ function _preserveVarByPost($varname, $value)
+ {
+ if (is_array($value)) {
+ foreach ($value as $id => $val) {
+ $this->_preserveVarByPost($varname . '[' . $id . ']', $val);
+ }
+ } else {
+ $varname = htmlspecialchars($varname);
+ $value = htmlspecialchars($value);
+ printf('<input type="hidden" id="%1$s" name="%1$s" value="%2$s" />'."\n",
+ $varname,
+ $value);
+ }
+ }
+
+ function listFormVars($form)
+ {
+ $variables = $form->getVariables(true, true);
+ $vars = array();
+ if ($variables) {
+ foreach ($variables as $var) {
+ if (is_object($var)) {
+ if (!$var->isReadonly()) {
+ $vars[$var->getVarName()] = 1;
+ }
+ } else {
+ $vars[$var] = 1;
+ }
+ }
+ }
+ require_once 'Horde/NLS.php';
+ echo '<input type="hidden" name="_formvars" value="'
+ . htmlspecialchars(serialize($vars), ENT_QUOTES, NLS::getCharset())
+ . '" />';
+ }
+
+ public function renderActive($form, $action, $method = 'get', $enctype = null, $focus = true)
+ {
+ $this->_name = $form->getName();
+
+ echo "<form class=\"horde-form\" action=\"$action\" method=\"$method\""
+ . (empty($this->_name) ? '' : ' id="' . $this->_name. '"')
+ . (is_null($this->_enctype) ? '' : ' enctype="' . $this->_enctype . '"')
+ . ">\n";
+ echo Util::formInput();
+
+ $this->listFormVars($form);
+
+ if (!empty($this->_name)) {
+ $this->_preserveVarByPost('formname', $this->_name);
+ }
+
+ if ($form->useToken()) {
+ $this->_preserveVarByPost($this->_name . '_formToken', Horde_Token::generateId($this->_name));
+ }
+
+ if (count($form->getSections())) {
+ $this->_preserveVarByPost('__formOpenSection', $form->getOpenSection());
+ }
+
+ $vars = $form->getVars();
+
+ $variables = $form->getVariables();
+ foreach ($variables as $var) {
+ if ($var->getOption('trackchange')) {
+ $varname = $var->getVarName();
+ $this->preserveVarByPost($vars, $varname, '__old_' . $varname);
+ }
+ }
+
+ foreach ($form->getHiddenVariables() as $var) {
+ $this->preserveVarByPost($vars, $var->getVarName());
+ }
+
+ $this->_renderBeginActive($form->getTitle());
+ $this->_renderForm($form, true);
+ $this->submit($this->_submit, $this->_reset);
+
+ echo "\n</fieldset>\n</form>\n";
+ if ($focus && !empty($this->_firstField)) {
+ echo '<script type="text/javascript">
+try {
+ document.getElementById("'. $this->_firstField .'").focus();
+} catch (e) {}
+</script>
+';
+ }
+ }
+
+ function renderInactive($form)
+ {
+ $this->_name = $form->getName();
+ $this->_renderBeginInactive($form->getTitle());
+ $this->_renderForm($form, false);
+ }
+
+ function _renderForm($form, $active)
+ {
+ $vars = $form->getVars();
+
+ /* If help is present 3 columns are needed. */
+ $this->_cols = $form->hasHelp() ? 3 : 2;
+
+ $variables = $form->getVariables(false);
+
+ /* Check for a form token error. */
+ if (($tokenError = $form->getError('_formToken')) !== null) {
+ printf('<p class="form-error">%s</p>'."\n", $tokenError);
+ }
+
+ $error_section = null;
+ reset($variables);
+ if (count($variables) > 1 || key($variables) != '__base') {
+ $this->_renderSectionTabs($form);
+ }
+
+ foreach ($variables as $section_id => $section) {
+ $this->_renderSectionBegin($form, $section_id);
+ foreach ($section as $var) {
+ switch (get_class($var->type)) {
+ case 'Horde_Form_Type_header':
+ $this->_renderHeader($var->getHumanName(), $form->getError($var->getVarName()));
+ break;
+
+ case 'Horde_Form_Type_description':
+ $this->_renderDescription($var->getHumanName());
+ break;
+
+ case 'Horde_Form_Type_spacer':
+ $this->_renderSpacer();
+ break;
+
+ default:
+ $isInput = ($active && !$var->isReadonly());
+ $format = $isInput ? 'Input' : 'Display';
+ $begin = "_renderVar${format}Begin";
+ $end = "_renderVar${format}End";
+
+ $this->$begin($form, $var);
+ echo $this->_varRenderer->render($form, $var, $vars, $isInput);
+ $this->$end($form, $var);
+
+ /* Print any javascript if actions present. */
+ if ($var->hasAction()) {
+ $var->_action->printJavaScript();
+ }
+
+ /* Keep first field. */
+ if ($active && empty($this->_firstField) && !$var->isReadonly()
+ && !$var->isHidden()) {
+ $this->_firstField = $var->getVarName();
+ }
+
+ /* Keep section with first error. */
+ if (is_null($error_section) && $form->getError($var)) {
+ $error_section = $section_id;
+ }
+ }
+ }
+
+ $this->_renderSectionEnd();
+ }
+
+ if (!is_null($error_section)) {
+ echo '<script type="text/javascript">' .
+ "\n" . sprintf('sections_%s.toggle(\'%s\');',
+ $form->getName(),
+ $error_section) .
+ "\n</script>\n";
+ }
+
+ echo '</fieldset>' . $this->_varRenderer->renderEnd();
+ }
+
+ function submit($submit = null, $reset = false)
+ {
+ if (is_null($submit) || empty($submit)) {
+ $submit = _("Submit");
+ }
+ if ($reset === true) {
+ $reset = _("Reset");
+ }
+ $this->_renderSubmit($submit, $reset);
+ }
+
+ /**
+ * Implementation specific begin function.
+ */
+ function _renderBeginActive($name)
+ {
+ echo '<fieldset class="horde-form" id="fieldset_' . htmlspecialchars($this->_name) . '">'."\n";
+ if ($this->_showHeader) {
+ $this->_renderSectionHeader($name);
+ }
+ if ($this->_requiredLegend) {
+ echo '<div class="form-error-example">' . $this->_requiredMarker
+ . ' = ' . _("Required Field") . '</div>'."\n";
+ }
+ }
+
+ /**
+ * Implementation specific begin function.
+ */
+ function _renderBeginInactive($name)
+ {
+ echo '<fieldset class="horde-form" id="fieldset_' . htmlspecialchars($this->_name) . '">';
+ if ($this->_showHeader) {
+ $this->_renderSectionHeader($name);
+ }
+ }
+
+ function _renderHeader($header, $error = '')
+ {
+ echo '<div class="form-header">'. $header . '</div>';
+ if (!empty($error)) {
+ echo '<div class="form-error">'. $error . '</div>';
+ }
+ }
+
+ function _renderDescription($description)
+ {
+ echo '<div class="form-description">'. $description . '</div>';
+ }
+
+ function _renderSpacer()
+ {
+ // TODO: fix this later so we're not inserting nonsemantic elements just for spacing
+ // ... maybe append form-spacer to class of next or previous element
+ echo '<div class="form-spacer"> </div>';
+ }
+
+ function _renderSubmit($submit, $reset)
+ {
+ echo '<fieldset class="form-buttons">'."\n";
+ if (!is_array($submit)) $submit = array($submit);
+ foreach ($submit as $submitbutton) {
+ echo '<input class="button" name="submitbutton" type="submit"';
+ // allow for default-value submit buttons (e.g. _renderSubmit(""))
+ if (!empty($submitbutton)) {
+ echo ' value="'. $submitbutton .'"';
+ }
+ echo ' />'."\n";
+ }
+ if (!empty($reset)) {
+ echo '<input class="button" name="resetbutton" type="reset"
+ value="'. $reset .'" />'."\n";
+ }
+ }
+
+ /**
+ * Renders the beginning of an writeable form entry, including the label
+ * and any form error related to this variable.
+ *
+ * @access private
+ * @author Matt Warden <mwarden@gmail.com>
+ * @author Robert E. Coyle <robertecoyle@hotmail.com>
+ */
+ function _renderVarInputBegin($form, $var, $readonly = false)
+ {
+ // get error message for variable, if any
+ $message = $form->getError($var);
+ // if no message, then no error
+ $isvalid = empty($message);
+
+ $classnames = 'form-input'
+ . (!$isvalid ? ' form-error' : '')
+ . ($var->isRequired() ? ' form-required' : '');
+
+ echo '<div class="', $classnames, '">';
+
+ if (!$isvalid) {
+ echo '<p class="form-error">', $message, '</p>', "\n";
+ }
+
+ printf('<label%s>%s</label>',
+ ($readonly ? '' : ' for="'. $var->getVarName() .'"'),
+ $var->getHumanName());
+ }
+
+ /**
+ * Renders the end of an writeable form entry, including any form notes
+ * and help info.
+ *
+ * @access private
+ * @author Matt Warden <mwarden@gmail.com>
+ * @author Robert E. Coyle <robertecoyle@hotmail.com>
+ */
+ function _renderVarInputEnd($form, $var)
+ {
+ /* Display any help for the field. */
+ if ($var->hasHelp()) {
+ global $registry;
+ if (isset($registry) && is_a($registry, 'Registry')) {
+ $help = Help::link($GLOBALS['registry']->getApp(), $var->getHelp());
+ } else {
+ $help = @htmlspecialchars($var->getHelp());
+ }
+ echo '<p class="form-hint">', $help, '</p>';
+ }
+
+ /* Display any description for the field. */
+ if ($var->hasDescription()) {
+ echo '<div class="form-note"><p>', $var->getDescription(), '</p></div>';
+ } else {
+ echo '<br class="clear" />';
+ }
+
+ echo '</div>';
+ }
+
+ /**
+ * Renders the beginning of a readonly form entry.
+ *
+ * @access private
+ * @author Matt Warden <mwarden@gmail.com>
+ * @author Robert E. Coyle <robertecoyle@hotmail.com>
+ */
+ function _renderVarDisplayBegin($form, $var)
+ {
+ return $this->_renderVarInputBegin($form, $var, true);
+ }
+
+ /**
+ * Renders the end of a readonly form entry. Help and notes are not
+ * applicable.
+ *
+ * @access private
+ * @author Matt Warden <mwarden@gmail.com>
+ * @author Robert E. Coyle <robertecoyle@hotmail.com>
+ */
+ function _renderVarDisplayEnd()
+ {
+ echo '</div>';
+ }
+
+ /**
+ * Renders the header for the section.
+ *
+ * @access private
+ * @author Matt Warden <mwarden@gmail.com>
+ * @author Robert E. Coyle <robertecoyle@hotmail.com>
+ * @param string $title section header title
+ */
+ function _renderSectionHeader($title)
+ {
+ if (!empty($title)) {
+ echo "\n".'<legend>';
+ echo $this->_encodeTitle ? htmlspecialchars($title) : $title;
+ echo '</legend>'."\n";
+ }
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Horde_Form_Type Class
+ *
+ * @author Robert E. Coyle <robertecoyle@hotmail.com>
+ * @package Horde_Form
+ */
+abstract class Horde_Form_Type {
+
+ protected $_properties = array();
+
+ /**
+ * Type constructor. Takes a hash of key/value parameters.
+ *
+ * @param array $properties Any type properties to initialize.
+ */
+ public function __construct($properties = array())
+ {
+ $this->_properties = array();
+ $vars = array_keys(get_object_vars($this));
+ foreach ($vars as $var) {
+ $this->_properties[] = substr($var, 1);
+ }
+
+ if ($this->_properties && $properties) {
+ $properties = array_combine(array_slice($this->_properties, 0, count($properties)), $properties);
+ foreach ($properties as $property => $value) {
+ $this->__set($property, $value);
+ }
+ }
+ }
+
+ /**
+ */
+ abstract public function isValid($var, $vars, $value, &$message);
+
+ /**
+ */
+ function getInfo($vars, $var, &$info)
+ {
+ $info = $var->getValue($vars);
+ }
+
+ /**
+ */
+ public function onSubmit()
+ {
+ }
+
+ /**
+ * To get the 'escape' property of a type:
+ * $escape = $type->escape;
+ * If the property is not set this will return null.
+ *
+ * @param string $property The property to retrieve.
+ */
+ protected function __get($property)
+ {
+ if (in_array($property, $this->_properties)) {
+ $prop = '_' . $property;
+ return $this->$prop;
+ }
+
+ return null;
+ }
+
+ /**
+ * To set the 'escape' property of a type to true:
+ * $type->escape = true;
+ *
+ * @param string $property The property name to set.
+ * @param mixed $value The property value.
+ */
+ protected function __set($property, $value)
+ {
+ if (in_array($property, $this->_properties)) {
+ $prop = '_' . $property;
+ $this->$prop = $value;
+ }
+ }
+
+ /**
+ * To check if a type has a property named 'escape':
+ * if (isset($type->escape)) { ... }
+ *
+ * @param string $property Property name to check existance of.
+ */
+ protected function __isset($property)
+ {
+ $prop = '_' . $property;
+ return isset($this->$prop);
+ }
+
+ /**
+ * To unset a Type property named 'escape':
+ * unset($type->escape);
+ *
+ * @param string $property Property name to unset.
+ */
+ protected function __unset($property)
+ {
+ $prop = '_' . $property;
+ unset($this->$prop);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * An on/off value
+ */
+class Horde_Form_Type_Boolean extends Horde_Form_Type {
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ return true;
+ }
+
+ public function getInfo($vars, $var, &$info)
+ {
+ $info = String::lower($vars->get($var->name)) == 'on';
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Color
+ */
+class Horde_Form_Type_Color extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->required && empty($value)) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (empty($value) || preg_match('/^#([0-9a-z]){6}$/i', $value)) {
+ return true;
+ }
+
+ $message = _("This field must contain a color code in the RGB Hex format, for example '#1234af'.");
+ return false;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Credit card number
+ */
+class Horde_Form_Type_creditcard extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if (empty($value) && $var->required) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (!empty($value)) {
+ /* getCardType() will also verify the checksum. */
+ $type = $this->getCardType($value);
+ if ($type === false || $type == 'unknown') {
+ $message = _("This does not seem to be a valid card number.");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function getChecksum($ccnum)
+ {
+ $len = strlen($ccnum);
+ if (!is_long($len / 2)) {
+ $weight = 2;
+ $digit = $ccnum[0];
+ } elseif (is_long($len / 2)) {
+ $weight = 1;
+ $digit = $ccnum[0] * 2;
+ }
+ if ($digit > 9) {
+ $digit = $digit - 9;
+ }
+ $i = 1;
+ $checksum = $digit;
+ while ($i < $len) {
+ if ($ccnum[$i] != ' ') {
+ $digit = $ccnum[$i] * $weight;
+ $weight = ($weight == 1) ? 2 : 1;
+ if ($digit > 9) {
+ $digit = $digit - 9;
+ }
+ $checksum += $digit;
+ }
+ $i++;
+ }
+
+ return $checksum;
+ }
+
+ function getCardType($ccnum)
+ {
+ $sum = $this->getChecksum($ccnum);
+ $l = strlen($ccnum);
+
+ // Screen checksum.
+ if (($sum % 10) != 0) {
+ return false;
+ }
+
+ // Check for Visa.
+ if ((($l == 16) || ($l == 13)) &&
+ ($ccnum[0] == 4)) {
+ return 'visa';
+ }
+
+ // Check for MasterCard.
+ if (($l == 16) &&
+ ($ccnum[0] == 5) &&
+ ($ccnum[1] >= 1) &&
+ ($ccnum[1] <= 5)) {
+ return 'mastercard';
+ }
+
+ // Check for Amex.
+ if (($l == 15) &&
+ ($ccnum[0] == 3) &&
+ (($ccnum[1] == 4) || ($ccnum[1] == 7))) {
+ return 'amex';
+ }
+
+ // Check for Discover (Novus).
+ if (strlen($ccnum) == 16 &&
+ substr($ccnum, 0, 4) == '6011') {
+ return 'discover';
+ }
+
+ // If we got this far, then no card matched.
+ return 'unknown';
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Date
+ */
+class Horde_Form_Type_Date extends Horde_Form_Type {
+
+ var $_format = '%a %d %B';
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ $valid = true;
+
+ if ($var->required) {
+ $valid = strlen(trim($value)) > 0;
+
+ if (!$valid) {
+ $message = _("This field is required.");
+ }
+ }
+
+ return $valid;
+ }
+
+ public static function getAgo($timestamp)
+ {
+ if ($timestamp === null) {
+ return '';
+ }
+
+ $diffdays = Date_Calc::dateDiff(date('j', $timestamp),
+ date('n', $timestamp),
+ date('Y', $timestamp),
+ date('j'), date('n'), date('Y'));
+
+ /* An error occured. */
+ if ($diffdays == -1) {
+ return;
+ }
+
+ $ago = $diffdays * Date_Calc::compareDates(date('j', $timestamp),
+ date('n', $timestamp),
+ date('Y', $timestamp),
+ date('j'), date('n'),
+ date('Y'));
+ if ($ago < -1) {
+ return sprintf(_(" (%s days ago)"), $diffdays);
+ } elseif ($ago == -1) {
+ return _(" (yesterday)");
+ } elseif ($ago == 0) {
+ return _(" (today)");
+ } elseif ($ago == 1) {
+ return _(" (tomorrow)");
+ } else {
+ return sprintf(_(" (in %s days)"), $diffdays);
+ }
+ }
+
+ public function getFormattedTime($timestamp, $format = null, $showago = true)
+ {
+ if (empty($format)) {
+ $format = $this->_format;
+ }
+ if (!empty($timestamp)) {
+ return strftime($format, $timestamp) . ($showago ? self::getAgo($timestamp) : '');
+ } else {
+ return '';
+ }
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Date and time selection
+ */
+class Horde_Form_Type_DateTime extends Horde_Form_Type {
+
+ var $_date;
+ var $_time;
+
+ /**
+ * Return the date supplied as a Horde_Date object.
+ *
+ * @param integer $start_year The first available year for input.
+ * @param integer $end_year The last available year for input.
+ * @param boolean $picker Do we show the DHTML calendar?
+ * @param integer $format_in The format to use when sending the date
+ * for storage. Defaults to Unix epoch.
+ * Similar to the strftime() function.
+ * @param integer $format_out The format to use when displaying the
+ * date. Similar to the strftime() function.
+ * @param boolean $show_seconds Include a form input for seconds.
+ */
+ function init($start_year = '', $end_year = '', $picker = true,
+ $format_in = null, $format_out = '%x', $show_seconds = false)
+ {
+ $this->_date = new Horde_Form_Type_Date();
+ $this->_date->init($start_year, $end_year, $picker, $format_in, $format_out);
+
+ $this->_time = new Horde_Form_Type_Time();
+ $this->_time->init($show_seconds);
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->required) {
+ return $this->_date->isValid($var, $vars, $value, $message) &&
+ $this->_time->isValid($var, $vars, $value, $message);
+ }
+ return true;
+ }
+
+ function getInfo(&$vars, &$var, &$info)
+ {
+ /* If any component is empty consider it a bad date and return the
+ * default. */
+ $value = $var->getValue($vars);
+ if ($this->emptyDateArray($value) == 1 || $this->emptyTimeArray($value)) {
+ $info = $var->getDefault();
+ return;
+ }
+
+ $date = $this->getDateOb($value);
+ $time = $this->getTimeOb($value);
+ $date->hour = $time->hour;
+ $date->min = $time->min;
+ $date->sec = $time->sec;
+ if (is_null($this->format_in)) {
+ $info = $date->timestamp();
+ } else {
+ $info = $date->strftime($this->format_in);
+ }
+ }
+
+ function __get($property)
+ {
+ if ($property == 'show_seconds') {
+ return $this->_time->$property;
+ } else {
+ return $this->_date->$property;
+ }
+ }
+
+ function __set($property, $value)
+ {
+ if ($property == 'show_seconds') {
+ $this->_time->$property = $value;
+ } else {
+ $this->_date->$property = $value;
+ }
+ }
+
+ function checktime($hour, $minute, $second)
+ {
+ return $this->_time->checktime($hour, $minute, $second);
+ }
+
+ function getTimeOb($time_in)
+ {
+ return $this->_time->getTimeOb($time_in);
+ }
+
+ function getTimeParts($time_in)
+ {
+ return $this->_time->getTimeParts($time_in);
+ }
+
+ function emptyTimeArray($time)
+ {
+ return $this->_time->emptyTimeArray($time);
+ }
+
+ function emptyDateArray($date)
+ {
+ return $this->_date->emptyDateArray($date);
+ }
+
+ function getDateParts($date_in)
+ {
+ return $this->_date->getDateParts($date_in);
+ }
+
+ function getDateOb($date_in)
+ {
+ return $this->_date->getDateOb($date_in);
+ }
+
+ function formatDate($date)
+ {
+ if ($date === null) {
+ return '';
+ }
+ return $this->_date->formatDate($date);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Email
+ */
+class Horde_Form_Type_Email extends Horde_Form_Type {
+
+ /**
+ * Allow multiple addresses?
+ *
+ * @type boolean
+ * @var boolean
+ */
+ var $_allow_multi = false;
+
+ /**
+ * Strip domain from the address?
+ *
+ * @type boolean
+ * @var boolean
+ */
+ var $_strip_domain = false;
+
+ /**
+ * Make displayed email addresses clickable?
+ *
+ * @type boolean
+ * @var boolean
+ */
+ var $_link_compose = false;
+
+ /**
+ * The compose name to use
+ *
+ * @type text
+ * @var boolean
+ */
+ var $_link_name;
+
+ /**
+ * The character to separate multiple email addresses
+ *
+ * @type text
+ * @var string
+ */
+ var $_delimiters = ',';
+
+ /**
+ * Contact the target mail server to see if the email address is deliverable?
+ *
+ * @type boolean
+ * @var boolean
+ */
+ var $_check_smtp = false;
+
+ /**
+ */
+ public function init($allow_multi = false, $strip_domain = false,
+ $link_compose = false, $link_name = null,
+ $delimiters = ',')
+ {
+ $this->_allow_multi = $allow_multi;
+ $this->_strip_domain = $strip_domain;
+ $this->_link_compose = $link_compose;
+ $this->_link_name = $link_name;
+ $this->_delimiters = $delimiters;
+ }
+
+ /**
+ */
+ public function isValid($var, $vars, $value, &$message)
+ {
+ // Split into individual addresses.
+ $emails = $this->splitEmailAddresses($value);
+
+ // Check for too many.
+ if (!$this->_allow_multi && count($emails) > 1) {
+ $message = _("Only one email address is allowed.");
+ return false;
+ }
+
+ // Check for all valid and at least one non-empty.
+ $nonEmpty = 0;
+ foreach ($emails as $email) {
+ if (!strlen($email)) {
+ continue;
+ }
+ if (!$this->validateEmailAddress($email)) {
+ $message = sprintf(_("\"%s\" is not a valid email address."), $email);
+ return false;
+ }
+ ++$nonEmpty;
+ }
+
+ if (!$nonEmpty && $var->required) {
+ if ($this->_allow_multi) {
+ $message = _("You must enter at least one email address.");
+ } else {
+ $message = _("You must enter an email address.");
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Explodes an RFC 2822 string, ignoring a delimiter if preceded
+ * by a "\" character, or if the delimiter is inside single or
+ * double quotes.
+ *
+ * @param string $string The RFC 822 string.
+ *
+ * @return array The exploded string in an array.
+ */
+ public function splitEmailAddresses($string)
+ {
+ $quotes = array('"', "'");
+ $emails = array();
+ $pos = 0;
+ $in_quote = null;
+ $in_group = false;
+ $prev = null;
+
+ if (!strlen($string)) {
+ return array();
+ }
+
+ $char = $string[0];
+ if (in_array($char, $quotes)) {
+ $in_quote = $char;
+ } elseif ($char == ':') {
+ $in_group = true;
+ } elseif (strpos($this->_delimiters, $char) !== false) {
+ $emails[] = '';
+ $pos = 1;
+ }
+
+ for ($i = 1, $iMax = strlen($string); $i < $iMax; ++$i) {
+ $char = $string[$i];
+ if (in_array($char, $quotes)) {
+ if ($prev !== '\\') {
+ if ($in_quote === $char) {
+ $in_quote = null;
+ } elseif (is_null($in_quote)) {
+ $in_quote = $char;
+ }
+ }
+ } elseif ($in_group) {
+ if ($char == ';') {
+ $emails[] = substr($string, $pos, $i - $pos + 1);
+ $pos = $i + 1;
+ $in_group = false;
+ }
+ } elseif ($char == ':') {
+ $in_group = true;
+ } elseif (strpos($this->_delimiters, $char) !== false &&
+ $prev !== '\\' &&
+ is_null($in_quote)) {
+ $emails[] = substr($string, $pos, $i - $pos);
+ $pos = $i + 1;
+ }
+ $prev = $char;
+ }
+
+ if ($pos != $i) {
+ /* The string ended without a delimiter. */
+ $emails[] = substr($string, $pos, $i - $pos);
+ }
+
+ return $emails;
+ }
+
+ /**
+ * RFC(2)822 Email Parser.
+ *
+ * By Cal Henderson <cal@iamcal.com>
+ * This code is licensed under a Creative Commons Attribution-ShareAlike 2.5 License
+ * http://creativecommons.org/licenses/by-sa/2.5/
+ *
+ * http://code.iamcal.com/php/rfc822/
+ *
+ * http://iamcal.com/publish/articles/php/parsing_email
+ *
+ * Revision 4
+ *
+ * @param string $email An individual email address to validate.
+ *
+ * @return boolean
+ */
+ public function validateEmailAddress($email)
+ {
+ static $comment_regexp, $email_regexp;
+ if ($comment_regexp === null) {
+ $this->_defineValidationRegexps($comment_regexp, $email_regexp);
+ }
+
+ // We need to strip comments first (repeat until we can't find
+ // any more).
+ while (true) {
+ $new = preg_replace("!$comment_regexp!", '', $email);
+ if (strlen($new) == strlen($email)){
+ break;
+ }
+ $email = $new;
+ }
+
+ // Now match what's left.
+ $result = (bool)preg_match("!^$email_regexp$!", $email);
+ if ($result && $this->_check_smtp) {
+ $result = $this->validateEmailAddressSmtp($email);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Attempt partial delivery of mail to an address to validate it.
+ *
+ * @param string $email An individual email address to validate.
+ *
+ * @return boolean
+ */
+ public function validateEmailAddressSmtp($email)
+ {
+ list(, $maildomain) = explode('@', $email, 2);
+
+ // Try to get the real mailserver from MX records.
+ if (function_exists('getmxrr') &&
+ @getmxrr($maildomain, $mxhosts, $mxpriorities)) {
+ // MX record found.
+ array_multisort($mxpriorities, $mxhosts);
+ $mailhost = $mxhosts[0];
+ } else {
+ // No MX record found, try the root domain as the mail
+ // server.
+ $mailhost = $maildomain;
+ }
+
+ $fp = @fsockopen($mailhost, 25, $errno, $errstr, 5);
+ if (!$fp) {
+ return false;
+ }
+
+ // Read initial response.
+ fgets($fp, 4096);
+
+ // HELO
+ fputs($fp, "HELO $mailhost\r\n");
+ fgets($fp, 4096);
+
+ // MAIL FROM
+ fputs($fp, "MAIL FROM: <root@example.com>\r\n");
+ fgets($fp, 4096);
+
+ // RCPT TO - gets the result we want.
+ fputs($fp, "RCPT TO: <$email>\r\n");
+ $result = trim(fgets($fp, 4096));
+
+ // QUIT
+ fputs($fp, "QUIT\r\n");
+ fgets($fp, 4096);
+ fclose($fp);
+
+ return substr($result, 0, 1) == '2';
+ }
+
+ /**
+ * RFC(2)822 Email Parser.
+ *
+ * By Cal Henderson <cal@iamcal.com>
+ * This code is licensed under a Creative Commons Attribution-ShareAlike 2.5 License
+ * http://creativecommons.org/licenses/by-sa/2.5/
+ *
+ * http://code.iamcal.com/php/rfc822/
+ *
+ * http://iamcal.com/publish/articles/php/parsing_email
+ *
+ * Revision 4
+ *
+ * @param string &$comment The regexp for comments.
+ * @param string &$addr_spec The regexp for email addresses.
+ */
+ protected function _defineValidationRegexps(&$comment, &$addr_spec)
+ {
+ /**
+ * NO-WS-CTL = %d1-8 / ; US-ASCII control characters
+ * %d11 / ; that do not include the
+ * %d12 / ; carriage return, line feed,
+ * %d14-31 / ; and white space characters
+ * %d127
+ * ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
+ * DIGIT = %x30-39
+ */
+ $no_ws_ctl = "[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]";
+ $alpha = "[\\x41-\\x5a\\x61-\\x7a]";
+ $digit = "[\\x30-\\x39]";
+ $cr = "\\x0d";
+ $lf = "\\x0a";
+ $crlf = "($cr$lf)";
+
+ /**
+ * obs-char = %d0-9 / %d11 / ; %d0-127 except CR and
+ * %d12 / %d14-127 ; LF
+ * obs-text = *LF *CR *(obs-char *LF *CR)
+ * text = %d1-9 / ; Characters excluding CR and LF
+ * %d11 /
+ * %d12 /
+ * %d14-127 /
+ * obs-text
+ * obs-qp = "\" (%d0-127)
+ * quoted-pair = ("\" text) / obs-qp
+ */
+ $obs_char = "[\\x00-\\x09\\x0b\\x0c\\x0e-\\x7f]";
+ $obs_text = "($lf*$cr*($obs_char$lf*$cr*)*)";
+ $text = "([\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f]|$obs_text)";
+ $obs_qp = "(\\x5c[\\x00-\\x7f])";
+ $quoted_pair = "(\\x5c$text|$obs_qp)";
+
+ /**
+ * obs-FWS = 1*WSP *(CRLF 1*WSP)
+ * FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
+ * obs-FWS
+ * ctext = NO-WS-CTL / ; Non white space controls
+ * %d33-39 / ; The rest of the US-ASCII
+ * %d42-91 / ; characters not including "(",
+ * %d93-126 ; ")", or "\"
+ * ccontent = ctext / quoted-pair / comment
+ * comment = "(" *([FWS] ccontent) [FWS] ")"
+ * CFWS = *([FWS] comment) (([FWS] comment) / FWS)
+ *
+ * @note: We translate ccontent only partially to avoid an
+ * infinite loop. Instead, we'll recursively strip comments
+ * before processing the input.
+ */
+ $wsp = "[\\x20\\x09]";
+ $obs_fws = "($wsp+($crlf$wsp+)*)";
+ $fws = "((($wsp*$crlf)?$wsp+)|$obs_fws)";
+ $ctext = "($no_ws_ctl|[\\x21-\\x27\\x2A-\\x5b\\x5d-\\x7e])";
+ $ccontent = "($ctext|$quoted_pair)";
+ $comment = "(\\x28($fws?$ccontent)*$fws?\\x29)";
+ $cfws = "(($fws?$comment)*($fws?$comment|$fws))";
+ $cfws = "$fws*";
+
+ /**
+ * atext = ALPHA / DIGIT / ; Any character except controls,
+ * "!" / "#" / ; SP, and specials.
+ * "$" / "%" / ; Used for atoms
+ * "&" / "'" /
+ * "*" / "+" /
+ * "-" / "/" /
+ * "=" / "?" /
+ * "^" / "_" /
+ * "`" / "{" /
+ * "|" / "}" /
+ * "~"
+ * atom = [CFWS] 1*atext [CFWS]
+ */
+ $atext = "($alpha|$digit|[\\x21\\x23-\\x27\\x2a\\x2b\\x2d\\x2e\\x3d\\x3f\\x5e\\x5f\\x60\\x7b-\\x7e])";
+ $atom = "($cfws?$atext+$cfws?)";
+
+ /**
+ * qtext = NO-WS-CTL / ; Non white space controls
+ * %d33 / ; The rest of the US-ASCII
+ * %d35-91 / ; characters not including "\"
+ * %d93-126 ; or the quote character
+ * qcontent = qtext / quoted-pair
+ * quoted-string = [CFWS]
+ * DQUOTE *([FWS] qcontent) [FWS] DQUOTE
+ * [CFWS]
+ * word = atom / quoted-string
+ */
+ $qtext = "($no_ws_ctl|[\\x21\\x23-\\x5b\\x5d-\\x7e])";
+ $qcontent = "($qtext|$quoted_pair)";
+ $quoted_string = "($cfws?\\x22($fws?$qcontent)*$fws?\\x22$cfws?)";
+ $word = "($atom|$quoted_string)";
+
+ /**
+ * obs-local-part = word *("." word)
+ * obs-domain = atom *("." atom)
+ */
+ $obs_local_part = "($word(\\x2e$word)*)";
+ $obs_domain = "($atom(\\x2e$atom)*)";
+
+ /**
+ * dot-atom-text = 1*atext *("." 1*atext)
+ * dot-atom = [CFWS] dot-atom-text [CFWS]
+ */
+ $dot_atom_text = "($atext+(\\x2e$atext+)*)";
+ $dot_atom = "($cfws?$dot_atom_text$cfws?)";
+
+ /**
+ * domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
+ * dcontent = dtext / quoted-pair
+ * dtext = NO-WS-CTL / ; Non white space controls
+ *
+ * %d33-90 / ; The rest of the US-ASCII
+ * %d94-126 ; characters not including "[",
+ * ; "]", or "\"
+ */
+ $dtext = "($no_ws_ctl|[\\x21-\\x5a\\x5e-\\x7e])";
+ $dcontent = "($dtext|$quoted_pair)";
+ $domain_literal = "($cfws?\\x5b($fws?$dcontent)*$fws?\\x5d$cfws?)";
+
+ /**
+ * local-part = dot-atom / quoted-string / obs-local-part
+ * domain = dot-atom / domain-literal / obs-domain
+ * addr-spec = local-part "@" domain
+ */
+ $local_part = "($dot_atom|$quoted_string|$obs_local_part)";
+ $domain = "($dot_atom|$domain_literal|$obs_domain)";
+ $addr_spec = "($local_part\\x40$domain)";
+ }
+
+}
+
+/**
+ * Email with confirmation
+ */
+class Horde_Form_Type_EmailConfirm extends Horde_Form_Type {
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->required && empty($value['original'])) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if ($value['original'] != $value['confirm']) {
+ $message = _("Email addresses must match.");
+ return false;
+ } else {
+ require_once 'Horde/MIME.php';
+ $parsed_email = MIME::parseAddressList($value['original'], false,
+ true);
+ if (is_a($parsed_email, 'PEAR_Error')) {
+ $message = $parsed_email->getMessage();
+ return false;
+ }
+ if (count($parsed_email) > 1) {
+ $message = _("Only one email address allowed.");
+ return false;
+ }
+ if (empty($parsed_email[0]->mailbox)) {
+ $message = _("You did not enter a valid email address.");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Choose one from a list of values
+ */
+class Horde_Form_Type_Enum extends Horde_Form_Type {
+
+ /**
+ * List of values to choose from
+ *
+ * @type stringlist
+ * @var array
+ */
+ protected $_values = array();
+
+ /**
+ * Initial prompt value, if any
+ *
+ * @type text
+ * @var string
+ */
+ protected $_prompt;
+
+ /**
+ */
+ public function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->required && $value == '' && !isset($this->_values[$value])) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (count($this->_values) == 0 || isset($this->_values[$value]) ||
+ ($this->_prompt && empty($value))) {
+ return true;
+ }
+
+ $message = _("Invalid data.");
+ return false;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Integer
+ */
+class Horde_Form_Type_Int extends Horde_Form_Type {
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->required && empty($value) && ((string)(int)$value !== $value)) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (empty($value) || preg_match('/^[0-9]+$/', $value)) {
+ return true;
+ }
+
+ $message = _("This field may only contain integers.");
+ return false;
+ }
+
+}
--- /dev/null
+<?php
+class Horde_Form_Type_invalid extends Horde_Form_Type {
+
+ var $message;
+
+ function init($message)
+ {
+ $this->message = $message;
+ }
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ return false;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Number
+ */
+class Horde_Form_Type_Number extends Horde_Form_Type {
+
+ /**
+ */
+ protected $_fraction;
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->required && empty($value) && ((string)(double)$value !== $value)) {
+ $message = _("This field is required.");
+ return false;
+ } elseif (empty($value)) {
+ return true;
+ }
+
+ /* If matched, then this is a correct numeric value. */
+ if (preg_match($this->_getValidationPattern(), $value)) {
+ return true;
+ }
+
+ $message = _("This field must be a valid number.");
+ return false;
+ }
+
+ /**
+ */
+ public function getInfo($vars, $var, &$info)
+ {
+ $value = $vars->get($var->name);
+ $linfo = NLS::getLocaleInfo();
+ $value = str_replace($linfo['mon_thousands_sep'], '', $value);
+ $info = str_replace($linfo['mon_decimal_point'], '.', $value);
+ }
+
+ /**
+ */
+ protected function _getValidationPattern()
+ {
+ static $pattern = '';
+ if (!empty($pattern)) {
+ return $pattern;
+ }
+
+ /* Get current locale information. */
+ $linfo = NLS::getLocaleInfo();
+
+ /* Build the pattern. */
+ $pattern = '(-)?';
+
+ /* Only check thousands separators if locale has any. */
+ if (!empty($linfo['mon_thousands_sep'])) {
+ /* Regex to check for correct thousands separators (if any). */
+ $pattern .= '((\d+)|((\d{0,3}?)([' . $linfo['mon_thousands_sep'] . ']\d{3})*?))';
+ } else {
+ /* No locale thousands separator, check for only digits. */
+ $pattern .= '(\d+)';
+ }
+ /* If no decimal point specified default to dot. */
+ if (empty($linfo['mon_decimal_point'])) {
+ $linfo['mon_decimal_point'] = '.';
+ }
+ /* Regex to check for correct decimals (if any). */
+ if (empty($this->_fraction)) {
+ $fraction = '*';
+ } else {
+ $fraction = '{0,' . $this->_fraction . '}';
+ }
+ $pattern .= '([' . $linfo['mon_decimal_point'] . '](\d' . $fraction . '))?';
+
+ /* Put together the whole regex pattern. */
+ $pattern = '/^' . $pattern . '$/';
+
+ return $pattern;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Octal
+ */
+class Horde_Form_Type_Octal extends Horde_Form_Type {
+
+ function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->required && empty($value) && ((string)(int)$value !== $value)) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (empty($value) || preg_match('/^[0-7]+$/', $value)) {
+ return true;
+ }
+
+ $message = _("This field may only contain octal values.");
+ return false;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Password
+ */
+class Horde_Form_Type_Password extends Horde_Form_Type {
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ $valid = true;
+
+ if ($var->required) {
+ $valid = strlen(trim($value)) > 0;
+
+ if (!$valid) {
+ $message = _("This field is required.");
+ }
+ }
+
+ return $valid;
+ }
+
+}
+
+
+/**
+ * Password with confirmation
+ */
+class Horde_Form_Type_passwordConfirm extends Horde_Form_Type {
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->required && empty($value['original'])) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if ($value['original'] != $value['confirm']) {
+ $message = _("Passwords must match.");
+ return false;
+ }
+
+ return true;
+ }
+
+ function getInfo($vars, $var, &$info)
+ {
+ $value = $vars->get($var->name);
+ $info = $value['original'];
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Phone number
+ */
+class Horde_Form_Type_Phone extends Horde_Form_Type {
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ $valid = true;
+
+ if ($var->required) {
+ $valid = strlen(trim($value)) > 0;
+ if (!$valid) {
+ $message = _("This field is required.");
+ }
+ } else {
+ $valid = preg_match('/^\+?[\d()\-\/ ]*$/', $value);
+ if (!$valid) {
+ $message = _("You must enter a valid phone number, digits only with an optional '+' for the international dialing prefix.");
+ }
+ }
+
+ return $valid;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Mobile Phone Number
+ */
+class Horde_Form_Type_Phone_Mobile extends Horde_Form_Type_Phone {}
--- /dev/null
+<?php
+/**
+ * Set of values
+ */
+class Horde_Form_Type_Set extends Horde_Form_Type {
+
+ /**
+ * Values
+ *
+ * @type stringlist
+ * @var string
+ */
+ protected $_values;
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ if (count($this->_values) == 0 || count($value) == 0) {
+ return true;
+ }
+ foreach ($value as $item) {
+ if (!isset($this->_values[$item])) {
+ $error = true;
+ break;
+ }
+ }
+ if (!isset($error)) {
+ return true;
+ }
+
+ $message = _("Invalid data.");
+ return false;
+ }
+
+}
+
+class Horde_Form_Type_multienum extends Horde_Form_Type_enum {
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ if (is_array($value)) {
+ foreach ($value as $val) {
+ if (!$this->isValid($var, $vars, $val, $message)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ if (empty($value) && ((string)(int)$value !== $value)) {
+ if ($var->required) {
+ $message = _("This field is required.");
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ if (count($this->_values) == 0 || isset($this->_values[$value])) {
+ return true;
+ }
+
+ $message = _("Invalid data.");
+ return false;
+ }
+
+}
+
+class Horde_Form_Type_keyval_multienum extends Horde_Form_Type_multienum {
+
+ function getInfo($vars, $var, &$info)
+ {
+ $value = $vars->get($var->name);
+ $info = array();
+ foreach ($value as $key) {
+ $info[$key] = $this->_values[$key];
+ }
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * String
+ */
+class Horde_Form_Type_String extends Horde_Form_Type {
+
+ /**
+ * Validation regex
+ *
+ * @type string
+ * @var string
+ */
+ protected $_regex;
+
+ /**
+ * Maximum length
+ *
+ * @type int
+ * @var integer
+ */
+ protected $_maxlength;
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ $valid = true;
+
+ if (!empty($this->_maxlength) && String::length($value) > $this->_maxlength) {
+ $valid = false;
+ $message = sprintf(_("Value is over the maximum length of %s."), $this->_maxlength);
+ } elseif ($var->required && empty($this->_regex)) {
+ if (!($valid = strlen(trim($value)) > 0)) {
+ $message = _("This field is required.");
+ }
+ } elseif (strlen($this->_regex)) {
+ if (!($valid = preg_match($this->_regex, $value))) {
+ $message = _("You must enter a valid value.");
+ }
+ }
+
+ return $valid;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Time
+ */
+class Horde_Form_Type_Time extends Horde_Form_Type {
+
+ public function isValid($var, $vars, $value, &$message)
+ {
+ if ($var->required && empty($value) && ((string)(double)$value !== $value)) {
+ $message = _("This field is required.");
+ return false;
+ }
+
+ if (empty($value) || preg_match('/^[0-2]?[0-9]:[0-5][0-9]$/', $value)) {
+ return true;
+ }
+
+ $message = _("This field may only contain numbers and the colon.");
+ return false;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Horde_Form_VarRenderer:: class provides base functionality for
+ * other Horde_Form elements.
+ *
+ * $Horde: incubator/Horde_Form/Horde/Form/VarRenderer.php,v 1.8 2008/01/02 11:12:48 jan Exp $
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ * Copyright 2005-2007 Matt Warden <mwarden@gmail.com>
+ *
+ * See the enclosed file LICENSE for license information (LGPL).
+ *
+ * @author Jason M. Felice <jason.m.felice@gmail.com>
+ * @package Horde_Form
+ */
+class Horde_Form_VarRenderer {
+
+ /**
+ * Renders a variable.
+ *
+ * @param Horde_Form $form Reference to a Horde_Form instance,
+ * or null if none is available.
+ * @param Horde_Form_Variable $var Reference to a Horde_Form_Variable.
+ * @param Variables $vars A Variables instance.
+ * @param boolean $isInput Whether this is an input field.
+ */
+ public function render($form, $var, $vars, $isInput = false)
+ {
+ if ($isInput) {
+ $state = 'Input';
+ } else {
+ $state = 'Display';
+ }
+ $method = "_renderVar${state}_" . str_replace('Horde_Form_Type_', '', get_class($var->type));
+ if (!method_exists($this, $method)) {
+ $method = "_renderVar${state}Default";
+ }
+ return $this->$method($form, $var, $vars);
+ }
+
+ /**
+ * Finishes rendering after all fields are output.
+ */
+ public function renderEnd()
+ {
+ return '';
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Horde_Form_VarRenderer_Xhtml:: class renders variables as Xhtml.
+ *
+ * $Horde: incubator/Horde_Form/Horde/Form/VarRenderer/Xhtml.php,v 1.14 2008/01/02 11:12:48 jan Exp $
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ * Copyright 2005 Matt Warden <mwarden@gmail.com>
+ *
+ * See the enclosed file LICENSE for license information (LGPL).
+ *
+ * @author Jason M. Felice <jason.m.felice@gmail.com>
+ * @package Horde_Form
+ */
+class Horde_Form_VarRenderer_Xhtml extends Horde_Form_VarRenderer {
+
+ protected $_onLoadJS = array();
+
+ /**
+ * Handles the end of rendering of variables; writes onload JavaScript.
+ *
+ * @access public
+ * @author ?
+ * @return string the javascript to execute, and its container script tags,
+ * or and empty string if there is nothing to execute onload
+ */
+ public function renderEnd()
+ {
+ if (count($this->_onLoadJS)) {
+ return "<script type=\"text/javascript\">" .
+ "<!--\n" . implode("\n", $this->_onLoadJS) . "\n// -->\n" .
+ "</script>";
+ } else {
+ return '';
+ }
+ }
+
+ function _renderVarInputDefault($form, $var, $vars)
+ {
+ throw new Horde_Form_Exception('Unknown variable type:' . get_class($var->type));
+ }
+
+ function _renderVarInput_number($form, $var, $vars)
+ {
+ $value = $var->getValue($vars);
+ if ($var->type->fraction) {
+ $value = sprintf('%01.' . $var->type->fraction . 'f', $value);
+ }
+ $linfo = NLS::getLocaleInfo();
+ /* Only if there is a mon_decimal_point do the
+ * substitution. */
+ if (!empty($linfo['mon_decimal_point'])) {
+ $value = str_replace('.', $linfo['mon_decimal_point'], $value);
+ }
+ return sprintf(' <input type="text" class="form-input-number" name="%1$s" id="%1$s" value="%2$s"%3$s />',
+ $var->getVarName(),
+ $value,
+ $this->_getActionScripts($form, $var)
+ );
+ }
+
+ function _renderVarInput_int($form, $var, $vars)
+ {
+ return sprintf(' <input type="text" class="form-input-int" name="%1$s" id="%1$s" value="%2$s"%3$s />',
+ $var->getVarName(),
+ $value = $var->getValue($vars),
+ $this->_getActionScripts($form, $var)
+ );
+ }
+
+ function _renderVarInput_octal($form, $var, $vars)
+ {
+ return sprintf('<input type="text" class="form-input-octal" name="%1$s" id="%1$s" value="%2$s"%3$s />',
+ $var->getVarName(),
+ sprintf('0%o', octdec($var->getValue($vars))),
+ $this->_getActionScripts($form, $var)
+ );
+ }
+
+ function _renderVarInput_intlist($form, $var, $vars)
+ {
+ return sprintf('<input type="text" class="form-input-intlist" name="%1$s" id="%1$s" value="%2$s"%3$s />',
+ $var->getVarName(),
+ $value = $var->getValue($vars),
+ $this->_getActionScripts($form, $var)
+ );
+ }
+
+ function _renderVarInput_text($form, $var, $vars)
+ {
+ return sprintf(
+ '<input type="text" class="form-input-text%1$s" name="%2$s" '
+ . 'id="%2$s" value="%3$s"%4$s%5$s%6$s />',
+ ($var->isDisabled() ? ' form-input-disabled" ' : ''),
+ $var->getVarName(),
+ htmlspecialchars($var->getValue($vars), ENT_QUOTES, NLS::getCharset()),
+ ($var->isDisabled() ? ' disabled="disabled" ' : ''),
+ ($var->type->maxlength ? ' maxlength="' . $var->type->maxlength . '"' : ''),
+ $this->_getActionScripts($form, $var)
+ );
+ }
+
+ function _renderVarInput_stringlist($form, $var, $vars)
+ {
+ return sprintf(
+ '<input type="text" class="form-input-stringlist" name="%s" value="%s"%s />',
+ $var->getVarName(),
+ $value = $var->getValue($vars),
+ $this->_getActionScripts($form, $var)
+ );
+ }
+
+ function _renderVarInput_phone($form, $var, $vars)
+ {
+ return sprintf(
+ '<input type="text" class="form-input-phone" name="%1$s" id="%1$s" value="%2$s" %3$s%4$s />',
+ $var->getVarName(),
+ htmlspecialchars($var->getValue($vars), ENT_QUOTES, NLS::getCharset()),
+ ($var->isDisabled() ? ' disabled="disabled" ' : ''),
+ $this->_getActionScripts($form, $var)
+ );
+ }
+
+ function _renderVarInput_cellphone($form, $var, $vars)
+ {
+ return $this->_renderVarInput_phone($form, $var, $vars);
+ }
+
+ function _renderVarInput_ipaddress($form, $var, $vars)
+ {
+ return sprintf(' <input type="text" class="form-input-ipaddress" name="%1$s" id="%1$s" value="%2$s" %3$s%4$s />',
+ $var->getVarName(),
+ htmlspecialchars($var->getValue($vars), ENT_QUOTES, NLS::getCharset()),
+ $var->isDisabled() ? ' disabled="disabled" ' : '',
+ $this->_getActionScripts($form, $var)
+ );
+ }
+
+ function _renderVarInput_file($form, $var, $vars)
+ {
+ $file = $var->getValue($vars);
+ return sprintf(' <input type="file" class="form-input-file" name="%1$s" id="%1$s"%2$s />',
+ $var->getVarName(),
+ $this->_getActionScripts($form, $var));
+ }
+
+ /**
+ * @todo Show image dimensions in the width/height boxes.
+ */
+ function _renderVarInput_image($form, $var, $vars)
+ {
+ $varname = $var->getVarName();
+ $image = $var->getValue($vars);
+
+ /* Check if existing image data is being loaded. */
+ $var->type->loadImageData($image);
+
+ Horde::addScriptFile('image.js', 'horde', true);
+ $graphics_dir = $GLOBALS['registry']->getImageDir('horde');
+ $img_dir = $graphics_dir . '/image';
+
+ $html = '';
+
+ /* Check if there is existing img information stored. */
+ if (isset($image['img'])) {
+ /* Hidden tag to store the preview image filename. */
+ $html = sprintf(' <input type="hidden" name="%1$s" id="%1$s" value="%2$s" />',
+ $varname . '[img]',
+ htmlspecialchars($image['img'], ENT_QUOTES, NLS::getCharset()));
+
+ /* Unserialize the img information to get the full array. */
+ $image['img'] = @unserialize($image['img']);
+ }
+
+ /* Output the input tag. */
+ if (empty($image['img'])) {
+ $js = "
+var p = document.getElementById('" . $varname . "[preview]');
+o = '\\\\'; a = '/';
+tmp = '' + document.getElementById('" . $varname . "[new]').value;
+if (tmp) {
+ while (tmp.indexOf(o) > -1) {
+ pos = tmp.indexOf(o);
+ tmp = '' + (tmp.substring(0, pos) + a + tmp.substring((pos + o.length), tmp.length));
+ }
+ p.src = 'file:///' + tmp;
+ p.alt = '" . addslashes(_("If you see this message but no image, the image you want to upload can't be displayed by your browser.")) . "';
+}";
+ $browser = Horde_Browser::singleton();
+ if ($browser->isBrowser('msie')) {
+ $html .= sprintf(' <input type="file" class="form-input-file" name="%1$s" id="%1$s" onchange="%2$s" />',
+ $varname . '[new]',
+ $js);
+ } else {
+ $html .= sprintf(' <input type="file" class="form-input-file" name="%1$s" id="%1$s"
+ onclick="window.setTimeout(\'document.getElementById(\\\'%1$s\\\').blur();\', 5);"
+ onblur="%2$s" />',
+ $varname . '[new]',
+ $js);
+ }
+ } else {
+ $html .= sprintf(' <input type="file" class="form-input-file" name="%1$s" id="%1$s" />',
+ $varname . '[new]');
+ }
+
+ /* Output the button to upload/reset the image. */
+ if ($var->type->show_upload) {
+ $html .= ' ';
+ $html .= sprintf(' <input class="form-button-upload" name="%1$s" id="%1$s" type="submit" value="%2$s" /> ',
+ '_do_' . $varname,
+ _("Upload"));
+ }
+
+ if (empty($image['img'])) {
+ /* No image information stored yet, show a blank
+ * preview. */
+ $html .= Horde::img('tree/blank.png', _("Preview"),
+ 'class="form-image-preview-blank" id="' . $varname . '[preview]"',
+ $graphics_dir);
+ } else {
+ /* Image information stored, show preview, add buttons for
+ * image manipulation. */
+ $html .= '<br />';
+ $img = Horde::url($GLOBALS['registry']->get('webroot', 'horde') . '/services/images/view.php');
+ if (isset($image['img']['vfs_id'])) {
+ /* Calling an image from VFS. */
+ $img = Util::addParameter($img, array('f' => $image['img']['vfs_id'],
+ 's' => 'vfs',
+ 'p' => $image['img']['vfs_path']));
+ } else {
+ /* Calling an image from a tmp directory (uploads). */
+ $img = Util::addParameter($img, 'f', $image['img']['file']);
+ }
+
+ // TODO: possible to change to unobtrusive JS?
+ /* Rotate 270. */
+ $html .= Horde::link('#', '', '', '', 'showImage(\'' . Util::addParameter($img, array('a' => 'rotate', 'v' => '270')) . '\', \'_p_' . $varname . '\', true);') . Horde::img('rotate-270.png', _("Rotate Left"), '', $img_dir) . '</a>';
+
+ /* Rotate 180. */
+ $html .= Horde::link('#', '', '', '', 'showImage(\'' . Util::addParameter($img, array('a' => 'rotate', 'v' => '180')) . '\', \'_p_' . $varname . '\', true);') . Horde::img('rotate-180.png', _("Rotate 180"), '', $img_dir) . '</a>';
+
+ /* Rotate 90. */
+ $html .= Horde::link('#', '', '', '', 'showImage(\'' . Util::addParameter($img, array('a' => 'rotate', 'v' => '90')) . '\', \'_p_' . $varname . '\', true);') . Horde::img('rotate-90.png', _("Rotate Right"), '', $img_dir) . '</a>';
+
+ /* Flip image. */
+ $html .= Horde::link('#', '', '', '', 'showImage(\'' . Util::addParameter($img, 'a', 'flip') . '\', \'_p_' . $varname . '\', true);') . Horde::img('flip.png', _("Flip"), '', $img_dir) . '</a>';
+
+ /* Mirror image. */
+ $html .= Horde::link('#', '', '', '', 'showImage(\'' . Util::addParameter($img, 'a', 'mirror') . '\', \'_p_' . $varname . '\', true);') . Horde::img('mirror.png', _("Mirror"), '', $img_dir) . '</a>';
+
+ /* Apply grayscale. */
+ $html .= Horde::link('#', '', '', '', 'showImage(\'' . Util::addParameter($img, 'a', 'grayscale') . '\', \'_p_' . $varname . '\', true);') . Horde::img('grayscale.png', _("Grayscale"), '', $img_dir) . '</a>';
+
+ /* Resize width. */
+ $html .= sprintf('%s <input type="text" class="form-input-resize" onchange="src=getResizeSrc(\'%s\', \'%s\');showImage(src, \'_p_%s\', true);" %s />',
+ _("w:"),
+ Util::addParameter($img, 'a', 'resize'),
+ $varname,
+ $varname,
+ '_w_'. $varname);
+
+ /* Resize height. */
+ $html .= sprintf('%s <input type="text" class="form-input-resize" onchange="src=getResizeSrc(\'%s\', \'%s\');showImage(src, \'_p_%s\', true);" %s />',
+ _("h:"),
+ Util::addParameter($img, 'a', 'resize'),
+ $varname,
+ $varname,
+ '_h_'. $varname);
+
+ /* Apply fixed ratio resize. */
+ $html .= Horde::link('#', '', '', '', 'src=getResizeSrc(\'' . Util::addParameter($img, 'a', 'resize') . '\', \'' . $varname . '\', \'1\');showImage(src, \'_p_' . $varname . '\', true);') . Horde::img('ratio.png', _("Fix ratio"), '', $img_dir) . '</a>';
+
+ /* Keep also original if it has been requested. */
+ if ($var->type->show_keeporig) {
+ $html .= sprintf(' <input type="checkbox" class="form-input-checkbox" name="%s"%s />%s' . "\n",
+ $varname . '[keep_orig]',
+ !empty($image['keep_orig']) ? ' checked="checked"' : '',
+ _("Keep original?"));
+ }
+
+ /* The preview image element. */
+ $html .= '<br /><img src="' . $img . '" id="_p_' . $varname .'" />'."\n";
+ }
+
+ return $html;
+ }
+
+ function _renderVarInput_longtext($form, $var, $vars)
+ {
+ global $browser;
+
+ $html = sprintf('<textarea class="form-input-longtext" id="%1$s" name="%1$s" '
+ .'cols="%2$s" rows="%3$s"%4$s%5$s>%6$s</textarea>',
+ $var->getVarName(),
+ $var->type->cols,
+ $var->type->rows,
+ $this->_getActionScripts($form, $var),
+ $var->isDisabled() ? ' disabled="disabled"' : '',
+ htmlspecialchars($var->getValue($vars)));
+
+ if ($var->type->hasHelper('rte') && $browser->hasFeature('rte')) {
+ $editor = Horde_Editor::factory('Xinha', array('id' => $var->getVarName()));
+ }
+
+ if ($var->type->hasHelper() && $browser->hasFeature('javascript')) {
+ $html .= '<div class="form-html-helper">';
+ Horde::addScriptFile('open_html_helper.js', 'horde');
+ $imgId = $var->getVarName() . 'ehelper';
+ if ($var->type->hasHelper('emoticons')) {
+ $html .= Horde::link('#', _("Emoticons"), '', '', 'openHtmlHelper(\'emoticons\', \'' . $var->getVarName() . '\'); return false;')
+ . Horde::img('smile.png', _("Emoticons"), 'id="' . $imgId . '" align="middle"', $GLOBALS['registry']->getImageDir('horde') . '/emoticons')
+ . '</a>'."\n";
+ }
+ $html .= '</div><div id="htmlhelper_' . $var->getVarName()
+ . '" class="form-control"></div>'."\n";
+ }
+
+ return $html;
+ }
+
+ function _renderVarInput_countedtext($form, $var, $vars)
+ {
+ return sprintf('<textarea class="form-input-countedtext" id="%1$s" name="%1$s" '
+ .'cols="%2$s" rows="%3$s"%4$s%5$s>%6$s</textarea>',
+ $var->getVarName(),
+ $var->type->cols,
+ $var->type->rows,
+ $this->_getActionScripts($form, $var),
+ $var->isDisabled() ? ' disabled="disabled"' : '',
+ $var->getValue($vars));
+ }
+
+ function _renderVarInput_address($form, $var, $vars)
+ {
+ return sprintf('<textarea class="form-input-address" id="%1$s" name="%1$s" '
+ .'cols="%2$s" rows="%3$s"%4$s%5$s>%6$s</textarea>',
+ $var->getVarName(),
+ $var->type->cols,
+ $var->type->rows,
+ $this->_getActionScripts($form, $var),
+ $var->isDisabled() ? ' disabled="disabled"' : '',
+ $var->getValue($vars));
+ }
+
+ function _renderVarInput_date($form, $var, $vars)
+ {
+ return sprintf(' <input type="text" class="form-input-date" name="%1$s" id="%1$s" '
+ .'value="%2$s"%3$s />',
+ $var->getVarName(),
+ $value = $var->getValue($vars),
+ $this->_getActionScripts($form, $var));
+ }
+
+ function _renderVarInput_time($form, $var, $vars)
+ {
+ return sprintf(' <input type="text" class="form-input-time" name="%1$s" id="%1$s" '
+ .'value="%2$s"%3$s />',
+ $var->getVarName(),
+ $value = $var->getValue($vars),
+ $this->_getActionScripts($form, $var));
+ }
+
+ function _renderVarInput_hourminutesecond($form, $var, $vars)
+ {
+ $varname = $var->getVarName();
+ $time = $var->type->getTimeParts($var->getValue($vars));
+
+ /* Output hours. */
+ $hours = array('' => _("hh"));
+ for ($i = 0; $i <= 23; $i++) {
+ $hours[sprintf('%02d', $i)] = $i;
+ }
+ $html = sprintf('<select name="%1$s[hour]" id="%1$s[hour]"%2$s>%3$s </select>',
+ $varname,
+ $this->_selectOptions($hours, $time['hour']),
+ $this->_getActionScripts($form, $var));
+
+ /* Output minutes. */
+ $minutes = array('' => _("mm"));
+ for ($i = 0; $i <= 59; $i++) {
+ $minutes[sprintf('%02d', $i)] = $i;
+ }
+ $html .= sprintf('<select name="%1$s[minute]" id="%1$s[minute]"%2$s>%3$s </select>',
+ $varname,
+ $this->_selectOptions($minutes, $time['minute']),
+ $this->_getActionScripts($form, $var));
+
+ /* Return if seconds are not required. */
+ if ($var->type->show_seconds) {
+ /* Output seconds. */
+ $seconds = array('' => _("ss"));
+ for ($i = 0; $i <= 59; $i++) {
+ $seconds[sprintf('%02d', $i)] = $i;
+ }
+ $html .= sprintf('<select name="%1$s[second]" id="%1$s[second]"%2$s>%3$s </select>',
+ $varname,
+ $this->_getActionScripts($form, $var),
+ $this->_selectOptions($seconds, $time['second']));
+ }
+
+ return $html;
+ }
+
+ function _renderVarInput_monthyear($form, $var, $vars)
+ {
+ $dates = array();
+ $dates['month'] = array('' => _("MM"),
+ 1 => _("January"),
+ 2 => _("February"),
+ 3 => _("March"),
+ 4 => _("April"),
+ 5 => _("May"),
+ 6 => _("June"),
+ 7 => _("July"),
+ 8 => _("August"),
+ 9 => _("September"),
+ 10 => _("October"),
+ 11 => _("November"),
+ 12 => _("December"));
+ $dates['year'] = array('' => _("YYYY"));
+ if ($var->type->start_year > $var->type->end_year) {
+ for ($i = $var->type->start_year; $i >= $var->type->end_year; $i--) {
+ $dates['year'][$i] = $i;
+ }
+ } else {
+ for ($i = $var->type->start_year; $i <= $var->type->end_year; $i++) {
+ $dates['year'][$i] = $i;
+ }
+ }
+ $html = sprintf('<select name="%1$s" id="%1$s"%2$s>%3$s </select>',
+ $var->type->getMonthVar($var),
+ $this->_getActionScripts($form, $var),
+ $this->_selectOptions($dates['month'], $vars->get($var->type->getMonthVar($var))));
+
+ $html .= sprintf('<select name="%1$s" id="%1$s"%2$s>%3$s </select>',
+ $var->type->getYearVar($var),
+ $this->_getActionScripts($form, $var),
+ $this->_selectOptions($dates['year'], $vars->get($var->type->getYearVar($var))));
+
+ return $html;
+ }
+
+ function _renderVarInput_monthdayyear($form, $var, $vars)
+ {
+ $dates = array();
+ $dates['month'] = array('' => _("MM"),
+ '1' => _("January"),
+ '2' => _("February"),
+ '3' => _("March"),
+ '4' => _("April"),
+ '5' => _("May"),
+ '6' => _("June"),
+ '7' => _("July"),
+ '8' => _("August"),
+ '9' => _("September"),
+ '10' => _("October"),
+ '11' => _("November"),
+ '12' => _("December"));
+ $dates['day'] = array('' => _("DD"));
+ for ($i = 1; $i <= 31; $i++) {
+ $dates['day'][$i] = $i;
+ }
+ $dates['year'] = array('' => _("YYYY"));
+ if ($var->type->start_year > $var->type->end_year) {
+ for ($i = $var->type->start_year; $i >= $var->type->end_year; $i--) {
+ $dates['year'][$i] = $i;
+ }
+ } else {
+ for ($i = $var->type->start_year; $i <= $var->type->end_year; $i++) {
+ $dates['year'][$i] = $i;
+ }
+ }
+ $date = $var->type->getDateParts($var->getValue($vars));
+
+ // TODO: use NLS to get the order right for the Rest Of The
+ // World.
+ $html = '';
+ $date_parts = array('month', 'day', 'year');
+ foreach ($date_parts as $part) {
+ $varname = $var->getVarName() . '[' . $part . ']';
+ $html .= sprintf('<select name="%1$s" id="%1$s"%2$s>%3$s </select>',
+ $varname,
+ $this->_getActionScripts($form, $var),
+ $this->_selectOptions($dates[$part], $date[$part]));
+ }
+
+ if ($var->type->picker && $GLOBALS['browser']->hasFeature('javascript')) {
+ Horde::addScriptFile('open_calendar.js', 'horde');
+ $imgId = $var->getVarName() .'goto';
+ $html .= '<div id="goto"></div>';
+ $html .= Horde::link('#', _("Select a date"), '', '', 'openCalendar(\'' . $imgId . '\', \'' . $var->getVarName() . '\'); return false;')
+ . Horde::img('calendar.png', _("Calendar"), 'id="' . $imgId . '" ', $GLOBALS['registry']->getImageDir('horde'))
+ . '</a>';
+ }
+
+ return $html;
+ }
+
+ function _renderVarInput_datetime($form, $var, $vars)
+ {
+ return parent::_renderVarInput_monthdayyear($form, $var, $vars) .
+ parent::_renderVarInput_hourminutesecond($form, $var, $vars);
+ }
+
+ function _renderVarInput_colorpicker($form, $var, $vars)
+ {
+ $html = '<div class="form-colorpicker">'
+ . '<input type="text" maxlength="7" name="'
+ . $var->getVarName() . '" id="' . $var->getVarName()
+ . '" value="' . $var->getValue($vars) . '" />';
+
+ if ($GLOBALS['browser']->hasFeature('javascript')) {
+ Horde::addScriptFile('open_colorpicker.js', 'horde', true);
+ $html .= Horde::img('blank.gif', '', array('class' => 'form-colorpicker-preview',
+ 'id' => 'colordemo_' . $var->getVarName(),
+ 'style' => 'background:' . $var->getValue($vars)), $GLOBALS['registry']->getImageDir('horde'))
+ . Horde::link('#', _("Color Picker"), '', '', 'openColorPicker(\''. $var->getVarName() .'\'); return false;')
+ . Horde::img('colorpicker.png', _("Color Picker"), '', $GLOBALS['registry']->getImageDir('horde')) . '</a>'
+ . '<div id="colorpicker_' . $var->getVarName() . '" class="form-colorpicker-palette"></div>';
+ }
+
+ return $html . '</div>';
+ }
+
+ function _renderVarInput_sorter($form, $var, $vars)
+ {
+ global $registry;
+
+ $varname = $var->getVarName();
+ $instance = $var->type->instance;
+
+ Horde::addScriptFile('sorter.js', 'horde', true);
+
+ return ' <input type="hidden" name="'. $varname
+ . '[array]" value="" id="'. $varname .'-array-" />'."\n"
+ . ' <select class="leftFloat" multiple="multiple" size="'
+ . $var->type->size . '" name="' . $varname
+ . '[list]" onchange="' . $instance . '.deselectHeader();" '
+ . ' id="'. $varname . '-list-">'
+ . $var->type->getOptions($var->getValue($vars)) . ' </select><div class="leftFloat">'
+ . Horde::link('#', _("Move up"), '', '', $instance . '.moveColumnUp(); return false;')
+ . Horde::img('nav/up.png', _("Move up"), '', $registry->getImageDir('horde'))
+ . '</a><br />'
+ . Horde::link('#', _("Move up"), '', '', $instance . '.moveColumnDown(); return false;')
+ . Horde::img('nav/down.png', _("Move down"), '', $registry->getImageDir('horde'))
+ . '</a></div>'
+ . '<script type="text/javascript">' . "\n"
+ . sprintf('%1$s = new Horde_Form_Sorter(\'%1$s\', \'%2$s\', \'%3$s\');' . "\n",
+ $instance, $varname, $var->type->header)
+ . sprintf("%s.setHidden();\n</script>\n", $instance);
+ }
+
+ function _renderVarInput_assign($form, $var, $vars)
+ {
+ global $registry;
+
+ Horde::addScriptFile('form_assign.js', 'horde', true);
+
+ $name = $var->getVarName();
+ $fname = $form->getName() . '.' . $name;
+ $width = $var->type->width;
+ $lhdr = (bool)$var->type->getHeader(0);
+ $rhdr = (bool)$var->type->getHeader(1);
+ $this->_onLoadJS[] = 'Horde_Form_Assign.setField(\'' . $fname . '\');';
+
+ $html = '<div class="form-input-assign">'
+ . ' <input type="hidden" name="' . $name . '__values" id="' . $name . '__values" />'
+ . sprintf(' <select name="%1$s__left" id="%1$s__left" multiple="multiple" '
+ .'size="%2$d" style="width:%3$s"%4$s>',
+ $name, $var->type->size, $width,
+ $lhdr ? ' onchange="Horde_Form_Assign.deselectHeaders(\'' . $fname . '\', 0);"' : '')
+ . $var->type->getOptions(0, $fname)
+ . ' </select>'
+ . '<div><a href="" onclick="Horde_Form_Assign.move(\''. $fname .'\', 0); return false;">'
+ . Horde::img('rhand.png', _("Add column"), null, $registry->getImageDir('horde'))
+ . '</a><br /><a href="" onclick="Horde_Form_Assign.move(\''
+ . $fname . '\', 1); return false;">'
+ . Horde::img('lhand.png', _("Remove column"), null, $registry->getImageDir('horde'))
+ . '</a></div>'
+ . sprintf(' <select name="%s__right" multiple="multiple" size="%d" style="width:%s"%s>',
+ $name, $size, $width,
+ $rhdr ? ' onchange="Horde_Form_Assign.deselectHeaders(\'' . $fname . '\', 1);"' : '')
+ . $var->type->getOptions(1, $fname)
+ . ' </select></div>';
+
+ return $html;
+ }
+
+ function _renderVarInput_invalid($form, $var, $vars)
+ {
+ return $this->_renderVarDisplay_invalid($form, $var, $vars);
+ }
+
+ function _renderVarInput_enum($form, $var, $vars)
+ {
+ $values = $var->getValues();
+ $prompt = $var->type->prompt;
+ $htmlchars = $var->getOption('htmlchars');
+ if ($prompt) {
+ $prompt = '<option value="">' . ($htmlchars ? htmlspecialchars($prompt, ENT_QUOTES, NLS::getCharset()) : $prompt) . '</option>';
+ }
+ return sprintf(' <select name="%1$s" id="%1$s"%2$s>%3$s%4$s </select>',
+ $var->getVarName(),
+ $this->_getActionScripts($form, $var),
+ $prompt,
+ $this->_selectOptions($values, $var->getValue($vars), $htmlchars));
+ }
+
+ function _renderVarInput_mlenum($form, $var, $vars)
+ {
+ $varname = $var->getVarName();
+ $values = $var->getValues();
+ $prompts = $var->type->prompts;
+ $selected = $var->getValue($vars);
+
+ /* If passing a non-array value need to get the keys. */
+ if (!is_array($selected)) {
+ foreach ($values as $key_1 => $values_2) {
+ if (isset($values_2[$selected])) {
+ $selected = array('1' => $key_1, '2' => $selected);
+ break;
+ }
+ }
+ }
+
+ /* Hidden tag to store the current first level. */
+ $html = sprintf(' <input type="hidden" name="%1$s[old]" id="%1$s[old]" value="%2$s" />',
+ $varname,
+ htmlspecialchars($selected['1'], ENT_QUOTES, NLS::getCharset()));
+
+ /* First level. */
+ $values_1 = Horde_Array::valuesToKeys(array_keys($values));
+ $html .= sprintf(' <select id="%1$s[1]" name="%1$s[1]" onchange="%2$s"%3$s>',
+ $varname,
+ 'if (this.value) { document.' . $form->getName() . '.formname.value=\'\';' . 'document.' . $form->getName() . '.submit() }',
+ ($var->hasAction() ? ' ' . $this->_genActionScript($form, $var->_action, $varname) : ''));
+ if (!empty($prompts)) {
+ $html .= '<option value="">' . htmlspecialchars($prompts[0], ENT_QUOTES, NLS::getCharset()) . '</option>';
+ }
+ $html .= $this->_selectOptions($values_1, $selected['1']);
+ $html .= ' </select>';
+
+ /* Second level. */
+ $html .= sprintf(' <select id="%1$s[2]" name="%1$s[2]"%2$s>',
+ $varname,
+ ($var->hasAction() ? ' ' . $this->_genActionScript($form, $var->_action, $varname) : ''));
+ if (!empty($prompts)) {
+ $html .= '<option value="">' . htmlspecialchars($prompts[1], ENT_QUOTES, NLS::getCharset()) . '</option>';
+ }
+ $values_2 = array();
+ if (!empty($selected['1'])) {
+ $values_2 = $values[$selected['1']];
+ }
+ return $html . $this->_selectOptions($values_2, $selected['2']) . ' </select>';
+ }
+
+ function _renderVarInput_multienum($form, $var, $vars)
+ {
+ $values = $var->getValues();
+ $selected = $vars->getExists($var->getVarName(), $wasset);
+ if (!$wasset) {
+ $selected = $var->getDefault();
+ }
+ $html = sprintf(' <select multiple="multiple" size="%1$s" name="%2$s[]" id="%2$s[]" %3$s>%4$s </select>',
+ $var->type->size,
+ $var->getVarName(),
+ $this->_getActionScripts($form, $var),
+ $this->_multiSelectOptions($values, $selected));
+ return $html . '<p class="form-hint">'
+ . _("To select multiple items, hold down the Control (PC) or Command (Mac) key while clicking.")
+ . "</p>\n";
+ }
+
+ function _renderVarInput_keyval_multienum($form, $var, $vars)
+ {
+ return $this->_renderVarInput_multienum($form, $var, $vars);
+ }
+
+ function _renderVarInput_radio($form, $var, $vars)
+ {
+ return $this->_radioButtons($var->getVarName(),
+ $var->getValues(),
+ $var->getValue($vars),
+ $this->_getActionScripts($form, $var));
+ }
+
+ function _renderVarInput_set($form, $var, $vars)
+ {
+ $html = $this->_checkBoxes($var->getVarName(),
+ $var->getValues(),
+ $var->getValue($vars),
+ $this->_getActionScripts($form, $var));
+
+ if ($var->type->checkAll) {
+ $form_name = $form->getName();
+ $var_name = $var->getVarName() . '[]';
+ $function_name = 'select' . $form_name . $var->getVarName();
+ $enable = _("Select all");
+ $disable = _("Select none");
+ $invert = _("Invert selection");
+ $html .= <<<EOT
+<script type="text/javascript">
+function $function_name()
+{
+ for (var i = 0; i < document.$form_name.elements.length; i++) {
+ f = document.$form_name.elements[i];
+ if (f.name != '$var_name') {
+ continue;
+ }
+ if (arguments.length) {
+ f.checked = arguments[0];
+ } else {
+ f.checked = !f.checked;
+ }
+ }
+}
+</script>
+<a href="#" onclick="$function_name(true); return false;">$enable</a>,
+<a href="#" onclick="$function_name(false); return false;">$disable</a>,
+<a href="#" onclick="$function_name(); return false;">$invert</a>
+EOT;
+ }
+
+ return $html;
+ }
+
+ function _renderVarInput_link($form, $var, $vars)
+ {
+ return $this->_renderVarDisplay_link($form, $var, $vars);
+ }
+
+ function _renderVarInput_html($form, $var, $vars)
+ {
+ return $this->_renderVarDisplay_html($form, $var, $vars);
+ }
+
+ function _renderVarInput_email($form, $var, $vars)
+ {
+ return sprintf(' <input type="text" id="%1$s" name="%1$s" value="%2$s"%3$s />',
+ $var->getVarName(),
+ $value = $var->getValue($vars),
+ $this->_getActionScripts($form, $var));
+ }
+
+ function _renderVarInput_matrix($form, $var, $vars)
+ {
+ $varname = $var->getVarName();
+ $var_array = $var->getValue($vars);
+ $cols = $var->type->cols;
+ $rows = $var->type->rows;
+ $matrix = $var->type->matrix;
+ $new_input = $var->type->new_input;
+
+ $html = '<table cellspacing="0"><tr>';
+
+ $html .= '<td align="right" width="20%"></td>';
+ foreach ($cols as $col_title) {
+ $html .= sprintf('<td align="center" width="1%%">%s</td>', $col_title);
+ }
+ $html .= '<td align="right" width="60%"></td></tr>';
+
+ /* Offer a new row of data to be added to the matrix? */
+ if ($new_input) {
+ $html .= '<tr><td>'."\n";
+ if (is_array($new_input)) {
+ $html .= sprintf(' <select%s name="%s[n][r]"><option value="">%s</option>%s </select><br />'."\n",
+ ' id="'. $varname .'-n--r-"',
+ $varname,
+ _("-- select --"),
+ $this->_selectOptions($new_input, $var_array['n']['r']));
+ } elseif ($new_input == true) {
+ $html .= sprintf(' <input%s type="text" name="%s[n][r]" value="%s" />',
+ ' id="'. $varname .'-n--r-',
+ $varname,
+ $var_array['n']['r']);
+ }
+ $html .= ' </td>';
+ foreach ($cols as $col_id => $col_title) {
+ $html .= sprintf('<td align="center"><input type="checkbox" class="checkbox" name="%s[n][v][%s]" /></td>', $varname, $col_id);
+ }
+ $html .= '<td> </td></tr>'."\n";
+ }
+
+ /* Loop through the rows and create checkboxes for each column. */
+ foreach ($rows as $row_id => $row_title) {
+ $html .= sprintf('<tr><td>%s</td>', $row_title);
+ foreach ($cols as $col_id => $col_title) {
+ $html .= sprintf('<td align="center"><input type="checkbox" class="checkbox" name="%s[r][%s][%s]"%s /></td>', $varname, $row_id, $col_id, (!empty($matrix[$row_id][$col_id]) ? ' checked="checked"' : ''));
+ }
+ $html .= '<td> </td></tr>'."\n";
+ }
+
+ $html .= '</table>'."\n";
+ return $html;
+ }
+
+ function _renderVarInput_password($form, $var, $vars)
+ {
+ return sprintf('<input type="password" id="%1$s" name="%1$s" value="%2$s"%3$s />',
+ $var->getVarName(),
+ $value = $var->getValue($vars),
+ $this->_getActionScripts($form, $var));
+ }
+
+ function _renderVarInput_emailconfirm($form, $var, $vars)
+ {
+ $email = $var->getValue($vars);
+ return '<ul><li>' . sprintf('<input type="text" class="form-input-emailconfirm"' .
+ ' id="%1$s" name="%1$s[original]" value="%2$s"%3$s />',
+ $var->getVarName(),
+ $value = $email['original'],
+ $this->_getActionScripts($form, $var)) . '</li><li>' .
+ sprintf('<input type="text" class="form-input-emailconfirm"' .
+ ' id="%1$s-confirm-" name="%1$s[confirm]" value="%2$s"%3$s />',
+ $var->getVarName(),
+ $value = $email['confirm'],
+ $this->_getActionScripts($form, $var)) . '</li></ul>';
+ }
+
+ function _renderVarInput_passwordconfirm($form, $var, $vars)
+ {
+ $password = $var->getValue($vars);
+ return '<ul><li>' . sprintf('<input type="password" class="form-input-passwordconfirm"'
+ .' id="%1$s" name="%1$s[original]" value="%2$s"%3$s />',
+ $var->getVarName(),
+ $value = $password['original'],
+ $this->_getActionScripts($form, $var)) . '</li><li>' .
+ sprintf('<input type="password" class="form-input-passwordconfirm"'
+ .' id="%1$s-confirm-" name="%1$s[confirm]" value="%2$s"%3$s />',
+ $var->getVarName(),
+ $value = $password['confirm'],
+ $this->_getActionScripts($form, $var)) . '</li></ul>';
+ }
+
+ function _renderVarInput_boolean($form, $var, $vars)
+ {
+ $varName = $var->getVarName();
+
+ $html = ' <input type="checkbox" class="form-input-checkbox" id="' . $varName . '"'
+ . ' name="' . $varName . '"'
+ . ($var->getValue($vars) ? ' checked="checked"' : '');
+ if ($var->hasAction()) {
+ $html .= $this->_genActionScript($form, $var->_action,
+ $var->getVarName());
+ }
+ $html .= ' />';
+ return $html;
+ }
+
+ function _renderVarInput_creditcard($form, $var, $vars)
+ {
+ $varName = $var->getVarName();
+
+ $html = ' <input type="text" class="form-input-creditcard" id="' . $varName . '"'
+ . ' name="' . $varName . '"'
+ .$var->getValue($vars);
+ if ($var->hasAction()) {
+ $html .= $this->_genActionScript($form, $var->_action,
+ $var->getVarName());
+ }
+
+ return $html . ' />';
+ }
+
+ function _renderVarInput_obrowser($form, $var, $vars)
+ {
+ $varname = $var->getVarName();
+ $varvalue = $vars->get($varname);
+ $fieldId = 'obrowser_' . hash('md5', uniqid(rand(), true));
+ $html = '
+ <script type="text/javascript">
+ var obrowserWindowName;
+ function obrowserCallback(name, oid)
+ {
+ if (name == obrowserWindowName) {
+ document.getElementById(\'' . $fieldId . '\').value = oid;
+ return false;
+ } else {
+ return "Invalid window name supplied";
+ }
+ }
+ </script>
+ ';
+ $html .= sprintf('<input type="hidden" name="%s" id="%s"%s value="%s" />',
+ $varname,
+ $fieldId,
+ $this->_getActionScripts($form, $var),
+ $varvalue);
+ if (!empty($varvalue)) {
+ $html .= $varvalue;
+ }
+
+ if ($GLOBALS['browser']->hasFeature('javascript')) {
+ Horde::addScriptFile('popup.js', 'horde', true);
+ $imgId = $varname .'goto';
+ $html .= '<div id="goto" class="headerbox"
+ style="position:absolute;visibility:hidden;padding:0"></div>';
+ $html .= Horde::link('#', _("Select an object"), '', '', 'obrowserWindow = popup(\'' . $GLOBALS['registry']->get('webroot', 'horde') . '/services/obrowser/' . '\'); obrowserWindowName = obrowserWindow.name; return false;') . Horde::img('tree/leaf.png', _("Object"), 'id="' . $imgId . '" align="middle"', $GLOBALS['registry']->getImageDir('horde')) . "</a>\n";
+ }
+
+ return $html;
+ }
+
+ function _renderVarInput_dblookup($form, $var, $vars)
+ {
+ return $this->_renderVarInput_enum($form, $var, $vars);
+ }
+
+ function _renderVarInput_figlet($form, $var, $vars)
+ {
+ return sprintf(' <input type="text" class="form-input-figlet" id="%1$s" name="%1$s" size="%2$s" value="%3$s" />',
+ $var->getVarName(),
+ strlen($var->type->text),
+ htmlspecialchars($var->getValue($vars))) .
+ '<p class="form-input-figlet">' . _("Enter the letters below:") . '</p>' .
+ $this->_renderVarDisplay_figlet($form, $var, $vars);
+ }
+
+ function _renderVarDisplayDefault($form, $var, $vars)
+ {
+ return nl2br(htmlspecialchars($var->getValue($vars), ENT_QUOTES,
+ NLS::getCharset()));
+ }
+
+ function _renderVarDisplay_html($form, $var, $vars)
+ {
+ return $var->getValue($vars);
+ }
+
+ function _renderVarDisplay_email($form, $var, $vars)
+ {
+ $display_email = $email = $var->getValue($vars);
+
+ if ($var->type->strip_domain && strpos($email, '@') !== false) {
+ $display_email = str_replace(array('@', '.'),
+ array(' (at) ', ' (dot) '),
+ $email);
+ }
+
+ if ($var->type->link_compose) {
+ $email_val = trim($email);
+
+ // Format the address according to RFC822.
+ $mailbox_host = explode('@', $email_val);
+ if (!isset($mailbox_host[1])) {
+ $mailbox_host[1] = '';
+ }
+
+ $name = $var->type->link_name;
+
+ require_once 'Horde/MIME.php';
+ $address = MIME::rfc822WriteAddress($mailbox_host[0], $mailbox_host[1], $name);
+
+ // Get rid of the trailing @ (when no host is included in
+ // the email address).
+ $address = str_replace('@>', '>', $address);
+ $mail_link = $GLOBALS['registry']->call('mail/compose', array(array('to' => addslashes($address))));
+ if (is_a($mail_link, 'PEAR_Error')) {
+ $mail_link = 'mailto:' . urlencode($address);
+ }
+
+ return Horde::link($mail_link, $email_val)
+ . htmlspecialchars($display_email) . '</a>';
+ } else {
+ return nl2br(htmlspecialchars($display_email, ENT_QUOTES, NLS::getCharset()));
+ }
+ }
+
+ function _renderVarDisplay_password($form, $var, $vars)
+ {
+ return '********';
+ }
+
+ function _renderVarDisplay_passwordconfirm($form, $var, $vars)
+ {
+ return '********';
+ }
+
+ function _renderVarDisplay_octal($form, $var, $vars)
+ {
+ return sprintf('0%o', octdec($var->getValue($vars)));
+ }
+
+ function _renderVarDisplay_boolean($form, $var, $vars)
+ {
+ return $var->getValue($vars) ? _("Yes") : _("No");
+ }
+
+ function _renderVarDisplay_enum($form, $var, $vars)
+ {
+ $values = $var->getValues();
+ $value = $var->getValue($vars);
+ if (count($values) == 0) {
+ return _("No values");
+ } elseif (isset($values[$value]) && $value != '') {
+ return htmlspecialchars($values[$value], ENT_QUOTES, NLS::getCharset());
+ }
+ }
+
+ function _renderVarDisplay_radio($form, $var, $vars)
+ {
+ $values = $var->getValues();
+ if (count($values) == 0) {
+ return _("No values");
+ } elseif (isset($values[$var->getValue($vars)])) {
+ return htmlspecialchars($values[$var->getValue($vars)], ENT_QUOTES, NLS::getCharset());
+ }
+ }
+
+ function _renderVarDisplay_multienum($form, $var, $vars)
+ {
+ $values = $var->getValues();
+ $on = $var->getValue($vars);
+ if (!count($values) || !count($on)) {
+ return _("No values");
+ } else {
+ $display = array();
+ foreach ($values as $value => $name) {
+ if (in_array($value, $on)) {
+ $display[] = $name;
+ }
+ }
+ return htmlspecialchars(implode(', ', $display), ENT_QUOTES, NLS::getCharset());
+ }
+ }
+
+ function _renderVarDisplay_set($form, $var, $vars)
+ {
+ $values = $var->getValues();
+ $on = $var->getValue($vars);
+ if (!count($values) || !count($on)) {
+ return _("No values");
+ } else {
+ $display = array();
+ foreach ($values as $value => $name) {
+ if (in_array($value, $on)) {
+ $display[] = $name;
+ }
+ }
+ return htmlspecialchars(implode(', ', $display), ENT_QUOTES, NLS::getCharset());
+ }
+ }
+
+ function _renderVarDisplay_image($form, $var, $vars)
+ {
+ $img_params = $var->getValue($vars);
+ $img_url = Horde::url($GLOBALS['registry']->get('webroot', 'horde') . '/services/images/view.php');
+ $img_url = Util::addParameter($img_url, $img_params);
+
+ return Horde::img($img_url, isset($img_params['f']) ? $img_params['f'] : '', '', '');
+ }
+
+ function _renderVarDisplay_phone($form, &$var, &$vars)
+ {
+ global $registry;
+
+ $number = $var->getValue($vars);
+ $html = htmlspecialchars($number, ENT_QUOTES, $this->_charset);
+
+ if ($number && $registry->hasMethod('telephony/dial')) {
+ $url = $registry->call('telephony/dial', array($number));
+ $label = sprintf(_("Dial %s"), $number);
+ $html .= ' ' . Horde::link($url, $label) . Horde::img('phone.png', $label, '', $registry->getImageDir('horde')) . '</a>';
+ }
+
+ return $html;
+ }
+
+ function _renderVarDisplay_cellphone($form, &$var, &$vars)
+ {
+ global $registry;
+
+ $html = $this->_renderVarDisplay_phone($form, $var, $vars);
+
+ $number = $var->getValue($vars);
+ if ($number && $registry->hasMethod('sms/compose')) {
+ $url = $registry->link('sms/compose', array('to' => $number));
+ $html .= ' ' . Horde::link($url, _("Send SMS")) . Horde::img('mobile.png', _("Send SMS"), '', $registry->getImageDir('horde')) . '</a>';
+ }
+
+ return $html;
+ }
+
+ function _renderVarDisplay_address($form, $var, $vars)
+ {
+ global $registry;
+
+ $address = $var->getValue($vars);
+
+ if (preg_match('/((?: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, $postcode)) {
+ /* UK postcode detected. */
+ /* Multimap.co.uk generated map */
+ $mapurl = 'http://www.multimap.com/map/browse.cgi?pc=' . urlencode($postcode[1]);
+ $desc = _("Multimap UK map");
+ $icon = 'map.png';
+ } elseif (preg_match('/ACT|NSW|NT|QLD|SA|TAS|VIC|WA/', $address)) {
+ /* Australian state detected. */
+ /* Whereis.com.au generated map */
+ $mapurl = 'http://www.whereis.com.au/whereis/mapping/geocodeAddress.do?';
+ $desc = _("Whereis Australia map");
+ $icon = 'map.png';
+ /* Split out the address, line-by-line. */
+ $addressLines = explode("\n", $address);
+ for ($i = 0; $i < count($addressLines); $i++) {
+ /* See if it's the street number & name. */
+ if (preg_match('/(\d+\s*\/\s*)?(\d+|\d+[a-zA-Z])\s+([a-zA-Z ]*)/', $addressLines[$i], $lineParts)) {
+ $mapurl .= '&streetNumber=' . urlencode($lineParts[2]);
+ $mapurl .= '&streetName=' . urlencode($lineParts[3]);
+ }
+ /* Look for "Suburb, State". */
+ if (preg_match('/([a-zA-Z ]*),?\s+' . $aus_state_regexp . '/', $addressLines[$i], $lineParts)) {
+ $mapurl .= '&suburb=' . urlencode($lineParts[1]);
+ }
+ /* Look for "State <4 digit postcode>". */
+ if (preg_match('/(' . $aus_state_regexp . ')\s+(\d{4})/', $addressLines[$i], $lineParts)) {
+ $mapurl .= '&state=' . urlencode($lineParts[1]);
+ }
+ }
+ } elseif (preg_match('/(.*)\n(.*)\s*,\s*(\w+)\.?\s+(\d+|[a-zA-Z]\d[a-zA-Z]\s?\d[a-zA-Z]\d)/', $address, $addressParts)) {
+ /* American/Canadian address style. */
+ /* Mapquest generated map */
+ $mapurl = 'http://www.mapquest.com/maps/map.adp?size=big&zoom=7';
+ $desc = _("MapQuest map");
+ $icon = 'map.png';
+ $country = null;
+ if (!empty($addressParts[4]) && preg_match('|[a-zA-Z]\d[a-zA-Z]\s?\d[a-zA-Z]\d|', $addressParts[4])) {
+ $country = 'CA';
+ }
+ if (!empty($addressParts[1])) {
+ $mapurl .= '&address=' . urlencode($addressParts[1]);
+ }
+ if (!empty($addressParts[2])) {
+ $mapurl .= '&city=' . urlencode($addressParts[2]);
+ }
+ if (!empty($addressParts[3])) {
+ $mapurl .= '&state=' . urlencode($addressParts[3]);
+ }
+ if (!empty($addressParts[4])) {
+ if ($country == 'CA') {
+ $mapurl .= '&country=CA';
+ }
+ $mapurl .= '&zipcode=' . urlencode($addressParts[4]);
+ }
+
+ /* Yahoo! generated map. */
+ $mapurl2 = 'http://us.rd.yahoo.com/maps/home/submit_a/*-http://maps.yahoo.com/maps?srchtype=a&getmap=Get+Map&';
+ $desc2 = _("Yahoo! map");
+ $icon2 = 'map.png';
+ if (!empty($addressParts[1])) {
+ $mapurl2 .= '&addr=' . urlencode($addressParts[1]);
+ }
+ /* Give precedence to zipcode over city/state */
+ if (empty($addressParts[4]) && !empty($addressParts[2]) && !empty($addressParts[3])) {
+ $mapurl2 .= '&csz=' . urlencode($addressParts[2] . ' ' . $addressParts[3]);
+ }
+ if (!empty($addressParts[4])) {
+ if (preg_match('|([a-zA-Z]\d[a-zA-Z])\s?(\d[a-zA-Z]\d)|', $addressParts[4], $pcParts)) {
+ $mapurl2 .= '&country=ca';
+ /* make sure the postal-code has a space */
+ $addressParts[4] = $pcParts[1] . ' ' . $pcParts[2];
+ }
+ $mapurl2 .= '&csz=' . urlencode($addressParts[4]);
+ }
+
+ /* Google generated map. */
+ $mapurl3 = 'http://maps.google.com/maps?q=' . urlencode($addressParts[0]) . '&hl=en';
+ $desc3 = _("Google Maps");
+ $icon3 = 'map.png';
+
+ } elseif (preg_match('/(.*?)\r?\n([A-Z]{1,3})-(\d{5})\s+(.*)/i', $address, $addressParts)) {
+ /* European address style. */
+ include 'Horde/NLS/carsigns.php';
+ $country = array_search(String::upper($addressParts[2]), $carsigns);
+
+ /* Map24 generated map. */
+ if (in_array($country, array('al', 'ad', 'am', 'az', 'be', 'ba',
+ 'bg', 'de', 'dk', 'ee', 'fo', 'fi',
+ 'fr', 'ge', 'gr', 'gb', 'ie', 'is',
+ 'it', 'hr', 'lv', 'li', 'lt', 'lu',
+ 'mt', 'mk', 'md', 'mc', 'nl', 'no',
+ 'pl', 'pt', 'ro', 'ru', 'se', 'ch',
+ 'cs', 'sk', 'si', 'es', 'cz', 'tr',
+ 'ua', 'hu', 'by', 'cy', 'at'))) {
+ if (in_array($country, array('at', 'be', 'ch', 'de', 'dk',
+ 'es', 'fi', 'fr', 'it', 'nl',
+ 'no', 'se'))) {
+ $mirror = $country;
+ } else {
+ $mirror = 'uk';
+ }
+ $mapurl = 'http://www.' . $mirror . '.map24.com/source/address/v2.0.0/cnt_nav_maplet.php?cid=validateaddr&country=' . $country;
+ $desc = _("Map24 map");
+ $icon = 'map_eu.png';
+ if (!empty($addressParts[1])) {
+ $mapurl .= '&street=' . urlencode($addressParts[1]);
+ }
+ if (!empty($addressParts[3])) {
+ $mapurl .= '&zip=' . urlencode($addressParts[3]);
+ }
+ if (!empty($addressParts[4])) {
+ $mapurl .= '&city=' . urlencode($addressParts[4]);
+ }
+ }
+
+ /* Mapquest generated map. */
+ $mapurl2 = 'http://www.mapquest.com/maps/map.adp?country=' . String::upper($country);
+ $desc2 = _("MapQuest map");
+ $icon2 = 'map_eu.png';
+ if (!empty($addressParts[1])) {
+ $mapurl2 .= '&address=' . urlencode($addressParts[1]);
+ }
+ if (!empty($addressParts[3])) {
+ $mapurl2 .= '&zipcode=' . urlencode($addressParts[3]);
+ }
+ if (!empty($addressParts[4])) {
+ $mapurl2 .= '&city=' . urlencode($addressParts[4]);
+ }
+ }
+
+ $html = nl2br(htmlspecialchars($var->getValue($vars), ENT_QUOTES, NLS::getCharset()));
+ if (!empty($mapurl)) {
+ $html .= ' ' . Horde::link(Horde::externalUrl($mapurl), $desc, null, '_blank') . Horde::img($icon, $desc, '', $registry->getImageDir('horde')) . '</a>';
+ }
+ if (!empty($mapurl2)) {
+ $html .= ' ' . Horde::link(Horde::externalUrl($mapurl2), $desc2, null, '_blank') . Horde::img($icon2, $desc2, '', $registry->getImageDir('horde')) . '</a>';
+ }
+ if (!empty($mapurl3)) {
+ $html .= ' ' . Horde::link(Horde::externalUrl($mapurl3), $desc3, null, '_blank') . Horde::img($icon3, $desc3, '', $registry->getImageDir('horde')) . '</a>';
+ }
+
+ return $html;
+ }
+
+ function _renderVarDisplay_date($form, $var, $vars)
+ {
+ return $var->type->getFormattedTime($var->getValue($vars));
+ }
+
+ function _renderVarDisplay_monthyear($form, $var, $vars)
+ {
+ return $vars->get($var->getVarName() . '[month]') . ', ' . $vars->get($var->getVarName() . '[year]');
+ }
+
+ function _renderVarDisplay_monthdayyear($form, $var, $vars)
+ {
+ $date = $var->getValue($vars);
+ if ((is_array($date) && !empty($date['year']) &&
+ !empty($date['month']) && !empty($date['day']))
+ || (!is_array($date) && !empty($date))) {
+ return $var->type->formatDate($date);
+ }
+ return '';
+ }
+
+ function _renderVarDisplay_invalid($form, $var, $vars)
+ {
+ return '<p class="form-error form-inline">'
+ . htmlspecialchars($var->type->message, ENT_QUOTES, NLS::getCharset())
+ . '</p>';
+ }
+
+ function _renderVarDisplay_link($form, $var, $vars)
+ {
+ $values = $var->getValues();
+ if (!isset($values[0])) {
+ $values = array($values);
+ }
+
+
+ $count = count($values);
+ $html = '';
+ for ($i = 0; $i < $count; $i++) {
+ if (empty($values[$i]['url']) || empty($values[$i]['text'])) {
+ continue;
+ }
+ if (!isset($values[$i]['target'])) {
+ $values[$i]['target'] = '';
+ }
+ if (!isset($values[$i]['onclick'])) {
+ $values[$i]['onclick'] = '';
+ }
+ if (!isset($values[$i]['title'])) {
+ $values[$i]['title'] = '';
+ }
+ if (!isset($values[$i]['accesskey'])) {
+ $values[$i]['accesskey'] = '';
+ }
+ if ($i > 0) {
+ $html .= ' | ';
+ }
+ $html .= Horde::link($values[$i]['url'], $values[$i]['text'],
+ 'widget', $values[$i]['target'], $values[$i]['onclick'],
+ $values[$i]['title'], $values[$i]['accesskey'])
+ . $values[$i]['text'] . '</a>';
+ }
+
+ return $html;
+ }
+
+ function _renderVarDisplay_dblookup($form, $var, $vars)
+ {
+ return $this->_renderVarDisplay_enum($form, $var, $vars);
+ }
+
+ function _renderVarDisplay_figlet($form, $var, $vars)
+ {
+ $figlet = new Text_Figlet();
+ $result = $figlet->loadFont($var->type->font);
+ if (is_a($result, 'PEAR_Error')) {
+ return $result->getMessage();
+ }
+
+ return '<pre>' . $figlet->lineEcho($var->type->text) . '</pre>';
+ }
+
+ function _renderVarInput_selectFiles($form, $var, $vars)
+ {
+ /* Needed for gollem js calls */
+ $html = sprintf('<input type="hidden" id="%1$s" name="%1$s" value="%2$s" />',
+ 'selectlist_selectid',
+ $var->type->selectid)
+ . sprintf('<input type="hidden" id="%1$s" name="%1$s" />', 'actionID');
+
+ /* Form field. */
+ $html .= sprintf('<input type="hidden" id="%1$s" name="%1$s" value="%2$s" />',
+ $var->getVarName(),
+ $var->type->selectid);
+
+ /* Open window link. */
+ $param = array($var->type->link_text,
+ $var->type->link_style,
+ $form->getName(),
+ $var->type->icon,
+ $var->type->selectid);
+ $html .= "<p>\n" . $GLOBALS['registry']->call('files/selectlistLink', $param) . "</p>\n";
+
+ if ($var->type->selectid) {
+ $param = array($var->type->selectid);
+ $files = $GLOBALS['registry']->call('files/selectlistResults', $param);
+ if ($files) {
+ $html .= '<ol>';
+ foreach ($files as $id => $file) {
+ $dir = key($file);
+ $filename = current($file);
+ if ($GLOBALS['registry']->hasMethod('files/getViewLink')) {
+ $filename = basename($filename);
+ $url = $GLOBALS['registry']->call('files/getViewLink', array($dir, $filename));
+ $filename = Horde::link($url, _("Preview"), null, 'form_file_view') . htmlspecialchars(Util::realPath($dir . '/' . $filename), ENT_QUOTES, $this->_charset) . '</a>';
+ } else {
+ if (!empty($dir) && ($dir != '.')) {
+ $filename = $dir . '/' . $filename;
+ }
+ $filename = htmlspecialchars($filename, ENT_QUOTES, $this->_charset);
+ }
+ $html .= '<li>' . $filename . "</li>\n";
+ }
+ $html .= '</ol>';
+ }
+ }
+
+ return $html;
+ }
+
+ function _selectOptions($values, $selectedValue = false, $htmlchars = true)
+ {
+ $result = '';
+ $sel = false;
+ foreach ($values as $value => $display) {
+ if (!is_null($selectedValue) && !$sel && $value == $selectedValue
+ && strlen($value) == strlen($selectedValue)) {
+ $selected = ' selected="selected"';
+ $sel = true;
+ } else {
+ $selected = '';
+ }
+ $result .= ' <option value="';
+ $result .= ($htmlchars) ? htmlspecialchars($value, ENT_QUOTES, NLS::getCharset()) : $value;
+ $result .= '"' . $selected . '>';
+ $result .= ($htmlchars) ? htmlspecialchars($display) : $display;
+ $result .= "</option>\n";
+ }
+
+ return $result;
+ }
+
+ function _multiSelectOptions($values, $selectedValues)
+ {
+ $result = '';
+ $sel = false;
+ foreach ($values as $value => $display) {
+ if (@in_array($value, $selectedValues)) {
+ $selected = ' selected="selected"';
+ } else {
+ $selected = '';
+ }
+ $result .= " <option value=\""
+ . htmlspecialchars($value, ENT_QUOTES, NLS::getCharset())
+ . "\"$selected>" . htmlspecialchars($display) . "</option>\n";
+ }
+
+ return $result;
+ }
+
+ function _checkBoxes($name, $values, $checkedValues, $actions = '')
+ {
+ $result = '';
+ if (!is_array($checkedValues)) {
+ $checkedValues = array();
+ }
+
+ if (count($values) > 0) {
+ $result .= " <ul>\n";
+ }
+
+ $i = 0;
+ foreach ($values as $value => $display) {
+ $checked = in_array($value, $checkedValues) ? ' checked="checked"' : '';
+ $result .= sprintf(' <li>'
+ .'<input id="%1$s%2$s" type="checkbox"'
+ .' class="form-input-checkbox" name="%1$s[]"'
+ .' value="%3$s"%4$s%5$s />'
+ .' <label class="form-inline" for="%1$s%2$s">'
+ .'%6$s</label></li>'."\n",
+ $name,
+ $i,
+ $value,
+ $checked,
+ $actions,
+ $display);
+ $i++;
+ }
+
+ if (count($values) > 0) {
+ $result .= " </ul>";
+ }
+
+
+ return $result;
+ }
+
+ function _radioButtons($name, $values, $checkedValue = null, $actions = '')
+ {
+ $result = '';
+
+ if (count($values) > 0) {
+ $result .= " <ul>\n";
+ }
+
+ $i = 0;
+ foreach ($values as $value => $display) {
+ $checked = (!is_null($checkedValue) && $value == $checkedValue) ? ' checked="checked"' : '';
+ $result .= sprintf(' <li>'
+ .'<input id="%1$s%2$s" type="radio"'
+ .' class="form-input-checkbox" name="%1$s"'
+ .' value="%3$s"%4$s%5$s />'
+ .' <label class="form-inline" for="%1$s%2$s">'
+ .'%6$s</label></li>'."\n",
+ $name,
+ $i,
+ $value,
+ $checked,
+ $actions,
+ $display);
+ $i++;
+ }
+
+ if (count($values) > 0) {
+ $result .= " </ul>";
+ }
+
+ return $result;
+ }
+
+ /**
+ *
+ * @access private
+ * @author ?
+ * @deprecated
+ */
+ function _genID($name, $fulltag = true)
+ {
+ return $fulltag ? 'id="' . htmlspecialchars($name) . '"' : $name;
+ }
+
+ /**
+ * Returns script for an rendered variable. TODO: make this unobtrusive.
+ *
+ * @access private
+ * @author ?
+ * @return string html representing an attribute with action script as value,
+ * or and empty string, if the action is to happen window.onload
+ */
+ function _genActionScript($form, $action, $varname)
+ {
+ $html = '';
+ $triggers = $action->getTrigger();
+ if (!is_array($triggers)) {
+ $triggers = array($triggers);
+ }
+ $js = $action->getActionScript($form, $this, $varname);
+ foreach ($triggers as $trigger) {
+ if ($trigger == 'onload') {
+ $this->_onLoadJS[] = $js;
+ } else {
+ $html .= ' ' . $trigger . '="' . $js . '"';
+ }
+ }
+ return $html;
+ }
+
+ /**
+ * Returns scripts for an rendered variable. TODO: make this unobtrusive.
+ *
+ * @access private
+ * @author ?
+ * @return string html representing attributes with action script as values,
+ * or and empty string, if the actions are all to happen window.onload
+ */
+ function _getActionScripts($form, $var)
+ {
+ $actions = '';
+ if ($var->hasAction()) {
+ $varname = $var->getVarName();
+ $action = &$var->_action;
+ $triggers = $action->getTrigger();
+ if (!is_array($triggers)) {
+ $triggers = array($triggers);
+ }
+ $js = $action->getActionScript($form, $this, $varname);
+ foreach ($triggers as $trigger) {
+ if ($trigger == 'onload') {
+ $this->_onLoadJS[] = $js;
+ } else {
+ $actions .= ' ' . $trigger . '="' . $js . '"';
+ }
+ }
+ }
+ return $actions;
+ }
+
+}
--- /dev/null
+/* http://www.quirksmode.org/dom/maxlength.html */
+
+/*
+<textarea id="text" name="text" maxlength="1500"></textarea>
+*/
+
+
+function setMaxLength()
+{
+ var x = document.getElementsByTagName('textarea');
+ var counter = document.createElement('div');
+ counter.className = 'counter';
+ for (var i=0;i<x.length;i++)
+ {
+ if (x[i].getAttribute('maxlength'))
+ {
+ var counterClone = counter.cloneNode(true);
+ counterClone.relatedElement = x[i];
+ counterClone.innerHTML = '<span>0</span>/'+x[i].getAttribute('maxlength');
+ x[i].parentNode.insertBefore(counterClone,x[i].nextSibling);
+ x[i].relatedElement = counterClone.getElementsByTagName('span')[0];
+
+ x[i].onkeyup = x[i].onchange = checkMaxLength;
+ x[i].onkeyup();
+ }
+ }
+}
+
+function checkMaxLength()
+{
+ var maxLength = this.getAttribute('maxlength');
+ var currentLength = this.value.length;
+ if (currentLength > maxLength)
+ this.relatedElement.className = 'toomuch';
+ else
+ this.relatedElement.className = '';
+ this.relatedElement.firstChild.nodeValue = currentLength;
+ // not innerHTML
+}
--- /dev/null
+<?php
+/**
+ * Incubator Horde_Form rewrite example page.
+ *
+ * The initial Horde_Form xhtml rewrite was supported by Google SoC
+ * 2005.
+ *
+ * $Horde: incubator/Horde_Form/test.php,v 1.25 2008/09/02 17:43:09 chuck Exp $
+ */
+
+@define('HORDE_BASE', dirname(__FILE__) . '/../..');
+@define('INCUBATOR_BASE', dirname(__FILE__));
+
+require_once HORDE_BASE . '/lib/core.php';
+require_once 'Horde/Variables.php';
+require_once 'Horde/Autoloader.php';
+Horde_Autoloader::addClassPath(dirname(__FILE__));
+$registry = Registry::singleton();
+$vars = Variables::getDefaultVariables();
+
+$vars->set('example_bar', 'text with a beginning and an end');
+$form = new Horde_Form($vars, 'Horde_Form Test');
+
+$choices = array('big' => 'BIG',
+ 'small' => 'small',
+ 'other' => 'Other');
+$form->add('condchoices', 'Enum', _("Select something"), '', true, false, array($choices, true));
+
+$o = $form->add('other_text', 'String', _("If other, please describe"), '', false);
+$params = array('target' => 'condchoices',
+ 'enabled' => true,
+ 'values' => array('other'));
+$o->setAction(new Horde_Form_Action_ConditionalEnable($params));
+
+$form->add('color', 'Color', _("Color"), null, false);
+
+$vars->set('form', 'add');
+$enum = array('' => _("Select:"),
+ 1 => _("Yes"),
+ 0 => _("No"));
+$form->add('opciones', 'Enum', _("Simple description"), '', true, false, array($enum));
+$form->add('bool', 'Boolean', _("Boolean"));
+$form->add('number', 'Int', _("Integer"));
+$form->add('mybday', 'date', _("A Date"), '', false);
+$form->addHidden('form', 'String', true);
+$unamevar = $form->add('user_name', 'String', _("Username"));
+$form->add('password', 'password', _("Password"));
+$form->addHidden('example_hidden', 'int', false);
+$form->add('some_text', 'String', _("Insert some text"), _("Insert some text in this box"), false);
+$choices = array('big' => 'BIG',
+ 'small' => 'small',
+ 'mixed' => 'mIxED');
+$form->add('choices', 'enum', _("Select something2"), 'Use the selection box to make your choice', true, false, array($choices, true));
+$form->add('email_address', 'email', _("Email"));
+$form->add('email_address2', 'emailconfirm', _("Email2"));
+$form->add('a_creditcard', 'creditcard', _("Credit Card"));
+$form->add('a_password', 'password', _("Password"));
+$form->add('a_password2', 'passwordconfirm', _("Password with confirmation"), _("type the password twice to confirm"));
+$form->add('a_octal', 'Octal', _("Octal"), false);
+$form->add('a_radiogroup', 'set', _("Radio Group"), '', true, false, array($choices));
+
+$t = $form->add('example_bar', 'String', _("Bar field"), _("You have to fill in some long text here"), true, false, array(4, 40));
+$t->setAction(new Horde_Form_Action_setcursorpos(array(4)));
+
+$form->add('a_checkboxgroup', 'set', _("Checkbox Group"), '', false, false, array($choices));
+//$form->add('a_obrowser', 'obrowser', _("obrowser"));
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<title>Incubator Horde_Form Test</title>
+<link rel="stylesheet" type="text/css" href="themes/form.css" />
+<script type="text/javascript" src="<?=$registry->get('jsuri', 'horde')?>/horde.js"></script>
+<script type="text/javascript" src="<?=$registry->get('jsuri', 'horde')?>/form_helpers.js"></script>
+</head>
+<body>
+<?php
+if ($form->validate()) {
+ $form->getInfo($info);
+ echo 'You have submitted:<br /><pre>';
+ var_dump($info);
+ echo '</pre>';
+}
+
+/* Render the form. */
+$renderer = new Horde_Form_Renderer_Xhtml;
+$renderer->setButtons(_("Add user"), _("Reset"));
+$renderer->renderActive($form, 'test.php', 'post');
+
+?>
+</body>
+</html>
--- /dev/null
+form.horde-form {
+ font-size: 100%;
+ font-weight: normal;
+}
+
+form.horde-form input[type="text"], form.horde-form input[type="password"],
+form.horde-form select, form.horde-form textarea {
+ width: 130px;
+ margin: .2em 0 .1em .1em;
+}
+
+form.horde-form input[type="text"], form.horde-form input[type="password"], form.horde-form textarea {
+ padding: .1em;
+}
+
+.clear {
+ clear: both;
+}
+
+.horde-form fieldset {
+ padding: .5em;
+ margin: 0;
+ border: 1px solid #ccc;
+}
+
+.horde-form fieldset.form-buttons {
+ color: #000;
+ background: #ccc;
+ border: 1px solid #aaa;
+}
+
+fieldset legend {
+ color: #000;
+ background: #ccc;
+ padding: .5em;
+ margin-bottom: -1em;
+ border: 1px solid #999;
+ border-bottom: none;
+ font-weight: bold;
+}
+
+fieldset.form-section {
+ padding: .5em;
+ margin: .5em 0;
+}
+
+.form-button, .form-button-upload {
+ font-size: 90%;
+}
+
+.form-colorpicker {
+ float: left;
+}
+.form-colorpicker img {
+ border: 0;
+ padding: 0;
+ margin: 2px;
+ height: 16px;
+ width: 16px;
+}
+.form-colorpicker input {
+ width: 100px;
+ clear: none;
+}
+.form-colorpicker-palette {
+ display: none;
+ margin: 2px;
+}
+
+.form-description {
+ padding: 8px;
+}
+
+.form-error, .form-error-example {
+ color: #f00;
+}
+
+p.form-error {
+ background-color: #f00;
+ color: #fff;
+ padding: 3px;
+ border: 1px solid #000;
+ margin: auto 70px;
+}
+
+div.form-error {
+ background-color: #ffffe1;
+ background-image: url("graphics/required.png");
+ background-repeat: no-repeat;
+ background-position: top left;
+ color: #000;
+}
+
+.form-hint {
+ display: block;
+ margin: 0 0 5px 142px;
+ padding: 1px 3px;
+ font-size: 88%;
+}
+
+.form-header {
+ vertical-align: bottom;
+ font-weight: bold;
+}
+
+.form-image-preview-blank {
+ width: 50px;
+ height: 40px;
+ vertical-align: top;
+}
+
+.form-inline {
+ display: inline;
+}
+
+.form-input {
+ vertical-align: top;
+ clear: both;
+ padding: 4px;
+ margin: 2px 0;
+}
+
+.form-input label {
+ vertical-align: top;
+ text-align: right;
+ float: left;
+ clear: left;
+ display: block;
+ width: 10em;
+ padding: 0.3em;
+}
+
+.form-input label.form-inline {
+ float: none;
+ width: auto;
+ display: inline;
+}
+
+.form-input ul, .form-input ol {
+ list-style-type: none;
+ display: block;
+ float: left;
+}
+
+.form-input ul, .form-input ol, .form-input li {
+ margin-top: 0;
+ margin-left: 0;
+ padding-top: 0;
+ padding-left: 0;
+}
+.form-input ul {
+ margin-bottom: .5em;
+}
+
+.form-input-address {
+}
+
+.form-input-assign {
+}
+
+.form-input-assign select, .form-input-assign div {
+ display: inline;
+ clear: none;
+}
+
+.form-input-checkbox {
+ border: 0;
+ height: 14px;
+ width: 14px;
+ background: transparent;
+}
+
+.form-input-text, .form-input-intlist, .form-input-octal, .form-input-int,
+.form-input-number, .form-input-phone, .form-input-file {
+ width: 100px;
+}
+
+.form-input-resize {
+ width: 25px;
+}
+
+.form-input-stringlist {
+ width: 150px;
+}
+
+.form-input-time {
+ width: 30px;
+}
+
+.form-note {
+ clear: left;
+ width: 130px;
+ height: auto;
+ padding: .3em;
+ margin: 0 0 0 10.7em;
+ border: 1px solid #666;
+ background-color: #ffc;
+}
+.form-note p {
+ margin: 0;
+ padding: 0;
+ font-style: italic;
+ font-size: 70%;
+}
+
+.form-required {
+ background: url("graphics/required.png") .5em .5em no-repeat;
+}
+
+.form-required label {
+ font-weight: bold;
+}
+
+.form-sectionhidden {
+ position: absolute;
+ left: 0;
+ top: -500px;
+ width: 1px;
+ height: 1px;
+ overflow: hidden;
+ display: block;
+}
+
+.form-sectionshown {
+ display: block;
+}
+
+.form-spacer {
+ padding: .9em;
+}
+
+.rowEven {
+ background-color: #eef;
+}
+.rowOdd {
+ background-color: #fff;
+}
+
+/* Form styles. */
+.htmlarea .statusBar .statusBarTree a {
+ font: inherit;
+}
+.htmlarea table {
+ width: auto;
+}
+input, select {
+}
+input {
+ padding: 1px;
+}
+option {
+ padding: 0 5px 0 3px;
+}
+
+.button {
+ font-size: 90%;
+}
+a.button {
+ padding: 2px;
+ font-weight: normal;
+ text-decoration: none;
+}