diff --git a/phpgwapi/inc/class.html.inc.php b/phpgwapi/inc/class.html.inc.php
new file mode 100644
index 0000000000..25002fe178
--- /dev/null
+++ b/phpgwapi/inc/class.html.inc.php
@@ -0,0 +1,1180 @@
+ *
+ * -------------------------------------------- *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU General Public License as published by the *
+ * Free Software Foundation; either version 2 of the License, or (at your *
+ * option) any later version. *
+ \**************************************************************************/
+
+ /* $Id$ */
+
+/**
+ * generates html with methods representing html-tags or higher widgets
+ *
+ * @package api
+ * @subpackage html
+ * @author RalfBecker-AT-outdoor-training.de
+ * @license GPL
+ */
+class html
+{
+ /**
+ * user-agent: 'mozilla','msie','konqueror', 'safari', 'opera'
+ * @var string
+ */
+ var $user_agent;
+ /**
+ * version of user-agent as specified by browser
+ * @var string
+ */
+ var $ua_version;
+ /**
+ * what attribute to use for the title of an image: 'title' for everything but netscape4='alt'
+ * @var string
+ */
+ var $prefered_img_title;
+ /**
+ * charset used by the page, as returned by $GLOBALS['egw']->translation->charset()
+ * @var string
+ */
+ var $charset;
+ /**
+ * URL (NOT path) of the js directory in the api
+ * @var string
+ */
+ var $phpgwapi_js_url;
+ /**
+ * do we need to set the wz_tooltip class, to be included at the end of the page
+ * @var boolean
+ */
+ var $wz_tooltip_included = False;
+
+ /**
+ * Constructor: initialised the class-vars
+ */
+ function html()
+ {
+ // should be Ok for all HTML 4 compatible browsers
+ if (!eregi('(Safari)/([0-9.]+)',$_SERVER['HTTP_USER_AGENT'],$parts) &&
+ !eregi('compatible; ([a-z_]+)[/ ]+([0-9.]+)',$_SERVER['HTTP_USER_AGENT'],$parts))
+ {
+ eregi('^([a-z_]+)/([0-9.]+)',$_SERVER['HTTP_USER_AGENT'],$parts);
+ }
+ list(,$this->user_agent,$this->ua_version) = $parts;
+ $this->user_agent = strtolower($this->user_agent);
+
+ $this->netscape4 = $this->user_agent == 'mozilla' && $this->ua_version < 5;
+ $this->prefered_img_title = $this->netscape4 ? 'alt' : 'title';
+ //echo "
\n";
+
+ if ($GLOBALS['egw']->translation)
+ {
+ $this->charset = $GLOBALS['egw']->translation->charset();
+ }
+ $this->phpgwapi_js_url = $GLOBALS['egw_info']['server']['webserver_url'].'/phpgwapi/js';
+ }
+
+ /**
+ * Created an input-field with an attached color-picker
+ *
+ * Please note: it need to be called before the call to phpgw_header() !!!
+ *
+ * @param string $name the name of the input-field
+ * @param string $value the actual value for the input-field, default ''
+ * @param string $title tooltip/title for the picker-activation-icon
+ * @return string the html
+ */
+ function inputColor($name,$value='',$title='')
+ {
+ $id = str_replace(array('[',']'),array('_',''),$name).'_colorpicker';
+ $onclick = "javascript:window.open('".$this->phpgwapi_js_url.'/colorpicker/select_color.html?id='.urlencode($id)."&color='+document.getElementById('$id').value,'colorPicker','width=240,height=187,scrollbars=no,resizable=no,toolbar=no');";
+ return ' '.
+ ''.
+ '";
+ }
+
+ /**
+ * Handles tooltips via the wz_tooltip class from Walter Zorn
+ *
+ * Note: The wz_tooltip.js file gets automaticaly loaded at the end of the page
+ *
+ * @param string/boolean $text text or html for the tooltip, all chars allowed, they will be quoted approperiate
+ * Or if False the content (innerHTML) of the element itself is used.
+ * @param boolean $do_lang (default False) should the text be run though lang()
+ * @param array $options param/value pairs, eg. 'TITLE' => 'I am the title'. Some common parameters:
+ * title (string) gives extra title-row, width (int,'auto') , padding (int), above (bool), bgcolor (color), bgimg (URL)
+ * For a complete list and description see http://www.walterzorn.com/tooltip/tooltip_e.htm
+ * @return string to be included in any tag, like '
tooltip('Hello Ralf').'>Text with tooltip
'
+ */
+ function tooltip($text,$do_lang=False,$options=False)
+ {
+ if (!$this->wz_tooltip_included)
+ {
+ if (!strstr('wz_tooltip',$GLOBALS['egw_info']['flags']['need_footer']))
+ {
+ $GLOBALS['egw_info']['flags']['need_footer'] .= ''."\n";
+ }
+ $this->wz_tooltip_included = True;
+ }
+ if ($do_lang) $text = lang($text);
+
+ $opt_out = 'this.T_WIDTH = 200;';
+ if (is_array($options))
+ {
+ foreach($options as $option => $value)
+ {
+ $opt_out .= 'this.T_'.strtoupper($option).'='.(is_numeric($value)?$value:"'".str_replace(array("'",'"'),array("\\'",'"'),$value)."'").'; ';
+
+ }
+ }
+ if ($text === False) return ' onmouseover="'.$opt_out.'return escape(this.innerHTML);"';
+
+ return ' onmouseover="'.$opt_out.'return escape(\''.str_replace(array("\n","\r","'",'"'),array('','',"\\'",'"'),$text).'\')"';
+ }
+
+ /**
+ * activates URLs in a text, URLs get replaced by html-links
+ *
+ * @param string $content text containing URLs
+ * @return string html with activated links
+ */
+ function activate_links($content)
+ {
+ // Exclude everything which is already a link
+ $NotAnchor = '(?\\1 AT \\2 DOT \\3',
+ $content);
+
+ // First match things beginning with http:// (or other protocols)
+ $Protocol = '(http|ftp|https):\/\/';
+ $Domain = '([\w]+.[\w]+)';
+ $Subdir = '([\w\-\.,@?^=%&;:\/~\+#]*[\w\-\@?^=%&\/~\+#])?';
+ $Expr = '/' . $NotAnchor . $Protocol . $Domain . $Subdir . '/i';
+
+ $result = preg_replace( $Expr, "$2$3", $result );
+
+ // Now match things beginning with www.
+ $NotHTTP = '(?$0", $result );
+ }
+
+ /**
+ * escapes chars with special meaning in html as entities
+ *
+ * Allows to use and char in the html-output and prefents XSS attacks.
+ * Some entities are allowed and get NOT escaped:
+ * - some translations (AFAIK the arabic ones) need this
+ * - < > for convinience
+ *
+ * @param string $str string to escape
+ * @return string
+ */
+ function htmlspecialchars($str)
+ {
+ // add @ by lkneschke to supress warning about unknown charset
+ $str = @htmlspecialchars($str,ENT_COMPAT,$this->charset);
+
+ // we need '' unchanged, so we translate it back
+ $str = str_replace(array('&#',' ','<','>'),array('',' ','<','>'),$str);
+
+ return $str;
+ }
+
+ /**
+ * allows to show and select one item from an array
+ *
+ * @param string $name string with name of the submitted var which holds the key of the selected item form array
+ * @param string/array $key key(s) of already selected item(s) from $arr, eg. '1' or '1,2' or array with keys
+ * @param array $arr array with items to select, eg. $arr = array ( 'y' => 'yes','n' => 'no','m' => 'maybe');
+ * @param boolean $no_lang NOT run the labels of the options through lang(), default false=use lang()
+ * @param string $options additional options (e.g. 'width')
+ * @param int $multiple number of lines for a multiselect, default 0 = no multiselect
+ * @return string to set for a template or to echo into html page
+ */
+ function select($name, $key, $arr=0,$no_lang=false,$options='',$multiple=0)
+ {
+ if (!is_array($arr))
+ {
+ $arr = array('no','yes');
+ }
+ if ((int)$multiple > 0)
+ {
+ $options .= ' multiple="1" size="'.(int)$multiple.'"';
+ if (substr($name,-2) != '[]')
+ {
+ $name .= '[]';
+ }
+ }
+ $out = "\n";
+
+ return $out;
+ }
+
+ /**
+ * emulating a multiselectbox using checkboxes
+ *
+ * Unfortunaly this is not in all aspects like a multi-selectbox, eg. you cant select options via javascript
+ * in the same way. Therefor I made it an extra function.
+ *
+ * @param string $name string with name of the submitted var which holds the key of the selected item form array
+ * @param string/array $key key(s) of already selected item(s) from $arr, eg. '1' or '1,2' or array with keys
+ * @param array $arr array with items to select, eg. $arr = array ( 'y' => 'yes','n' => 'no','m' => 'maybe');
+ * @param boolean $no_lang NOT run the labels of the options through lang(), default false=use lang()
+ * @param string $options additional options (e.g. 'width')
+ * @param int $multiple number of lines for a multiselect, default 3
+ * @param boolean $selected_first show the selected items before the not selected ones, default true
+ * @param string $style='' extra style settings like "width: 100%", default '' none
+ * @return string to set for a template or to echo into html page
+ */
+ function checkbox_multiselect($name, $key, $arr=0,$no_lang=false,$options='',$multiple=3,$selected_first=true,$style='')
+ {
+ //echo "
\n";
+ if (!is_array($vars))
+ {
+ parse_str($vars,$vars);
+ }
+ list($url,$v) = explode('?',$url); // url may contain additional vars
+ if ($v)
+ {
+ parse_str($v,$v);
+ $vars += $v;
+ }
+ return $GLOBALS['egw']->link($url,$vars);
+ }
+
+ /**
+ * represents html checkbox
+ *
+ * @param string $name name
+ * @param boolean $checked box checked on display
+ * @param string $value value the var should be set to, default 'True'
+ * @param string $options attributes for the tag, default ''=none
+ * @return string html
+ */
+ function checkbox($name,$checked=false,$value='True',$options='')
+ {
+ return '\n";
+ }
+
+ /**
+ * represents a html form
+ *
+ * @param string $content of the form, if '' only the opening tag gets returned
+ * @param array $hidden_vars array with name-value pairs for hidden input fields
+ * @param string $url eGW relative URL, will be run through the link function, if empty the current url is used
+ * @param string/array $url_vars parameters for the URL, send to link function too
+ * @param string $name name of the form, defaul ''=none
+ * @param string $options attributes for the tag, default ''=none
+ * @param string $method method of the form, default 'POST'
+ * @return string html
+ */
+ function form($content,$hidden_vars,$url,$url_vars='',$name='',$options='',$method='POST')
+ {
+ $url = $url ? $this->link($url,$url_vars) : $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'];
+ $html = "\n";
+ }
+ return $html;
+ }
+
+ /**
+ * represents a html form with one button
+ *
+ * @param string $name name of the button
+ * @param string $label label of the button
+ * @param array $hidden_vars array with name-value pairs for hidden input fields
+ * @param string $url eGW relative URL, will be run through the link function
+ * @param string/array $url_vars parameters for the URL, send to link function too
+ * @param string $options attributes for the tag, default ''=none
+ * @param string $form_name name of the form, defaul ''=none
+ * @param string $method method of the form, default 'POST'
+ * @return string html
+ */
+ function form_1button($name,$label,$hidden_vars,$url,$url_vars='',$form_name='',$method='POST')
+ {
+ return $this->form($this->submit_button($name,$label),$hidden_vars,$url,$url_vars,$form_name,'',$method);
+ }
+
+ /**
+ * creates table from array of rows
+ *
+ * abstracts the html stuff for the table creation
+ * Example: $rows = array (
+ * '1' => array(
+ * 1 => 'cell1', '.1' => 'colspan=3',
+ * 2 => 'cell2',
+ * 3 => 'cell3', '.3' => 'width="10%"'
+ * ),'.1' => 'BGCOLOR="#0000FF"' );
+ * table($rows,'width="100%"') = '
cell1
cell2
cell3
'
+ *
+ * @param array $rows with rows, each row is an array of the cols
+ * @param string $options options for the table-tag
+ * @param boolean $no_table_tr dont return the table- and outmost tr-tabs, default false=return table+tr
+ * @return string with html-code of the table
+ */
+ function table($rows,$options = '',$no_table_tr=False)
+ {
+ $html = $no_table_tr ? '' : "
\n";
+
+ if ($no_table_tr)
+ {
+ $html = substr($html,0,-16);
+ }
+ return $html;
+ }
+
+ /**
+ * changes a selectbox to submit the form if it gets changed, to be used with the sbox-class
+ *
+ * @param string $sbox html with the select-box
+ * @param boolean $no_script if true generate a submit-button if javascript is off
+ * @return string html
+ */
+ function sbox_submit( $sbox,$no_script=false )
+ {
+ $html = str_replace('