Page MenuHomePhorge

No OneTemporary

Size
70 KB
Referenced Files
None
Subscribers
None
diff --git a/program/include/rcube_shared.inc b/program/include/rcube_shared.inc
index 6cf641893..a26fc108b 100644
--- a/program/include/rcube_shared.inc
+++ b/program/include/rcube_shared.inc
@@ -1,1574 +1,1572 @@
<?php
/*
+-----------------------------------------------------------------------+
| rcube_shared.inc |
| |
| This file is part of the RoundCube PHP suite |
| Copyright (C) 2005-2006, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
| CONTENTS: |
| Shared functions and classes used in PHP projects |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
// ********* round cube schared classes *********
class rcube_html_page
{
var $css;
var $scripts_path = '';
var $script_files = array();
var $external_scripts = array();
var $scripts = array();
var $charset = 'ISO-8859-1';
var $script_tag_file = "<script type=\"text/javascript\" src=\"%s%s\"></script>\n";
var $script_tag = "<script type=\"text/javascript\">\n<!--\n%s\n\n//-->\n</script>\n";
var $default_template = "<html>\n<head><title></title></head>\n<body></body>\n</html>";
var $tag_format_external_script = "<script type=\"text/javascript\" src=\"%s\"></script>\n";
var $title = '';
var $header = '';
var $footer = '';
var $body = '';
var $body_attrib = array();
var $meta_tags = array();
// PHP 5 constructor
function __construct()
{
$this->css = new rcube_css();
}
// PHP 4 compatibility
function rcube_html_page()
{
$this->__construct();
}
function include_script($file, $position='head')
{
static $sa_files = array();
if (in_array($file, $sa_files))
return;
if (!is_array($this->script_files[$position]))
$this->script_files[$position] = array();
$this->script_files[$position][] = $file;
}
function include_external_script($script_location, $position='head')
{
if (!is_array($this->external_scripts[$position]))
{
$this->external_scripts[$position] = array();
}
$this->external_scripts[$position][] = $script_location;
}
function add_script($script, $position='head')
{
if (!isset($this->scripts[$position]))
$this->scripts[$position] = "\n$script";
else
$this->scripts[$position] .= "\n$script";
}
function set_title($t)
{
$this->title = $t;
}
function set_charset($charset)
{
global $MBSTRING;
$this->charset = $charset;
if ($MBSTRING && function_exists("mb_internal_encoding"))
{
if(!@mb_internal_encoding($charset))
$MBSTRING = FALSE;
}
}
function get_charset()
{
return $this->charset;
}
function reset()
{
$this->css = new rcube_css();
$this->script_files = array();
$this->scripts = array();
$this->title = '';
}
function write($templ='', $base_path='')
{
$output = empty($templ) ? $this->default_template : trim($templ);
// set default page title
if (empty($this->title))
$this->title = 'RoundCube Mail';
// replace specialchars in content
$__page_title = Q($this->title, 'show', FALSE);
$__page_header = $__page_body = $__page_footer = '';
// include meta tag with charset
if (!empty($this->charset))
{
header('Content-Type: text/html; charset='.$this->charset);
$__page_header = '<meta http-equiv="content-type" content="text/html; charset='.$this->charset.'" />'."\n";
}
// definition of the code to be placed in the document header and footer
if (is_array($this->script_files['head']))
foreach ($this->script_files['head'] as $file)
$__page_header .= sprintf($this->script_tag_file, $this->scripts_path, $file);
if (is_array($this->external_scripts['head']))
{
foreach ($this->external_scripts['head'] as $xscript)
{
$__page_header .= sprintf($this->tag_format_external_script, $xscript);
}
}
if (!empty($this->scripts['head']))
$__page_header .= sprintf($this->script_tag, $this->scripts['head']);
if (is_array($this->script_files['foot']))
{
foreach ($this->script_files['foot'] as $file)
$__page_footer .= sprintf($this->script_tag_file, $this->scripts_path, $file);
}
if (!empty($this->scripts['foot']))
$__page_footer .= sprintf($this->script_tag, $this->scripts['foot']);
if ($this->footer)
$__page_footer .= "\n" . $this->footer;
$__page_header .= $this->css->show();
// find page header
if($hpos = rc_strpos(rc_strtolower($output), '</head>'))
$__page_header .= "\n";
else
{
if (!is_numeric($hpos))
$hpos = rc_strpos(rc_strtolower($output), '<body');
if (!is_numeric($hpos) && ($hpos = rc_strpos(rc_strtolower($output), '<html')))
{
while($output[$hpos]!='>')
$hpos++;
$hpos++;
}
$__page_header = "<head>\n<title>$__page_title</title>\n$__page_header\n</head>\n";
}
// add page hader
if($hpos)
$output = rc_substr($output,0,$hpos) . $__page_header . rc_substr($output,$hpos,rc_strlen($output));
else
$output = $__page_header . $output;
// find page body
if($bpos = rc_strpos(rc_strtolower($output), '<body'))
{
while($output[$bpos]!='>') $bpos++;
$bpos++;
}
else
$bpos = rc_strpos(rc_strtolower($output), '</head>')+7;
// add page body
if($bpos && $__page_body)
$output = rc_substr($output,0,$bpos) . "\n$__page_body\n" . rc_substr($output,$bpos,rc_strlen($output));
// find and add page footer
$output_lc = rc_strtolower($output);
if(($fpos = strrstr($output_lc, '</body>')) ||
($fpos = strrstr($output_lc, '</html>')))
$output = substr($output, 0, $fpos) . "$__page_footer\n" . substr($output, $fpos);
else
$output .= "\n$__page_footer";
// reset those global vars
$__page_header = $__page_footer = '';
// correct absolute paths in images and other tags
$output = preg_replace('/(src|href|background)=(["\']?)(\/[a-z0-9_\-]+)/Ui', "\\1=\\2$base_path\\3", $output);
$output = str_replace('$__skin_path', $base_path, $output);
print rcube_charset_convert($output, 'UTF-8', $this->charset);
}
function _parse($templ)
{
}
}
class rcube_css
{
var $css_data = array();
var $css_groups = array();
var $include_files = array();
var $grouped_output = TRUE;
var $content_type = 'text/css';
var $base_path = '';
var $indent_chars = "\t";
// add or overwrite a css definition
// either pass porperty and value as separate arguments
// or provide an associative array as second argument
function set_style($selector, $property, $value='')
{
$a_elements = $this->_parse_selectors($selector);
foreach ($a_elements as $element)
{
if (!is_array($property))
$property = array($property => $value);
foreach ($property as $name => $value)
$this->css_data[$element][strtolower($name)] = $value;
}
// clear goups array
$this->css_groups = array();
}
// unset a style property
function remove_style($selector, $property)
{
if (!is_array($property))
$property = array($property);
foreach ($property as $key)
unset($this->css_data[$selector][strtolower($key)]);
// clear goups array
$this->css_groups = array();
}
// define base path for external css files
function set_basepath($path)
{
$this->base_path = preg_replace('/\/$/', '', $path);
}
// enable/disable grouped output
function set_grouped_output($grouped)
{
$this->grouped_output = $grouped;
}
// add a css file as external source
function include_file($filename, $media='')
{
// include multiple files
if (is_array($filename))
{
foreach ($filename as $file)
$this->include_file($file, $media);
}
// add single file
else if (!in_array($filename, $this->include_files))
$this->include_files[] = array('file' => $filename,
'media' => $media);
}
// parse css code
function import_string($str)
{
$ret = FALSE;
if (strlen($str))
$ret = $this->_parse($str);
return $ret;
}
// open and parse a css file
function import_file($file)
{
$ret = FALSE;
if (!is_file($file))
return $ret;
// for php version >= 4.3.0
if (function_exists('file_get_contents'))
$ret = $this->_parse(file_get_contents($file));
// for order php versions
else if ($fp = fopen($file, 'r'))
{
$ret = $this->_parse(fread($fp, filesize($file)));
fclose($fp);
}
return $ret;
}
// copy all properties inherited from superior styles to a specific selector
function copy_inherited_styles($selector)
{
// get inherited props from body and tag/class selectors
$css_props = $this->_get_inherited_styles($selector);
// write modified props back and clear goups array
if (sizeof($css_props))
{
$this->css_data[$selector] = $css_props;
$this->css_groups = array();
}
}
// return css definition for embedding in HTML
function show()
{
$out = '';
// include external css files
if (sizeof($this->include_files))
foreach ($this->include_files as $file_arr)
$out .= sprintf('<link rel="stylesheet" type="%s" href="%s"%s>'."\n",
$this->content_type,
$this->_get_file_path($file_arr['file']),
$file_arr['media'] ? ' media="'.$file_arr['media'].'"' : '');
// compose css string
if (sizeof($this->css_data))
$out .= sprintf("<style type=\"%s\">\n<!--\n\n%s-->\n</style>",
$this->content_type,
$this->to_string());
return $out;
}
// return valid css code of the current styles grid
function to_string($selector=NULL)
{
// return code for a single selector
if ($selector)
{
$indent_str = $this->indent_chars;
$this->indent_chars = '';
$prop_arr = $this->to_array($selector);
$out = $this->_style2string($prop_arr, TRUE);
$this->indent_chars = $indent_str;
}
// compose css code for complete data grid
else
{
$out = '';
$css_data = $this->to_array();
foreach ($css_data as $key => $prop_arr)
$out .= sprintf("%s {\n%s}\n\n",
$key,
$this->_style2string($prop_arr, TRUE));
}
return $out;
}
// return a single-line string of a css definition
function to_inline($selector)
{
if ($this->css_data[$selector])
return str_replace('"', '\\"', $this->_style2string($this->css_data[$selector], FALSE));
}
// return an associative array with selector(s) as key and styles array as value
function to_array($selector=NULL)
{
if (!$selector && $this->grouped_output)
{
// build groups if desired
if (!sizeof($this->css_groups))
$this->_build_groups();
// modify group array to get an array(selector => properties)
$out_arr = array();
foreach ($this->css_groups as $group_arr)
{
$key = join(', ', $group_arr['selectors']);
$out_arr[$key] = $group_arr['properties'];
}
}
else
$out_arr = $this->css_data;
return $selector ? $out_arr[$selector] : $out_arr;
}
// create a css file
function to_file($filepath)
{
if ($fp = fopen($filepath, 'w'))
{
fwrite($fp, $this->to_string());
fclose($fp);
return TRUE;
}
return FALSE;
}
// alias method for import_string() [DEPRECATED]
function add($str)
{
$this->import_string($str);
}
// alias method for to_string() [DEPRECATED]
function get()
{
return $this->to_string();
}
// ******** private methods ********
// parse a string and add styles to internal data grid
function _parse($str)
{
// remove comments
$str = preg_replace("/\/\*(.*)?\*\//Usi", '', $str);
// parse style definitions
if (!preg_match_all ('/([a-z0-9\.#*:_][a-z0-9\.\-_#:*,\[\]\(\)\s\"\'\+\|>~=]+)\s*\{([^\}]*)\}/ims', $str, $matches, PREG_SET_ORDER))
return FALSE;
foreach ($matches as $match_arr)
{
// split selectors into array
$a_keys = $this->_parse_selectors(trim($match_arr[1]));
// parse each property of an element
$codes = explode(";", trim($match_arr[2]));
foreach ($codes as $code)
{
if (strlen(trim($code))>0)
{
// find the property and the value
if (!($sep = strpos($code, ':')))
continue;
$property = strtolower(trim(substr($code, 0, $sep)));
$value = trim(substr($code, $sep+1));
// add the property to the object array
foreach ($a_keys as $key)
$this->css_data[$key][$property] = $value;
}
}
}
// clear goups array
if (sizeof($matches))
{
$this->css_groups = array();
return TRUE;
}
return FALSE;
}
// split selector group
function _parse_selectors($selector)
{
// trim selector and remove multiple spaces
$selector = preg_replace('/\s+/', ' ', trim($selector));
if (strpos($selector, ','))
return preg_split('/[\t\s\n\r]*,[\t\s\n\r]*/mi', $selector);
else
return array($selector);
}
// compare identical styles and make groups
function _build_groups()
{
// clear group array
$this->css_groups = array();
$string_group_map = array();
// bulild css string for each selector and check if the same is already defines
foreach ($this->css_data as $selector => $prop_arr)
{
// make shure to compare props in the same order
ksort($prop_arr);
$compare_str = preg_replace('/[\s\t]+/', '', $this->_style2string($prop_arr, FALSE));
// add selector to extisting group
if (isset($string_group_map[$compare_str]))
{
$group_index = $string_group_map[$compare_str];
$this->css_groups[$group_index]['selectors'][] = $selector;
}
// create new group
else
{
$i = sizeof($this->css_groups);
$string_group_map[$compare_str] = $i;
$this->css_groups[$i] = array('selectors' => array($selector),
'properties' => $this->css_data[$selector]);
}
}
}
// convert the prop array into a valid css definition
function _style2string($prop_arr, $multiline=TRUE)
{
$out = '';
$delm = $multiline ? "\n" : '';
$spacer = $multiline ? ' ' : '';
$indent = $multiline ? $this->indent_chars : '';
if (is_array($prop_arr))
foreach ($prop_arr as $prop => $value)
if (strlen($value))
$out .= sprintf('%s%s:%s%s;%s',
$indent,
$prop,
$spacer,
$value,
$delm);
return $out;
}
// copy all properties inherited from superior styles to a specific selector
function _get_inherited_styles($selector, $loop=FALSE)
{
$css_props = $this->css_data[$selector] ? $this->css_data[$selector] : array();
// get styles from tag selector
if (preg_match('/(([a-z0-9]*)(\.[^\s]+)?)$/i', $selector, $regs))
{
$sel = $regs[1];
$tagname = $regs[2];
$class = $regs[3];
if ($sel && is_array($this->css_data[$sel]))
$css_props = $this->_merge_styles($this->css_data[$sel], $css_props);
if ($class && is_array($this->css_data[$class]))
$css_props = $this->_merge_styles($this->css_data[$class], $css_props);
if ($tagname && is_array($this->css_data[$tagname]))
$css_props = $this->_merge_styles($this->css_data[$tagname], $css_props);
}
// analyse inheritance
if (strpos($selector, ' '))
{
$a_hier = split(' ', $selector);
if (sizeof($a_hier)>1)
{
array_pop($a_hier);
$base_selector = join(' ', $a_hier);
// call this method recursively
$new_props = $this->_get_inherited_styles($base_selector, TRUE);
$css_props = $this->_merge_styles($new_props, $css_props);
}
}
// get body style
if (!$loop && is_array($this->css_data['body']))
$css_props = $this->_merge_styles($this->css_data['body'], $css_props);
return $css_props;
}
// merge two arrays with style properties together like a browser would do
function _merge_styles($one, $two)
{
// these properties are additive
foreach (array('text-decoration') as $prop)
if ($one[$prop] && $two[$prop])
{
// if value contains 'none' it's ignored
if (strstr($one[$prop], 'none'))
continue;
else if (strstr($two[$prop], 'none'))
unset($two[$prop]);
$a_values_one = split(' ', $one[$prop]);
$a_values_two = split(' ', $two[$prop]);
$two[$prop] = join(' ', array_unique(array_merge($a_values_one, $a_values_two)));
}
return array_merge($one, $two);
}
// resolve file path
function _get_file_path($file)
{
if (!$this->base_path && $GLOBALS['CSS_PATH'])
$this->set_basepath($GLOBALS['CSS_PATH']);
$base = ($file{0}=='/' || $file{0}=='.' || substr($file, 0, 7)=='http://') ? '' :
($this->base_path ? $this->base_path.'/' : '');
return $base.$file;
}
}
class base_form_element
{
var $uppertags = FALSE;
var $upperattribs = FALSE;
var $upperprops = FALSE;
var $newline = FALSE;
var $attrib = array();
// create string with attributes
function create_attrib_string($tagname='')
{
if (!sizeof($this->attrib))
return '';
if ($this->name!='')
$this->attrib['name'] = $this->name;
$attrib_arr = array();
foreach ($this->attrib as $key => $value)
{
// don't output some internally used attributes
if (in_array($key, array('form', 'quicksearch')))
continue;
// skip if size if not numeric
if (($key=='size' && !is_numeric($value)))
continue;
// skip empty eventhandlers
if ((strpos($key,'on')===0 && $value==''))
continue;
// encode textarea content
if ($key=='value')
$value = Q($value, 'strict', FALSE);
// attributes with no value
if (in_array($key, array('checked', 'multiple', 'disabled', 'selected')))
{
if ($value)
$attrib_arr[] = $key;
}
// don't convert size of value attribute
else if ($key=='value')
$attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $value, 'value');
// regular tag attributes
else
$attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $this->_conv_case($value, 'value'));
}
return sizeof($attrib_arr) ? ' '.implode(' ', $attrib_arr) : '';
}
// convert tags and attributes to upper-/lowercase
// $type can either be "tag" or "attrib"
function _conv_case($str, $type='attrib')
{
if ($type == 'tag')
return $this->uppertags ? strtoupper($str) : strtolower($str);
else if ($type == 'attrib')
return $this->upperattribs ? strtoupper($str) : strtolower($str);
else if ($type == 'value')
return $this->upperprops ? strtoupper($str) : strtolower($str);
}
}
class input_field extends base_form_element
{
var $type = 'text';
// PHP 5 constructor
function __construct($attrib=NULL)
{
if (is_array($attrib))
$this->attrib = $attrib;
if ($attrib['type'])
$this->type = $attrib['type'];
if ($attrib['newline'])
$this->newline = TRUE;
}
// PHP 4 compatibility
function input_field($attrib=array())
{
$this->__construct($attrib);
}
// compose input tag
function show($value=NULL, $attrib=NULL)
{
// overwrite object attributes
if (is_array($attrib))
$this->attrib = array_merge($this->attrib, $attrib);
// set value attribute
if ($value!==NULL)
$this->attrib['value'] = $value;
$this->attrib['type'] = $this->type;
// return final tag
return sprintf('<%s%s />%s',
$this->_conv_case('input', 'tag'),
$this->create_attrib_string(),
($this->newline ? "\n" : ""));
}
}
class textfield extends input_field
{
var $type = 'text';
}
class passwordfield extends input_field
{
var $type = 'password';
}
class radiobutton extends input_field
{
var $type = 'radio';
}
class checkbox extends input_field
{
var $type = 'checkbox';
function show($value='', $attrib=NULL)
{
// overwrite object attributes
if (is_array($attrib))
$this->attrib = array_merge($this->attrib, $attrib);
$this->attrib['type'] = $this->type;
if ($value && (string)$value==(string)$this->attrib['value'])
$this->attrib['checked'] = TRUE;
else
$this->attrib['checked'] = FALSE;
// return final tag
return sprintf('<%s%s />%s',
$this->_conv_case('input', 'tag'),
$this->create_attrib_string(),
($this->newline ? "\n" : ""));
}
}
class textarea extends base_form_element
{
// PHP 5 constructor
function __construct($attrib=array())
{
$this->attrib = $attrib;
if ($attrib['newline'])
$this->newline = TRUE;
}
// PHP 4 compatibility
function textarea($attrib=array())
{
$this->__construct($attrib);
}
function show($value='', $attrib=NULL)
{
// overwrite object attributes
if (is_array($attrib))
$this->attrib = array_merge($this->attrib, $attrib);
// take value attribute as content
if ($value=='')
$value = $this->attrib['value'];
// make shure we don't print the value attribute
if (isset($this->attrib['value']))
unset($this->attrib['value']);
if (!empty($value) && !isset($this->attrib['mce_editable']))
$value = Q($value, 'strict', FALSE);
// return final tag
return sprintf('<%s%s>%s</%s>%s',
$this->_conv_case('textarea', 'tag'),
$this->create_attrib_string(),
$value,
$this->_conv_case('textarea', 'tag'),
($this->newline ? "\n" : ""));
}
}
class hiddenfield extends base_form_element
{
var $fields_arr = array();
var $newline = TRUE;
// PHP 5 constructor
function __construct($attrib=NULL)
{
if (is_array($attrib))
$this->add($attrib);
}
// PHP 4 compatibility
function hiddenfield($attrib=NULL)
{
$this->__construct($attrib);
}
// add a hidden field to this instance
function add($attrib)
{
$this->fields_arr[] = $attrib;
}
function show()
{
$out = '';
foreach ($this->fields_arr as $attrib)
{
$this->attrib = $attrib;
$this->attrib['type'] = 'hidden';
$out .= sprintf('<%s%s />%s',
$this->_conv_case('input', 'tag'),
$this->create_attrib_string(),
($this->newline ? "\n" : ""));
}
return $out;
}
}
class select extends base_form_element
{
var $options = array();
/*
syntax:
-------
// create instance. arguments are used to set attributes of select-tag
$select = new select(array('name' => 'fieldname'));
// add one option
$select->add('Switzerland', 'CH');
// add multiple options
$select->add(array('Switzerland', 'Germany'),
array('CH', 'DE'));
// add 10 blank options with 50 chars
// used to fill with javascript (necessary for 4.x browsers)
$select->add_blank(10, 50);
// generate pulldown with selection 'Switzerland' and return html-code
// as second argument the same attributes available to instanciate can be used
print $select->show('CH');
*/
// PHP 5 constructor
function __construct($attrib=NULL)
{
if (is_array($attrib))
$this->attrib = $attrib;
if ($attrib['newline'])
$this->newline = TRUE;
}
// PHP 4 compatibility
function select($attrib=NULL)
{
$this->__construct($attrib);
}
function add($names, $values=NULL)
{
if (is_array($names))
{
foreach ($names as $i => $text)
$this->options[] = array('text' => $text, 'value' => (string)$values[$i]);
}
else
{
$this->options[] = array('text' => $names, 'value' => (string)$values);
}
}
function add_blank($nr, $width=0)
{
$text = $width ? str_repeat('&nbsp;', $width) : '';
for ($i=0; $i < $nr; $i++)
$this->options[] = array('text' => $text);
}
function show($select=array(), $attrib=NULL)
{
$options_str = "\n";
$value_str = $this->_conv_case(' value="%s"', 'attrib');
if (!is_array($select))
$select = array((string)$select);
foreach ($this->options as $option)
{
$selected = ((!empty($option['value']) && in_array($option['value'], $select, TRUE)) ||
(in_array($option['text'], $select, TRUE))) ? $this->_conv_case(' selected', 'attrib') : '';
$options_str .= sprintf("<%s%s%s>%s</%s>\n",
$this->_conv_case('option', 'tag'),
!empty($option['value']) ? sprintf($value_str, $option['value']) : '',
$selected,
Q($option['text'], 'strict', FALSE),
$this->_conv_case('option', 'tag'));
}
// return final tag
return sprintf('<%s%s>%s</%s>%s',
$this->_conv_case('select', 'tag'),
$this->create_attrib_string(),
$options_str,
$this->_conv_case('select', 'tag'),
($this->newline ? "\n" : ""));
}
}
// ********* rcube schared functions *********
// provide details about the client's browser
function rcube_browser()
{
$HTTP_USER_AGENT = $_SERVER['HTTP_USER_AGENT'];
$bw['ver'] = 0;
$bw['win'] = stristr($HTTP_USER_AGENT, 'win');
$bw['mac'] = stristr($HTTP_USER_AGENT, 'mac');
$bw['linux'] = stristr($HTTP_USER_AGENT, 'linux');
$bw['unix'] = stristr($HTTP_USER_AGENT, 'unix');
$bw['ns4'] = stristr($HTTP_USER_AGENT, 'mozilla/4') && !stristr($HTTP_USER_AGENT, 'msie');
$bw['ns'] = ($bw['ns4'] || stristr($HTTP_USER_AGENT, 'netscape'));
$bw['ie'] = stristr($HTTP_USER_AGENT, 'msie');
$bw['mz'] = stristr($HTTP_USER_AGENT, 'mozilla/5');
$bw['opera'] = stristr($HTTP_USER_AGENT, 'opera');
$bw['safari'] = stristr($HTTP_USER_AGENT, 'safari');
if($bw['ns'])
{
$test = eregi("mozilla\/([0-9\.]+)", $HTTP_USER_AGENT, $regs);
$bw['ver'] = $test ? (float)$regs[1] : 0;
}
if($bw['mz'])
{
$test = ereg("rv:([0-9\.]+)", $HTTP_USER_AGENT, $regs);
$bw['ver'] = $test ? (float)$regs[1] : 0;
}
if($bw['ie'])
{
$test = eregi("msie ([0-9\.]+)", $HTTP_USER_AGENT, $regs);
$bw['ver'] = $test ? (float)$regs[1] : 0;
}
if($bw['opera'])
{
$test = eregi("opera ([0-9\.]+)", $HTTP_USER_AGENT, $regs);
$bw['ver'] = $test ? (float)$regs[1] : 0;
}
if(eregi(" ([a-z]{2})-([a-z]{2})", $HTTP_USER_AGENT, $regs))
$bw['lang'] = $regs[1];
else
$bw['lang'] = 'en';
$bw['dom'] = ($bw['mz'] || $bw['safari'] || ($bw['ie'] && $bw['ver']>=5) || ($bw['opera'] && $bw['ver']>=7));
$bw['pngalpha'] = $bw['mz'] || $bw['safari'] || ($bw['ie'] && $bw['ver']>=5.5) ||
($bw['ie'] && $bw['ver']>=5 && $bw['mac']) || ($bw['opera'] && $bw['ver']>=7) ? TRUE : FALSE;
return $bw;
}
// get text in the desired language from the language file
function rcube_label($attrib)
{
global $sess_user_lang, $INSTALL_PATH, $OUTPUT;
static $sa_text_data, $s_language, $utf8_decode;
// extract attributes
if (is_string($attrib))
$attrib = array('name' => $attrib);
$nr = is_numeric($attrib['nr']) ? $attrib['nr'] : 1;
$vars = isset($attrib['vars']) ? $attrib['vars'] : '';
$command_name = !empty($attrib['command']) ? $attrib['command'] : NULL;
$alias = $attrib['name'] ? $attrib['name'] : ($command_name && $command_label_map[$command_name] ? $command_label_map[$command_name] : '');
// load localized texts
if (!$sa_text_data || $s_language != $sess_user_lang)
{
$sa_text_data = array();
// get english labels (these should be complete)
@include($INSTALL_PATH.'program/localization/en_US/labels.inc');
@include($INSTALL_PATH.'program/localization/en_US/messages.inc');
if (is_array($labels))
$sa_text_data = $labels;
if (is_array($messages))
$sa_text_data = array_merge($sa_text_data, $messages);
// include user language files
if ($sess_user_lang!='en' && is_dir($INSTALL_PATH.'program/localization/'.$sess_user_lang))
{
include_once($INSTALL_PATH.'program/localization/'.$sess_user_lang.'/labels.inc');
include_once($INSTALL_PATH.'program/localization/'.$sess_user_lang.'/messages.inc');
if (is_array($labels))
$sa_text_data = array_merge($sa_text_data, $labels);
if (is_array($messages))
$sa_text_data = array_merge($sa_text_data, $messages);
}
$s_language = $sess_user_lang;
}
// text does not exist
if (!($text_item = $sa_text_data[$alias]))
{
/*
raise_error(array('code' => 500,
'type' => 'php',
'line' => __LINE__,
'file' => __FILE__,
'message' => "Missing localized text for '$alias' in '$sess_user_lang'"), TRUE, FALSE);
*/
return "[$alias]";
}
// make text item array
$a_text_item = is_array($text_item) ? $text_item : array('single' => $text_item);
// decide which text to use
if ($nr==1)
$text = $a_text_item['single'];
else if ($nr>0)
$text = $a_text_item['multiple'];
else if ($nr==0)
{
if ($a_text_item['none'])
$text = $a_text_item['none'];
else if ($a_text_item['single'])
$text = $a_text_item['single'];
else if ($a_text_item['multiple'])
$text = $a_text_item['multiple'];
}
// default text is single
if ($text=='')
$text = $a_text_item['single'];
// replace vars in text
if (is_array($attrib['vars']))
{
foreach ($attrib['vars'] as $var_key=>$var_value)
$a_replace_vars[substr($var_key, 0, 1)=='$' ? substr($var_key, 1) : $var_key] = $var_value;
}
if ($a_replace_vars)
$text = preg_replace('/\${?([_a-z]{1}[_a-z0-9]*)}?/ei', '$a_replace_vars["\1"]', $text);
// remove variables in text which were not available in arg $vars and $nr
eval("\$text = <<<EOF
$text
EOF;
");
// format output
if (($attrib['uppercase'] && strtolower($attrib['uppercase']=='first')) || $attrib['ucfirst'])
return ucfirst($text);
else if ($attrib['uppercase'])
return strtoupper($text);
else if ($attrib['lowercase'])
return strtolower($text);
- else
- return $text;
return $text;
}
// send HTTP header for no-cacheing steps
function send_nocacheing_headers()
{
if (headers_sent())
return;
header("Expires: ".gmdate("D, d M Y H:i:s")." GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
header("Pragma: no-cache");
}
// send header with expire date 30 days in future
function send_future_expire_header()
{
if (headers_sent())
return;
header("Expires: ".gmdate("D, d M Y H:i:s", mktime()+2600000)." GMT");
header("Cache-Control: ");
header("Pragma: ");
}
// function to convert an array to a javascript array
function array2js($arr, $type='')
{
if (!$type)
$type = 'mixed';
if (is_array($arr))
{
// no items in array
if (!sizeof($arr))
return 'new Array()';
else
{
$a_pairs = array();
$keys_arr = array_keys($arr);
$is_assoc = $have_numeric = 0;
for ($i=0; $i<sizeof($keys_arr); ++$i)
{
if(is_numeric($keys_arr[$i]))
$have_numeric = 1;
if (!is_numeric($keys_arr[$i]) || $keys_arr[$i]!=$i)
$is_assoc = 1;
if($is_assoc && $have_numeric)
break;
}
$previous_was_array = false;
while (list($key, $value) = each($arr))
{
// enclose key with quotes if it is not variable-name conform
if (!ereg("^[_a-zA-Z]{1}[_a-zA-Z0-9]*$", $key) /* || is_js_reserved_word($key) */)
$key = "'$key'";
if (!is_array($value) && is_string($value))
{
$value = str_replace("\r\n", '\n', $value);
$value = str_replace("\n", '\n', $value);
}
$is_string = false;
if (!is_array($value))
{
if ($type=='string')
$is_string = true;
else if (($type == 'mixed' && is_bool($value)) || $type == 'bool')
{
$is_string = false;
$value = $value ? "true" : "false";
}
else if ((($type=='mixed' && is_numeric($value)) || $type=='int') && rc_strlen($value)<16) // js interprets numbers with digits >15 as ...e+...
$is_string = FALSE;
else
$is_string = TRUE;
}
if ($is_string)
$value = "'".preg_replace("/(?<!\\\)'/", "\'", $value)."'";
$a_pairs[] = sprintf("%s%s",
$is_assoc ? "$key:" : '',
is_array($value) ? array2js($value, $type) : $value);
}
if ($a_pairs)
{
if ($is_assoc)
$return = '{'.implode(',', $a_pairs).'}';
else
$return = '['.implode(',', $a_pairs).']';
}
return $return;
}
}
else
{
return $arr;
}
}
// similar function as in_array() ut case-insensitive
function in_array_nocase($needle, $haystack)
{
foreach ($haystack as $value)
{
if (strtolower($needle)===strtolower($value))
return TRUE;
}
return FALSE;
}
// find out if the string content means TRUE or FALSE
function get_boolean($str)
{
$str = strtolower($str);
if(in_array($str, array('false', '0', 'no', 'nein', ''), TRUE))
return FALSE;
else
return TRUE;
}
// parse a human readable string for a number of bytes
function parse_bytes($str)
{
if (is_numeric($str))
return intval($str);
if (preg_match('/([0-9]+)([a-z])/i', $str, $regs))
{
$bytes = floatval($regs[1]);
switch (strtolower($regs[2]))
{
case 'g':
$bytes *= 1073741824;
break;
case 'm':
$bytes *= 1048576;
break;
case 'k':
$bytes *= 1024;
break;
}
}
return intval($bytes);
}
// create a human readable string for a number of bytes
function show_bytes($bytes)
{
if ($bytes > 1073741824)
{
$gb = $bytes/1073741824;
$str = sprintf($gb>=10 ? "%d GB" : "%.1f GB", $gb);
}
else if ($bytes > 1048576)
{
$mb = $bytes/1048576;
$str = sprintf($mb>=10 ? "%d MB" : "%.1f MB", $mb);
}
else if ($bytes > 1024)
$str = sprintf("%d KB", round($bytes/1024));
else
$str = sprintf('%d B', $bytes);
return $str;
}
// convert paths like ../xxx to an absolute path using a base url
function make_absolute_url($path, $base_url)
{
$host_url = $base_url;
$abs_path = $path;
// cut base_url to the last directory
if (strpos($base_url, '/')>7)
{
$host_url = substr($base_url, 0, strpos($base_url, '/'));
$base_url = substr($base_url, 0, strrpos($base_url, '/'));
}
// $path is absolute
if ($path{0}=='/')
$abs_path = $host_url.$path;
else
{
// strip './' because its the same as ''
$path = preg_replace('/^\.\//', '', $path);
if(preg_match_all('/\.\.\//', $path, $matches, PREG_SET_ORDER))
foreach($matches as $a_match)
{
if (strrpos($base_url, '/'))
$base_url = substr($base_url, 0, strrpos($base_url, '/'));
$path = substr($path, 3);
}
$abs_path = $base_url.'/'.$path;
}
return $abs_path;
}
// wrapper function for strlen
function rc_strlen($str)
{
if (function_exists('mb_strlen'))
return mb_strlen($str);
else
return strlen($str);
}
// wrapper function for strtolower
function rc_strtolower($str)
{
if (function_exists('mb_strtolower'))
return mb_strtolower($str);
else
return strtolower($str);
}
// wrapper function for substr
function rc_substr($str, $start, $len)
{
if (function_exists('mb_substr'))
return mb_substr($str, $start, $len);
else
return substr($str, $start, $len);
}
// wrapper function for strpos
function rc_strpos($haystack, $needle, $offset=0)
{
if (function_exists('mb_strpos'))
return mb_strpos($haystack, $needle, $offset);
else
return strpos($haystack, $needle, $offset);
}
// wrapper function for strrpos
function rc_strrpos($haystack, $needle, $offset=0)
{
if (function_exists('mb_strrpos'))
return mb_strrpos($haystack, $needle, $offset);
else
return strrpos($haystack, $needle, $offset);
}
// replace the middle part of a string with ...
// if it is longer than the allowed length
function abbrevate_string($str, $maxlength, $place_holder='...')
{
$length = rc_strlen($str);
$first_part_length = floor($maxlength/2) - rc_strlen($place_holder);
if ($length > $maxlength)
{
$second_starting_location = $length - $maxlength + $first_part_length + 1;
$str = rc_substr($str, 0, $first_part_length) . $place_holder . rc_substr($str, $second_starting_location, $length);
}
return $str;
}
// make sure the string ends with a slash
function slashify($str)
{
return unslashify($str).'/';
}
// remove slash at the end of the string
function unslashify($str)
{
return preg_replace('/\/$/', '', $str);
}
// delete all files within a folder
function clear_directory($dir_path)
{
$dir = @opendir($dir_path);
if(!$dir) return FALSE;
while ($file = readdir($dir))
if (strlen($file)>2)
unlink("$dir_path/$file");
closedir($dir);
return TRUE;
}
// create a unix timestamp with a specified offset from now
function get_offset_time($offset_str, $factor=1)
{
if (preg_match('/^([0-9]+)\s*([smhdw])/i', $offset_str, $regs))
{
$amount = (int)$regs[1];
$unit = strtolower($regs[2]);
}
else
{
$amount = (int)$offset_str;
$unit = 's';
}
$ts = mktime();
switch ($unit)
{
case 'w':
$amount *= 7;
case 'd':
$amount *= 24;
case 'h':
$amount *= 60;
case 'h':
$amount *= 60;
case 's':
$ts += $amount * $factor;
}
return $ts;
}
/**
* strrstr
*
* return the last occurence of a string in another string
* @param haystack string string in which to search
* @param needle string string for which to search
* @return index of needle within haystack, or false if not found
*/
function strrstr($haystack, $needle)
{
$pver = phpversion();
if ($pver[0] >= 5)
{
return strrpos($haystack, $needle);
}
else
{
$index = strpos(strrev($haystack), strrev($needle));
if($index === false) {
return false;
}
$index = strlen($haystack) - strlen($needle) - $index;
return $index;
}
}
?>
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 1c2639d9b..211f9fbe8 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -1,910 +1,910 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/compose.inc |
| |
| This file is part of the RoundCube Webmail client |
| Copyright (C) 2005, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Compose a new mail message with all headers and attachments |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
require_once('Mail/mimeDecode.php');
require_once('lib/html2text.inc');
// define constants for message compose mode
define('RCUBE_COMPOSE_REPLY', 0x0106);
define('RCUBE_COMPOSE_FORWARD', 0x0107);
define('RCUBE_COMPOSE_DRAFT', 0x0108);
// remove an attachment
if ($_action=='remove-attachment' && preg_match('/^rcmfile([0-9]+)$/', $_GET['_file'], $regs))
{
$id = $regs[1];
if (is_array($_SESSION['compose']['attachments'][$id]))
{
@unlink($_SESSION['compose']['attachments'][$id]['path']);
$_SESSION['compose']['attachments'][$id] = NULL;
$commands = sprintf("parent.%s.remove_from_attachment_list('rcmfile%d');\n", $JS_OBJECT_NAME, $id);
rcube_remote_response($commands);
exit;
}
}
$MESSAGE_FORM = NULL;
$MESSAGE = NULL;
// Nothing below is called during message composition, only at "new/forward/reply/draft" initialization or
// if a compose-ID is given (i.e. when the compose step is opened in a new window/tab).
// Since there are many ways to leave the compose page improperly, it seems necessary to clean-up an old
// compose when a "new/forward/reply/draft" is called - otherwise the old session attachments will appear
if (!is_array($_SESSION['compose']) || $_SESSION['compose']['id'] != get_input_value('_id', RCUBE_INPUT_GET))
{
rcmail_compose_cleanup();
$_SESSION['compose'] = array('id' => uniqid(rand()));
}
// add some labels to client
rcube_add_label('nosubject', 'norecipientwarning', 'nosubjectwarning', 'nobodywarning', 'notsentwarning', 'savingmessage', 'sendingmessage', 'messagesaved', 'converting');
// add config parameter to client script
$OUTPUT->add_script(sprintf("%s.set_env('draft_autosave', %d);", $JS_OBJECT_NAME, !empty($CONFIG['drafts_mbox']) ? $CONFIG['draft_autosave'] : 0));
// get reference message and set compose mode
if ($msg_uid = get_input_value('_reply_uid', RCUBE_INPUT_GET))
$compose_mode = RCUBE_COMPOSE_REPLY;
else if ($msg_uid = get_input_value('_forward_uid', RCUBE_INPUT_GET))
$compose_mode = RCUBE_COMPOSE_FORWARD;
else if ($msg_uid = get_input_value('_draft_uid', RCUBE_INPUT_GET))
$compose_mode = RCUBE_COMPOSE_DRAFT;
if (!empty($msg_uid))
{
// similar as in program/steps/mail/show.inc
$MESSAGE = array('UID' => $msg_uid);
$MESSAGE['headers'] = &$IMAP->get_headers($msg_uid);
$MESSAGE['structure'] = &$IMAP->get_structure($msg_uid);
$MESSAGE['subject'] = $IMAP->decode_header($MESSAGE['headers']->subject);
$MESSAGE['parts'] = $IMAP->get_mime_numbers($MESSAGE['structure']);
if ($compose_mode == RCUBE_COMPOSE_REPLY)
{
$_SESSION['compose']['reply_uid'] = $msg_uid;
$_SESSION['compose']['reply_msgid'] = $MESSAGE['headers']->messageID;
$_SESSION['compose']['references'] = $MESSAGE['headers']->reference;
$_SESSION['compose']['references'] .= !empty($MESSAGE['headers']->reference) ? ' ' : '';
$_SESSION['compose']['references'] .= $MESSAGE['headers']->messageID;
if (!empty($_GET['_all']))
$MESSAGE['reply_all'] = 1;
}
else if ($compose_mode == RCUBE_COMPOSE_FORWARD)
{
$_SESSION['compose']['forward_uid'] = $msg_uid;
}
else if ($compose_mode == RCUBE_COMPOSE_DRAFT)
{
$_SESSION['compose']['draft_uid'] = $msg_uid;
}
}
/****** compose mode functions ********/
function rcmail_compose_headers($attrib)
{
global $IMAP, $MESSAGE, $DB, $compose_mode;
static $sa_recipients = array();
list($form_start, $form_end) = get_form_tags($attrib);
$out = '';
$part = strtolower($attrib['part']);
switch ($part)
{
case 'from':
return rcmail_compose_header_from($attrib);
case 'to':
$fname = '_to';
$header = 'to';
// we have contact id's as get parameters
if (!empty($_GET['_to']) && preg_match('/^[0-9]+(,[0-9]+)*$/', $_GET['_to']))
{
$a_recipients = array();
$sql_result = $DB->query("SELECT name, email
FROM ".get_table_name('contacts')."
WHERE user_id=?
AND del<>1
AND contact_id IN (".$_GET['_to'].")",
$_SESSION['user_id']);
while ($sql_arr = $DB->fetch_assoc($sql_result))
$a_recipients[] = format_email_recipient($sql_arr['email'], $sql_arr['name']);
if (sizeof($a_recipients))
$fvalue = join(', ', $a_recipients);
}
else if (!empty($_GET['_to']))
$fvalue = get_input_value('_to', RCUBE_INPUT_GET);
case 'cc':
if (!$fname)
{
$fname = '_cc';
$header = 'cc';
}
case 'bcc':
if (!$fname)
{
$fname = '_bcc';
$header = 'bcc';
}
$allow_attrib = array('id', 'class', 'style', 'cols', 'rows', 'wrap', 'tabindex');
$field_type = 'textarea';
break;
case 'replyto':
case 'reply-to':
$fname = '_replyto';
$allow_attrib = array('id', 'class', 'style', 'size', 'tabindex');
$field_type = 'textfield';
break;
}
if ($fname && !empty($_POST[$fname]))
$fvalue = get_input_value($fname, RCUBE_INPUT_POST, TRUE);
else if ($header && $compose_mode == RCUBE_COMPOSE_REPLY)
{
// get recipent address(es) out of the message headers
if ($header=='to' && !empty($MESSAGE['headers']->replyto))
$fvalue = $MESSAGE['headers']->replyto;
else if ($header=='to' && !empty($MESSAGE['headers']->from))
$fvalue = $MESSAGE['headers']->from;
// add recipent of original message if reply to all
else if ($header=='cc' && !empty($MESSAGE['reply_all']))
{
if ($v = $MESSAGE['headers']->to)
$fvalue .= $v;
if ($v = $MESSAGE['headers']->cc)
$fvalue .= (!empty($fvalue) ? ', ' : '') . $v;
}
// split recipients and put them back together in a unique way
if (!empty($fvalue))
{
$to_addresses = $IMAP->decode_address_list($fvalue);
$fvalue = '';
foreach ($to_addresses as $addr_part)
{
if (!in_array($addr_part['mailto'], $sa_recipients) && (!$MESSAGE['FROM'] || !in_array($addr_part['mailto'], $MESSAGE['FROM'])))
{
$fvalue .= (strlen($fvalue) ? ', ':'').$addr_part['string'];
$sa_recipients[] = $addr_part['mailto'];
}
}
}
}
else if ($header && $compose_mode == RCUBE_COMPOSE_DRAFT)
{
// get drafted headers
if ($header=='to' && !empty($MESSAGE['headers']->to))
$fvalue = $IMAP->decode_header($MESSAGE['headers']->to);
if ($header=='cc' && !empty($MESSAGE['headers']->cc))
$fvalue = $IMAP->decode_header($MESSAGE['headers']->cc);
if ($header=='bcc' && !empty($MESSAGE['headers']->bcc))
$fvalue = $IMAP->decode_header($MESSAGE['headers']->bcc);
}
if ($fname && $field_type)
{
// pass the following attributes to the form class
$field_attrib = array('name' => $fname);
foreach ($attrib as $attr => $value)
if (in_array($attr, $allow_attrib))
$field_attrib[$attr] = $value;
// create teaxtarea object
$input = new $field_type($field_attrib);
$out = $input->show($fvalue);
}
if ($form_start)
$out = $form_start.$out;
return $out;
}
function rcmail_compose_header_from($attrib)
{
global $IMAP, $MESSAGE, $DB, $OUTPUT, $JS_OBJECT_NAME, $compose_mode;
// pass the following attributes to the form class
$field_attrib = array('name' => '_from');
foreach ($attrib as $attr => $value)
if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex')))
$field_attrib[$attr] = $value;
// extract all recipients of the reply-message
$a_recipients = array();
if ($compose_mode == RCUBE_COMPOSE_REPLY && is_object($MESSAGE['headers']))
{
$MESSAGE['FROM'] = array();
$a_to = $IMAP->decode_address_list($MESSAGE['headers']->to);
foreach ($a_to as $addr)
{
if (!empty($addr['mailto']))
$a_recipients[] = $addr['mailto'];
}
if (!empty($MESSAGE['headers']->cc))
{
$a_cc = $IMAP->decode_address_list($MESSAGE['headers']->cc);
foreach ($a_cc as $addr)
{
if (!empty($addr['mailto']))
$a_recipients[] = $addr['mailto'];
}
}
}
// get this user's identities
$sql_result = $DB->query("SELECT identity_id, name, email, signature, html_signature
FROM ".get_table_name('identities')."
WHERE user_id=?
AND del<>1
ORDER BY ".$DB->quoteIdentifier('standard')." DESC, name ASC",
$_SESSION['user_id']);
if ($DB->num_rows($sql_result))
{
$from_id = 0;
$a_signatures = array();
$field_attrib['onchange'] = "$JS_OBJECT_NAME.change_identity(this)";
$select_from = new select($field_attrib);
while ($sql_arr = $DB->fetch_assoc($sql_result))
{
$identity_id = $sql_arr['identity_id'];
$select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $identity_id);
// add signature to array
if (!empty($sql_arr['signature']))
{
$a_signatures[$identity_id]['text'] = $sql_arr['signature'];
$a_signatures[$identity_id]['is_html'] = ($sql_arr['html_signature'] == 1) ? true : false;
if ($a_signatures[$identity_id]['is_html'])
{
$h2t = new html2text($a_signatures[$identity_id]['text'], false, false);
$plainTextPart = $h2t->get_text();
$a_signatures[$identity_id]['plain_text'] = trim($plainTextPart);
}
}
// set identity if it's one of the reply-message recipients
if (in_array($sql_arr['email'], $a_recipients))
$from_id = $sql_arr['identity_id'];
if ($compose_mode == RCUBE_COMPOSE_REPLY && is_array($MESSAGE['FROM']))
$MESSAGE['FROM'][] = $sql_arr['email'];
if ($compose_mode == RCUBE_COMPOSE_DRAFT && strstr($MESSAGE['headers']->from, $sql_arr['email']))
$from_id = $sql_arr['identity_id'];
}
// overwrite identity selection with post parameter
if (isset($_POST['_from']))
$from_id = get_input_value('_from', RCUBE_INPUT_POST);
$out = $select_from->show($from_id);
// add signatures to client
$OUTPUT->add_script(sprintf("%s.set_env('signatures', %s);", $JS_OBJECT_NAME, array2js($a_signatures)));
}
else
{
$input_from = new textfield($field_attrib);
$out = $input_from->show($_POST['_from']);
}
if ($form_start)
$out = $form_start.$out;
return $out;
}
function rcmail_compose_body($attrib)
{
global $CONFIG, $OUTPUT, $MESSAGE, $JS_OBJECT_NAME, $compose_mode;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
if (empty($attrib['id']))
$attrib['id'] = 'rcmComposeMessage';
$attrib['name'] = '_message';
if ($CONFIG['htmleditor'])
$isHtml = true;
else
$isHtml = false;
$body = '';
// use posted message body
if (!empty($_POST['_message']))
{
$body = get_input_value('_message', RCUBE_INPUT_POST, TRUE);
}
// compose reply-body
else if ($compose_mode == RCUBE_COMPOSE_REPLY)
{
$hasHtml = rcmail_has_html_part($MESSAGE['parts']);
if ($hasHtml && $CONFIG['htmleditor'])
{
$body = rcmail_first_html_part($MESSAGE);
$isHtml = true;
}
else
{
$body = rcmail_first_text_part($MESSAGE);
$isHtml = false;
}
if (strlen($body))
$body = rcmail_create_reply_body($body, $isHtml);
}
// forward message body inline
else if ($compose_mode == RCUBE_COMPOSE_FORWARD)
{
$hasHtml = rcmail_has_html_part($MESSAGE['parts']);
if ($hasHtml && $CONFIG['htmleditor'])
{
$body = rcmail_first_html_part($MESSAGE);
$isHtml = true;
}
else
{
$body = rcmail_first_text_part($MESSAGE);
$isHtml = false;
}
if (strlen($body))
$body = rcmail_create_forward_body($body, $isHtml);
}
else if ($compose_mode == RCUBE_COMPOSE_DRAFT)
{
$hasHtml = rcmail_has_html_part($MESSAGE['parts']);
if ($hasHtml && $CONFIG['htmleditor'])
{
$body = rcmail_first_html_part($MESSAGE);
$isHtml = true;
}
else
{
$body = rcmail_first_text_part($MESSAGE);
$isHtml = false;
}
if (strlen($body))
$body = rcmail_create_draft_body($body, $isHtml);
}
$OUTPUT->include_script('tiny_mce/tiny_mce.js');
$OUTPUT->include_script("editor.js");
$OUTPUT->add_script('rcmail_editor_init("$__skin_path");');
$out = $form_start ? "$form_start\n" : '';
$saveid = new hiddenfield(array('name' => '_draft_saveid', 'value' => $compose_mode==RCUBE_COMPOSE_DRAFT ? str_replace(array('<','>'), "", $MESSAGE['headers']->messageID) : ''));
$out .= $saveid->show();
$drafttoggle = new hiddenfield(array('name' => '_draft', 'value' => 'yes'));
$out .= $drafttoggle->show();
$msgtype = new hiddenfield(array('name' => '_is_html', 'value' => ($isHtml?"1":"0")));
$out .= $msgtype->show();
// If desired, set this text area to be editable by TinyMCE
if ($isHtml)
$attrib['mce_editable'] = "true";
$textarea = new textarea($attrib);
$out .= $textarea->show($body);
$out .= $form_end ? "\n$form_end" : '';
// include GoogieSpell
if (!empty($CONFIG['enable_spellcheck']) && !$isHtml)
{
$lang_set = '';
if (!empty($CONFIG['spellcheck_languages']) && is_array($CONFIG['spellcheck_languages']))
$lang_set = "googie.setLanguages(".array2js($CONFIG['spellcheck_languages']).");\n";
$OUTPUT->include_script('googiespell.js');
$OUTPUT->add_script(sprintf(
"var googie = new GoogieSpell('\$__skin_path/images/googiespell/','%s&_action=spell&lang=');\n".
"googie.lang_chck_spell = \"%s\";\n".
"googie.lang_rsm_edt = \"%s\";\n".
"googie.lang_close = \"%s\";\n".
"googie.lang_revert = \"%s\";\n".
"googie.lang_no_error_found = \"%s\";\n%s".
"googie.setCurrentLanguage('%s');\n".
"googie.decorateTextarea('%s');\n".
"%s.set_env('spellcheck', googie);",
$GLOBALS['COMM_PATH'],
JQ(Q(rcube_label('checkspelling'))),
JQ(Q(rcube_label('resumeediting'))),
JQ(Q(rcube_label('close'))),
JQ(Q(rcube_label('revertto'))),
JQ(Q(rcube_label('nospellerrors'))),
$lang_set,
substr($_SESSION['user_lang'], 0, 2),
$attrib['id'],
$JS_OBJECT_NAME), 'foot');
rcube_add_label('checking');
}
$out .= "\n".'<iframe name="savetarget" src="program/blank.gif" style="width:0;height:0;visibility:hidden;"></iframe>';
return $out;
}
function rcmail_create_reply_body($body, $bodyIsHtml)
{
global $IMAP, $MESSAGE;
if (! $bodyIsHtml)
{
// soft-wrap message first
$body = wordwrap($body, 75);
// split body into single lines
$a_lines = preg_split('/\r?\n/', $body);
// add > to each line
for($n=0; $n<sizeof($a_lines); $n++)
{
if (strpos($a_lines[$n], '>')===0)
$a_lines[$n] = '>'.$a_lines[$n];
else
$a_lines[$n] = '> '.$a_lines[$n];
}
$body = join("\n", $a_lines);
// add title line
$prefix = sprintf("\n\n\nOn %s, %s wrote:\n",
$MESSAGE['headers']->date,
$IMAP->decode_header($MESSAGE['headers']->from));
// try to remove the signature
if ($sp = strrstr($body, '-- '))
{
if ($body{$sp+3}==' ' || $body{$sp+3}=="\n" || $body{$sp+3}=="\r")
$body = substr($body, 0, $sp-1);
}
$suffix = '';
}
else
{
$prefix = sprintf("<br><br>On %s, %s wrote:<br><blockquote type=\"cite\" " .
"style=\"padding-left: 5px; border-left: #1010ff 2px solid; " .
"margin-left: 5px; width: 100%%\">",
$MESSAGE['headers']->date,
$IMAP->decode_header($MESSAGE['headers']->from));
$suffix = "</blockquote>";
}
return $prefix.$body.$suffix;
}
function rcmail_create_forward_body($body, $bodyIsHtml)
{
global $IMAP, $MESSAGE;
if (! $bodyIsHtml)
{
// soft-wrap message first
$body = wordwrap($body, 80);
$prefix = sprintf("\n\n\n-------- Original Message --------\nSubject: %s\nDate: %s\nFrom: %s\nTo: %s\n\n",
$MESSAGE['subject'],
$MESSAGE['headers']->date,
$IMAP->decode_header($MESSAGE['headers']->from),
$IMAP->decode_header($MESSAGE['headers']->to));
}
else
{
$prefix = sprintf(
"<br><br>-------- Original Message --------" .
"<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody>" .
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">Subject: </th><td>%s</td></tr>" .
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">Date: </th><td>%s</td></tr>" .
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">From: </th><td>%s</td></tr>" .
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">To: </th><td>%s</td></tr>" .
"</tbody></table><br>",
Q($MESSAGE['subject']),
Q($MESSAGE['headers']->date),
Q($IMAP->decode_header($MESSAGE['headers']->from)),
Q($IMAP->decode_header($MESSAGE['headers']->to)));
}
// add attachments
if (!isset($_SESSION['compose']['forward_attachments']) &&
is_array($MESSAGE['parts']) && sizeof($MESSAGE['parts'])>1)
rcmail_write_compose_attachments($MESSAGE);
return $prefix.$body;
}
function rcmail_create_draft_body($body, $bodyIsHtml)
{
global $IMAP, $MESSAGE;
// add attachments
if (!isset($_SESSION['compose']['forward_attachments']) &&
is_array($MESSAGE['parts']) && sizeof($MESSAGE['parts'])>1)
rcmail_write_compose_attachments($MESSAGE);
return $body;
}
function rcmail_write_compose_attachments(&$message)
{
global $IMAP, $CONFIG;
$temp_dir = unslashify($CONFIG['temp_dir']);
if (!is_array($_SESSION['compose']['attachments']))
$_SESSION['compose']['attachments'] = array();
foreach ($message['parts'] as $pid => $part)
{
if ($part->ctype_primary != 'message' && $part->ctype_primary != 'text' &&
($part->disposition=='attachment' || $part->disposition=='inline' || $part->headers['content-id'] ||
(empty($part->disposition) && ($part->d_parameters['filename'] || $part->ctype_parameters['name']))))
{
$tmp_path = tempnam($temp_dir, 'rcmAttmnt');
if ($fp = fopen($tmp_path, 'w'))
{
fwrite($fp, $IMAP->get_message_part($message['UID'], $pid, $part->encoding));
fclose($fp);
$filename = !empty($part->d_parameters['filename']) ? $part->d_parameters['filename'] :
(!empty($part->ctype_parameters['name']) ? $part->ctype_parameters['name'] :
(!empty($part->headers['content-description']) ? $part->headers['content-description'] : 'file'));
$_SESSION['compose']['attachments'][] = array(
'name' => rcube_imap::decode_mime_string($filename),
'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary,
'path' => $tmp_path
);
}
}
}
$_SESSION['compose']['forward_attachments'] = TRUE;
}
function rcmail_compose_subject($attrib)
{
global $CONFIG, $MESSAGE, $compose_mode;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
$attrib['name'] = '_subject';
$textfield = new textfield($attrib);
$subject = '';
// use subject from post
if (isset($_POST['_subject']))
$subject = get_input_value('_subject', RCUBE_INPUT_POST, TRUE);
// create a reply-subject
else if ($compose_mode == RCUBE_COMPOSE_REPLY)
{
if (eregi('^re:', $MESSAGE['subject']))
$subject = $MESSAGE['subject'];
else
$subject = 'Re: '.$MESSAGE['subject'];
}
// create a forward-subject
else if ($compose_mode == RCUBE_COMPOSE_FORWARD)
{
if (eregi('^fwd:', $MESSAGE['subject']))
$subject = $MESSAGE['subject'];
else
$subject = 'Fwd: '.$MESSAGE['subject'];
}
// creeate a draft-subject
else if ($compose_mode == RCUBE_COMPOSE_DRAFT)
$subject = $MESSAGE['subject'];
$out = $form_start ? "$form_start\n" : '';
$out .= $textfield->show($subject);
$out .= $form_end ? "\n$form_end" : '';
return $out;
}
function rcmail_compose_attachment_list($attrib)
{
global $OUTPUT, $JS_OBJECT_NAME, $CONFIG;
// add ID if not given
if (!$attrib['id'])
$attrib['id'] = 'rcmAttachmentList';
// allow the following attributes to be added to the <ul> tag
$attrib_str = create_attrib_string($attrib, array('id', 'class', 'style'));
$out = '<ul'. $attrib_str . ">\n";
if (is_array($_SESSION['compose']['attachments']))
{
if ($attrib['deleteicon'])
$button = sprintf('<img src="%s%s" alt="%s" border="0" style="padding-right:2px;vertical-align:middle" />',
$CONFIG['skin_path'],
$attrib['deleteicon'],
rcube_label('delete'));
else
$button = rcube_label('delete');
foreach ($_SESSION['compose']['attachments'] as $id => $a_prop)
$out .= sprintf('<li id="rcmfile%d"><a href="#delete" onclick="return %s.command(\'remove-attachment\',\'rcmfile%d\', this)" title="%s">%s</a>%s</li>',
$id,
$JS_OBJECT_NAME,
$id,
Q(rcube_label('delete')),
$button,
Q($a_prop['name']));
}
$OUTPUT->add_script(sprintf("%s.gui_object('attachmentlist', '%s');", $JS_OBJECT_NAME, $attrib['id']));
$out .= '</ul>';
return $out;
}
function rcmail_compose_attachment_form($attrib)
{
global $OUTPUT, $JS_OBJECT_NAME, $SESS_HIDDEN_FIELD;
// add ID if not given
if (!$attrib['id'])
$attrib['id'] = 'rcmUploadbox';
// allow the following attributes to be added to the <div> tag
$attrib_str = create_attrib_string($attrib, array('id', 'class', 'style'));
$input_field = rcmail_compose_attachment_field(array());
$label_send = rcube_label('upload');
$label_close = rcube_label('close');
$out = <<<EOF
<div$attrib_str>
<form action="./" method="post" enctype="multipart/form-data">
$SESS_HIDDEN_FIELD
$input_field<br />
<input type="button" value="$label_close" class="button" onclick="document.getElementById('$attrib[id]').style.visibility='hidden'" />
<input type="button" value="$label_send" class="button" onclick="$JS_OBJECT_NAME.command('send-attachment', this.form)" />
</form>
</div>
EOF;
$OUTPUT->add_script(sprintf("%s.gui_object('uploadbox', '%s');", $JS_OBJECT_NAME, $attrib['id']));
return $out;
}
function rcmail_compose_attachment_field($attrib)
{
// allow the following attributes to be added to the <input> tag
$attrib_str = create_attrib_string($attrib, array('id', 'class', 'style', 'size'));
$out = '<input type="file" name="_attachments[]"'. $attrib_str . " />";
return $out;
}
function rcmail_priority_selector($attrib)
{
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
$attrib['name'] = '_priority';
$selector = new select($attrib);
$selector->add(array(rcube_label('lowest'),
rcube_label('low'),
rcube_label('normal'),
rcube_label('high'),
rcube_label('highest')),
array(5, 4, 0, 2, 1));
- $sel = isset($_POST['_priority']) ? $_POST['_priority'] : 0;
+ $sel = isset($_POST['_priority']) ? $_POST['_priority'] : rcube_label('normal');
$out = $form_start ? "$form_start\n" : '';
$out .= $selector->show($sel);
$out .= $form_end ? "\n$form_end" : '';
return $out;
}
function rcmail_receipt_checkbox($attrib)
{
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
if (!isset($attrib['id']))
$attrib['id'] = 'receipt';
$attrib['name'] = '_receipt';
$attrib['value'] = '1';
$checkbox = new checkbox($attrib);
$out = $form_start ? "$form_start\n" : '';
$out .= $checkbox->show(0);
$out .= $form_end ? "\n$form_end" : '';
return $out;
}
function rcmail_editor_selector($attrib)
{
global $CONFIG, $MESSAGE, $compose_mode;
$choices = array(
'html' => 'htmltoggle',
'plain' => 'plaintoggle'
);
// determine whether HTML or plain text should be checked
if ($CONFIG['htmleditor'])
$useHtml = true;
else
$useHtml = false;
if ($compose_mode == RCUBE_COMPOSE_REPLY ||
$compose_mode == RCUBE_COMPOSE_FORWARD ||
$compose_mode == RCUBE_COMPOSE_DRAFT)
{
$hasHtml = rcmail_has_html_part($MESSAGE['parts']);
$useHtml = ($hasHtml && $CONFIG['htmleditor']);
}
$selector = '';
$attrib['name'] = '_editorSelect';
$attrib['onchange'] = 'return rcmail_toggle_editor(this)';
foreach ($choices as $value => $text)
{
$checked = '';
if ((($value == 'html') && $useHtml) ||
(($value != 'html') && !$useHtml))
$attrib['checked'] = 'true';
else
unset($attrib['checked']);
$attrib['id'] = '_' . $value;
$rb = new radiobutton($attrib);
$selector .= sprintf("<td>%s</td><td class=\"title\"><label for=\"%s\">%s</label></td>",
$rb->show($value),
$attrib['id'],
rcube_label($text));
}
return $selector;
}
function get_form_tags($attrib)
{
global $CONFIG, $OUTPUT, $JS_OBJECT_NAME, $MESSAGE_FORM, $SESS_HIDDEN_FIELD;
$form_start = '';
if (!strlen($MESSAGE_FORM))
{
$hiddenfields = new hiddenfield(array('name' => '_task', 'value' => $GLOBALS['_task']));
$hiddenfields->add(array('name' => '_action', 'value' => 'send'));
$form_start = empty($attrib['form']) ? '<form name="form" action="./" method="post">' : '';
$form_start .= "\n$SESS_HIDDEN_FIELD\n";
$form_start .= $hiddenfields->show();
}
$form_end = (strlen($MESSAGE_FORM) && !strlen($attrib['form'])) ? '</form>' : '';
$form_name = !empty($attrib['form']) ? $attrib['form'] : 'form';
if (!strlen($MESSAGE_FORM))
$OUTPUT->add_script("$JS_OBJECT_NAME.gui_object('messageform', '$form_name');");
$MESSAGE_FORM = $form_name;
return array($form_start, $form_end);
}
function format_email_recipient($email, $name='')
{
if ($name && $name != $email)
return sprintf('%s <%s>', strpos($name, ",") ? '"'.$name.'"' : $name, $email);
else
return $email;
}
function rcmail_charset_pulldown($selected='ISO-8859-1')
{
$select = new select();
return $select->show($selected);
}
/****** get contacts for this user and add them to client scripts ********/
$sql_result = $DB->query("SELECT name, email
FROM ".get_table_name('contacts')." WHERE user_id=?
AND del<>1",$_SESSION['user_id']);
if ($DB->num_rows($sql_result))
{
$a_contacts = array();
while ($sql_arr = $DB->fetch_assoc($sql_result))
if ($sql_arr['email'])
$a_contacts[] = format_email_recipient($sql_arr['email'], JQ($sql_arr['name']));
$OUTPUT->add_script(sprintf("$JS_OBJECT_NAME.set_env('contacts', %s);", array2js($a_contacts)));
}
parse_template('compose');
?>

File Metadata

Mime Type
text/x-diff
Expires
Thu, Mar 19, 8:50 AM (19 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
457970
Default Alt Text
(70 KB)

Event Timeline