summaryrefslogtreecommitdiff
path: root/program/steps
diff options
context:
space:
mode:
authoralecpl <alec@alec.pl>2010-09-29 12:36:28 +0000
committeralecpl <alec@alec.pl>2010-09-29 12:36:28 +0000
commite99991996dbb9e7b0b0ff6cfa94dc0fb2522eb66 (patch)
tree8031feaef48d8d30de1253318993f8c0a2223674 /program/steps
parentd7f9eb573b82ca55c521b68f7cf3ad8de55ab8ba (diff)
- Add Internationalized Domain Name (IDNA) support (#1483894)
Diffstat (limited to 'program/steps')
-rw-r--r--program/steps/mail/addcontact.inc4
-rw-r--r--program/steps/mail/compose.inc77
-rw-r--r--program/steps/mail/func.inc53
-rw-r--r--program/steps/mail/sendmail.inc39
-rw-r--r--program/steps/settings/edit_identity.inc4
-rw-r--r--program/steps/settings/func.inc2
-rw-r--r--program/steps/settings/save_identity.inc25
7 files changed, 128 insertions, 76 deletions
diff --git a/program/steps/mail/addcontact.inc b/program/steps/mail/addcontact.inc
index 128cb4ea3..7a2b69e3d 100644
--- a/program/steps/mail/addcontact.inc
+++ b/program/steps/mail/addcontact.inc
@@ -36,7 +36,9 @@ if (!empty($_POST['_address']) && is_object($CONTACTS))
'email' => $contact_arr[1]['mailto'],
'name' => $contact_arr[1]['name']
);
-
+
+ $contact['email'] = idn_to_utf8($contact['email']);
+
// use email address part for name
if (empty($contact['name']) || $contact['name'] == $contact['email'])
$contact['name'] = ucfirst(preg_replace('/[\.\-]/', ' ', substr($contact['email'], 0, strpos($contact['email'], '@'))));
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 521a0f7b4..d01ca36ca 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -227,14 +227,12 @@ function rcmail_compose_headers($attrib)
$fvalue = urldecode($_SESSION['mailto'][$mailto_id]);
case 'cc':
- if (!$fname)
- {
+ if (!$fname) {
$fname = '_cc';
$header = $param = 'cc';
}
case 'bcc':
- if (!$fname)
- {
+ if (!$fname) {
$fname = '_bcc';
$header = $param = 'bcc';
}
@@ -251,7 +249,7 @@ function rcmail_compose_headers($attrib)
$field_type = 'html_inputfield';
break;
}
-
+
if ($fname && !empty($_POST[$fname])) {
$fvalue = get_input_value($fname, RCUBE_INPUT_POST, TRUE);
}
@@ -262,13 +260,10 @@ function rcmail_compose_headers($attrib)
// 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))
- {
+ else if ($header=='cc' && !empty($MESSAGE->reply_all)) {
if ($v = $MESSAGE->headers->to)
$fvalue .= $v;
@@ -277,39 +272,58 @@ function rcmail_compose_headers($attrib)
}
// split recipients and put them back together in a unique way
- if (!empty($fvalue))
- {
+ if (!empty($fvalue)) {
$to_addresses = $IMAP->decode_address_list($fvalue);
$fvalue = '';
- foreach ($to_addresses as $addr_part)
- {
- if (!empty($addr_part['mailto'])
- && !in_array($addr_part['mailto'], $sa_recipients)
+ foreach ($to_addresses as $addr_part) {
+ if (empty($addr_part['mailto']))
+ continue;
+
+ $mailto = idn_to_utf8($addr_part['mailto']);
+
+ if (!in_array($mailto, $sa_recipients)
&& (!$MESSAGE->compose_from
- || !in_array_nocase($addr_part['mailto'], $MESSAGE->compose_from)
- || (count($to_addresses)==1 && $header=='to'))) // allow reply to yourself
- {
- $fvalue .= (strlen($fvalue) ? ', ':'').$addr_part['string'];
+ || !in_array_nocase($mailto, $MESSAGE->compose_from)
+ || (count($to_addresses)==1 && $header=='to')) // allow reply to yourself
+ ) {
+ if ($addr_part['name'] && $addr_part['mailto'] != $addr_part['name'])
+ $string = format_email_recipient($mailto, $addr_part['name']);
+ else
+ $string = $mailto;
+ $fvalue .= (strlen($fvalue) ? ', ':'') . $string;
$sa_recipients[] = $addr_part['mailto'];
}
}
}
}
- else if ($header && in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT)))
- {
+ else if ($header && in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) {
// get drafted headers
if ($header=='to' && !empty($MESSAGE->headers->to))
$fvalue = $MESSAGE->get_header('to');
-
- if ($header=='cc' && !empty($MESSAGE->headers->cc))
+ else if ($header=='cc' && !empty($MESSAGE->headers->cc))
$fvalue = $MESSAGE->get_header('cc');
-
- if ($header=='bcc' && !empty($MESSAGE->headers->bcc))
+ else if ($header=='bcc' && !empty($MESSAGE->headers->bcc))
$fvalue = $MESSAGE->get_header('bcc');
+
+ $addresses = $IMAP->decode_address_list($fvalue);
+ $fvalue = '';
+
+ foreach ($addresses as $addr_part) {
+ if (empty($addr_part['mailto']))
+ continue;
+
+ $mailto = idn_to_utf8($addr_part['mailto']);
+
+ if ($addr_part['name'] && $addr_part['mailto'] != $addr_part['name'])
+ $string = format_email_recipient($mailto, $addr_part['name']);
+ else
+ $string = $mailto;
+ $fvalue .= (strlen($fvalue) ? ', ':'') . $string;
+ }
}
-
+
if ($fname && $field_type)
{
// pass the following attributes to the form class
@@ -326,7 +340,7 @@ function rcmail_compose_headers($attrib)
if ($form_start)
$out = $form_start.$out;
- return $out;
+ return $out;
}
@@ -350,7 +364,7 @@ function rcmail_compose_header_from($attrib)
foreach ($a_to as $addr)
{
if (!empty($addr['mailto']))
- $a_recipients[] = mb_strtolower($addr['mailto']);
+ $a_recipients[] = mb_strtolower(idn_to_utf8($addr['mailto']));
}
if (!empty($MESSAGE->headers->cc))
@@ -359,7 +373,7 @@ function rcmail_compose_header_from($attrib)
foreach ($a_cc as $addr)
{
if (!empty($addr['mailto']))
- $a_recipients[] = mb_strtolower($addr['mailto']);
+ $a_recipients[] = mb_strtolower(idn_to_utf8($addr['mailto']));
}
}
}
@@ -377,6 +391,7 @@ function rcmail_compose_header_from($attrib)
foreach ($user_identities as $sql_arr)
{
+ $sql_arr['email'] = mb_strtolower(idn_to_utf8($sql_arr['email']));
$identity_id = $sql_arr['identity_id'];
$select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $identity_id);
@@ -401,7 +416,7 @@ function rcmail_compose_header_from($attrib)
if ($compose_mode == RCUBE_COMPOSE_DRAFT && strstr($MESSAGE->headers->from, $sql_arr['email']))
$from_id = $sql_arr['identity_id'];
// set identity if it's one of the reply-message recipients (with prio for default identity)
- else if (in_array(mb_strtolower($sql_arr['email']), $a_recipients) && (empty($from_id) || $sql_arr['standard']))
+ else if (in_array($sql_arr['email'], $a_recipients) && (empty($from_id) || $sql_arr['standard']))
$from_id = $sql_arr['identity_id'];
}
}
@@ -925,7 +940,7 @@ function rcmail_compose_subject($attrib)
$out = $form_start ? "$form_start\n" : '';
$out .= $textfield->show($subject);
$out .= $form_end ? "\n$form_end" : '';
-
+
return $out;
}
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 119a5da31..95bae0b10 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -24,7 +24,9 @@ $SENT_MBOX = $RCMAIL->config->get('sent_mbox');
$DRAFTS_MBOX = $RCMAIL->config->get('drafts_mbox');
$SEARCH_MODS_DEFAULT = array('*' => array('subject'=>1, 'from'=>1), $SENT_MBOX => array('subject'=>1, 'to'=>1), $DRAFTS_MBOX => array('subject'=>1, 'to'=>1));
-$EMAIL_ADDRESS_PATTERN = '([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9][a-z0-9\-\.]*\\.[a-z]{2,5})';
+// Simplified for IDN in Unicode
+//$EMAIL_ADDRESS_PATTERN = '([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9][a-z0-9\-\.]*\\.[a-z]{2,5})';
+$EMAIL_ADDRESS_PATTERN = '([a-z0-9][a-z0-9\-\.\+\_]*@[^.].*\\.[a-z]{2,5})';
// actions that do not require imap connection here
$NOIMAP_ACTIONS = array('addcontact', 'autocomplete', 'upload', 'display-attachment', 'remove-attachment', 'get');
@@ -1241,7 +1243,7 @@ function rcmail_alter_html_link($matches)
*/
function rcmail_address_string($input, $max=null, $linked=false, $addicon=null)
{
- global $IMAP, $RCMAIL, $PRINT_MODE, $CONFIG, $OUTPUT, $EMAIL_ADDRESS_PATTERN;
+ global $IMAP, $RCMAIL, $PRINT_MODE, $CONFIG;
static $got_writable_abook = null;
$a_parts = $IMAP->decode_address_list($input);
@@ -1259,27 +1261,40 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null)
foreach ($a_parts as $part) {
$j++;
+
+ $name = $part['name'];
+ $mailto = $part['mailto'];
+ $string = $part['string'];
+
+ // IDNA ASCII to Unicode
+ if ($name == $mailto)
+ $name = idn_to_utf8($name);
+ if ($string == $mailto)
+ $string = idn_to_utf8($string);
+ $mailto = idn_to_utf8($mailto);
+
if ($PRINT_MODE) {
- $out .= sprintf('%s &lt;%s&gt;', Q($part['name']), $part['mailto']);
+ $out .= sprintf('%s &lt;%s&gt;', Q($name), $mailto);
}
else if (check_email($part['mailto'], false)) {
if ($linked) {
$out .= html::a(array(
- 'href' => 'mailto:'.$part['mailto'],
- 'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($part['mailto'])),
- 'title' => $part['mailto'],
+ 'href' => 'mailto:'.$mailto,
+ 'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($mailto)),
+ 'title' => $mailto,
'class' => "rcmContactAddress",
),
- Q($part['name']));
+ Q($name ? $name : $mailto));
}
else {
- $out .= html::span(array('title' => $part['mailto'], 'class' => "rcmContactAddress"), Q($part['name']));
+ $out .= html::span(array('title' => $mailto, 'class' => "rcmContactAddress"),
+ Q($name ? $name : $mailto));
}
if ($addicon && $got_writable_abook) {
$out .= '&nbsp;' . html::a(array(
'href' => "#add",
- 'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, urlencode($part['string'])),
+ 'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, urlencode($string)),
'title' => rcube_label('addtoaddressbook'),
),
html::img(array(
@@ -1289,10 +1304,10 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null)
}
}
else {
- if ($part['name'])
- $out .= Q($part['name']);
- if ($part['mailto'])
- $out .= (strlen($out) ? ' ' : '') . sprintf('&lt;%s&gt;', Q($part['mailto']));
+ if ($name)
+ $out .= Q($name);
+ if ($mailto)
+ $out .= (strlen($out) ? ' ' : '') . sprintf('&lt;%s&gt;', Q($mailto));
}
if ($c>$j)
@@ -1375,7 +1390,7 @@ function rcmail_draftinfo_decode($str)
function rcmail_message_part_controls()
- {
+{
global $MESSAGE;
$part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC));
@@ -1397,12 +1412,12 @@ function rcmail_message_part_controls()
}
return $table->show($attrib);
- }
+}
function rcmail_message_part_frame($attrib)
- {
+{
global $MESSAGE;
$part = $MESSAGE->mime_parts[asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))];
@@ -1411,21 +1426,21 @@ function rcmail_message_part_frame($attrib)
$attrib['src'] = './?' . str_replace('_frame=', ($ctype_primary=='text' ? '_show=' : '_preload='), $_SERVER['QUERY_STRING']);
return html::iframe($attrib);
- }
+}
/**
* clear message composing settings
*/
function rcmail_compose_cleanup()
- {
+{
if (!isset($_SESSION['compose']))
return;
$rcmail = rcmail::get_instance();
$rcmail->plugins->exec_hook('attachments_cleanup', array());
$rcmail->session->remove('compose');
- }
+}
/**
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index 75d406b71..45afa046f 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -60,8 +60,7 @@ if (!$savedraft) {
function rcmail_encrypt_header($what)
{
global $CONFIG, $RCMAIL;
- if (!$CONFIG['http_received_header_encrypt'])
- {
+ if (!$CONFIG['http_received_header_encrypt']) {
return $what;
}
return $RCMAIL->encrypt($what);
@@ -69,30 +68,21 @@ function rcmail_encrypt_header($what)
// get identity record
function rcmail_get_identity($id)
- {
+{
global $USER, $OUTPUT;
- if ($sql_arr = $USER->get_identity($id))
- {
+ if ($sql_arr = $USER->get_identity($id)) {
$out = $sql_arr;
$out['mailto'] = $sql_arr['email'];
-
- // Special chars as defined by RFC 822 need to in quoted string (or escaped).
- if (preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $sql_arr['name']))
- $name = '"' . addcslashes($sql_arr['name'], '"') . '"';
- else
- $name = $sql_arr['name'];
-
- $out['string'] = rcube_charset_convert($name, RCMAIL_CHARSET, $OUTPUT->get_charset());
- if ($sql_arr['email'])
- $out['string'] .= ' <' . $sql_arr['email'] . '>';
+ $out['string'] = format_email_recipient($sql_arr['email'],
+ rcube_charset_convert($sql_arr['name'], RCMAIL_CHARSET, $OUTPUT->get_charset()));
return $out;
- }
-
- return FALSE;
}
+ return FALSE;
+}
+
/**
* go from this:
* <img src="http[s]://.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
@@ -146,7 +136,7 @@ function rcmail_fix_emoticon_paths(&$mime_message)
}
// parse email address input (and count addresses)
-function rcmail_email_input_format($mailto, $count=false)
+function rcmail_email_input_format($mailto, $count=false, $check=true)
{
global $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT;
@@ -163,9 +153,11 @@ function rcmail_email_input_format($mailto, $count=false)
$item = trim($item);
// address in brackets without name (do nothing)
if (preg_match('/^<\S+@\S+>$/', $item)) {
+ $item = idn_to_ascii($item);
$result[] = $item;
// address without brackets and without name (add brackets)
} else if (preg_match('/^\S+@\S+$/', $item)) {
+ $item = idn_to_ascii($item);
$result[] = '<'.$item.'>';
// address with name (handle name)
} else if (preg_match('/\S+@\S+>*$/', $item, $matches)) {
@@ -176,6 +168,7 @@ function rcmail_email_input_format($mailto, $count=false)
&& preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $name)) {
$name = '"'.addcslashes($name, '"').'"';
}
+ $address = idn_to_ascii($address);
if (!preg_match('/^<\S+@\S+>$/', $address))
$address = '<'.$address.'>';
@@ -187,7 +180,7 @@ function rcmail_email_input_format($mailto, $count=false)
// check address format
$item = trim($item, '<>');
- if ($item && !check_email($item)) {
+ if ($item && $check && !check_email($item)) {
$EMAIL_FORMAT_ERROR = $item;
return;
}
@@ -297,7 +290,7 @@ if (!empty($mailcc))
if (!empty($mailbcc))
$headers['Bcc'] = $mailbcc;
-
+
if (!empty($identity_arr['bcc'])) {
$headers['Bcc'] = ($headers['Bcc'] ? $headers['Bcc'].', ' : '') . $identity_arr['bcc'];
$RECIPIENT_COUNT ++;
@@ -319,11 +312,11 @@ if (!empty($identity_arr['organization']))
if (!empty($_POST['_replyto']))
$headers['Reply-To'] = rcmail_email_input_format(get_input_value('_replyto', RCUBE_INPUT_POST, TRUE, $message_charset));
else if (!empty($identity_arr['reply-to']))
- $headers['Reply-To'] = $identity_arr['reply-to'];
+ $headers['Reply-To'] = rcmail_email_input_format($identity_arr['reply-to'], false, true);
if (!empty($_SESSION['compose']['reply_msgid']))
$headers['In-Reply-To'] = $_SESSION['compose']['reply_msgid'];
-
+
// remember reply/forward UIDs in special headers
if (!empty($_SESSION['compose']['reply_uid']) && $savedraft)
$headers['X-Draft-Info'] = array('type' => 'reply', 'uid' => $_SESSION['compose']['reply_uid']);
diff --git a/program/steps/settings/edit_identity.inc b/program/steps/settings/edit_identity.inc
index 1a3df9555..d6af6e52c 100644
--- a/program/steps/settings/edit_identity.inc
+++ b/program/steps/settings/edit_identity.inc
@@ -94,6 +94,10 @@ function rcube_identity_form($attrib)
$form['adressing']['content']['email']['class'] = 'disabled';
}
+ $IDENTITY_RECORD['email'] = idn_to_utf8($IDENTITY_RECORD['email']);
+ $IDENTITY_RECORD['reply-to'] = idn_to_utf8($IDENTITY_RECORD['reply-to']);
+ $IDENTITY_RECORD['bcc'] = idn_to_utf8($IDENTITY_RECORD['bcc']);
+
// Allow plugins to modify identity form content
$plugin = $RCMAIL->plugins->exec_hook('identity_form', array(
'form' => $form, 'record' => $IDENTITY_RECORD));
diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc
index 196a509c1..b03947845 100644
--- a/program/steps/settings/func.inc
+++ b/program/steps/settings/func.inc
@@ -72,7 +72,7 @@ function rcmail_identities_list($attrib)
// get identities list and define 'mail' column
$list = $USER->list_identities();
foreach ($list as $idx => $row)
- $list[$idx]['mail'] = trim($row['name'] . ' <' . $row['email'] .'>');
+ $list[$idx]['mail'] = trim($row['name'] . ' <' . idn_to_utf8($row['email']) .'>');
// get all identites from DB and define list of cols to be displayed
$plugin = $RCMAIL->plugins->exec_hook('identities_list', array(
diff --git a/program/steps/settings/save_identity.inc b/program/steps/settings/save_identity.inc
index 895ddea62..313e9df4d 100644
--- a/program/steps/settings/save_identity.inc
+++ b/program/steps/settings/save_identity.inc
@@ -56,6 +56,18 @@ foreach ($a_boolean_cols as $col)
if (IDENTITIES_LEVEL == 1 || IDENTITIES_LEVEL == 3)
unset($save_data['email']);
+// Validate e-mail addresses
+foreach (array('email', 'reply-to', 'bcc') as $item) {
+ if ($email = $save_data[$item]) {
+ $ascii_email = idn_to_ascii($email);
+ if (!check_email($ascii_email, false)) {
+ // show error message
+ $OUTPUT->show_message('emailformaterror', 'error', array('email' => $email), false);
+ rcmail_overwrite_action('edit-identity');
+ return;
+ }
+ }
+}
// update an existing contact
if ($_POST['_iid'])
@@ -64,6 +76,13 @@ if ($_POST['_iid'])
$plugin = $RCMAIL->plugins->exec_hook('identity_update', array('id' => $iid, 'record' => $save_data));
$save_data = $plugin['record'];
+ if ($save_data['email'])
+ $save_data['email'] = idn_to_ascii($save_data['email']);
+ if ($save_data['bcc'])
+ $save_data['bcc'] = idn_to_ascii($save_data['bcc']);
+ if ($save_data['reply-to'])
+ $save_data['reply-to'] = idn_to_ascii($save_data['reply-to']);
+
if (!$plugin['abort'] && ($updated = $USER->update_identity($iid, $save_data)))
{
$OUTPUT->show_message('successfullysaved', 'confirmation');
@@ -74,7 +93,7 @@ if ($_POST['_iid'])
if ($_POST['_framed'])
{
// update the changed col in list
- // ...
+ // ...
}
}
else if ($plugin['abort'] || $DB->is_error())
@@ -95,6 +114,10 @@ else if (IDENTITIES_LEVEL < 2)
$plugin = $RCMAIL->plugins->exec_hook('identity_create', array('record' => $save_data));
$save_data = $plugin['record'];
+ $save_data['email'] = idn_to_ascii($save_data['email']);
+ $save_data['bcc'] = idn_to_ascii($save_data['bcc']);
+ $save_data['reply-to'] = idn_to_ascii($save_data['reply-to']);
+
if (!$plugin['abort'] && $save_data['email'] && ($insert_id = $USER->insert_identity($save_data)))
{
$OUTPUT->show_message('successfullysaved', 'confirmation', null, false);