| | |
| | | static $mbstring_list = null; |
| | | static $convert_warning = false; |
| | | static $conv = null; |
| | | |
| | | |
| | | $error = false; |
| | | |
| | | $to = empty($to) ? strtoupper(RCMAIL_CHARSET) : rcube_parse_charset($to); |
| | |
| | | '/UNICODE-1-1-*/', // RFC1641/1642 |
| | | '/^X-/', // X- prefix (e.g. X-ROMAN8 => ROMAN8) |
| | | ), '', $charset); |
| | | |
| | | if ($charset == 'BINARY') |
| | | return $charsets[$input] = null; |
| | | |
| | | # Aliases: some of them from HTML5 spec. |
| | | $aliases = array( |
| | |
| | | { |
| | | if (!$html_encode_arr) |
| | | { |
| | | $html_encode_arr = get_html_translation_table(HTML_SPECIALCHARS); |
| | | $html_encode_arr = get_html_translation_table(HTML_SPECIALCHARS); |
| | | unset($html_encode_arr['?']); |
| | | } |
| | | |
| | |
| | | } |
| | | else if ($mode=='remove') |
| | | $str = strip_tags($str); |
| | | |
| | | |
| | | $out = strtr($str, $encode_arr); |
| | | |
| | | // avoid douple quotation of & |
| | | $out = preg_replace('/&([A-Za-z]{2,6}|#[0-9]{2,4});/', '&\\1;', strtr($str, $encode_arr)); |
| | | |
| | | $out = preg_replace('/&([A-Za-z]{2,6}|#[0-9]{2,4});/', '&\\1;', $out); |
| | | |
| | | return $newlines ? nl2br($out) : $out; |
| | | } |
| | | |
| | |
| | | $replacements = new rcube_string_replacer; |
| | | |
| | | // ignore the whole block if evil styles are detected |
| | | $stripped = preg_replace('/[^a-z\(:]/', '', rcmail_xss_entity_decode($source)); |
| | | if (preg_match('/expression|behavior|url\(|import/', $stripped)) |
| | | $stripped = preg_replace('/[^a-z\(:;]/', '', rcmail_xss_entity_decode($source)); |
| | | if (preg_match('/expression|behavior|url\(|import[^a]/', $stripped)) |
| | | return '/* evil! */'; |
| | | |
| | | // remove css comments (sometimes used for some ugly hacks) |
| | |
| | | * @return string Formatted date string |
| | | */ |
| | | function format_date($date, $format=NULL) |
| | | { |
| | | { |
| | | global $CONFIG; |
| | | |
| | | $ts = NULL; |
| | |
| | | |
| | | if (empty($ts)) |
| | | return ''; |
| | | |
| | | |
| | | // get user's timezone |
| | | if ($CONFIG['timezone'] === 'auto') |
| | | $tz = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : date('Z')/3600; |
| | |
| | | |
| | | // convert time to user's timezone |
| | | $timestamp = $ts - date('Z', $ts) + ($tz * 3600); |
| | | |
| | | |
| | | // get current timestamp in user's timezone |
| | | $now = time(); // local time |
| | | $now -= (int)date('Z'); // make GMT time |
| | |
| | | $now_date = getdate($now); |
| | | |
| | | $today_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday'], $now_date['year']); |
| | | $week_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']); |
| | | $week_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']); |
| | | |
| | | // define date format depending on current time |
| | | if (!$format) { |
| | | if ($CONFIG['prettydate'] && $timestamp > $today_limit && $timestamp < $now) |
| | | return sprintf('%s %s', rcube_label('today'), date($CONFIG['date_today'] ? $CONFIG['date_today'] : 'H:i', $timestamp)); |
| | | if ($CONFIG['prettydate'] && $timestamp > $today_limit && $timestamp < $now) { |
| | | $format = $CONFIG['date_today'] ? $CONFIG['date_today'] : 'H:i'; |
| | | $today = true; |
| | | } |
| | | else if ($CONFIG['prettydate'] && $timestamp > $week_limit && $timestamp < $now) |
| | | $format = $CONFIG['date_short'] ? $CONFIG['date_short'] : 'D H:i'; |
| | | else |
| | | $format = $CONFIG['date_long'] ? $CONFIG['date_long'] : 'd.m.Y H:i'; |
| | | } |
| | | } |
| | | |
| | | // strftime() format |
| | | if (preg_match('/%[a-z]+/i', $format)) |
| | | return strftime($format, $timestamp); |
| | | if (preg_match('/%[a-z]+/i', $format)) { |
| | | $format = strftime($format, $timestamp); |
| | | return $today ? (rcube_label('today') . ' ' . $format) : $format; |
| | | } |
| | | |
| | | // parse format string manually in order to provide localized weekday and month names |
| | | // an alternative would be to convert the date() format string to fit with strftime() |
| | | $out = ''; |
| | | for($i=0; $i<strlen($format); $i++) |
| | | { |
| | | for($i=0; $i<strlen($format); $i++) { |
| | | if ($format{$i}=='\\') // skip escape chars |
| | | continue; |
| | | |
| | | |
| | | // write char "as-is" |
| | | if ($format{$i}==' ' || $format{$i-1}=='\\') |
| | | $out .= $format{$i}; |
| | |
| | | $out .= strftime('%x %X', $timestamp); |
| | | else |
| | | $out .= date($format{$i}, $timestamp); |
| | | } |
| | | |
| | | return $out; |
| | | } |
| | | |
| | | if ($today) { |
| | | $label = rcube_label('today'); |
| | | // replcae $ character with "Today" label (#1486120) |
| | | if (strpos($out, '$') !== false) { |
| | | $out = preg_replace('/\$/', $label, $out, 1); |
| | | } |
| | | else { |
| | | $out = $label . ' ' . $out; |
| | | } |
| | | } |
| | | |
| | | return $out; |
| | | } |
| | | |
| | | |
| | | /** |
| | |
| | | if (!$RCMAIL->config->get('log_logins') || !$RCMAIL->user) |
| | | return; |
| | | |
| | | $address = $_SERVER['REMOTE_ADDR']; |
| | | // append the NGINX X-Real-IP header, if set |
| | | if (!empty($_SERVER['HTTP_X_REAL_IP'])) { |
| | | $remote_ip[] = 'X-Real-IP: ' . $_SERVER['HTTP_X_REAL_IP']; |
| | | } |
| | | // append the X-Forwarded-For header, if set |
| | | if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { |
| | | $remote_ip[] = 'X-Forwarded-For: ' . $_SERVER['HTTP_X_FORWARDED_FOR']; |
| | | } |
| | | |
| | | if (!empty($remote_ip)) |
| | | $address .= '(' . implode(',', $remote_ip) . ')'; |
| | | |
| | | write_log('userlogins', sprintf('Successful login for %s (ID: %d) from %s', |
| | | $RCMAIL->user->get_username(), $RCMAIL->user->ID, $address)); |
| | | $RCMAIL->user->get_username(), $RCMAIL->user->ID, rcmail_remote_ip())); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns remote IP address and forwarded addresses if found |
| | | * |
| | | * @return string Remote IP address(es) |
| | | */ |
| | | function rcmail_remote_ip() |
| | | { |
| | | $address = $_SERVER['REMOTE_ADDR']; |
| | | |
| | | // append the NGINX X-Real-IP header, if set |
| | | if (!empty($_SERVER['HTTP_X_REAL_IP'])) { |
| | | $remote_ip[] = 'X-Real-IP: ' . $_SERVER['HTTP_X_REAL_IP']; |
| | | } |
| | | // append the X-Forwarded-For header, if set |
| | | if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { |
| | | $remote_ip[] = 'X-Forwarded-For: ' . $_SERVER['HTTP_X_FORWARDED_FOR']; |
| | | } |
| | | |
| | | if (!empty($remote_ip)) |
| | | $address .= '(' . implode(',', $remote_ip) . ')'; |
| | | |
| | | return $address; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Check whether the HTTP referer matches the current request |
| | | * |
| | | * @return boolean True if referer is the same host+path, false if not |
| | | */ |
| | | function rcube_check_referer() |
| | | { |
| | | $uri = parse_url($_SERVER['REQUEST_URI']); |
| | | $referer = parse_url(rc_request_header('Referer')); |
| | | return $referer['host'] == rc_request_header('Host') && $referer['path'] == $uri['path']; |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | return microtime(true); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * @access private |
| | |
| | | { |
| | | global $RCMAIL; |
| | | static $a_mailboxes; |
| | | |
| | | |
| | | $attrib += array('maxlength' => 100, 'realnames' => false); |
| | | |
| | | // add some labels to client |
| | | $RCMAIL->output->add_label('purgefolderconfirm', 'deletemessagesconfirm'); |
| | | |
| | | |
| | | $type = $attrib['type'] ? $attrib['type'] : 'ul'; |
| | | unset($attrib['type']); |
| | | |
| | |
| | | |
| | | // get mailbox list |
| | | $mbox_name = $RCMAIL->imap->get_mailbox_name(); |
| | | |
| | | |
| | | // build the folders tree |
| | | if (empty($a_mailboxes)) { |
| | | // get mailbox list |
| | |
| | | // allow plugins to alter the folder tree or to localize folder names |
| | | $hook = $RCMAIL->plugins->exec_hook('render_mailboxlist', array('list' => $a_mailboxes, 'delimiter' => $delimiter)); |
| | | |
| | | if ($type=='select') { |
| | | if ($type == 'select') { |
| | | $select = new html_select($attrib); |
| | | |
| | | |
| | | // add no-selection option |
| | | if ($attrib['noselection']) |
| | | $select->add(rcube_label($attrib['noselection']), '0'); |
| | | |
| | | $select->add(rcube_label($attrib['noselection']), ''); |
| | | |
| | | rcmail_render_folder_tree_select($hook['list'], $mbox_name, $attrib['maxlength'], $select, $attrib['realnames']); |
| | | $out = $select->show(); |
| | | } |
| | | else { |
| | | $js_mailboxlist = array(); |
| | | $out = html::tag('ul', $attrib, rcmail_render_folder_tree_html($hook['list'], $mbox_name, $js_mailboxlist, $attrib), html::$common_attrib); |
| | | |
| | | |
| | | $RCMAIL->output->add_gui_object('mailboxlist', $attrib['id']); |
| | | $RCMAIL->output->set_env('mailboxes', $js_mailboxlist); |
| | | $RCMAIL->output->set_env('collapsed_folders', $RCMAIL->config->get('collapsed_folders')); |
| | |
| | | function rcmail_mailbox_select($p = array()) |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | |
| | | $p += array('maxlength' => 100, 'realnames' => false); |
| | | $a_mailboxes = array(); |
| | | |
| | | foreach ($RCMAIL->imap->list_mailboxes() as $folder) |
| | | |
| | | if ($p['unsubscribed']) |
| | | $list = $RCMAIL->imap->list_unsubscribed(); |
| | | else |
| | | $list = $RCMAIL->imap->list_mailboxes(); |
| | | |
| | | foreach ($list as $folder) |
| | | if (empty($p['exceptions']) || !in_array($folder, $p['exceptions'])) |
| | | rcmail_build_folder_tree($a_mailboxes, $folder, $RCMAIL->imap->get_hierarchy_delimiter()); |
| | | |
| | |
| | | */ |
| | | function rcmail_build_folder_tree(&$arrFolders, $folder, $delm='/', $path='') |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | $pos = strpos($folder, $delm); |
| | | |
| | | if ($pos !== false) { |
| | |
| | | $currentFolder = substr($folder, 0, $pos); |
| | | |
| | | // sometimes folder has a delimiter as the last character |
| | | if (empty($subFolders)) |
| | | if (!strlen($subFolders)) |
| | | $virtual = false; |
| | | else if (!isset($arrFolders[$currentFolder])) |
| | | $virtual = true; |
| | |
| | | |
| | | $path .= $currentFolder; |
| | | |
| | | // Check \Noselect option (if options are in cache) |
| | | if (!$virtual && ($opts = $RCMAIL->imap->mailbox_options($path))) { |
| | | $virtual = in_array('\\Noselect', $opts); |
| | | } |
| | | |
| | | if (!isset($arrFolders[$currentFolder])) { |
| | | $arrFolders[$currentFolder] = array( |
| | | 'id' => $path, |
| | |
| | | else |
| | | $arrFolders[$currentFolder]['virtual'] = $virtual; |
| | | |
| | | if (!empty($subFolders)) |
| | | if (strlen($subFolders)) |
| | | rcmail_build_folder_tree($arrFolders[$currentFolder]['folders'], $subFolders, $delm, $path.$delm); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Return html for a structured list <ul> for the mailbox tree |
| | |
| | | function rcmail_render_folder_tree_html(&$arrFolders, &$mbox_name, &$jslist, $attrib, $nestLevel=0) |
| | | { |
| | | global $RCMAIL, $CONFIG; |
| | | |
| | | |
| | | $maxlength = intval($attrib['maxlength']); |
| | | $realnames = (bool)$attrib['realnames']; |
| | | $msgcounts = $RCMAIL->imap->get_cache('messagecount'); |
| | |
| | | $classes[] = 'inbox'; |
| | | else |
| | | $classes[] = '_'.asciiwords($folder_class ? $folder_class : strtolower($folder['id']), true); |
| | | |
| | | |
| | | $classes[] = $zebra_class; |
| | | |
| | | |
| | | if ($folder['id'] == $mbox_name) |
| | | $classes[] = 'selected'; |
| | | |
| | | $collapsed = preg_match('/&'.rawurlencode($folder['id']).'&/', $RCMAIL->config->get('collapsed_folders')); |
| | | $unread = $msgcounts ? intval($msgcounts[$folder['id']]['UNSEEN']) : 0; |
| | | |
| | | |
| | | if ($folder['virtual']) |
| | | $classes[] = 'virtual'; |
| | | else if ($unread) |
| | |
| | | 'style' => "position:absolute", |
| | | 'onclick' => sprintf("%s.command('collapse-folder', '%s')", JS_OBJECT_NAME, $js_name) |
| | | ), ' ') : '')); |
| | | |
| | | |
| | | $jslist[$folder_id] = array('id' => $folder['id'], 'name' => $foldername, 'virtual' => $folder['virtual']); |
| | | |
| | | |
| | | if (!empty($folder['folders'])) { |
| | | $out .= html::tag('ul', array('style' => ($collapsed ? "display:none;" : null)), |
| | | rcmail_render_folder_tree_html($folder['folders'], $mbox_name, $jslist, $attrib, $nestLevel+1)); |
| | |
| | | * @return string |
| | | */ |
| | | function rcmail_render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames=false, $nestLevel=0) |
| | | { |
| | | $idx = 0; |
| | | { |
| | | $out = ''; |
| | | foreach ($arrFolders as $key=>$folder) |
| | | { |
| | | |
| | | foreach ($arrFolders as $key=>$folder) { |
| | | if (!$realnames && ($folder_class = rcmail_folder_classname($folder['id']))) |
| | | $foldername = rcube_label($folder_class); |
| | | else |
| | | { |
| | | else { |
| | | $foldername = $folder['name']; |
| | | |
| | | |
| | | // shorten the folder name to a given length |
| | | if ($maxlength && $maxlength>1) |
| | | $foldername = abbreviate_string($foldername, $maxlength); |
| | | } |
| | | } |
| | | |
| | | $select->add(str_repeat(' ', $nestLevel*4) . $foldername, $folder['id']); |
| | | |
| | | if (!empty($folder['folders'])) |
| | | $out .= rcmail_render_folder_tree_select($folder['folders'], $mbox_name, $maxlength, $select, $realnames, $nestLevel+1); |
| | | |
| | | $idx++; |
| | | } |
| | | } |
| | | |
| | | return $out; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | |
| | | function rcmail_quota_display($attrib) |
| | | { |
| | | global $OUTPUT; |
| | | |
| | | if (!$attrib['id']) |
| | | $attrib['id'] = 'rcmquotadisplay'; |
| | | |
| | | if(isset($attrib['display'])) |
| | | $_SESSION['quota_display'] = $attrib['display']; |
| | | |
| | | $OUTPUT->add_gui_object('quotadisplay', $attrib['id']); |
| | | |
| | | $quota = rcmail_quota_content($attrib); |
| | | |
| | | $OUTPUT->add_script('$(document).ready(function(){ |
| | | rcmail.set_quota('.json_serialize($quota).')});', 'foot'); |
| | | |
| | | return html::span($attrib, ''); |
| | | } |
| | | |
| | | |
| | | function rcmail_quota_content($attrib=NULL) |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | $quota = $RCMAIL->imap->get_quota(); |
| | | $quota = $RCMAIL->plugins->exec_hook('quota', $quota); |
| | | |
| | | $quota_result = (array) $quota; |
| | | $quota_result['type'] = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : ''; |
| | | |
| | | if (!$quota['total'] && $RCMAIL->config->get('quota_zero_as_unlimited')) { |
| | | $quota_result['title'] = rcube_label('unlimited'); |
| | | $quota_result['percent'] = 0; |
| | | } |
| | | else if ($quota['total']) { |
| | | if (!isset($quota['percent'])) |
| | | $quota_result['percent'] = min(100, round(($quota['used']/max(1,$quota['total']))*100)); |
| | | |
| | | $title = sprintf('%s / %s (%.0f%%)', |
| | | show_bytes($quota['used'] * 1024), show_bytes($quota['total'] * 1024), |
| | | $quota_result['percent']); |
| | | |
| | | $quota_result['title'] = $title; |
| | | |
| | | if ($attrib['width']) |
| | | $quota_result['width'] = $attrib['width']; |
| | | if ($attrib['height']) |
| | | $quota_result['height'] = $attrib['height']; |
| | | } |
| | | else { |
| | | $quota_result['title'] = rcube_label('unknown'); |
| | | $quota_result['percent'] = 0; |
| | | } |
| | | |
| | | return $quota_result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Outputs error message according to server error/response codes |
| | | * |
| | | * @param string Fallback message label |
| | | * @param string Fallback message label arguments |
| | | * |
| | | * @return void |
| | | */ |
| | | function rcmail_display_server_error($fallback=null, $fallback_args=null) |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | $err_code = $RCMAIL->imap->get_error_code(); |
| | | $res_code = $RCMAIL->imap->get_response_code(); |
| | | |
| | | if ($res_code == rcube_imap::NOPERM) { |
| | | $RCMAIL->output->show_message('errornoperm', 'error'); |
| | | } |
| | | else if ($res_code == rcube_imap::READONLY) { |
| | | $RCMAIL->output->show_message('errorreadonly', 'error'); |
| | | } |
| | | else if ($err_code && ($err_str = $RCMAIL->imap->get_error_str())) { |
| | | $RCMAIL->output->show_message('servererrormsg', 'error', array('msg' => $err_str)); |
| | | } |
| | | else if ($fallback) { |
| | | $RCMAIL->output->show_message($fallback, 'error', $fallback_args); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Output HTML editor scripts |
| | | * |
| | |
| | | { |
| | | global $RCMAIL, $CONFIG; |
| | | |
| | | $hook = $RCMAIL->plugins->exec_hook('hmtl_editor', array('mode' => $mode)); |
| | | $hook = $RCMAIL->plugins->exec_hook('html_editor', array('mode' => $mode)); |
| | | |
| | | if ($hook['abort']) |
| | | return; |
| | |
| | | |
| | | $RCMAIL->output->include_script('tiny_mce/tiny_mce.js'); |
| | | $RCMAIL->output->include_script('editor.js'); |
| | | $RCMAIL->output->add_script('rcmail_editor_init("$__skin_path", |
| | | "'.JQ($lang).'", '.intval($CONFIG['enable_spellcheck']).', "'.$mode.'");'); |
| | | $RCMAIL->output->add_script(sprintf("rcmail_editor_init('\$__skin_path', '%s', %d, '%s');", |
| | | JQ($lang), intval($CONFIG['enable_spellcheck']), $mode), |
| | | 'foot'); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Replaces TinyMCE's emoticon images with plain-text representation |
| | | * |
| | | * @param string HTML content |
| | | * @return string HTML content |
| | | */ |
| | | function rcmail_replace_emoticons($html) |
| | | { |
| | | $emoticons = array( |
| | | '8-)' => 'smiley-cool', |
| | | ':-#' => 'smiley-foot-in-mouth', |
| | | ':-*' => 'smiley-kiss', |
| | | ':-X' => 'smiley-sealed', |
| | | ':-P' => 'smiley-tongue-out', |
| | | ':-@' => 'smiley-yell', |
| | | ":'(" => 'smiley-cry', |
| | | ':-(' => 'smiley-frown', |
| | | ':-D' => 'smiley-laughing', |
| | | ':-)' => 'smiley-smile', |
| | | ':-S' => 'smiley-undecided', |
| | | ':-$' => 'smiley-embarassed', |
| | | 'O:-)' => 'smiley-innocent', |
| | | ':-|' => 'smiley-money-mouth', |
| | | ':-O' => 'smiley-surprised', |
| | | ';-)' => 'smiley-wink', |
| | | ); |
| | | |
| | | foreach ($emoticons as $idx => $file) { |
| | | // <img title="Cry" src="http://.../program/js/tiny_mce/plugins/emotions/img/smiley-cry.gif" border="0" alt="Cry" /> |
| | | $search[] = '/<img title="[a-z ]+" src="https?:\/\/[a-z0-9_.\/-]+\/tiny_mce\/plugins\/emotions\/img\/'.$file.'.gif"[^>]+\/>/i'; |
| | | $replace[] = $idx; |
| | | } |
| | | |
| | | return preg_replace($search, $replace, $html); |
| | | } |
| | | |
| | | |
| | |
| | | * Replaces hostname variables |
| | | * |
| | | * @param string $name Hostname |
| | | * @param string $host Optional IMAP hostname |
| | | * @return string |
| | | */ |
| | | function rcube_parse_host($name) |
| | | function rcube_parse_host($name, $host='') |
| | | { |
| | | // %n - host |
| | | $n = preg_replace('/:\d+$/', '', $_SERVER['SERVER_NAME']); |
| | | // %d - domain name without first part, e.g. %d=mail.domain.tld, %m=domain.tld |
| | | $d = preg_replace('/^[^\.]+\./', '', $n); |
| | | // %h - IMAP host |
| | | $h = $_SESSION['imap_host']; |
| | | $h = $_SESSION['imap_host'] ? $_SESSION['imap_host'] : $host; |
| | | // %z - IMAP domain without first part, e.g. %h=imap.domain.tld, %z=domain.tld |
| | | $z = preg_replace('/^[^\.]+\./', '', $h); |
| | | |
| | |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | /* |
| | | * Idn_to_ascii wrapper. |
| | | * Intl/Idn modules version of this function doesn't work with e-mail address |
| | | */ |
| | | function rcube_idn_to_ascii($str) |
| | | { |
| | | return rcube_idn_convert($str, true); |
| | | } |
| | | |
| | | /* |
| | | * Idn_to_ascii wrapper. |
| | | * Intl/Idn modules version of this function doesn't work with e-mail address |
| | | */ |
| | | function rcube_idn_to_utf8($str) |
| | | { |
| | | return rcube_idn_convert($str, false); |
| | | } |
| | | |
| | | function rcube_idn_convert($input, $is_utf=false) |
| | | { |
| | | if ($at = strpos($input, '@')) { |
| | | $user = substr($input, 0, $at); |
| | | $domain = substr($input, $at+1); |
| | | } |
| | | else { |
| | | $domain = $input; |
| | | } |
| | | |
| | | $domain = $is_utf ? idn_to_ascii($domain) : idn_to_utf8($domain); |
| | | |
| | | if ($domain === false) { |
| | | return ''; |
| | | } |
| | | |
| | | return $at ? $user . '@' . $domain : $domain; |
| | | } |
| | | |
| | | |
| | |
| | | flush(); |
| | | } |
| | | } |
| | | |