Author: ralfbecker
New Revision: 55365
URL: http://svn.stylite.de/viewvc/egroupware?rev=55365&view=rev
Log:
split html class to Api\Html, Api\Header\Content, Api\Header\UserAgent and translation
Added:
trunk/egroupware/api/src/Header/
trunk/egroupware/api/src/Header/Content.php
- copied, changed from r55357, trunk/phpgwapi/inc/class.html.inc.php
trunk/egroupware/api/src/Header/UserAgent.php
- copied, changed from r55357, trunk/phpgwapi/inc/class.html.inc.php
trunk/egroupware/api/src/Html.php
- copied, changed from r55357, trunk/phpgwapi/inc/class.html.inc.php
Removed:
trunk/phpgwapi/js/colorpicker/
Modified:
trunk/egroupware/api/src/Db/Backup.php
trunk/egroupware/api/src/Image.php
trunk/egroupware/api/src/Link.php
trunk/egroupware/api/src/Session.php
trunk/egroupware/api/src/Storage/Tracking.php
trunk/mail/inc/class.mail_compose.inc.php
trunk/phpgwapi/inc/class.egw_htmLawed.inc.php
trunk/phpgwapi/inc/class.html.inc.php
trunk/phpgwapi/inc/class.translation.inc.php
— trunk/egroupware/api/src/Db/Backup.php (original)
+++ trunk/egroupware/api/src/Db/Backup.php Sun Mar 13 12:22:44 2016
@@ -15,8 +15,6 @@
use EGroupware\Api;
use ZipArchive;
-use html;
/**
- DB independent backup and restore of EGroupware database
@@ -1100,7 +1098,7 @@
else
{
$def = “<?php\n\t/* EGroupware schema-backup from “.date(‘Y-m-d H:i:s’).” */\n\n”.$def;
— trunk/phpgwapi/inc/class.html.inc.php (original)
+++ trunk/egroupware/api/src/Header/Content.php Sun Mar 13 12:22:44 2016
@@ -1,1525 +1,27 @@
<?php
/**
- * eGroupWare API: generates html with methods representing html-tags or higher widgets
+ * EGroupware API: safe content type and disposition headers
*
* @link http://www.egroupware.org
* @author Ralf Becker complete rewrite in 6/2006 and earlier modifications
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @author RalfBecker-AT-outdoor-training.de
- * @copyright 2001-2014 by RalfBecker@outdoor-training.de
+ * @copyright 2001-2016 by RalfBecker@outdoor-training.de
* @package api
- * @subpackage html
* @version $Id$
*/
+namespace EGroupware\Api\Header;
+
+use EGroupware\Api;
+
/**
- * Generates html with methods representing html-tags or higher widgets
- *
- * The class has only static methods now, so there's no need to instanciate as object anymore!
+ * Safe content type and disposition headers
*/
-class html
+class Content
{
/**
- * user-agent: 'firefox', 'msie', 'safari' (incl. iPhone), 'chrome', 'opera', 'konqueror', 'mozilla'
- * @var string
- */
- static $user_agent;
- /**
- * User agent is mobile browser: "iphone", "ipod", "ipad", "android", "symbianos", "blackberry", "kindle", "opera mobi", "windows phone"
- * @var string with name of mobile browser or null, if not mobile browser
- */
- static $ua_mobile;
- /**
- * version of user-agent as specified by browser
- * @var string
- */
- static $ua_version;
- /**
- * what attribute to use for the title of an image: 'title' for everything but netscape4='alt'
- * @var string
- */
- static $netscape4;
- static private $prefered_img_title;
- /**
- * charset used by the page, as returned by $GLOBALS['egw']->translation->charset()
- * @var string
- */
- static $charset;
- /**
- * URL (NOT path) of the js directory in the api
- * @var string
- */
- static $api_js_url;
-
- /**
- * Automatically turn on enhanced selectboxes if there's more than this many options
- */
- const SELECT_ENHANCED_ROW_COUNT = 12;
-
- /**
- * initialise our static vars
- */
- static function _init_static()
- {
- // should be Ok for all HTML 4 compatible browsers
- $parts = $all_parts = null;
- if(!preg_match('/compatible; ([a-z]+)[\/ ]+([0-9.]+)/i',$_SERVER['HTTP_USER_AGENT'],$parts))
- {
- preg_match_all('/([a-z]+)\/([0-9.]+)/i',$_SERVER['HTTP_USER_AGENT'],$all_parts,PREG_SET_ORDER);
- $parts = array_pop($all_parts);
- foreach($all_parts as $p)
- {
- if ($p[1] == 'Chrome' && $parts[1] != 'Edge')
- {
- $parts = $p;
- break;
- }
- }
- }
- list(,self::$user_agent,self::$ua_version) = $parts;
- if ((self::$user_agent = strtolower(self::$user_agent)) == 'version') self::$user_agent = 'opera';
- // IE no longer reports MSIE, but "Trident/7.0; rv:11.0"
- if (self::$user_agent=='trident')
- {
- self::$user_agent='msie';
- $matches = null;
- self::$ua_version = preg_match('|Trident/[0-9.]+; rv:([0-9.]+)|i', $_SERVER['HTTP_USER_AGENT'], $matches) ?
- $matches[1] : 11.0;
- }
- // iceweasel is based on mozilla and we treat it like as firefox
- if (self::$user_agent == 'iceweasel')
- {
- self::$user_agent = 'firefox';
- }
- // MS Edge sometimes reports just "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
- if (self::$user_agent == 'mozilla' && self::$ua_version == '5.0')
- {
- self::$user_agent = 'edge';
- self::$ua_version = '12.0';
- }
- self::$ua_mobile = preg_match('/(iPhone|iPod|iPad|Android|SymbianOS|Blackberry|Kindle|Opera Mobi|Windows Phone)/i',
- $_SERVER['HTTP_USER_AGENT'], $matches) ? strtolower($matches[1]) : null;
-
- self::$netscape4 = self::$user_agent == 'mozilla' && self::$ua_version < 5;
- self::$prefered_img_title = self::$netscape4 ? 'alt' : 'title';
- //error_log("HTTP_USER_AGENT='$_SERVER[HTTP_USER_AGENT]', UserAgent: '".self::$user_agent."', Version: '".self::$ua_version."', isMobile=".array2string(self::$ua_mobile).", img_title: '".self::$prefered_img_title."'");
-
- if ($GLOBALS['egw']->translation)
- {
- self::$charset = $GLOBALS['egw']->translation->charset();
- }
- self::$api_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 egw_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
- * @param string $options ='' options for input
- * @return string the html
- */
- static function inputColor($name,$value='',$title='',$options='')
- {
- $options .= ' id="'.htmlspecialchars($id=str_replace(array('[',']'),array('_',''),$name).'_colorpicker').'"';
- $onclick = "javascript:egw_openWindowCentered2('".self::$api_js_url.'/colorpicker/select_color.html?id='.urlencode($id)."&color='+encodeURIComponent(document.getElementById('$id').value),'colorPicker',240,187);";
- if (preg_match('/^#[0-9A-F]{6}$/i',$value))
- {
- $options .= ' style="background-color: '.$value.'"';
- }
- $options .= ' onChange="this.style.backgroundColor=this.value.match(/^(#[0-9A-F]+|[a-z]+)$/i)?this.value:\'#FFFFFF\'+(this.value=\'\')"';
- return self::input($name, $value, 'text', $options.' size="7" maxsize="7"').' '.
- '
'.
- '!['.self::htmlspecialchars($title).']()
";
- }
-
- /**
- * Handles tooltips via the wz_tooltip class from Walter Zorn
- *
- * @param string $text text or html for the tooltip, all chars allowed, they will be quoted approperiate
- * @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
- * @param boolean $return_as_attributes true to return array(onmouseover, onmouseout) attributes
- * @return string|array to be included in any tag, like '<p'.html::tooltip('Hello
Ralf').'>Text with tooltip'
- */
- static function tooltip($text,$do_lang=False,$options=False, $return_as_attributes=false)
- {
- // tell egw_framework to include wz_tooltip.js
- $GLOBALS['egw_info']['flags']['include_wz_tooltip'] = true;
-
- if ($do_lang) $text = lang($text);
-
- $ttip = 'Tip(\''.str_replace(array("\n","\r","'",'"'),array('','',"\\'",'"'),$text).'\'';
-
- $sticky = false;
- if (is_array($options))
- {
- foreach($options as $option => $value)
- {
- $option = strtoupper($option);
- if ($option == 'STICKY') $sticky = (bool)$value;
-
- switch(gettype($value))
- {
- case 'boolean':
- $value = $value ? 'true' : 'false';
- break;
- case 'string':
- if (stripos($value,"'")===false) $value = "'$value'";
- break;
- }
- $ttip .= ','.$option.','.$value;
- }
- }
- $ttip .= ')';
-
- $untip = 'UnTip()';
-
- return $return_as_attributes ? array($ttip, $untip) :
- ' onmouseover="'.self::htmlspecialchars($ttip).'" onmouseout="'.$untip.'"';
- }
-
- /**
- * activates URLs in a text, URLs get replaced by html-links
- *
- * @param string $content text containing URLs
- * @return string html with activated links
- */
- static function activate_links($content)
- {
- if (!$content || strlen($content) < 20) return $content; // performance
-
- // Exclude everything which is already a link
- $NotAnchor = '(?<!"|href=|href\s=\s|href=\s|href\s=)';
-
- // spamsaver emailaddress
- $result = preg_replace('/'.$NotAnchor.'mailto:([a-z0-9._-]+)@([a-z0-9_-]+)\.([a-z0-9._-]+)/i',
-// '
\\1 AT \\2 DOT \\3',
- "
$1 AT $2 DOT $3",
- $content);
-
- // First match things beginning with http:// (or other protocols)
- $optBracket0 = '(<|<)';
- $Protocol = '(http:\/\/|(ftp:\/\/|https:\/\/))'; // only http:// gets removed, other protocolls are shown
- $Domain = '([\w-]+\.[\w-.]+)';
- $Subdir = '([\w\-\.,@?^=%&;:\/~\+#]*[\w\-\@?^=%&\/~\+#])?';
- $optBracket = '';
- $optBracket = '(>|>)';
- $Expr = '/' .$optBracket0. $NotAnchor . $Protocol . $Domain . $Subdir . $optBracket . '/i';
- // use preg_replace_callback as we experienced problems with https links
- $result2 = preg_replace_callback( $Expr, function ($match) {
- //error_log(__METHOD__.__LINE__.array2string($match));
- return $match[1]."
".$match[4].$match[5]."".$match[6];
- }, $result );
-//error_log(__METHOD__.__LINE__.array2string($Expr));
-//error_log(__METHOD__.__LINE__.array2string($result2));
- // First match things beginning with http:// (or other protocols)
- $Protocol = '(http:\/\/|(ftp:\/\/|https:\/\/))'; // only http:// gets removed, other protocolls are shown
- $Domain = '([\w-]+\.[\w-.]+)';
- $Subdir = '([\w\-\.,@?^=%&;:\/~\+#]*[\w\-\@?^=%&\/~\+#])?';
- $Expr = '/' . $NotAnchor . $Protocol . $Domain . $Subdir . '/i';
- // use preg_replace_callback as we experienced problems with https links
- $result3 = preg_replace_callback( $Expr, function ($match) {
- //error_log(__METHOD__.__LINE__.array2string($match));
- return "
".$match[3].$match[4]."";
- }, $result2 );
-//error_log(__METHOD__.__LINE__.array2string($Expr));
-//error_log(__METHOD__.__LINE__.array2string($result3));
- // Now match things beginning with www.
- $optBracket0 = '(<|<)?';
- $NotHTTP = '(?)'; // avoid running again on http://www links already handled above
- $Domain2 = 'www(\.[\w-.]+)';
- $Subdir2 = '([\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])?';
- $optBracket = '(>|>)?';
- $Expr = '/' .$optBracket0. $NotAnchor . $NotHTTP . $Domain2 . $Subdir2 .$optBracket. '/i';
- //$Expr = '/' . $NotAnchor . $NotHTTP . $Domain . $Subdir . $optBracket . '/i';
-
- $result4 = preg_replace( $Expr, "$1
www$2$3$4$5$6", $result3 );
- //return preg_replace( $Expr, "
www$1$2$3 ", $result );
-//error_log(__METHOD__.__LINE__.array2string($Expr));
-//error_log(__METHOD__.__LINE__.array2string($result4));
- return $result4;
- }
-
- /**
- * escapes chars with special meaning in html as entities
- *
- * Allows to use and char in the html-output and prevents XSS attacks.
- * Some entities are allowed and get NOT escaped: -> prevented by 4th param = doubleencode=false
- * - &# some translations (AFAIK: the arabic ones) need this;
- * - < > for convenience -> should not happen anymore, as we do not doubleencode anymore (20101020)
- *
- * @param string $str string to escape
- * @param boolean $double_encoding =false do we want double encoding or not, default no
- * @return string
- */
- static function htmlspecialchars($str, $double_encoding=false)
- {
- //if (!is_scalar($str) && !is_null($str)) error_log(__METHOD__.'('.array2string($str).') '.function_backtrace());
- // as EGroupware supports only utf-8 we should not need to worry about wrong charsets
- //if (is_array($str)) error_log(__METHOD__.__LINE__.' string expected -> array given:'.array2string($str).'->'.function_backtrace());
- return htmlspecialchars($str,ENT_COMPAT,self::$charset,$double_encoding);
- // we need '&#' unchanged, so we translate it back -> this is provided by 4th param = false -> do not doubleencode
- //$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, < 0 sets size without multiple
- * @param boolean $enhanced Use enhanced selectbox with search. Null for default yes if more than 12 options.
- * @return string to set for a template or to echo into html page
- */
- static function select($name, $key, $arr=0,$no_lang=false,$options='',$multiple=0,$enhanced=null)
- {
- if(is_null($enhanced)) $enhanced = false; //disabled by default (count($arr) > self::SELECT_ENHANCED_ROW_COUNT);
-
- if (!is_array($arr))
- {
- $arr = array('no','yes');
- }
- if ((int)$multiple > 0)
- {
- $options .= ' multiple="1" size="'.(int)$multiple.'"';
- if (substr($name,-2) != '[]')
- {
- $name .= '[]';
- }
- }
- elseif($multiple < 0)
- {
- $options .= ' size="'.abs($multiple).'"';
- }
- // fix width for MSIE < 9 in/for selectboxes
- if (self::$user_agent == 'msie' && self::$ua_version < 9)
- {
- if (stripos($options,'onfocus="') === false)
- {
- $options .= ' onfocus="window.dropdown_menu_hack(this);" ';
- }
- else
- {
- $options = str_ireplace('onfocus="','onfocus="window.dropdown_menu_hack(this);',$options);
- }
- }
- $out = "\n";
-
- if (!is_array($key))
- {
- // explode on ',' only if multiple values expected and the key contains just numbers and commas
- $key = $multiple > 0 && preg_match('/^[,0-9]+$/',$key) ? explode(',',$key) : array($key);
- }
- foreach($arr as $k => $data)
- {
- if (!is_array($data) || count($data) == 2 && isset($data['label']) && isset($data['title']))
- {
- $out .= self::select_option($k,is_array($data)?$data['label']:$data,$key,$no_lang,
- is_array($data)?$data['title']:'');
- }
- else
- {
- if (isset($data['lable']))
- {
- $k = $data['lable'];
- unset($data['lable']);
- }
- $out .= '\n";
-
- foreach($data as $k => $label)
- {
- $out .= self::select_option($k,is_array($label)?$label['label']:$label,$key,$no_lang,
- is_array($label)?$label['title']:'');
- }
- $out .= "\n";
- }
- }
- $out .= "\n";
-
- if($enhanced) {
- egw_framework::validate_file('/phpgwapi/js/jquery/chosen/chosen.jquery.js');
- egw_framework::includeCSS('/phpgwapi/js/jquery/chosen/chosen.css',null,false);
- $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
- */
- static function checkbox_multiselect($name, $key, $arr=0,$no_lang=false,$options='',$multiple=3,$selected_first=true,$style='',$enhanced = null)
- {
- //echo "
checkbox_multiselect('$name',".array2string($key).",".array2string($arr).",$no_lang,'$options',$multiple,$selected_first,'$style')
\n";
- if(is_null($enhanced)) $enhanced = (count($arr) > self::SELECT_ENHANCED_ROW_COUNT);
-
- if (!is_array($arr))
- {
- $arr = array('no','yes');
- }
- if ((int)$multiple <= 0) $multiple = 1;
-
- if (substr($name,-2) != '[]')
- {
- $name .= '[]';
- }
- $base_name = substr($name,0,-2);
-
- if($enhanced) return self::select($name, $key, $arr,$no_lang,$options." style=\"$style\" ",$multiple,$enhanced);
-
- if (!is_array($key))
- {
- // explode on ',' only if multiple values expected and the key contains just numbers and commas
- $key = preg_match('/^[,0-9]+$/',$key) ? explode(',',$key) : array($key);
- }
- $html = '';
- $options_no_id = preg_replace('/id="[^"]+"/i','',$options);
-
- if ($selected_first)
- {
- $selected = $not_selected = array();
- foreach($arr as $val => $label)
- {
- if (in_array((string)$val,$key))
- {
- $selected[$val] = $label;
- }
- else
- {
- $not_selected[$val] = $label;
- }
- }
- $arr = $selected + $not_selected;
- }
- $max_len = 0;
- foreach($arr as $val => $label)
- {
- if (is_array($label))
- {
- $title = $label['title'];
- $label = $label['label'];
- }
- else
- {
- $title = '';
- }
- if ($label && !$no_lang) $label = lang($label);
- if ($title && !$no_lang) $title = lang($title);
-
- if (strlen($label) > $max_len) $max_len = strlen($label);
-
- $html .= self::label(self::checkbox($name,in_array((string)$val,$key),$val,$options_no_id.
- ' id="'.$base_name.'['.$val.']'.'"').self::htmlspecialchars($label),
- $base_name.'['.$val.']','',($title ? 'title="'.self::htmlspecialchars($title).'" ':''))."
\n";
- }
- if ($style && substr($style,-1) != ';') $style .= '; ';
- if (strpos($style,'height')===false) $style .= 'height: '.(1.7*$multiple).'em; ';
- if (strpos($style,'width')===false) $style .= 'width: '.(4+$max_len*($max_len < 15 ? 0.65 : 0.6)).'em; ';
- $style .= 'background-color: white; overflow: auto; border: lightgray 2px inset; text-align: left;';
-
- return self::div($html,$options,'',$style);
- }
-
- /**
- * generates an option-tag for a selectbox
- *
- * @param string $value value
- * @param string $label label
- * @param mixed $selected value or array of values of options to mark as selected
- * @param boolean $no_lang NOT running the label through lang(), default false=use lang()
- * @param string $extra extra text, e.g.: style="", default: ''
- * @return string html
- */
- static function select_option($value,$label,$selected,$no_lang=0,$title='',$extra='')
- {
- // the following compares strict as strings, to archive: '0' == 0 != ''
- // the first non-strict search via array_search, is for performance reasons, to not always search the whole array with php
- if (($found = ($key = array_search($value,$selected)) !== false) && (string) $value !== (string) $selected[$key])
- {
- $found = false;
- foreach($selected as $sel)
- {
- if (($found = (((string) $value) === ((string) $selected[$key])))) break;
- }
- unset($sel);
- }
- return ''.
- self::htmlspecialchars($no_lang || $label == '' ? $label : lang($label)) . "\n";
- }
-
- /**
- * generates a div-tag
- *
- * @param string $content of a div, or '' to generate only the opening tag
- * @param string $options to include in the tag, default ''=none
- * @param string $class css-class attribute, default ''=none
- * @param string $style css-styles attribute, default ''=none
- * @return string html
- */
- static function div($content,$options='',$class='',$style='')
- {
- if ($class) $options .= ' class="'.$class.'"';
- if ($style) $options .= ' style="'.$style.'"';
-
- return "
\n".($content ? "$content
\n" : '');
- }
-
- /**
- * generate one or more hidden input tag(s)
- *
- * @param array|string $vars var-name or array with name / value pairs
- * @param string $value value if $vars is no array, default ''
- * @param boolean $ignore_empty if true all empty, zero (!) or unset values, plus filer=none
- * @param string html
- */
- static function input_hidden($vars,$value='',$ignore_empty=True)
- {
- if (!is_array($vars))
- {
- $vars = array( $vars => $value );
- }
- foreach($vars as $name => $value)
- {
- if (is_array($value))
- {
- $value = json_encode($value);
- }
- if (!$ignore_empty || $value && !($name == 'filter' && $value == 'none')) // dont need to send all the empty vars
- {
- $html .= "\n";
- }
- }
- return $html;
- }
-
- /**
- * generate a textarea tag
- *
- * @param string $name name attr. of the tag
- * @param string $value default
- * @param boolean $ignore_empty if true all empty, zero (!) or unset values, plus filer=none
- * @param boolean $double_encoding =false do we want double encoding or not, default no
- * @param string html
- */
- static function textarea($name,$value='',$options='',$double_encoding=false)
- {
- return "".self::htmlspecialchars($value,$double_encoding)."\n";
- }
-
- /**
- * Checks if HTMLarea (or an other richtext editor) is availible for the used browser
- *
- * @return boolean
- */
- static function htmlarea_availible()
- {
- // this one is for testing how it will turn out, if you do not have the device or agent ready at your fingertips
- // if (stripos($_SERVER[HTTP_USER_AGENT],'mozilla') !== false) return false;
-
- // CKeditor will doublecheck availability for us, but its fallback does not look nice, and you will get
- // no conversion of html content to plain text, so we provide a check for known USER_AGENTS to fail the test
- return true;
- }
-
- /**
- * compability static function for former used htmlarea. Please use static function fckeditor now!
- *
- * creates a textarea inputfield for the htmlarea js-widget (returns the necessary html and js)
- */
- static function htmlarea($name,$content='',$style='',$base_href=''/*,$plugins='',$custom_toolbar='',$set_width_height_in_config=false*/)
- {
- /*if (!self::htmlarea_availible())
- {
- return self::textarea($name,$content,'style="'.$style.'"');
- }*/
- return self::fckEditor($name, $content, $style, array('toolbar_expanded' =>'true'), '400px', '100%', $base_href);
- }
-
- /**
- * this static function is a wrapper for fckEditor to create some reuseable layouts
- *
- * @param string $_name name and id of the input-field
- * @param string $_content of the tinymce (will be run through htmlspecialchars !!!), default ''
- * @param string $_mode display mode of the tinymce editor can be: simple, extended or advanced
- * @param array $_options (toolbar_expanded true/false)
- * @param string $_height ='400px'
- * @param string $_width ='100%'
- * @param string $_start_path ='' if passed activates the browser for image at absolute path passed
- * @param boolean $_purify =true run $_content through htmlpurifier before handing it to fckEditor
- * @param mixed (boolean/string) $_focusToBody=false USED only for CKEDIOR true means yes, focus on top, you may specify TOP or BOTTOM (to focus on the end of the editor area)
- * @param string $_executeJSAfterInit ='' Javascript to be executed after InstanceReady of CKEditor
- * @return string the necessary html for the textarea
- */
- static function fckEditor($_name, $_content, $_mode, $_options=array('toolbar_expanded' =>'true'),
- $_height='400px', $_width='100%',$_start_path='',$_purify=true, $_focusToBody=false, $_executeJSAfterInit='')
- {
- if (!self::htmlarea_availible() || $_mode == 'ascii')
- {
- return self::textarea($_name,$_content,'style="width: '.$_width.'; height: '.$_height.';" id="'.htmlspecialchars($_name).'"');
- }
-
- //include the ckeditor js file
- egw_framework::validate_file('ckeditor','ckeditor','phpgwapi');
-
- // run content through htmlpurifier
- if ($_purify && !empty($_content))
- $_content = self::purify($_content);
-
- // By default the editor start expanded
- $expanded = isset($_options['toolbar_expanded']) ?
- $_options['toolbar_expanded'] == 'true' : true;
-
- //Get the height in pixels from the pixels parameter
- $pxheight = (strpos('px', $_height) === false) ?
- (empty($_height) ? 400 : $_height) : str_replace('px', '', $_height);
-
- // User preferences
- $font = $GLOBALS['egw_info']['user']['preferences']['common']['rte_font'];
- $font_size = egw_ckeditor_config::font_size_from_prefs();
- $font_span = '
';
- if (empty($font) && empty($font_size)) $font_span = '';
-
- // we need to enable double encoding here, as ckEditor has to undo one level of encoding
- // otherwise < and > chars eg. from html markup entered in regular (not source) input, will turn into html!
- //error_log(__METHOD__.__LINE__.' '.self::$user_agent.','.self::$ua_version);
- return self::textarea($_name,$_content,'id="'.htmlspecialchars($_name).'"',true). // true = double encoding
-'
-
-';
- }
-
- /**
- * this static function is a wrapper for tinymce to create some reuseable layouts
- *
- * Please note: if you did not run init_tinymce already you this static function need to be called before the call to phpgw_header() !!!
- *
- * @param string $_name name and id of the input-field
- * @param string $_mode display mode of the tinymce editor can be: simple, extended or advanced
- * @param string $_content ='' of the tinymce (will be run through htmlspecialchars !!!), default ''
- * @param string $_height ='400px'
- * @param string $_width ='100%'
- * @param boolean $_purify =true
- * @param string $_border ='0px' NOT used for CKEditor
- * @param mixed (boolean/string) $_focusToBody=false USED only for CKEDIOR true means yes, focus on top, you may specify TOP or BOTTOM (to focus on the end of the editor area)
- * @param string $_executeJSAfterInit ='' Javascript to be executed after InstanceReady of CKEditor
- * @return string the necessary html for the textarea
- */
- static function fckEditorQuick($_name, $_mode, $_content='', $_height='400px', $_width='100%',$_purify=true, $_border='0px',$_focusToBody=false,$_executeJSAfterInit='')
- {
- if (!self::htmlarea_availible() || $_mode == 'ascii')
- {
- //TODO: use self::textarea
- return "$_content";
- }
- else
- {
- return self::fckEditor($_name, $_content, $_mode, array(), $_height, $_width,'',$_purify,$_focusToBody,$_executeJSAfterInit);
- }
- }
-
- /**
- * represents html's input tag
- *
- * @param string $name name
- * @param string $value default value of the field
- * @param string $type type, default ''=not specified = text
- * @param string $options attributes for the tag, default ''=none
- */
- static function input($name,$value='',$type='',$options='' )
- {
- switch ((string)$type)
- {
- case 'color':
- return self::inputColor($name, $value, '', $options);
- case '';
- break;
- default:
- $type = 'type="'.htmlspecialchars($type).'"';
- }
- return "\n";
- }
-
- static protected $default_background_images = array(
- 'save' => '/save(&|\]|$)/',
- 'apply' => '/apply(&|\]|$)/',
- 'cancel' => '/cancel(&|\]|$)/',
- 'delete' => '/delete(&|\]|$)/',
- 'edit' => '/edit(&|\]|$)/',
- 'next' => '/(next|continue)(&|\]|$)/',
- 'finish' => '/finish(&|\]|$)/',
- 'back' => '/(back|previous)(&|\]|$)/',
- 'copy' => '/copy(&|\]|$)/',
- 'more' => '/more(&|\]|$)/',
- 'check' => '/(yes|check)(&|\]|$)/',
- 'cancelled' => '/no(&|\]|$)/',
- 'ok' => '/ok(&|\]|$)/',
- 'close' => '/close(&|\]|$)/',
- 'add' => '/(add(&|\]|$)|create)/', // customfields use create*
- );
-
- static protected $default_classes = array(
- 'et2_button_cancel' => '/cancel(&|\]|$)/', // yellow
- 'et2_button_question' => '/(yes|no)(&|\]|$)/', // yellow
- 'et2_button_delete' => '/delete(&|\]|$)/' // red
- );
-
- /**
- * represents html's button (input type submit or input type button or image)
- *
- * @param string $name name
- * @param string $label label of the button
- * @param string $onClick javascript to call, when button is clicked
- * @param boolean $no_lang NOT running the label through lang(), default false=use lang()
- * @param string $options attributes for the tag, default ''=none
- * @param string $image to show instead of the label, default ''=none
- * @param string $app app to search the image in
- * @param string $buttontype which type of html button (button|submit), default ='submit'
- * @return string html
- */
- static function submit_button($name,$label,$onClick='',$no_lang=false,$options='',$image='',$app='phpgwapi', $buttontype='submit')
- {
- // workaround for idots and IE button problem (wrong cursor-image)
- if (self::$user_agent == 'msie')
- {
- $options .= ' style="cursor: pointer;"';
- }
- // add et2_classes to "old" buttons
- $classes = array('et2_button');
-
- if ($image != '')
- {
- $image = str_replace(array('.gif','.GIF','.png','.PNG'),'',$image);
-
- if (!($path = common::image($app,$image)))
- {
- $path = $image; // name may already contain absolut path
- }
- $image = ' src="'.$path.'"';
- $classes[] = 'image_button';
- }
- if (!$no_lang)
- {
- $label = lang($label);
- }
- if (($accesskey = @strstr($label,'&')) && $accesskey[1] != ' ' &&
- (($pos = strpos($accesskey,';')) === false || $pos > 5))
- {
- $label_u = str_replace('&'.$accesskey[1],''.$accesskey[1].'',$label);
- $label = str_replace('&','',$label);
- $options .= ' accesskey="'.$accesskey[1].'" '.$options;
- }
- else
- {
- $accesskey = '';
- $label_u = $label;
- }
- if ($onClick) $options .= ' onclick="'.str_replace('"','\\"',$onClick).'"';
-
- // add default background-image to get et2 like buttons
- foreach(self::$default_background_images as $img => $reg_exp)
- {
- if (preg_match($reg_exp, $name) && ($url = common::image($GLOBALS['egw_info']['flags']['currentapp'], $img)))
- {
- $options .= ' style="background-image: url('.$url.');"';
- $classes[] = 'et2_button_with_image';
- break;
- }
- }
- // add default class for cancel, delete or yes/no buttons
- foreach(self::$default_classes as $class => $reg_exp)
- {
- if (preg_match($reg_exp, $name))
- {
- $classes[] = $class;
- break;
- }
- }
- if (strpos($options, 'class="') !== false)
- {
- $options = str_replace('class="', 'class="'.implode(' ', $classes).' ', $options);
- }
- else
- {
- $options .= ' class="'.implode(' ', $classes).'"';
- }
-
- return ''.
- ($image != '' ? /*self::image($app,$image,$label,$options)*/' ' : '').
- ($image == '' || $accesskey ? self::htmlspecialchars($label_u) : '').'';
- }
-
- /**
- * creates an absolut link + the query / get-variables
- *
- * Example link('/index.php?menuaction=infolog.uiinfolog.get_list',array('info_id' => 123))
- * gives 'http://domain/phpgw-path/index.php?menuaction=infolog.uiinfolog.get_list&info_id=123'
- *
- * @param string $_url egw-relative link, may include query / get-vars
- * @param array|string $vars query or array ('name' => 'value', ...) with query
- * @return string absolut link already run through $phpgw->link
- */
- static function link($_url,$vars='')
- {
- //echo "html::link(url='$url',vars='"; print_r($vars); 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 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
- */
- static 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 static 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
- */
- static function form($content,$hidden_vars,$_url,$url_vars='',$name='',$options='',$method='POST')
- {
- $url = $_url ? self::link($_url, $url_vars) : $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'];
- $html = "\n";
- $html .= self::input_hidden($hidden_vars);
-
- if ($content)
- {
- $html .= $content;
- $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 static 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
- */
- static function form_1button($name,$label,$hidden_vars,$url,$url_vars='',$form_name='',$method='POST')
- {
- return self::form(self::submit_button($name,$label),$hidden_vars,$url,$url_vars,$form_name,' style="display: inline-block"',$method);
- }
-
- const THEAD = 1;
- const TFOOT = 2;
- const TBODY = 3;
- static $part2tag = array(
- self::THEAD => 'thead',
- self::TFOOT => 'tfoot',
- self::TBODY => 'tbody',
- );
-
- /**
- * creates table from array of rows
- *
- * abstracts the html stuff for the table creation
- * Example: $rows = array (
- * 'h1' => array( // optional header row(s)
- * ),
- * 'f1' => array( // optional footer row(s)
- * ),
- * '1' => array(
- * 1 => 'cell1', '.1' => 'colspan=3',
- * 2 => 'cell2',
- * 3 => 'cell3', '.3' => 'width="10%"'
- * ),'.1' => 'BGCOLOR="#0000FF"' );
- * table($rows,'width="100%"') = ''
- *
- * @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
- */
- static function table($rows,$options = '',$no_table_tr=False)
- {
- $html = $no_table_tr ? '' : "\n";
-
- $part = 0;
- foreach($rows as $key => $row)
- {
- if (!is_array($row))
- {
- continue; // parameter
- }
- // get the current part from the optional 'h' or 'f' prefix of the key
- $p = $key[0] == 'h' ? html::THEAD : ($key[0] == 'f' ? html::TFOOT : html::TBODY);
- if ($part < $p && ($part || $p < self::TBODY)) // add only allowed and neccessary transitions
- {
- if ($part) $html .= '\n";
- $html .= '<'.self::$part2tag[$part=$p].">\n";
- }
- $html .= $no_table_tr && $key == 1 ? '' : "\t\n";
-
- foreach($row as $key => $cell)
- {
- if ($key[0] == '.')
- {
- continue; // parameter
- }
- $table_pos = strpos($cell,'<table');
- $td_pos = strpos($cell,'<td');
- if ($td_pos !== False && ($table_pos === False || $td_pos < $table_pos))
- {
- $html .= $cell;
- }
- else
- {
- $html .= "\t\t| $cell | \n";
- }
- }
- $html .= "\t
\n";
- }
- if (!is_array($rows))
- {
- echo "".function_backtrace()."
\n";
- }
- if ($part) // close current part
- {
- $html .= "\n";
- }
- $html .= "
\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
- */
- static function sbox_submit( $sbox,$no_script=false )
- {
- $html = str_replace('<select','<select onchange="this.form.submit()" ',$sbox);
- if ($no_script)
- {
- $html .= ''.self::submit_button('send','>').'';
- }
- return $html;
- }
-
- /**
- * html-widget showing progessbar with a view div's (html4 only, textual percentage otherwise)
- *
- * @param mixed $_percent percent-value, gets casted to int
- * @param string $_title title for the progressbar, default ''=the percentage itself
- * @param string $options attributes for the outmost div (may include onclick="...")
- * @param string $width width, default 30px
- * @param string $color color, default '#D00000' (dark red)
- * @param string $height height, default 5px
- * @return string html
- */
- static function progressbar($_percent, $_title='',$options='',$width='',$color='',$height='' )
- {
- $percent = (int)$_percent;
- if (!$width) $width = '30px';
- if (!$height)$height= '5px';
- if (!$color) $color = '#D00000';
- $title = $_title ? self::htmlspecialchars($_title) : $percent.'%';
-
- if (self::$netscape4)
- {
- return $title;
- }
- return ''.$title.'
\n";
- }
-
- /**
- * representates a html img tag, output a picture
- *
- * If the name ends with a '%' and the rest is numeric, a progressionbar is shown instead of an image.
- * The vfs:/ pseudo protocoll allows to access images in the vfs, eg. vfs:/home/ralf/me.png
- * Instead of a name you specify an array with get-vars, it is passed to eGW's link function.
- * This way session-information gets passed, eg. $name=array('menuaction'=>'myapp.class.image','id'=>123).
- *
- * @param string $app app-name to search the image
- * @param string|array $name image-name or URL (incl. vfs:/) or array with get-vars
- * @param string $title tooltip, default '' = none
- * @param string $options further options for the tag, default '' = none
- * @return string the html
- */
- static function image( $app,$name,$title='',$options='' )
- {
- if (is_array($name)) // menuaction and other get-vars
- {
- $name = $GLOBALS['egw']->link('/index.php',$name);
- }
- if (substr($name,0,5) == 'vfs:/') // vfs pseudo protocoll
- {
- $name = egw::link(egw_vfs::download_url(substr($name,4)));
- }
- if ($name[0] == '/' || substr($name,0,7) == 'http://' || substr($name,0,8) == 'https://' || stripos($name,'etemplate/thumbnail.php') )
- {
- if (!($name[0] == '/' || substr($name,0,7) == 'http://' || substr($name,0,8) == 'https://')) $name = '/'.$name;
- $url = $name;
- }
- else // no URL, so try searching the image
- {
- $name = str_replace(array('.gif','.GIF','.png','.PNG'),'',$name);
-
- if (!($url = $GLOBALS['egw']->common->image($app,$name)))
- {
- $url = $name; // name may already contain absolut path
- }
- if($GLOBALS['egw_info']['server']['webserver_url'])
- {
- list(,$path) = explode($GLOBALS['egw_info']['server']['webserver_url'],$url);
-
- if (!is_null($path)) $path = EGW_SERVER_ROOT.$path;
- }
- else
- {
- $path = EGW_SERVER_ROOT.$url;
- }
-
- if (is_null($path) || (!@is_readable($path) && stripos($path,'webdav.php')===false))
- {
- // if the image-name is a percentage, use a progressbar
- if (substr($name,-1) == '%' && is_numeric($percent = substr($name,0,-1)))
- {
- return self::progressbar($percent,$title);
- }
- return $title;
- }
- }
- if ($title)
- {
- $options .= ' '.self::$prefered_img_title.'