Changeset e999919 in github


Ignore:
Timestamp:
Sep 29, 2010 8:36:28 AM (3 years ago)
Author:
alecpl <alec@…>
Branches:
master, HEAD, courier-fix, dev-browser-capabilities, pdo, release-0.6, release-0.7, release-0.8
Children:
a999682
Parents:
d7f9eb5
Message:
  • Add Internationalized Domain Name (IDNA) support (#1483894)
Files:
3 added
20 edited

Legend:

Unmodified
Added
Removed
  • CHANGELOG

    rd7f9eb5 re999919  
    44- Messages caching: performance improvements, fixed syncing, fixes related with #1486748 
    55- Add link to identities in compose window (#1486729) 
     6- Add Internationalized Domain Name (IDNA) support (#1483894) 
    67 
    78RELEASE 0.4.1 
  • installer/check.php

    re019f2d re999919  
    1616    'OpenSSL'   => 'openssl', 
    1717    'Mcrypt'    => 'mcrypt', 
     18    'Intl'      => 'intl', 
    1819); 
    1920 
     
    4546 
    4647$source_urls = array( 
    47     'Sockets' => 'http://www.php.net/manual/en/book.sockets.php', 
    48     'Session' => 'http://www.php.net/manual/en/book.session.php', 
    49     'PCRE' => 'http://www.php.net/manual/en/book.pcre.php', 
    50     'FileInfo' => 'http://www.php.net/manual/en/book.fileinfo.php', 
    51     'Libiconv' => 'http://www.php.net/manual/en/book.iconv.php', 
     48    'Sockets'   => 'http://www.php.net/manual/en/book.sockets.php', 
     49    'Session'   => 'http://www.php.net/manual/en/book.session.php', 
     50    'PCRE'      => 'http://www.php.net/manual/en/book.pcre.php', 
     51    'FileInfo'  => 'http://www.php.net/manual/en/book.fileinfo.php', 
     52    'Libiconv'  => 'http://www.php.net/manual/en/book.iconv.php', 
    5253    'Multibyte' => 'http://www.php.net/manual/en/book.mbstring.php', 
    53     'Mcrypt' => 'http://www.php.net/manual/en/book.mcrypt.php', 
    54     'OpenSSL' => 'http://www.php.net/manual/en/book.openssl.php', 
    55     'JSON' => 'http://www.php.net/manual/en/book.json.php', 
    56     'DOM' => 'http://www.php.net/manual/en/book.dom.php', 
    57     'PEAR' => 'http://pear.php.net', 
    58     'MDB2' => 'http://pear.php.net/package/MDB2', 
    59     'Net_SMTP' => 'http://pear.php.net/package/Net_SMTP', 
     54    'Mcrypt'    => 'http://www.php.net/manual/en/book.mcrypt.php', 
     55    'OpenSSL'   => 'http://www.php.net/manual/en/book.openssl.php', 
     56    'JSON'      => 'http://www.php.net/manual/en/book.json.php', 
     57    'DOM'       => 'http://www.php.net/manual/en/book.dom.php', 
     58    'Intl'      => 'http://www.php.net/manual/en/book.intl.php', 
     59    'PEAR'      => 'http://pear.php.net', 
     60    'MDB2'      => 'http://pear.php.net/package/MDB2', 
     61    'Net_SMTP'  => 'http://pear.php.net/package/Net_SMTP', 
    6062    'Mail_mime' => 'http://pear.php.net/package/Mail_mime', 
    6163); 
  • installer/test.php

    re019f2d re999919  
    250250  echo '<p>Trying to send email...<br />'; 
    251251 
    252   if (preg_match('/^' . $RCI->email_pattern . '$/i', trim($_POST['_from'])) && 
    253       preg_match('/^' . $RCI->email_pattern . '$/i', trim($_POST['_to']))) { 
    254  
     252  $from = idn_to_ascii(trim($_POST['_from'])); 
     253  $to   = idn_to_ascii(trim($_POST['_to'])); 
     254 
     255  if (preg_match('/^' . $RCI->email_pattern . '$/i', $from) && 
     256      preg_match('/^' . $RCI->email_pattern . '$/i', $to) 
     257  ) { 
    255258    $headers = array( 
    256       'From'    => trim($_POST['_from']), 
    257       'To'      => trim($_POST['_to']), 
     259      'From'    => $from, 
     260      'To'      => $to, 
    258261      'Subject' => 'Test message from Roundcube', 
    259262    ); 
     
    261264    $body = 'This is a test to confirm that Roundcube can send email.'; 
    262265    $smtp_response = array(); 
    263      
     266 
    264267    // send mail using configured SMTP server 
    265268    if ($RCI->getprop('smtp_server')) { 
     
    384387    $imap_port = $RCI->getprop('default_port'); 
    385388  } 
    386    
     389 
     390  $imap_host = idn_to_ascii($imap_host); 
     391  $imap_user = idn_to_ascii($_POST['_user']); 
     392 
    387393  $imap = new rcube_imap(null); 
    388   if ($imap->connect($imap_host, $_POST['_user'], $_POST['_pass'], $imap_port, $imap_ssl)) { 
     394  if ($imap->connect($imap_host, $imap_user, $_POST['_pass'], $imap_port, $imap_ssl)) { 
    389395    $RCI->pass('IMAP connect', 'SORT capability: ' . ($imap->get_capability('SORT') ? 'yes' : 'no')); 
    390396    $imap->close(); 
  • program/include/main.inc

    re019f2d re999919  
    17651765    } 
    17661766} 
    1767  
  • program/include/rcmail.php

    r6d94ab3 re999919  
    588588      $host = $a_host['host']; 
    589589      $imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null; 
    590       if(!empty($a_host['port'])) 
     590      if (!empty($a_host['port'])) 
    591591        $imap_port = $a_host['port']; 
    592592      else if ($imap_ssl && $imap_ssl != 'tls' && (!$config['default_port'] || $config['default_port'] == 143)) 
     
    619619      $this->imap_init(); 
    620620 
     621    // Here we need IDNA ASCII 
     622    // Only rcube_contacts class is using domain names in Unicode 
     623    $host = idn_to_ascii($host); 
     624    if (strpos($username, '@')) 
     625      $username = idn_to_ascii($username); 
     626 
    621627    // try IMAP login 
    622628    if (!($imap_login = $this->imap->connect($host, $username, $pass, $imap_port, $imap_ssl))) { 
  • program/include/rcube_config.php

    re019f2d re999919  
    275275     * Return the mail domain configured for the given host 
    276276     * 
    277      * @param string IMAP host 
     277     * @param string  IMAP host 
     278     * @param boolean If true, domain name will be converted to IDN ASCII 
    278279     * @return string Resolved SMTP host 
    279280     */ 
    280     public function mail_domain($host) 
     281    public function mail_domain($host, $encode=true) 
    281282    { 
    282283        $domain = $host; 
     
    289290            $domain = rcube_parse_host($this->prop['mail_domain']); 
    290291 
     292        if ($encode) 
     293            $domain = idn_to_ascii($domain); 
     294 
    291295        return $domain; 
    292296    } 
  • program/include/rcube_imap.php

    reacce9b re999919  
    35063506            $name = trim($val['name']); 
    35073507 
    3508             if (preg_match('/^[\'"]/', $name) && preg_match('/[\'"]$/', $name)) 
     3508            if ($name && preg_match('/^[\'"]/', $name) && preg_match('/[\'"]$/', $name)) 
    35093509                $name = trim($name, '\'"'); 
    35103510 
     
    35163516                $string = $name; 
    35173517 
    3518             $out[$j] = array('name' => $name, 
     3518            $out[$j] = array( 
     3519                'name'   => $name, 
    35193520                'mailto' => $address, 
    35203521                'string' => $string 
     
    39133914            } 
    39143915 
    3915             if (empty($result[$key]['name'])) 
    3916                 $result[$key]['name'] = $result[$key]['address']; 
    3917             elseif (empty($result[$key]['address'])) 
     3916//          if (empty($result[$key]['name'])) 
     3917//              $result[$key]['name'] = $result[$key]['address']; 
     3918            if (empty($result[$key]['address'])) 
    39183919                $result[$key]['address'] = $result[$key]['name']; 
    39193920        } 
  • program/include/rcube_ldap.php

    re019f2d re999919  
    100100    foreach ($this->prop['hosts'] as $host) 
    101101    { 
    102       $host = rcube_parse_host($host); 
     102      $host = idn_to_ascii(rcube_parse_host($host)); 
    103103      $this->_debug("C: Connect [$host".($this->prop['port'] ? ':'.$this->prop['port'] : '')."]"); 
    104104 
  • program/include/rcube_shared.inc

    r8603bbb re999919  
    681681} 
    682682 
     683/** 
     684 * intl replacement functions 
     685 */ 
     686 
     687if (!function_exists('idn_to_utf8')) 
     688{ 
     689    function idn_to_utf8($domain, $flags=null) 
     690    { 
     691        static $idn, $loaded; 
     692 
     693        if (!$loaded) { 
     694            $idn = new Net_IDNA2(); 
     695            $loaded = true; 
     696        } 
     697 
     698        if ($idn && $domain && preg_match('/(^|@|\.)xn--/i', $domain)) { 
     699            try { 
     700                $domain = $idn->decode($domain); 
     701            } 
     702            catch (Exception $e) { 
     703            } 
     704        } 
     705        return $domain; 
     706    } 
     707} 
     708 
     709if (!function_exists('idn_to_ascii')) 
     710{ 
     711    function idn_to_ascii($domain, $flags=null) 
     712    { 
     713        static $idn, $loaded; 
     714 
     715        if (!$loaded) { 
     716            $idn = new Net_IDNA2(); 
     717            $loaded = true; 
     718        } 
     719 
     720        if ($idn && $domain && preg_match('/[^\x20-\x7E]/', $domain)) { 
     721            try { 
     722                $domain = $idn->encode($domain); 
     723            } 
     724            catch (Exception $e) { 
     725            } 
     726        } 
     727        return $domain; 
     728    } 
     729} 
     730 
  • program/include/rcube_smtp.php

    re019f2d re999919  
    9999      $helo_host = 'localhost'; 
    100100 
     101    // IDNA Support 
     102    $smtp_host = idn_to_ascii($smtp_host); 
     103 
    101104    $this->conn = new Net_SMTP($smtp_host, $smtp_port, $helo_host); 
    102105 
     
    117120    $smtp_pass = str_replace('%p', $RCMAIL->decrypt($_SESSION['password']), $CONFIG['smtp_pass']); 
    118121    $smtp_auth_type = empty($CONFIG['smtp_auth_type']) ? NULL : $CONFIG['smtp_auth_type']; 
    119      
     122 
    120123    // attempt to authenticate to the SMTP server 
    121124    if ($smtp_user && $smtp_pass) 
    122125    { 
     126      // IDNA Support 
     127      if (strpos($smtp_user, '@')) 
     128        $smtp_user = idn_to_ascii($smtp_user); 
     129 
    123130      $result = $this->conn->auth($smtp_user, $smtp_pass, $smtp_auth_type, $use_tls); 
    124131 
  • program/include/rcube_template.php

    re019f2d re999919  
    995995        } 
    996996 
     997        // Current username is an e-mail address 
     998        if (strpos($_SESSION['username'], '@')) { 
     999            $username = $_SESSION['username']; 
     1000        } 
    9971001        // get e-mail address from default identity 
    998         if ($sql_arr = $this->app->user->get_identity()) { 
     1002        else if ($sql_arr = $this->app->user->get_identity()) { 
    9991003            $username = $sql_arr['email']; 
    10001004        } 
     
    10031007        } 
    10041008 
    1005         return $username; 
     1009        return idn_to_utf8($username); 
    10061010    } 
    10071011 
  • program/include/rcube_user.php

    re019f2d re999919  
    4545    { 
    4646        $this->db = rcmail::get_instance()->get_dbh(); 
    47      
     47 
    4848        if ($id && !$sql_arr) { 
    4949            $sql_result = $this->db->query( 
     
    122122        if (!$this->ID) 
    123123            return false; 
    124        
     124 
    125125        $config = rcmail::get_instance()->config; 
    126126        $old_prefs = (array)$this->get_prefs(); 
     
    129129        $save_prefs = $a_user_prefs + $old_prefs; 
    130130        unset($save_prefs['language']); 
    131      
     131 
    132132        // don't save prefs with default values if they haven't been changed yet 
    133133        foreach ($a_user_prefs as $key => $value) { 
     
    187187            " ORDER BY ".$this->db->quoteIdentifier('standard')." DESC, name ASC, identity_id ASC", 
    188188            $this->ID); 
    189      
     189 
    190190        while ($sql_arr = $this->db->fetch_assoc($sql_result)) { 
    191191            $result[] = $sql_arr; 
    192192        } 
    193      
     193 
    194194        return $result; 
    195195    } 
     
    209209 
    210210        $query_cols = $query_params = array(); 
    211      
     211 
    212212        foreach ((array)$data as $col => $value) { 
    213213            $query_cols[]   = $this->db->quoteIdentifier($col) . ' = ?'; 
     
    225225        call_user_func_array(array($this->db, 'query'), 
    226226            array_merge(array($sql), $query_params)); 
    227      
     227 
    228228        return $this->db->affected_rows(); 
    229229    } 
    230    
    231    
     230 
     231 
    232232    /** 
    233233     * Create a new identity record linked with this user 
     
    260260        return $this->db->insert_id('identities'); 
    261261    } 
    262    
    263    
     262 
     263 
    264264    /** 
    265265     * Mark the given identity as deleted 
     
    283283        if ($sql_arr['ident_count'] <= 1) 
    284284            return false; 
    285      
     285 
    286286        $this->db->query( 
    287287            "UPDATE ".get_table_name('identities'). 
     
    294294        return $this->db->affected_rows(); 
    295295    } 
    296    
    297    
     296 
     297 
    298298    /** 
    299299     * Make this identity the default one for this user 
     
    314314        } 
    315315    } 
    316    
    317    
     316 
     317 
    318318    /** 
    319319     * Update user's last_login timestamp 
     
    329329        } 
    330330    } 
    331    
    332    
     331 
     332 
    333333    /** 
    334334     * Clear the saved object state 
     
    339339        $this->data = null; 
    340340    } 
    341    
    342    
     341 
     342 
    343343    /** 
    344344     * Find a user record matching the given name and host 
     
    351351    { 
    352352        $dbh = rcmail::get_instance()->get_dbh(); 
    353      
     353 
    354354        // query for matching user name 
    355355        $query = "SELECT * FROM ".get_table_name('users')." WHERE mail_host = ? AND %s = ?"; 
    356356        $sql_result = $dbh->query(sprintf($query, 'username'), $host, $user); 
    357      
     357 
    358358        // query for matching alias 
    359359        if (!($sql_arr = $dbh->fetch_assoc($sql_result))) { 
     
    361361            $sql_arr = $dbh->fetch_assoc($sql_result); 
    362362        } 
    363      
     363 
    364364        // user already registered -> overwrite username 
    365365        if ($sql_arr) 
     
    368368            return false; 
    369369    } 
    370    
    371    
     370 
     371 
    372372    /** 
    373373     * Create a new user record and return a rcube_user instance 
     
    449449                $plugin = $rcmail->plugins->exec_hook('identity_create', 
    450450                        array('login' => true, 'record' => $record)); 
    451            
     451 
    452452                if (!$plugin['abort'] && $plugin['record']['email']) { 
    453453                    $rcmail->user->insert_identity($plugin['record']); 
     
    464464                'message' => "Failed to create new user"), true, false); 
    465465        } 
    466      
     466 
    467467        return $user_id ? $user_instance : false; 
    468468    } 
    469    
    470    
     469 
     470 
    471471    /** 
    472472     * Resolve username using a virtuser plugins 
  • program/js/common.js

    re019f2d re999919  
    485485{ 
    486486  if (input && window.RegExp) { 
    487     var qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'; 
    488     var dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]'; 
    489     var atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+'; 
    490     var quoted_pair = '\\x5c[\\x00-\\x7f]'; 
    491     var domain_literal = '\\x5b('+dtext+'|'+quoted_pair+')*\\x5d'; 
    492     var quoted_string = '\\x22('+qtext+'|'+quoted_pair+')*\\x22'; 
    493     var sub_domain = '('+atom+'|'+domain_literal+')'; 
    494     var word = '('+atom+'|'+quoted_string+')'; 
    495     var domain = sub_domain+'(\\x2e'+sub_domain+')*'; 
    496     var local_part = word+'(\\x2e'+word+')*'; 
    497     var addr_spec = local_part+'\\x40'+domain; 
    498     var delim = '[,;\s\n]'; 
    499     var reg1 = inline ? new RegExp('(^|<|'+delim+')'+addr_spec+'($|>|'+delim+')', 'i') : new RegExp('^'+addr_spec+'$', 'i'); 
     487    var qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]', 
     488      dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]', 
     489      atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+', 
     490      quoted_pair = '\\x5c[\\x00-\\x7f]', 
     491      quoted_string = '\\x22('+qtext+'|'+quoted_pair+')*\\x22', 
     492      // Use simplified domain matching, because we need to allow Unicode characters here 
     493      // So, e-mail address should be validated also on server side after idn_to_ascii() use 
     494      sub_domain = '[^@]+', 
     495      //domain_literal = '\\x5b('+dtext+'|'+quoted_pair+')*\\x5d', 
     496      //sub_domain = '('+atom+'|'+domain_literal+')', 
     497      word = '('+atom+'|'+quoted_string+')', 
     498      delim = '[,;\s\n]', 
     499      domain = sub_domain+'(\\x2e'+sub_domain+')*', 
     500      local_part = word+'(\\x2e'+word+')*', 
     501      addr_spec = local_part+'\\x40'+domain, 
     502      reg1 = inline ? new RegExp('(^|<|'+delim+')'+addr_spec+'($|>|'+delim+')', 'i') : new RegExp('^'+addr_spec+'$', 'i'); 
     503 
    500504    return reg1.test(input) ? true : false; 
    501505  } 
     506 
    502507  return false; 
    503508}; 
  • program/steps/mail/addcontact.inc

    re019f2d re999919  
    3737      'name' => $contact_arr[1]['name'] 
    3838    ); 
    39      
     39 
     40    $contact['email'] = idn_to_utf8($contact['email']); 
     41 
    4042    // use email address part for name 
    4143    if (empty($contact['name']) || $contact['name'] == $contact['email']) 
  • program/steps/mail/compose.inc

    re019f2d re999919  
    228228 
    229229    case 'cc': 
    230       if (!$fname) 
    231       { 
     230      if (!$fname) { 
    232231        $fname = '_cc'; 
    233232        $header = $param = 'cc'; 
    234233      } 
    235234    case 'bcc': 
    236       if (!$fname) 
    237       { 
     235      if (!$fname) { 
    238236        $fname = '_bcc'; 
    239237        $header = $param = 'bcc'; 
     
    252250      break; 
    253251  } 
    254   
     252 
    255253  if ($fname && !empty($_POST[$fname])) { 
    256254    $fvalue = get_input_value($fname, RCUBE_INPUT_POST, TRUE); 
     
    263261    if ($header=='to' && !empty($MESSAGE->headers->replyto)) 
    264262      $fvalue = $MESSAGE->headers->replyto; 
    265  
    266263    else if ($header=='to' && !empty($MESSAGE->headers->from)) 
    267264      $fvalue = $MESSAGE->headers->from; 
    268  
    269265    // add recipent of original message if reply to all 
    270     else if ($header=='cc' && !empty($MESSAGE->reply_all)) 
    271     { 
     266    else if ($header=='cc' && !empty($MESSAGE->reply_all)) { 
    272267      if ($v = $MESSAGE->headers->to) 
    273268        $fvalue .= $v; 
     
    278273 
    279274    // split recipients and put them back together in a unique way 
    280     if (!empty($fvalue)) 
    281     { 
     275    if (!empty($fvalue)) { 
    282276      $to_addresses = $IMAP->decode_address_list($fvalue); 
    283277      $fvalue = ''; 
    284278 
    285       foreach ($to_addresses as $addr_part) 
    286       { 
    287         if (!empty($addr_part['mailto']) 
    288             && !in_array($addr_part['mailto'], $sa_recipients) 
     279      foreach ($to_addresses as $addr_part) { 
     280        if (empty($addr_part['mailto'])) 
     281          continue; 
     282 
     283        $mailto = idn_to_utf8($addr_part['mailto']); 
     284 
     285        if (!in_array($mailto, $sa_recipients) 
    289286            && (!$MESSAGE->compose_from 
    290                 || !in_array_nocase($addr_part['mailto'], $MESSAGE->compose_from) 
    291                 || (count($to_addresses)==1 && $header=='to'))) // allow reply to yourself 
    292         { 
    293           $fvalue .= (strlen($fvalue) ? ', ':'').$addr_part['string']; 
     287                || !in_array_nocase($mailto, $MESSAGE->compose_from) 
     288                || (count($to_addresses)==1 && $header=='to')) // allow reply to yourself 
     289        ) { 
     290          if ($addr_part['name'] && $addr_part['mailto'] != $addr_part['name']) 
     291            $string = format_email_recipient($mailto, $addr_part['name']); 
     292          else 
     293            $string = $mailto; 
     294          $fvalue .= (strlen($fvalue) ? ', ':'') . $string; 
    294295          $sa_recipients[] = $addr_part['mailto']; 
    295296        } 
     
    297298    } 
    298299  } 
    299   else if ($header && in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) 
    300   { 
     300  else if ($header && in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) { 
    301301    // get drafted headers 
    302302    if ($header=='to' && !empty($MESSAGE->headers->to)) 
    303303      $fvalue = $MESSAGE->get_header('to'); 
    304  
    305     if ($header=='cc' && !empty($MESSAGE->headers->cc)) 
     304    else if ($header=='cc' && !empty($MESSAGE->headers->cc)) 
    306305      $fvalue = $MESSAGE->get_header('cc'); 
    307  
    308     if ($header=='bcc' && !empty($MESSAGE->headers->bcc)) 
     306    else if ($header=='bcc' && !empty($MESSAGE->headers->bcc)) 
    309307      $fvalue = $MESSAGE->get_header('bcc'); 
    310   } 
    311  
    312          
     308 
     309    $addresses = $IMAP->decode_address_list($fvalue); 
     310    $fvalue = ''; 
     311 
     312    foreach ($addresses as $addr_part) { 
     313      if (empty($addr_part['mailto'])) 
     314        continue; 
     315 
     316      $mailto = idn_to_utf8($addr_part['mailto']); 
     317 
     318      if ($addr_part['name'] && $addr_part['mailto'] != $addr_part['name']) 
     319        $string = format_email_recipient($mailto, $addr_part['name']); 
     320      else 
     321        $string = $mailto; 
     322      $fvalue .= (strlen($fvalue) ? ', ':'') . $string; 
     323    } 
     324  } 
     325 
     326 
    313327  if ($fname && $field_type) 
    314328  { 
     
    327341    $out = $form_start.$out; 
    328342 
    329   return $out;   
     343  return $out; 
    330344} 
    331345 
     
    351365    { 
    352366      if (!empty($addr['mailto'])) 
    353         $a_recipients[] = mb_strtolower($addr['mailto']); 
     367        $a_recipients[] = mb_strtolower(idn_to_utf8($addr['mailto'])); 
    354368    } 
    355369 
     
    360374      { 
    361375        if (!empty($addr['mailto'])) 
    362           $a_recipients[] = mb_strtolower($addr['mailto']); 
     376          $a_recipients[] = mb_strtolower(idn_to_utf8($addr['mailto'])); 
    363377      } 
    364378    } 
     
    378392    foreach ($user_identities as $sql_arr) 
    379393    { 
     394      $sql_arr['email'] = mb_strtolower(idn_to_utf8($sql_arr['email'])); 
    380395      $identity_id = $sql_arr['identity_id']; 
    381396      $select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $identity_id); 
     
    402417          $from_id = $sql_arr['identity_id']; 
    403418        // set identity if it's one of the reply-message recipients (with prio for default identity) 
    404         else if (in_array(mb_strtolower($sql_arr['email']), $a_recipients) && (empty($from_id) || $sql_arr['standard'])) 
     419        else if (in_array($sql_arr['email'], $a_recipients) && (empty($from_id) || $sql_arr['standard'])) 
    405420          $from_id = $sql_arr['identity_id']; 
    406421      } 
     
    926941  $out .= $textfield->show($subject); 
    927942  $out .= $form_end ? "\n$form_end" : ''; 
    928           
     943 
    929944  return $out; 
    930945} 
  • program/steps/mail/func.inc

    r2753a4c re999919  
    2525$SEARCH_MODS_DEFAULT = array('*' => array('subject'=>1, 'from'=>1), $SENT_MBOX => array('subject'=>1, 'to'=>1), $DRAFTS_MBOX => array('subject'=>1, 'to'=>1)); 
    2626 
    27 $EMAIL_ADDRESS_PATTERN = '([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9][a-z0-9\-\.]*\\.[a-z]{2,5})'; 
     27// Simplified for IDN in Unicode 
     28//$EMAIL_ADDRESS_PATTERN = '([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9][a-z0-9\-\.]*\\.[a-z]{2,5})'; 
     29$EMAIL_ADDRESS_PATTERN = '([a-z0-9][a-z0-9\-\.\+\_]*@[^.].*\\.[a-z]{2,5})'; 
    2830 
    2931// actions that do not require imap connection here 
     
    12421244function rcmail_address_string($input, $max=null, $linked=false, $addicon=null) 
    12431245{ 
    1244   global $IMAP, $RCMAIL, $PRINT_MODE, $CONFIG, $OUTPUT, $EMAIL_ADDRESS_PATTERN; 
     1246  global $IMAP, $RCMAIL, $PRINT_MODE, $CONFIG; 
    12451247  static $got_writable_abook = null; 
    12461248 
     
    12601262  foreach ($a_parts as $part) { 
    12611263    $j++; 
     1264 
     1265    $name   = $part['name']; 
     1266    $mailto = $part['mailto']; 
     1267    $string = $part['string']; 
     1268 
     1269    // IDNA ASCII to Unicode 
     1270    if ($name == $mailto) 
     1271      $name = idn_to_utf8($name); 
     1272    if ($string == $mailto) 
     1273      $string = idn_to_utf8($string); 
     1274    $mailto = idn_to_utf8($mailto); 
     1275 
    12621276    if ($PRINT_MODE) { 
    1263       $out .= sprintf('%s &lt;%s&gt;', Q($part['name']), $part['mailto']); 
     1277      $out .= sprintf('%s &lt;%s&gt;', Q($name), $mailto); 
    12641278    } 
    12651279    else if (check_email($part['mailto'], false)) { 
    12661280      if ($linked) { 
    12671281        $out .= html::a(array( 
    1268             'href' => 'mailto:'.$part['mailto'], 
    1269             'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($part['mailto'])), 
    1270             'title' => $part['mailto'], 
     1282            'href' => 'mailto:'.$mailto, 
     1283            'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($mailto)), 
     1284            'title' => $mailto, 
    12711285            'class' => "rcmContactAddress", 
    12721286          ), 
    1273         Q($part['name'])); 
     1287        Q($name ? $name : $mailto)); 
    12741288      } 
    12751289      else { 
    1276         $out .= html::span(array('title' => $part['mailto'], 'class' => "rcmContactAddress"), Q($part['name'])); 
     1290        $out .= html::span(array('title' => $mailto, 'class' => "rcmContactAddress"), 
     1291          Q($name ? $name : $mailto)); 
    12771292      } 
    12781293 
     
    12801295        $out .= '&nbsp;' . html::a(array( 
    12811296            'href' => "#add", 
    1282             'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, urlencode($part['string'])), 
     1297            'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, urlencode($string)), 
    12831298            'title' => rcube_label('addtoaddressbook'), 
    12841299          ), 
     
    12901305    } 
    12911306    else { 
    1292       if ($part['name']) 
    1293         $out .= Q($part['name']); 
    1294       if ($part['mailto']) 
    1295         $out .= (strlen($out) ? ' ' : '') . sprintf('&lt;%s&gt;', Q($part['mailto'])); 
     1307      if ($name) 
     1308        $out .= Q($name); 
     1309      if ($mailto) 
     1310        $out .= (strlen($out) ? ' ' : '') . sprintf('&lt;%s&gt;', Q($mailto)); 
    12961311    } 
    12971312 
     
    13761391 
    13771392function rcmail_message_part_controls() 
    1378   { 
     1393{ 
    13791394  global $MESSAGE; 
    13801395 
     
    13981413 
    13991414  return $table->show($attrib); 
    1400   } 
     1415} 
    14011416 
    14021417 
    14031418 
    14041419function rcmail_message_part_frame($attrib) 
    1405   { 
     1420{ 
    14061421  global $MESSAGE; 
    14071422 
     
    14121427 
    14131428  return html::iframe($attrib); 
    1414   } 
     1429} 
    14151430 
    14161431 
     
    14191434 */ 
    14201435function rcmail_compose_cleanup() 
    1421   { 
     1436{ 
    14221437  if (!isset($_SESSION['compose'])) 
    14231438    return; 
     
    14261441  $rcmail->plugins->exec_hook('attachments_cleanup', array()); 
    14271442  $rcmail->session->remove('compose'); 
    1428   } 
     1443} 
    14291444 
    14301445 
  • program/steps/mail/sendmail.inc

    re019f2d re999919  
    6161{ 
    6262  global $CONFIG, $RCMAIL; 
    63   if (!$CONFIG['http_received_header_encrypt']) 
    64   { 
     63  if (!$CONFIG['http_received_header_encrypt']) { 
    6564    return $what; 
    6665  } 
     
    7069// get identity record 
    7170function rcmail_get_identity($id) 
    72   { 
     71{ 
    7372  global $USER, $OUTPUT; 
    7473   
    75   if ($sql_arr = $USER->get_identity($id)) 
    76     { 
     74  if ($sql_arr = $USER->get_identity($id)) { 
    7775    $out = $sql_arr; 
    7876    $out['mailto'] = $sql_arr['email']; 
    79      
    80     // Special chars as defined by RFC 822 need to in quoted string (or escaped). 
    81     if (preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $sql_arr['name'])) 
    82       $name = '"' . addcslashes($sql_arr['name'], '"') . '"'; 
    83     else 
    84       $name = $sql_arr['name']; 
    85  
    86     $out['string'] = rcube_charset_convert($name, RCMAIL_CHARSET, $OUTPUT->get_charset()); 
    87     if ($sql_arr['email']) 
    88       $out['string'] .= ' <' . $sql_arr['email'] . '>'; 
     77    $out['string'] = format_email_recipient($sql_arr['email'], 
     78      rcube_charset_convert($sql_arr['name'], RCMAIL_CHARSET, $OUTPUT->get_charset())); 
    8979 
    9080    return $out; 
    91     } 
    92  
    93   return FALSE;   
    94   } 
     81  } 
     82 
     83  return FALSE; 
     84} 
    9585 
    9686/** 
     
    147137 
    148138// parse email address input (and count addresses) 
    149 function rcmail_email_input_format($mailto, $count=false) 
     139function rcmail_email_input_format($mailto, $count=false, $check=true) 
    150140{ 
    151141  global $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT; 
     
    164154    // address in brackets without name (do nothing) 
    165155    if (preg_match('/^<\S+@\S+>$/', $item)) { 
     156      $item = idn_to_ascii($item); 
    166157      $result[] = $item; 
    167158    // address without brackets and without name (add brackets) 
    168159    } else if (preg_match('/^\S+@\S+$/', $item)) { 
     160      $item = idn_to_ascii($item); 
    169161      $result[] = '<'.$item.'>'; 
    170162    // address with name (handle name) 
     
    177169          $name = '"'.addcslashes($name, '"').'"'; 
    178170      } 
     171      $address = idn_to_ascii($address); 
    179172      if (!preg_match('/^<\S+@\S+>$/', $address)) 
    180173        $address = '<'.$address.'>'; 
     
    188181    // check address format 
    189182    $item = trim($item, '<>'); 
    190     if ($item && !check_email($item)) { 
     183    if ($item && $check && !check_email($item)) { 
    191184      $EMAIL_FORMAT_ERROR = $item; 
    192185      return; 
     
    298291if (!empty($mailbcc)) 
    299292  $headers['Bcc'] = $mailbcc; 
    300    
     293 
    301294if (!empty($identity_arr['bcc'])) { 
    302295  $headers['Bcc'] = ($headers['Bcc'] ? $headers['Bcc'].', ' : '') . $identity_arr['bcc']; 
     
    320313  $headers['Reply-To'] = rcmail_email_input_format(get_input_value('_replyto', RCUBE_INPUT_POST, TRUE, $message_charset)); 
    321314else if (!empty($identity_arr['reply-to'])) 
    322   $headers['Reply-To'] = $identity_arr['reply-to']; 
     315  $headers['Reply-To'] = rcmail_email_input_format($identity_arr['reply-to'], false, true); 
    323316 
    324317if (!empty($_SESSION['compose']['reply_msgid'])) 
    325318  $headers['In-Reply-To'] = $_SESSION['compose']['reply_msgid']; 
    326    
     319 
    327320// remember reply/forward UIDs in special headers 
    328321if (!empty($_SESSION['compose']['reply_uid']) && $savedraft) 
  • program/steps/settings/edit_identity.inc

    re019f2d re999919  
    9595  } 
    9696 
     97  $IDENTITY_RECORD['email']    = idn_to_utf8($IDENTITY_RECORD['email']); 
     98  $IDENTITY_RECORD['reply-to'] = idn_to_utf8($IDENTITY_RECORD['reply-to']); 
     99  $IDENTITY_RECORD['bcc']      = idn_to_utf8($IDENTITY_RECORD['bcc']); 
     100 
    97101  // Allow plugins to modify identity form content 
    98102  $plugin = $RCMAIL->plugins->exec_hook('identity_form', array( 
  • program/steps/settings/func.inc

    re019f2d re999919  
    7373  $list = $USER->list_identities(); 
    7474  foreach ($list as $idx => $row) 
    75     $list[$idx]['mail'] = trim($row['name'] . ' <' . $row['email'] .'>'); 
     75    $list[$idx]['mail'] = trim($row['name'] . ' <' . idn_to_utf8($row['email']) .'>'); 
    7676 
    7777  // get all identites from DB and define list of cols to be displayed 
  • program/steps/settings/save_identity.inc

    re019f2d re999919  
    5757  unset($save_data['email']); 
    5858 
     59// Validate e-mail addresses 
     60foreach (array('email', 'reply-to', 'bcc') as $item) { 
     61  if ($email = $save_data[$item]) { 
     62    $ascii_email = idn_to_ascii($email); 
     63    if (!check_email($ascii_email, false)) { 
     64      // show error message 
     65      $OUTPUT->show_message('emailformaterror', 'error', array('email' => $email), false); 
     66      rcmail_overwrite_action('edit-identity'); 
     67      return; 
     68    } 
     69  } 
     70} 
    5971 
    6072// update an existing contact 
     
    6476  $plugin = $RCMAIL->plugins->exec_hook('identity_update', array('id' => $iid, 'record' => $save_data)); 
    6577  $save_data = $plugin['record']; 
     78 
     79  if ($save_data['email']) 
     80    $save_data['email'] = idn_to_ascii($save_data['email']); 
     81  if ($save_data['bcc']) 
     82    $save_data['bcc'] = idn_to_ascii($save_data['bcc']); 
     83  if ($save_data['reply-to']) 
     84    $save_data['reply-to'] = idn_to_ascii($save_data['reply-to']); 
    6685 
    6786  if (!$plugin['abort'] && ($updated = $USER->update_identity($iid, $save_data))) 
     
    7594    { 
    7695      // update the changed col in list 
    77       // ...       
     96      // ... 
    7897    } 
    7998  } 
     
    95114  $plugin = $RCMAIL->plugins->exec_hook('identity_create', array('record' => $save_data)); 
    96115  $save_data = $plugin['record']; 
     116 
     117  $save_data['email']    = idn_to_ascii($save_data['email']); 
     118  $save_data['bcc']      = idn_to_ascii($save_data['bcc']); 
     119  $save_data['reply-to'] = idn_to_ascii($save_data['reply-to']); 
    97120 
    98121  if (!$plugin['abort'] && $save_data['email'] && ($insert_id = $USER->insert_identity($save_data))) 
Note: See TracChangeset for help on using the changeset viewer.