diff options
Diffstat (limited to 'program')
146 files changed, 7288 insertions, 3278 deletions
diff --git a/program/include/bc.php b/program/include/bc.php index 0ddfb3215..a7d7b5ac1 100644 --- a/program/include/bc.php +++ b/program/include/bc.php @@ -62,7 +62,7 @@ function rcmail_url($action, $p=array(), $task=null) function rcmail_temp_gc() { - rcmail::get_instance()->temp_gc(); + rcmail::get_instance()->gc_temp(); } function rcube_charset_convert($str, $from, $to=NULL) @@ -405,6 +405,16 @@ function enriched_to_html($data) return rcube_enriched::to_html($data); } +function strip_quotes($str) +{ + return str_replace(array("'", '"'), '', $str); +} + +function strip_newlines($str) +{ + return preg_replace('/[\r\n]/', '', $str); +} + class rcube_html_page extends rcmail_html_page { } diff --git a/program/include/rcmail.php b/program/include/rcmail.php index 89f2f9647..800eddac6 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -51,6 +51,7 @@ class rcmail extends rcube */ public $action = ''; public $comm_path = './'; + public $filename = ''; private $address_books = array(); private $action_map = array(); @@ -65,12 +66,13 @@ class rcmail extends rcube /** * This implements the 'singleton' design pattern * + * @param string Environment name to run (e.g. live, dev, test) * @return rcmail The one and only instance */ - static function get_instance() + static function get_instance($env = '') { if (!self::$instance || !is_a(self::$instance, 'rcmail')) { - self::$instance = new rcmail(); + self::$instance = new rcmail($env); self::$instance->startup(); // init AFTER object was linked with self::$instance } @@ -86,6 +88,10 @@ class rcmail extends rcube { $this->init(self::INIT_WITH_DB | self::INIT_WITH_PLUGINS); + // set filename if not index.php + if (($basename = basename($_SERVER['SCRIPT_FILENAME'])) && $basename != 'index.php') + $this->filename = $basename; + // start session $this->session_init(); @@ -162,7 +168,7 @@ class rcmail extends rcube setlocale(LC_ALL, $lang . '.utf8', $lang . '.UTF-8', 'en_US.utf8', 'en_US.UTF-8'); // workaround for http://bugs.php.net/bug.php?id=18556 - if (in_array($lang, array('tr_TR', 'ku', 'az_AZ'))) { + if (version_compare(PHP_VERSION, '5.5.0', '<') && in_array($lang, array('tr_TR', 'ku', 'az_AZ'))) { setlocale(LC_CTYPE, 'en_US.utf8', 'en_US.UTF-8'); } } @@ -228,6 +234,11 @@ class rcmail extends rcube } if (!$contacts) { + // there's no default, just return + if ($default) { + return null; + } + self::raise_error(array( 'code' => 700, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, @@ -289,7 +300,7 @@ class rcmail extends rcube $list[$id] = array( 'id' => $id, 'name' => html::quote($prop['name']), - 'groups' => is_array($prop['groups']), + 'groups' => !empty($prop['groups']) || !empty($prop['group_filters']), 'readonly' => !$prop['writable'], 'hidden' => $prop['hidden'], 'autocomplete' => in_array($id, $autocomplete) @@ -719,7 +730,7 @@ class rcmail extends rcube $p['_task'] = $task; unset($p['task']); - $url = './'; + $url = './' . $this->filename; $delm = '?'; foreach (array_reverse($p) as $key => $val) { if ($val !== '' && $val !== null) { @@ -744,11 +755,6 @@ class rcmail extends rcube $book->close(); } - // before closing the database connection, write session data - if ($_SERVER['REMOTE_ADDR'] && is_object($this->session)) { - session_write_close(); - } - // write performance stats to logs/console if ($this->config->get('devel_mode')) { if (function_exists('memory_get_usage')) @@ -1325,6 +1331,7 @@ class rcmail extends rcube $realnames = (bool)$attrib['realnames']; $msgcounts = $this->storage->get_cache('messagecount'); $collapsed = $this->config->get('collapsed_folders'); + $realnames = $this->config->get('show_real_foldernames'); $out = ''; foreach ($arrFolders as $folder) { @@ -1481,8 +1488,10 @@ class rcmail extends rcube */ public function localize_foldername($name, $with_path = true) { + $realnames = $this->config->get('show_real_foldernames'); + // try to localize path of the folder - if ($with_path) { + if ($with_path && !$realnames) { $storage = $this->get_storage(); $delimiter = $storage->get_hierarchy_delimiter(); $path = explode($delimiter, $name); @@ -1499,12 +1508,11 @@ class rcmail extends rcube } } - if ($folder_class = $this->folder_classname($name)) { + if (!$realnames && ($folder_class = $this->folder_classname($name))) { return $this->gettext($folder_class); } - else { - return rcube_charset::convert($name, 'UTF7-IMAP'); - } + + return rcube_charset::convert($name, 'UTF7-IMAP'); } @@ -1559,11 +1567,7 @@ class rcmail extends rcube $quota_result = (array) $quota; $quota_result['type'] = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : ''; - if (!$quota['total'] && $this->config->get('quota_zero_as_unlimited')) { - $quota_result['title'] = $this->gettext('unlimited'); - $quota_result['percent'] = 0; - } - else if ($quota['total']) { + if ($quota['total'] > 0) { if (!isset($quota['percent'])) { $quota_result['percent'] = min(100, round(($quota['used']/max(1,$quota['total']))*100)); } @@ -1582,7 +1586,8 @@ class rcmail extends rcube } } else { - $quota_result['title'] = $this->gettext('unknown'); + $unlimited = $this->config->get('quota_zero_as_unlimited'); + $quota_result['title'] = $this->gettext($unlimited ? 'unlimited' : 'unknown'); $quota_result['percent'] = 0; } @@ -1761,7 +1766,8 @@ class rcmail extends rcube public function upload_init() { // Enable upload progress bar - if (($seconds = $this->config->get('upload_progress')) && ini_get('apc.rfc1867')) { + $rfc1867 = filter_var(ini_get('apc.rfc1867'), FILTER_VALIDATE_BOOLEAN); + if ($rfc1867 && ($seconds = $this->config->get('upload_progress'))) { if ($field_name = ini_get('apc.rfc1867_name')) { $this->output->set_env('upload_progress_name', $field_name); $this->output->set_env('upload_progress_time', (int) $seconds); diff --git a/program/include/rcmail_output_html.php b/program/include/rcmail_output_html.php index 02eef2fd1..998779509 100644 --- a/program/include/rcmail_output_html.php +++ b/program/include/rcmail_output_html.php @@ -67,11 +67,12 @@ class rcmail_output_html extends rcmail_output //$this->framed = $framed; $this->set_env('task', $task); $this->set_env('x_frame_options', $this->config->get('x_frame_options', 'sameorigin')); + $this->set_env('standard_windows', (bool) $this->config->get('standard_windows')); // add cookie info $this->set_env('cookie_domain', ini_get('session.cookie_domain')); $this->set_env('cookie_path', ini_get('session.cookie_path')); - $this->set_env('cookie_secure', ini_get('session.cookie_secure')); + $this->set_env('cookie_secure', filter_var(ini_get('session.cookie_secure'), FILTER_VALIDATE_BOOLEAN)); // load the correct skin (in case user-defined) $skin = $this->config->get('skin'); @@ -105,7 +106,6 @@ class rcmail_output_html extends rcmail_output )); } - /** * Set environment variable * @@ -121,7 +121,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Getter for the current page title * @@ -145,17 +144,17 @@ class rcmail_output_html extends rcmail_output return $title; } - /** * Set skin */ public function set_skin($skin) { $valid = false; + $path = RCUBE_INSTALL_PATH . 'skins/'; - if (!empty($skin) && is_dir('skins/'.$skin) && is_readable('skins/'.$skin)) { - $skin_path = 'skins/'.$skin; - $valid = true; + if (!empty($skin) && is_dir($path . $skin) && is_readable($path . $skin)) { + $skin_path = 'skins/' . $skin; + $valid = true; } else { $skin_path = $this->config->get('skin_path'); @@ -183,13 +182,16 @@ class rcmail_output_html extends rcmail_output $this->skin_paths[] = $skin_path; // read meta file and check for dependecies - $meta = @json_decode(@file_get_contents($skin_path.'/meta.json'), true); - if ($meta['extends'] && is_dir('skins/' . $meta['extends'])) { - $this->load_skin('skins/' . $meta['extends']); + $meta = @file_get_contents(RCUBE_INSTALL_PATH . $skin_path . '/meta.json'); + $meta = @json_decode($meta, true); + if ($meta['extends']) { + $path = RCUBE_INSTALL_PATH . 'skins/'; + if (is_dir($path . $meta['extends']) && is_readable($path . $meta['extends'])) { + $this->load_skin('skins/' . $meta['extends']); + } } } - /** * Check if a specific template exists * @@ -198,16 +200,17 @@ class rcmail_output_html extends rcmail_output */ public function template_exists($name) { - $found = false; foreach ($this->skin_paths as $skin_path) { - $filename = $skin_path . '/templates/' . $name . '.html'; - $found = (is_file($filename) && is_readable($filename)) || ($this->deprecated_templates[$name] && $this->template_exists($this->deprecated_templates[$name])); - if ($found) - break; + $filename = RCUBE_INSTALL_PATH . $skin_path . '/templates/' . $name . '.html'; + if ((is_file($filename) && is_readable($filename)) + || ($this->deprecated_templates[$name] && $this->template_exists($this->deprecated_templates[$name])) + ) { + return true; + } } - return $found; - } + return false; + } /** * Find the given file in the current skin path stack @@ -233,7 +236,6 @@ class rcmail_output_html extends rcmail_output return false; } - /** * Register a GUI object to the client script * @@ -246,7 +248,6 @@ class rcmail_output_html extends rcmail_output $this->add_script(self::JS_OBJECT_NAME.".gui_object('$obj', '$id');"); } - /** * Call a client method * @@ -262,7 +263,6 @@ class rcmail_output_html extends rcmail_output $this->js_commands[] = $cmd; } - /** * Add a localized label to the client environment */ @@ -277,7 +277,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Invoke display_message command * @@ -304,7 +303,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Delete all stored env variables and commands * @@ -327,7 +325,6 @@ class rcmail_output_html extends rcmail_output $this->body = ''; } - /** * Redirect to a certain url * @@ -343,7 +340,6 @@ class rcmail_output_html extends rcmail_output exit; } - /** * Send the request output to the client. * This will either parse a skin tempalte or send an AJAX response @@ -377,7 +373,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Process template and write to stdOut * @@ -413,7 +408,6 @@ class rcmail_output_html extends rcmail_output $this->_write($template, $this->config->get('skin_path')); } - /** * Parse a specific skin template and deliver to stdout (or return) * @@ -538,7 +532,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Return executable javascript code for all registered commands * @@ -570,7 +563,6 @@ class rcmail_output_html extends rcmail_output return $out; } - /** * Make URLs starting with a slash point to skin directory * @@ -590,7 +582,6 @@ class rcmail_output_html extends rcmail_output return $str; } - /** * Show error page and terminate script execution * @@ -625,7 +616,6 @@ class rcmail_output_html extends rcmail_output array($this, 'globals_callback'), $input); } - /** * Callback funtion for preg_replace_callback() in parse_with_globals() */ @@ -634,7 +624,6 @@ class rcmail_output_html extends rcmail_output return $GLOBALS[$matches[1]]; } - /** * Correct absolute paths in images and other tags * add timestamp to .js and .css filename @@ -646,7 +635,6 @@ class rcmail_output_html extends rcmail_output array($this, 'file_callback'), $output); } - /** * Callback function for preg_replace_callback in write() * @@ -655,7 +643,7 @@ class rcmail_output_html extends rcmail_output protected function file_callback($matches) { $file = $matches[3]; - $file[0] = preg_replace('!^/this/!', '/', $file[0]); + $file = preg_replace('!^/this/!', '/', $file); // correct absolute paths if ($file[0] == '/') { @@ -672,7 +660,6 @@ class rcmail_output_html extends rcmail_output return $matches[1] . '=' . $matches[2] . $file . $matches[4]; } - /** * Public wrapper to dipp into template parsing. * @@ -689,7 +676,6 @@ class rcmail_output_html extends rcmail_output return $input; } - /** * Parse for conditional tags * @@ -727,7 +713,6 @@ class rcmail_output_html extends rcmail_output return $input; } - /** * Determines if a given condition is met * @@ -740,7 +725,6 @@ class rcmail_output_html extends rcmail_output return $this->eval_expression($condition); } - /** * Inserts hidden field with CSRF-prevention-token into POST forms */ @@ -757,7 +741,6 @@ class rcmail_output_html extends rcmail_output return $out; } - /** * Parse & evaluate a given expression and return its result. * @@ -804,7 +787,6 @@ class rcmail_output_html extends rcmail_output return $fn($this->app, $this->browser, $this->env); } - /** * Search for special tags in input and replace them * with the appropriate content @@ -819,7 +801,6 @@ class rcmail_output_html extends rcmail_output return preg_replace_callback('/<roundcube:([-_a-z]+)\s+((?:[^>]|\\\\>)+)(?<!\\\\)>/Ui', array($this, 'xml_command'), $input); } - /** * Callback function for parsing an xml command tag * and turn it into real html content @@ -1023,12 +1004,13 @@ class rcmail_output_html extends rcmail_output } return html::quote($value); - break; + + case 'form': + return $this->form_tag($attrib); } return ''; } - /** * Include a specific file and return it's contents * @@ -1045,7 +1027,6 @@ class rcmail_output_html extends rcmail_output return $out; } - /** * Create and register a button * @@ -1201,7 +1182,6 @@ class rcmail_output_html extends rcmail_output return $out; } - /** * Link an external script file * @@ -1232,7 +1212,6 @@ class rcmail_output_html extends rcmail_output $this->script_files[$position][] = $file; } - /** * Add inline javascript code * @@ -1249,7 +1228,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Link an external css file * @@ -1260,7 +1238,6 @@ class rcmail_output_html extends rcmail_output $this->css_files[] = $file; } - /** * Add HTML code to the page header * @@ -1271,7 +1248,6 @@ class rcmail_output_html extends rcmail_output $this->header .= "\n" . $str; } - /** * Add HTML code to the page footer * To be added right befor </body> @@ -1283,7 +1259,6 @@ class rcmail_output_html extends rcmail_output $this->footer .= "\n" . $str; } - /** * Process template and write to stdOut * @@ -1408,7 +1383,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Returns iframe object, registers some related env variables * @@ -1439,7 +1413,6 @@ class rcmail_output_html extends rcmail_output /* ************* common functions delivering gui objects ************** */ - /** * Create a form tag with the necessary hidden fields * @@ -1461,12 +1434,11 @@ class rcmail_output_html extends rcmail_output $attrib['noclose'] = true; return html::tag('form', - $attrib + array('action' => "./", 'method' => "get"), + $attrib + array('action' => $this->app->comm_path, 'method' => "get"), $hidden . $content, array('id','class','style','name','method','action','enctype','onsubmit')); } - /** * Build a form tag with a unique request token * @@ -1497,7 +1469,6 @@ class rcmail_output_html extends rcmail_output return $this->form_tag($attrib, $hidden->show() . $content); } - /** * GUI object 'username' * Showing IMAP username of the current session @@ -1529,7 +1500,6 @@ class rcmail_output_html extends rcmail_output return rcube_utils::idn_to_utf8($username); } - /** * GUI object 'loginform' * Returns code for the webmail login form @@ -1629,7 +1599,6 @@ class rcmail_output_html extends rcmail_output return $out; } - /** * GUI object 'preloader' * Loads javascript code for images preloading @@ -1652,7 +1621,6 @@ class rcmail_output_html extends rcmail_output }', 'docready'); } - /** * GUI object 'searchform' * Returns code for search function @@ -1691,7 +1659,6 @@ class rcmail_output_html extends rcmail_output return $out; } - /** * Builder for GUI object 'message' * @@ -1709,7 +1676,6 @@ class rcmail_output_html extends rcmail_output return html::div($attrib, ''); } - /** * GUI object 'charsetselector' * diff --git a/program/js/app.js b/program/js/app.js index 101be65a3..45a17d640 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -44,7 +44,9 @@ function rcube_webmail() comm_path: './', blankpage: 'program/resources/blank.gif', recipients_separator: ',', - recipients_delimiter: ', ' + recipients_delimiter: ', ', + popup_width: 1150, + popup_width_small: 900 }; // create protected reference to myself @@ -189,7 +191,7 @@ function rcube_webmail() case 'mail': // enable mail commands - this.enable_command('list', 'checkmail', 'add-contact', 'search', 'reset-search', 'collapse-folder', true); + this.enable_command('list', 'checkmail', 'add-contact', 'search', 'reset-search', 'collapse-folder', 'import-messages', true); if (this.gui_objects.messagelist) { this.message_list = new rcube_list_widget(this.gui_objects.messagelist, { @@ -227,7 +229,7 @@ function rcube_webmail() this.set_button_titles(); this.env.message_commands = ['show', 'reply', 'reply-all', 'reply-list', - 'moveto', 'copy', 'delete', 'open', 'mark', 'edit', 'viewsource', + 'move', 'copy', 'delete', 'open', 'mark', 'edit', 'viewsource', 'print', 'load-attachment', 'download-attachment', 'show-headers', 'hide-headers', 'download', 'forward', 'forward-inline', 'forward-attachment', 'change-format']; @@ -253,7 +255,8 @@ function rcube_webmail() } } else if (this.env.action == 'compose') { - this.env.compose_commands = ['send-attachment', 'remove-attachment', 'send', 'cancel', 'toggle-editor', 'list-adresses', 'search', 'reset-search', 'extwin']; + this.env.address_group_stack = []; + this.env.compose_commands = ['send-attachment', 'remove-attachment', 'send', 'cancel', 'toggle-editor', 'list-adresses', 'pushgroup', 'search', 'reset-search', 'extwin']; if (this.env.drafts_mailbox) this.env.compose_commands.push('savedraft') @@ -274,12 +277,15 @@ function rcube_webmail() // init message compose form this.init_messageform(); } + else if (this.env.action == 'get') + this.enable_command('download', 'print', true); // show printing dialog - else if (this.env.action == 'print' && this.env.uid) + else if (this.env.action == 'print' && this.env.uid) { if (bw.safari) setTimeout('window.print()', 10); else window.print(); + } // get unread count for each mailbox if (this.gui_objects.mailboxlist) { @@ -320,11 +326,13 @@ function rcube_webmail() break; case 'addressbook': + this.env.address_group_stack = []; + if (this.gui_objects.folderlist) this.env.contactfolders = $.extend($.extend({}, this.env.address_sources), this.env.contactgroups); this.enable_command('add', 'import', this.env.writable_source); - this.enable_command('list', 'listgroup', 'listsearch', 'advanced-search', true); + this.enable_command('list', 'listgroup', 'pushgroup', 'popgroup', 'listsearch', 'advanced-search', true); if (this.gui_objects.contactslist) { this.contact_list = new rcube_list_widget(this.gui_objects.contactslist, @@ -368,7 +376,7 @@ function rcube_webmail() } if (this.gui_objects.qsearchbox) - this.enable_command('search', 'reset-search', 'moveto', true); + this.enable_command('search', 'reset-search', true); break; @@ -596,15 +604,16 @@ function rcube_webmail() case 'extwin': if (this.env.action == 'compose') { - var form = this.gui_objects.messageform; + var form = this.gui_objects.messageform, + win = this.open_window(''); $("input[name='_action']", form).val('compose'); form.action = this.url('mail/compose', { _id: this.env.compose_id, _extwin: 1 }); - form.target = this.open_window('', 1100, 900); + form.target = win.name; form.submit(); } else { - this.open_window(this.env.permaurl, 900, 900); + this.open_window(this.env.permaurl, true); } break; @@ -786,16 +795,18 @@ function rcube_webmail() // mail task commands case 'move': - case 'moveto': + case 'moveto': // deprecated if (this.task == 'mail') this.move_messages(props); else if (this.task == 'addressbook') - this.copy_contact(null, props); + this.move_contacts(props); break; case 'copy': if (this.task == 'mail') this.copy_messages(props); + else if (this.task == 'addressbook') + this.copy_contacts(props); break; case 'mark': @@ -857,11 +868,8 @@ function rcube_webmail() // open attachment in frame if it's of a supported mimetype if (command != 'download-attachment' && mimetype && this.env.mimetypes && $.inArray(mimetype, this.env.mimetypes) >= 0) { - var attachment_win = window.open(this.env.comm_path+'&_action=get&'+qstring+'&_frame=1', this.html_identifier('rcubemailattachment'+this.env.uid+props)); - if (attachment_win) { - setTimeout(function(){ attachment_win.focus(); }, 10); + if (this.open_window(this.env.comm_path+'&_action=get&'+qstring+'&_frame=1')) break; - } } this.goto_url('get', qstring+'&_download=1', false); @@ -1000,7 +1008,7 @@ function rcube_webmail() // Reset the auto-save timer clearTimeout(this.save_timer); - this.upload_file(props || this.gui_objects.uploadform); + this.upload_file(props || this.gui_objects.uploadform, 'upload'); break; case 'insert-sig': @@ -1044,10 +1052,12 @@ function rcube_webmail() break; case 'print': - if (uid = this.get_single_uid()) { - ref.printwin = window.open(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : '')); + if (this.env.action == 'get') { + this.gui_objects.messagepartframe.contentWindow.print(); + } + else if (uid = this.get_single_uid()) { + ref.printwin = this.open_window(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : ''), true, true); if (this.printwin) { - setTimeout(function(){ ref.printwin.focus(); }, 20); if (this.env.action != 'show') this.mark_message('read', uid); } @@ -1055,15 +1065,15 @@ function rcube_webmail() break; case 'viewsource': - if (uid = this.get_single_uid()) { - ref.sourcewin = window.open(this.env.comm_path+'&_action=viewsource&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)); - if (this.sourcewin) - setTimeout(function(){ ref.sourcewin.focus(); }, 20); - } + if (uid = this.get_single_uid()) + this.open_window(this.env.comm_path+'&_action=viewsource&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox), true, true); break; case 'download': - if (uid = this.get_single_uid()) + if (this.env.action == 'get') { + location.href = location.href.replace(/_frame=/, '_download='); + } + else if (uid = this.get_single_uid()) this.goto_url('viewsource', { _uid: uid, _mbox: this.env.mailbox, _save: 1 }); break; @@ -1100,11 +1110,31 @@ function rcube_webmail() } break; + case 'pushgroup': + // add group ID to stack + this.env.address_group_stack.push(props.id); + if (obj && event) + rcube_event.cancel(event); + case 'listgroup': this.reset_qsearch(); this.list_contacts(props.source, props.id); break; + case 'popgroup': + if (this.env.address_group_stack.length > 1) { + this.env.address_group_stack.pop(); + this.reset_qsearch(); + this.list_contacts(props.source, this.env.address_group_stack[this.env.address_group_stack.length-1]); + } + break; + + case 'import-messages': + var form = props || this.gui_objects.importform; + $('input[name="_unlock"]', form).val(this.set_busy(true, 'importwait')); + this.upload_file(form, 'import'); + break; + case 'import': if (this.env.action == 'import' && this.gui_objects.importform) { var file = document.getElementById('rcmimportfile'); @@ -1322,7 +1352,7 @@ function rcube_webmail() this.drag_menu = function(e, target) { var modkey = rcube_event.get_modifier(e), - menu = this.gui_objects.message_dragmenu; + menu = this.gui_objects.dragmenu; if (menu && modkey == SHIFT_KEY && this.commands['copy']) { var pos = rcube_event.get_mouse_pos(e); @@ -1336,7 +1366,7 @@ function rcube_webmail() this.drag_menu_action = function(action) { - var menu = this.gui_objects.message_dragmenu; + var menu = this.gui_objects.dragmenu; if (menu) { $(menu).hide(); } @@ -1451,8 +1481,12 @@ function rcube_webmail() list.draglayer.hide(); this.drag_end(e); - if (!this.drag_menu(e, target)) - this.command('moveto', target); + if (this.contact_list) { + if (!this.contacts_drag_menu(e, target)) + this.command('move', target); + } + else if (!this.drag_menu(e, target)) + this.command('move', target); } // reset 'pressed' buttons @@ -1499,7 +1533,7 @@ function rcube_webmail() } } // Multi-message commands - this.enable_command('delete', 'moveto', 'copy', 'mark', 'forward', 'forward-attachment', list.selection.length > 0); + this.enable_command('delete', 'move', 'copy', 'mark', 'forward', 'forward-attachment', list.selection.length > 0); // reset all-pages-selection if (selected || (list.selection.length && list.selection.length != list.rowcount)) @@ -1602,46 +1636,55 @@ function rcube_webmail() this.check_droptarget = function(id) { - if (this.task == 'mail') - return (this.env.mailboxes[id] && this.env.mailboxes[id].id != this.env.mailbox && !this.env.mailboxes[id].virtual) ? 1 : 0; + switch (this.task) { + case 'mail': + return (this.env.mailboxes[id] && this.env.mailboxes[id].id != this.env.mailbox && !this.env.mailboxes[id].virtual) ? 1 : 0; - if (this.task == 'settings') - return id != this.env.mailbox ? 1 : 0; + case 'settings': + return id != this.env.mailbox ? 1 : 0; - if (this.task == 'addressbook') { - if (id != this.env.source && this.env.contactfolders[id]) { - // droptarget is a group - contact add to group action - if (this.env.contactfolders[id].type == 'group') { - var target_abook = this.env.contactfolders[id].source; - if (this.env.contactfolders[id].id != this.env.group && !this.env.contactfolders[target_abook].readonly) { - // search result may contain contacts from many sources - return (this.env.selection_sources.length > 1 || $.inArray(target_abook, this.env.selection_sources) == -1) ? 2 : 1; + case 'addressbook': + var target; + if (id != this.env.source && (target = this.env.contactfolders[id])) { + // droptarget is a group + if (target.type == 'group') { + if (target.id != this.env.group && !this.env.contactfolders[target.source].readonly) { + var is_other = this.env.selection_sources.length > 1 || $.inArray(target.source, this.env.selection_sources) == -1; + return !is_other || this.commands.move ? 1 : 2; + } + } + // droptarget is a (writable) addressbook and it's not the source + else if (!target.readonly && (this.env.selection_sources.length > 1 || $.inArray(id, this.env.selection_sources) == -1)) { + return this.commands.move ? 1 : 2; } } - // droptarget is a (writable) addressbook - contact copy action - else if (!this.env.contactfolders[id].readonly) { - // search result may contain contacts from many sources - return (this.env.selection_sources.length > 1 || $.inArray(id, this.env.selection_sources) == -1) ? 2 : 0; - } - } } return 0; }; - this.open_window = function(url, width, height) + // open popup window + this.open_window = function(url, small, toolbar) { - var dh = (window.outerHeight || 0) - (window.innerHeight || 0), - dw = (window.outerWidth || 0) - (window.innerWidth || 0), - sh = screen.availHeight || screen.height, - sw = screen.availWidth || screen.width, - w = Math.min(width, sw), - h = Math.min(height, sh), - l = Math.max(0, (sw - w) / 2 + (screen.left || 0)), - t = Math.max(0, (sh - h) / 2 + (screen.top || 0)), - wname = 'rcmextwin' + new Date().getTime(), - extwin = window.open(url + (url.match(/\?/) ? '&' : '?') + '_extwin=1', wname, - 'width='+(w-dw)+',height='+(h-dh)+',top='+t+',left='+l+',resizable=yes,toolbar=no,status=no,location=no'); + var wname = 'rcmextwin' + new Date().getTime(); + + url += (url.match(/\?/) ? '&' : '?') + '_extwin=1'; + + if (this.env.standard_windows) + extwin = window.open(url, wname); + else { + var win = this.is_framed() ? parent.window : window, + page = $(win), + page_width = page.width(), + page_height = bw.mz ? $('body', win).height() : page.height(), + w = Math.min(small ? this.env.popup_width_small : this.env.popup_width, page_width), + h = page_height, // always use same height + l = (win.screenLeft || win.screenX) + 20, + t = (win.screenTop || win.screenY) + 20, + extwin = window.open(url, wname, + 'width='+w+',height='+h+',top='+t+',left='+l+',resizable=yes,location=no,scrollbars=yes' + +(toolbar ? ',toolbar=yes,menubar=yes,status=yes' : ',toolbar=no,menubar=no,status=no')); + } // write loading... message to empty windows if (!url && extwin.document) { @@ -1651,7 +1694,7 @@ function rcube_webmail() // focus window, delayed to bring to front window.setTimeout(function() { extwin.focus(); }, 10); - return wname; + return extwin; }; @@ -1945,7 +1988,7 @@ function rcube_webmail() } else { if (!preview && this.env.message_extwin && !this.env.extwin) - this.open_window(this.env.comm_path+url, 1000, 1200); + this.open_window(this.env.comm_path+url, true); else this.location_href(this.env.comm_path+url, target, true); @@ -1971,14 +2014,18 @@ function rcube_webmail() if (name && (frame = this.get_frame_element(name))) { if (!show && (win = this.get_frame_window(name))) { - if (win.location && win.location.href.indexOf(this.env.blankpage)<0) - win.location.href = this.env.blankpage; + if (win.stop) + win.stop(); + else // IE + win.document.execCommand('Stop'); + + win.location.href = this.env.blankpage; } else if (!bw.safari && !bw.konq) $(frame)[show ? 'show' : 'hide'](); } - if (!show && this.busy) + if (!show && this.env.frame_lock) this.set_busy(false, null, this.env.frame_lock); }; @@ -2106,12 +2153,12 @@ function rcube_webmail() this.clear_message_list = function() { - this.env.messages = {}; - this.last_selected = 0; + this.env.messages = {}; + this.last_selected = 0; - this.show_contentframe(false); - if (this.message_list) - this.message_list.clear(true); + this.show_contentframe(false); + if (this.message_list) + this.message_list.clear(true); }; // send remote request to load message list @@ -2556,7 +2603,7 @@ function rcube_webmail() // Hide message command buttons until a message is selected this.enable_command(this.env.message_commands, false); - this._with_selected_messages('moveto', post_data, lock); + this._with_selected_messages('move', post_data, lock); }; // delete selected messages from the current mailbox @@ -2615,7 +2662,7 @@ function rcube_webmail() this._with_selected_messages('delete', post_data); }; - // Send a specifc moveto/delete request with UIDs of all selected messages + // Send a specifc move/delete request with UIDs of all selected messages // @private this._with_selected_messages = function(action, post_data, lock) { @@ -2657,7 +2704,7 @@ function rcube_webmail() this.delete_excessive_thread_rows(); if (!lock) { - msg = action == 'moveto' ? 'movingmessage' : 'deletingmessage'; + msg = action == 'move' ? 'movingmessage' : 'deletingmessage'; lock = this.display_message(this.get_label(msg), 'loading'); } @@ -2971,11 +3018,12 @@ function rcube_webmail() // open new compose window if (this.env.compose_extwin && !this.env.extwin) { - this.open_window(url, 1150, 900); + this.open_window(url); } else { this.redirect(url); - window.resizeTo(Math.max(1150, $(window).width()), Math.max(900, $(window).height())); + if (this.env.extwin) + window.resizeTo(Math.max(this.env.popup_width, $(window).width()), $(window).height() + 24); } }; @@ -3017,7 +3065,7 @@ function rcube_webmail() this.set_caret_pos(input_message, this.env.top_posting ? 0 : $(input_message).val().length); // add signature according to selected identity // if we have HTML editor, signature is added in callback - if (input_from.prop('type') == 'select-one' && !this.env.opened_extwin) { + if (input_from.prop('type') == 'select-one') { this.change_identity(input_from[0]); } } @@ -3078,7 +3126,13 @@ function rcube_webmail() this.compose_recipient_select = function(list) { - this.enable_command('add-recipient', list.selection.length > 0); + var id, n, recipients = 0; + for (n=0; n < list.selection.length; n++) { + id = list.selection[n]; + if (this.env.contactdata[id]) + recipients++; + } + this.enable_command('add-recipient', recipients); }; this.compose_add_recipient = function(field) @@ -3348,12 +3402,54 @@ function rcube_webmail() if (!show_sig) show_sig = this.env.show_sig; - var cursor_pos, p = -1, + // first function execution + if (!this.env.identities_initialized) { + this.env.identities_initialized = true; + if (this.env.show_sig_later) + this.env.show_sig = true; + if (this.env.opened_extwin) + return; + } + + var i, rx, cursor_pos, p = -1, id = obj.options[obj.selectedIndex].value, input_message = $("[name='_message']"), message = input_message.val(), is_html = ($("input[name='_is_html']").val() == '1'), - sig = this.env.identity; + sig = this.env.identity, + delim = this.env.recipients_delimiter, + headers = ['replyto', 'bcc']; + + // update reply-to/bcc fields with addresses defined in identities + for (i in headers) { + var key = headers[i], + old_val = sig && this.env.identities[sig] ? this.env.identities[sig][key] : '', + new_val = id && this.env.identities[id] ? this.env.identities[id][key] : '', + input = $('[name="_'+key+'"]'), input_val = input.val(); + + // remove old address(es) + if (old_val && input_val) { + rx = new RegExp('\\s*' + RegExp.escape(old_val) + '\\s*'); + input_val = input_val.replace(rx, ''); + } + + // cleanup + rx = new RegExp(RegExp.escape(delim) + '\\s*' + RegExp(delim), 'g'); + input_val = input_val.replace(rx, delim) + rx = new RegExp('^\\s*' + RegExp.escape(delim) + '\\s*$'); + input_val = input_val.replace(rx, '') + + // add new address(es) + if (new_val) { + rx = new RegExp(RegExp.escape(delim) + '\\s*$'); + if (input_val && !rx.test(input_val)) + input_val += delim + ' '; + input_val += new_val + delim + ' '; + } + + if (old_val || new_val) + input.val(input_val).change(); + } // enable manual signature insert if (this.env.signatures && this.env.signatures[id]) { @@ -3453,8 +3549,8 @@ function rcube_webmail() return true; }; - // upload attachment file - this.upload_file = function(form) + // upload (attachment) file + this.upload_file = function(form, action) { if (!form) return false; @@ -3481,7 +3577,7 @@ function rcube_webmail() return; } - var frame_name = this.async_upload_form(form, 'upload', function(e) { + var frame_name = this.async_upload_form(form, action || 'upload', function(e) { var d, content = ''; try { if (this.contentDocument) { @@ -4063,7 +4159,7 @@ function rcube_webmail() if (this.preview_timer) clearTimeout(this.preview_timer); - var n, id, sid, ref = this, writable = false, + var n, id, sid, contact, ref = this, writable = false, source = this.env.source ? this.env.address_sources[this.env.source] : null; // we don't have dblclick handler here, so use 200 instead of this.dblclick_time @@ -4073,34 +4169,45 @@ function rcube_webmail() this.show_contentframe(false); if (list.selection.length) { + list.draggable = false; + // no source = search result, we'll need to detect if any of // selected contacts are in writable addressbook to enable edit/delete // we'll also need to know sources used in selection for copy // and group-addmember operations (drag&drop) this.env.selection_sources = []; - if (!source) { - for (n in list.selection) { + + if (source) { + this.env.selection_sources.push(this.env.source); + } + + for (n in list.selection) { + contact = list.data[list.selection[n]]; + if (!source) { sid = String(list.selection[n]).replace(/^[^-]+-/, ''); if (sid && this.env.address_sources[sid]) { - writable = writable || !this.env.address_sources[sid].readonly; + writable = writable || (!this.env.address_sources[sid].readonly && !contact.readonly); this.env.selection_sources.push(sid); } } - this.env.selection_sources = $.unique(this.env.selection_sources); - } - else { - this.env.selection_sources.push(this.env.source); - writable = !source.readonly; + else { + writable = writable || (!source.readonly && !contact.readonly); + } + + if (contact._type != 'group') + list.draggable = true; } + + this.env.selection_sources = $.unique(this.env.selection_sources); } // if a group is currently selected, and there is at least one contact selected // thend we can enable the group-remove-selected command - this.enable_command('group-remove-selected', this.env.group && list.selection.length > 0); + this.enable_command('group-remove-selected', this.env.group && list.selection.length > 0 && writable); this.enable_command('compose', this.env.group || list.selection.length > 0); - this.enable_command('export-selected', list.selection.length > 0); + this.enable_command('export-selected', 'copy', list.selection.length > 0); this.enable_command('edit', id && writable); - this.enable_command('delete', list.selection.length && writable); + this.enable_command('delete', 'move', list.selection.length > 0 && writable); return false; }; @@ -4128,11 +4235,29 @@ function rcube_webmail() else if (!this.env.search_request) folder = group ? 'G'+src+group : src; - this.select_folder(folder, '', true); - this.env.source = src; this.env.group = group; + // truncate groups listing stack + var index = $.inArray(this.env.group, this.env.address_group_stack); + if (index < 0) + this.env.address_group_stack = []; + else + this.env.address_group_stack = this.env.address_group_stack.slice(0,index); + + // make sure the current group is on top of the stack + if (this.env.group) { + this.env.address_group_stack.push(this.env.group); + + // mark the first group on the stack as selected in the directory list + folder = 'G'+src+this.env.address_group_stack[0]; + } + else if (this.gui_objects.addresslist_title) { + $(this.gui_objects.addresslist_title).html(this.get_label('contacts')); + } + + this.select_folder(folder, '', true); + // load contacts remotely if (this.gui_objects.contactslist) { this.list_contacts_remote(src, group, page); @@ -4187,16 +4312,38 @@ function rcube_webmail() this.list_contacts_clear = function() { + this.contact_list.data = {}; this.contact_list.clear(true); this.show_contentframe(false); - this.enable_command('delete', false); + this.enable_command('delete', 'move', 'copy', false); this.enable_command('compose', this.env.group ? true : false); }; + this.set_group_prop = function(prop) + { + if (this.gui_objects.addresslist_title) { + var boxtitle = $(this.gui_objects.addresslist_title).html(''); // clear contents + + // add link to pop back to parent group + if (this.env.address_group_stack.length > 1) { + $('<a href="#list">...</a>') + .addClass('poplink') + .appendTo(boxtitle) + .click(function(e){ return ref.command('popgroup','',this); }); + boxtitle.append(' » '); + } + + boxtitle.append($('<span>'+prop.name+'</span>')); + } + + this.triggerEvent('groupupdate', prop); + }; + // load contact record this.load_contact = function(cid, action, framed) { - var win, url = {}, target = window; + var win, url = {}, target = window, + rec = this.contact_list ? this.contact_list.data[cid] : null; if (win = this.get_frame_window(this.env.contentframe)) { url._framed = 1; @@ -4206,7 +4353,9 @@ function rcube_webmail() // load dummy content, unselect selected row(s) if (!cid) this.contact_list.clear_selection(); - this.enable_command('delete', 'compose', 'export-selected', cid); + + this.enable_command('compose', rec && rec.email); + this.enable_command('export-selected', rec && rec._type != 'group'); } else if (framed) return false; @@ -4236,14 +4385,38 @@ function rcube_webmail() this.http_post('group-'+what+'members', post_data, lock); }; - // copy a contact to the specified target (group or directory) - this.copy_contact = function(cid, to) + this.contacts_drag_menu = function(e, to) + { + var dest = to.type == 'group' ? to.source : to.id, + source = this.env.source; + + if (!this.env.address_sources[dest] || this.env.address_sources[dest].readonly) + return true; + + // search result may contain contacts from many sources, but if there is only one... + if (source == '' && this.env.selection_sources.length == 1) + source = this.env.selection_sources[0]; + + if (to.type == 'group' && dest == source) { + var cid = this.contact_list.get_selection().join(','); + this.group_member_change('add', cid, dest, to.id); + return true; + } + // move action is not possible, "redirect" to copy if menu wasn't requested + else if (!this.commands.move && rcube_event.get_modifier(e) != SHIFT_KEY) { + this.copy_contacts(to); + return true; + } + + return this.drag_menu(e, to); + }; + + // copy contact(s) to the specified target (group or directory) + this.copy_contacts = function(to) { var n, dest = to.type == 'group' ? to.source : to.id, source = this.env.source, - group = this.env.group ? this.env.group : ''; - - if (!cid) + group = this.env.group ? this.env.group : '', cid = this.contact_list.get_selection().join(','); if (!cid || !this.env.address_sources[dest] || this.env.address_sources[dest].readonly) @@ -4256,13 +4429,12 @@ function rcube_webmail() // tagret is a group if (to.type == 'group') { if (dest == source) - this.group_member_change('add', cid, dest, to.id); - else { - var lock = this.display_message(this.get_label('copyingcontact'), 'loading'), - post_data = {_cid: cid, _source: this.env.source, _to: dest, _togid: to.id, _gid: group}; + return; - this.http_post('copy', post_data, lock); - } + var lock = this.display_message(this.get_label('copyingcontact'), 'loading'), + post_data = {_cid: cid, _source: this.env.source, _to: dest, _togid: to.id, _gid: group}; + + this.http_post('copy', post_data, lock); } // target is an addressbook else if (to.id != source) { @@ -4273,19 +4445,53 @@ function rcube_webmail() } }; + // move contact(s) to the specified target (group or directory) + this.move_contacts = function(to) + { + var dest = to.type == 'group' ? to.source : to.id, + source = this.env.source, + group = this.env.group ? this.env.group : ''; + + if (!this.env.address_sources[dest] || this.env.address_sources[dest].readonly) + return; + + // search result may contain contacts from many sources, but if there is only one... + if (source == '' && this.env.selection_sources.length == 1) + source = this.env.selection_sources[0]; + + if (to.type == 'group') { + if (dest == source) + return; + + this._with_selected_contacts('move', {_to: dest, _togid: to.id}); + } + // target is an addressbook + else if (to.id != source) + this._with_selected_contacts('move', {_to: to.id}); + }; + + // delete contact(s) this.delete_contacts = function() { - var selection = this.contact_list.get_selection(), - undelete = this.env.source && this.env.address_sources[this.env.source].undelete; + var undelete = this.env.source && this.env.address_sources[this.env.source].undelete; - // exit if no mailbox specified or if selection is empty - if (!(selection.length || this.env.cid) || (!undelete && !confirm(this.get_label('deletecontactconfirm')))) + if (!undelete && !confirm(this.get_label('deletecontactconfirm'))) return; - var id, n, a_cids = [], - post_data = {_source: this.env.source, _from: (this.env.action ? this.env.action : '')}, - lock = this.display_message(this.get_label('contactdeleting'), 'loading'); + return this._with_selected_contacts('delete'); + }; + this._with_selected_contacts = function(action, post_data) + { + var selection = this.contact_list ? this.contact_list.get_selection() : []; + + // exit if no mailbox specified or if selection is empty + if (!selection.length && !this.env.cid) + return; + + var n, a_cids = [], + label = action == 'delete' ? 'contactdeleting' : 'movingcontact', + lock = this.display_message(this.get_label(label), 'loading'); if (this.env.cid) a_cids.push(this.env.cid); else { @@ -4300,6 +4506,11 @@ function rcube_webmail() this.show_contentframe(false); } + if (!post_data) + post_data = {}; + + post_data._source = this.env.source; + post_data._from = this.env.action; post_data._cid = a_cids.join(','); if (this.env.group) @@ -4310,13 +4521,13 @@ function rcube_webmail() post_data._search = this.env.search_request; // send request to server - this.http_post('delete', post_data, lock) + this.http_post(action, post_data, lock) return true; }; // update a contact record in the list - this.update_contact_row = function(cid, cols_arr, newcid, source) + this.update_contact_row = function(cid, cols_arr, newcid, source, data) { var c, row, list = this.contact_list; @@ -4330,10 +4541,11 @@ function rcube_webmail() } list.update_row(cid, cols_arr, newcid, true); + list.data[cid] = data; }; // add row to contacts list - this.add_contact_row = function(cid, cols, classes) + this.add_contact_row = function(cid, cols, classes, data) { if (!this.gui_objects.contactslist) return false; @@ -4355,6 +4567,8 @@ function rcube_webmail() row.cols.push(col); } + // store data in list member + list.data[cid] = data; list.insert_row(row); this.enable_command('export', list.rowcount > 0); @@ -5765,14 +5979,14 @@ function rcube_webmail() for (c=0, len=repl.length; c < len; c++) { cell = document.createElement('td'); - cell.innerHTML = repl[c].html; + cell.innerHTML = repl[c].html || ''; if (repl[c].id) cell.id = repl[c].id; if (repl[c].className) cell.className = repl[c].className; tr.appendChild(cell); } th.appendChild(tr); thead.parentNode.replaceChild(th, thead); - thead = th; + list.thead = thead = th; } for (n=0, len=this.env.coltypes.length; n<len; n++) { @@ -6182,7 +6396,7 @@ function rcube_webmail() this.enable_command('export-selected', false); } - case 'moveto': + case 'move': if (this.env.action == 'show') { // re-enable commands on move/delete error this.enable_command(this.env.message_commands, true); @@ -6223,6 +6437,7 @@ function rcube_webmail() if ((response.action == 'list' || response.action == 'search') && this.message_list) { this.msglist_select(this.message_list); + this.message_list.resize(); this.triggerEvent('listupdate', { folder:this.env.mailbox, rowcount:this.message_list.rowcount }); } } @@ -6233,6 +6448,7 @@ function rcube_webmail() this.enable_command('search-create', this.env.source == ''); this.enable_command('search-delete', this.env.search_id); this.update_group_commands(); + this.contact_list.resize(); this.triggerEvent('listupdate', { folder:this.env.source, rowcount:this.contact_list.rowcount }); } } @@ -6394,9 +6610,10 @@ function rcube_webmail() url: ref.url(ref.env.filedrop.action||'upload', { _id:ref.env.compose_id||ref.env.cid||'', _uploadid:ts, _remote:1 }), contentType: formdata ? false : 'multipart/form-data; boundary=' + boundary, processData: false, + timeout: 0, // disable default timeout set in ajaxSetup() data: formdata || multipart, headers: {'X-Roundcube-Request': ref.env.request_token}, - beforeSend: function(xhr, s) { if (!formdata && xhr.sendAsBinary) xhr.send = xhr.sendAsBinary; }, + xhr: function() { var xhr = jQuery.ajaxSettings.xhr(); if (!formdata && xhr.sendAsBinary) xhr.send = xhr.sendAsBinary; return xhr; }, success: function(data){ ref.http_response(data); }, error: function(o, status, err) { ref.http_error(o, status, err, null, 'attachment'); } }); @@ -6436,7 +6653,7 @@ function rcube_webmail() multipart += '; filename="' + (f.name_bin || file.name) + '"' + crlf; multipart += 'Content-Length: ' + file.size + crlf; multipart += 'Content-Type: ' + file.type + crlf + crlf; - multipart += e.target.result + crlf; + multipart += reader.result + crlf; multipart += dashdash + boundary + crlf; if (j == last) // we're done, submit the data diff --git a/program/js/common.js b/program/js/common.js index 53dce8cc2..de07ec131 100644 --- a/program/js/common.js +++ b/program/js/common.js @@ -251,7 +251,7 @@ remove_listener: function(p) }, /** - * Prevent event propagation and bubbeling + * Prevent event propagation and bubbling */ cancel: function(evt) { @@ -371,117 +371,6 @@ triggerEvent: function(evt, e) }; // end rcube_event_engine.prototype - -/** - * Roundcube generic layer (floating box) class - * - * @constructor - */ -function rcube_layer(id, attributes) -{ - this.name = id; - - // create a new layer in the current document - this.create = function(arg) - { - var l = (arg.x) ? arg.x : 0, - t = (arg.y) ? arg.y : 0, - w = arg.width, - h = arg.height, - z = arg.zindex, - vis = arg.vis, - parent = arg.parent, - obj = document.createElement('DIV'); - - obj.id = this.name; - obj.style.position = 'absolute'; - obj.style.visibility = (vis) ? (vis==2) ? 'inherit' : 'visible' : 'hidden'; - obj.style.left = l+'px'; - obj.style.top = t+'px'; - if (w) - obj.style.width = w.toString().match(/\%$/) ? w : w+'px'; - if (h) - obj.style.height = h.toString().match(/\%$/) ? h : h+'px'; - if (z) - obj.style.zIndex = z; - - if (parent) - parent.appendChild(obj); - else - document.body.appendChild(obj); - - this.elm = obj; - }; - - // create new layer - if (attributes != null) { - this.create(attributes); - this.name = this.elm.id; - } - else // just refer to the object - this.elm = document.getElementById(id); - - if (!this.elm) - return false; - - - // ********* layer object properties ********* - - this.css = this.elm.style; - this.event = this.elm; - this.width = this.elm.offsetWidth; - this.height = this.elm.offsetHeight; - this.x = parseInt(this.elm.offsetLeft); - this.y = parseInt(this.elm.offsetTop); - this.visible = (this.css.visibility=='visible' || this.css.visibility=='show' || this.css.visibility=='inherit') ? true : false; - - - // ********* layer object methods ********* - - // move the layer to a specific position - this.move = function(x, y) - { - this.x = x; - this.y = y; - this.css.left = Math.round(this.x)+'px'; - this.css.top = Math.round(this.y)+'px'; - }; - - // change the layers width and height - this.resize = function(w,h) - { - this.css.width = w+'px'; - this.css.height = h+'px'; - this.width = w; - this.height = h; - }; - - // show or hide the layer - this.show = function(a) - { - if(a == 1) { - this.css.visibility = 'visible'; - this.visible = true; - } - else if(a == 2) { - this.css.visibility = 'inherit'; - this.visible = true; - } - else { - this.css.visibility = 'hidden'; - this.visible = false; - } - }; - - // write new content into a Layer - this.write = function(cont) - { - this.elm.innerHTML = cont; - }; - -}; - - // check if input is a valid email address // By Cal Henderson <cal@iamcal.com> // http://code.iamcal.com/php/rfc822/ @@ -536,7 +425,7 @@ function rcube_clone_object(obj) for (var key in obj) { if (obj[key] && typeof obj[key] === 'object') - out[key] = clone_object(obj[key]); + out[key] = rcube_clone_object(obj[key]); else out[key] = obj[key]; } diff --git a/program/js/editor.js b/program/js/editor.js index 3782de869..e403d1f63 100644 --- a/program/js/editor.js +++ b/program/js/editor.js @@ -41,7 +41,7 @@ function rcmail_editor_init(config) $.extend(conf, { plugins: 'paste,tabfocus', theme_advanced_buttons1: 'bold,italic,underline,strikethrough,justifyleft,justifycenter,justifyright,justifyfull,separator,outdent,indent,charmap,hr,link,unlink,code,forecolor', - theme_advanced_buttons2: ',fontselect,fontsizeselect' + theme_advanced_buttons2: 'fontselect,fontsizeselect' }); else { // mail compose $.extend(conf, { @@ -80,7 +80,7 @@ function rcmail_editor_callback() if (rcmail.env.default_font) $(tinyMCE.get(rcmail.env.composebody).getBody()).css('font-family', rcmail.env.default_font); - if (elem && elem.type == 'select-one' && !rcmail.env.opened_extwin) { + if (elem && elem.type == 'select-one') { rcmail.change_identity(elem); // Focus previously focused element if (fe && fe.id != rcmail.env.composebody) { diff --git a/program/js/list.js b/program/js/list.js index 8b8a7196e..08e4444e1 100644 --- a/program/js/list.js +++ b/program/js/list.js @@ -33,6 +33,7 @@ function rcube_list_widget(list, p) this.tagname = this.list ? this.list.nodeName.toLowerCase() : 'table'; this.thead; this.tbody; + this.fixed_header; this.frame = null; this.rows = []; this.selection = []; @@ -152,6 +153,14 @@ init_header: function() if (this.thead) { this.colcount = 0; + if (this.fixed_header) { // copy (modified) fixed header back to the actual table + $(this.list.tHead).replaceWith($(this.fixed_header).find('thead').clone()); + $(this.list.tHead).find('tr td').attr('style', ''); // remove fixed widths + } + else if (this.list.className.indexOf('fixedheader') >= 0) { + this.init_fixed_header(); + } + var col, r, p = this; // add events for list columns moving if (this.column_movable && this.thead && this.thead.rows) { @@ -166,6 +175,47 @@ init_header: function() } }, +init_fixed_header: function() +{ + var clone = $(this.list.tHead).clone(); + + if (!this.fixed_header) { + this.fixed_header = $('<table>') + .attr('class', this.list.className + ' fixedcopy') + .css({ position:'fixed' }) + .append(clone) + .append('<tbody></tbody>'); + $(this.list).before(this.fixed_header); + + var me = this; + $(window).resize(function(){ me.resize() }); + } + else { + $(this.fixed_header).find('thead').replaceWith(clone); + } + + this.thead = clone.get(0); + this.resize(); +}, + +resize: function() +{ + if (!this.fixed_header) + return; + + var column_widths = []; + + // get column widths from original thead + $(this.tbody).parent().find('thead tr td').each(function(index) { + column_widths[index] = $(this).width(); + }); + + // apply fixed widths to fixed table header + $(this.thead).parent().width($(this.tbody).parent().width()); + $(this.thead).find('tr td').each(function(index) { + $(this).css('width', column_widths[index]); + }); +}, /** * Remove all list rows @@ -494,6 +544,7 @@ collapse: function(row) new_row = new_row.nextSibling; } + this.resize(); this.triggerEvent('listupdate'); return false; }, @@ -542,6 +593,7 @@ expand: function(row) new_row = new_row.nextSibling; } + this.resize(); this.triggerEvent('listupdate'); return false; }, @@ -585,6 +637,7 @@ collapse_all: function(row) new_row = new_row.nextSibling; } + this.resize(); this.triggerEvent('listupdate'); return false; }, @@ -623,6 +676,7 @@ expand_all: function(row) new_row = new_row.nextSibling; } + this.resize(); this.triggerEvent('listupdate'); return false; }, @@ -1531,6 +1585,9 @@ column_replace: function(from, to) else if (this.subject_col > from && to >= this.subject_col) this.subject_col--; + if (this.fixed_header) + this.init_header(); + this.triggerEvent('column_replace'); } diff --git a/program/lib/Mail/mime.php b/program/lib/Mail/mime.php index 69a032cb8..e079af7e9 100644 --- a/program/lib/Mail/mime.php +++ b/program/lib/Mail/mime.php @@ -48,7 +48,7 @@ * @author Aleksander Machniak <alec@php.net> * @copyright 2003-2006 PEAR <pear-group@php.net> * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @version Release: 1.8.7 + * @version CVS: $Id$ * @link http://pear.php.net/package/Mail_mime * * This class is based on HTML Mime Mail class from @@ -89,7 +89,7 @@ require_once 'Mail/mimePart.php'; * @author Sean Coates <sean@php.net> * @copyright 2003-2006 PEAR <pear-group@php.net> * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @version Release: 1.8.7 + * @version Release: @package_version@ * @link http://pear.php.net/package/Mail_mime */ class Mail_mime @@ -254,6 +254,7 @@ class Mail_mime $this->_txtbody .= $cont; } } + return true; } @@ -347,7 +348,7 @@ class Mail_mime } if (!$content_id) { - $content_id = md5(uniqid(time())); + $content_id = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true)); } $this->_html_images[] = array( @@ -429,8 +430,7 @@ class Mail_mime if (!strlen($filename)) { $msg = "The supplied filename for the attachment can't be empty"; - $err = PEAR::raiseError($msg); - return $err; + return $this->_raiseError($msg); } $this->_parts[] = array( @@ -465,16 +465,13 @@ class Mail_mime { // Check state of file and raise an error properly if (!file_exists($file_name)) { - $err = PEAR::raiseError('File not found: ' . $file_name); - return $err; + return $this->_raiseError('File not found: ' . $file_name); } if (!is_file($file_name)) { - $err = PEAR::raiseError('Not a regular file: ' . $file_name); - return $err; + return $this->_raiseError('Not a regular file: ' . $file_name); } if (!is_readable($file_name)) { - $err = PEAR::raiseError('File is not readable: ' . $file_name); - return $err; + return $this->_raiseError('File is not readable: ' . $file_name); } // Temporarily reset magic_quotes_runtime and read file contents @@ -500,7 +497,7 @@ class Mail_mime * @return object The text mimePart object * @access private */ - function _addTextPart(&$obj, $text) + function &_addTextPart(&$obj = null, $text = '') { $params['content_type'] = 'text/plain'; $params['encoding'] = $this->_build_params['text_encoding']; @@ -509,11 +506,11 @@ class Mail_mime if (is_object($obj)) { $ret = $obj->addSubpart($text, $params); - return $ret; } else { $ret = new Mail_mimePart($text, $params); - return $ret; } + + return $ret; } /** @@ -526,7 +523,7 @@ class Mail_mime * @return object The html mimePart object * @access private */ - function _addHtmlPart(&$obj) + function &_addHtmlPart(&$obj = null) { $params['content_type'] = 'text/html'; $params['encoding'] = $this->_build_params['html_encoding']; @@ -535,11 +532,11 @@ class Mail_mime if (is_object($obj)) { $ret = $obj->addSubpart($this->_htmlbody, $params); - return $ret; } else { $ret = new Mail_mimePart($this->_htmlbody, $params); - return $ret; } + + return $ret; } /** @@ -550,9 +547,8 @@ class Mail_mime * @return object The multipart/mixed mimePart object * @access private */ - function _addMixedPart() + function &_addMixedPart() { - $params = array(); $params['content_type'] = 'multipart/mixed'; $params['eol'] = $this->_build_params['eol']; @@ -572,17 +568,18 @@ class Mail_mime * @return object The multipart/mixed mimePart object * @access private */ - function _addAlternativePart(&$obj) + function &_addAlternativePart(&$obj = null) { $params['content_type'] = 'multipart/alternative'; $params['eol'] = $this->_build_params['eol']; if (is_object($obj)) { - return $obj->addSubpart('', $params); + $ret = $obj->addSubpart('', $params); } else { $ret = new Mail_mimePart('', $params); - return $ret; } + + return $ret; } /** @@ -596,17 +593,18 @@ class Mail_mime * @return object The multipart/mixed mimePart object * @access private */ - function _addRelatedPart(&$obj) + function &_addRelatedPart(&$obj = null) { $params['content_type'] = 'multipart/related'; $params['eol'] = $this->_build_params['eol']; if (is_object($obj)) { - return $obj->addSubpart('', $params); + $ret = $obj->addSubpart('', $params); } else { $ret = new Mail_mimePart('', $params); - return $ret; } + + return $ret; } /** @@ -619,7 +617,7 @@ class Mail_mime * @return object The image mimePart object * @access private */ - function _addHtmlImagePart(&$obj, $value) + function &_addHtmlImagePart(&$obj, $value) { $params['content_type'] = $value['c_type']; $params['encoding'] = 'base64'; @@ -650,7 +648,7 @@ class Mail_mime * @return object The image mimePart object * @access private */ - function _addAttachmentPart(&$obj, $value) + function &_addAttachmentPart(&$obj, $value) { $params['eol'] = $this->_build_params['eol']; $params['filename'] = $value['name']; @@ -700,9 +698,9 @@ class Mail_mime * * @param string $separation The separation between these two parts. * @param array $params The Build parameters passed to the - * &get() function. See &get for more info. + * get() function. See get() for more info. * @param array $headers The extra headers that should be passed - * to the &headers() function. + * to the headers() method. * See that function for more info. * @param bool $overwrite Overwrite the existing headers with new. * @@ -722,9 +720,7 @@ class Mail_mime return $body; } - $head = $this->txtHeaders($headers, $overwrite); - $mail = $head . $separation . $body; - return $mail; + return $this->txtHeaders($headers, $overwrite) . $separation . $body; } /** @@ -732,7 +728,7 @@ class Mail_mime * mail delivery method. * * @param array $params The Build parameters passed to the - * &get() function. See &get for more info. + * get() method. See get() for more info. * * @return mixed The e-mail body or PEAR error object * @access public @@ -748,9 +744,9 @@ class Mail_mime * * @param string $filename Output file location * @param array $params The Build parameters passed to the - * &get() function. See &get for more info. + * get() method. See get() for more info. * @param array $headers The extra headers that should be passed - * to the &headers() function. + * to the headers() function. * See that function for more info. * @param bool $overwrite Overwrite the existing headers with new. * @@ -762,8 +758,7 @@ class Mail_mime { // Check state of file and raise an error properly if (file_exists($filename) && !is_writable($filename)) { - $err = PEAR::raiseError('File is not writable: ' . $filename); - return $err; + return $this->_raiseError('File is not writable: ' . $filename); } // Temporarily reset magic_quotes_runtime and read file contents @@ -772,15 +767,13 @@ class Mail_mime } if (!($fh = fopen($filename, 'ab'))) { - $err = PEAR::raiseError('Unable to open file: ' . $filename); - return $err; + return $this->_raiseError('Unable to open file: ' . $filename); } // Write message headers into file (skipping Content-* headers) $head = $this->txtHeaders($headers, $overwrite, true); if (fwrite($fh, $head) === false) { - $err = PEAR::raiseError('Error writing to file: ' . $filename); - return $err; + return $this->_raiseError('Error writing to file: ' . $filename); } fclose($fh); @@ -797,10 +790,10 @@ class Mail_mime /** * Writes (appends) the complete e-mail body into file. - * + * * @param string $filename Output file location * @param array $params The Build parameters passed to the - * &get() function. See &get for more info. + * get() method. See get() for more info. * * @return mixed True or PEAR error object * @access public @@ -810,8 +803,7 @@ class Mail_mime { // Check state of file and raise an error properly if (file_exists($filename) && !is_writable($filename)) { - $err = PEAR::raiseError('File is not writable: ' . $filename); - return $err; + return $this->_raiseError('File is not writable: ' . $filename); } // Temporarily reset magic_quotes_runtime and read file contents @@ -820,8 +812,7 @@ class Mail_mime } if (!($fh = fopen($filename, 'ab'))) { - $err = PEAR::raiseError('Unable to open file: ' . $filename); - return $err; + return $this->_raiseError('Unable to open file: ' . $filename); } // Write the rest of the message into file @@ -844,7 +835,7 @@ class Mail_mime * @return mixed The MIME message content string, null or PEAR error object * @access public */ - function &get($params = null, $filename = null, $skip_head = false) + function get($params = null, $filename = null, $skip_head = false) { if (isset($params)) { while (list($key, $value) = each($params)) { @@ -1004,8 +995,7 @@ class Mail_mime } if (!isset($message)) { - $ret = null; - return $ret; + return null; } // Use saved boundary @@ -1023,16 +1013,14 @@ class Mail_mime return $headers; } $this->_headers = array_merge($this->_headers, $headers); - $ret = null; - return $ret; + return null; } else { $output = $message->encode($boundary, $skip_head); if ($this->_isError($output)) { return $output; } $this->_headers = array_merge($this->_headers, $output['headers']); - $body = $output['body']; - return $body; + return $output['body']; } } @@ -1050,7 +1038,7 @@ class Mail_mime * @return array Assoc array with the mime headers * @access public */ - function &headers($xtra_headers = null, $overwrite = false, $skip_content = false) + function headers($xtra_headers = null, $overwrite = false, $skip_content = false) { // Add mime version header $headers['MIME-Version'] = '1.0'; @@ -1473,7 +1461,7 @@ class Mail_mime } /** - * PEAR::isError wrapper + * PEAR::isError implementation * * @param mixed $data Object * @@ -1490,4 +1478,18 @@ class Mail_mime return false; } + /** + * PEAR::raiseError implementation + * + * @param $message A text error message + * + * @return PEAR_Error Instance of PEAR_Error + * @access private + */ + function _raiseError($message) + { + // PEAR::raiseError() is not PHP 5.4 compatible + return new PEAR_Error($message); + } + } // End of class diff --git a/program/lib/Mail/mimePart.php b/program/lib/Mail/mimePart.php index f3e75dd10..c6e9f4aa8 100644 --- a/program/lib/Mail/mimePart.php +++ b/program/lib/Mail/mimePart.php @@ -48,7 +48,7 @@ * @author Aleksander Machniak <alec@php.net> * @copyright 2003-2006 PEAR <pear-group@php.net> * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @version Release: 1.8.7 + * @version CVS: $Id$ * @link http://pear.php.net/package/Mail_mime */ @@ -70,7 +70,7 @@ * @author Aleksander Machniak <alec@php.net> * @copyright 2003-2006 PEAR <pear-group@php.net> * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @version Release: 1.8.7 + * @version Release: @package_version@ * @link http://pear.php.net/package/Mail_mime */ class Mail_mimePart @@ -368,12 +368,12 @@ class Mail_mimePart function encodeToFile($filename, $boundary=null, $skip_head=false) { if (file_exists($filename) && !is_writable($filename)) { - $err = PEAR::raiseError('File is not writeable: ' . $filename); + $err = $this->_raiseError('File is not writeable: ' . $filename); return $err; } if (!($fh = fopen($filename, 'ab'))) { - $err = PEAR::raiseError('Unable to open file: ' . $filename); + $err = $this->_raiseError('Unable to open file: ' . $filename); return $err; } @@ -456,7 +456,7 @@ class Mail_mimePart * @param array $params The parameters for the subpart, same * as the $params argument for constructor. * - * @return Mail_mimePart A reference to the part you just added. It is + * @return Mail_mimePart A reference to the part you just added. In PHP4, it is * crucial if using multipart/* in your subparts that * you use =& in your script when calling this function, * otherwise you will not be able to add further subparts. @@ -464,8 +464,8 @@ class Mail_mimePart */ function &addSubpart($body, $params) { - $this->_subparts[] = new Mail_mimePart($body, $params); - return $this->_subparts[count($this->_subparts) - 1]; + $this->_subparts[] = $part = new Mail_mimePart($body, $params); + return $part; } /** @@ -511,12 +511,12 @@ class Mail_mimePart function _getEncodedDataFromFile($filename, $encoding, $fh=null) { if (!is_readable($filename)) { - $err = PEAR::raiseError('Unable to read file: ' . $filename); + $err = $this->_raiseError('Unable to read file: ' . $filename); return $err; } if (!($fd = fopen($filename, 'rb'))) { - $err = PEAR::raiseError('Could not open file: ' . $filename); + $err = $this->_raiseError('Could not open file: ' . $filename); return $err; } @@ -648,7 +648,7 @@ class Mail_mimePart } /** - * Encodes the paramater of a header. + * Encodes the parameter of a header. * * @param string $name The name of the header-parameter * @param string $value The value of the paramter @@ -1013,7 +1013,7 @@ class Mail_mimePart $value = substr($value, $cutpoint); $cutpoint = $maxLength; // RFC 2047 specifies that any split header should - // be seperated by a CRLF SPACE. + // be separated by a CRLF SPACE. if ($output) { $output .= $eol . ' '; } @@ -1055,7 +1055,7 @@ class Mail_mimePart } // RFC 2047 specifies that any split header should - // be seperated by a CRLF SPACE + // be separated by a CRLF SPACE if ($output) { $output .= $eol . ' '; } @@ -1227,7 +1227,7 @@ class Mail_mimePart } /** - * PEAR::isError wrapper + * PEAR::isError implementation * * @param mixed $data Object * @@ -1244,4 +1244,18 @@ class Mail_mimePart return false; } + /** + * PEAR::raiseError implementation + * + * @param $message A text error message + * + * @return PEAR_Error Instance of PEAR_Error + * @access private + */ + function _raiseError($message) + { + // PEAR::raiseError() is not PHP 5.4 compatible + return new PEAR_Error($message); + } + } // End of class diff --git a/program/lib/Roundcube/bootstrap.php b/program/lib/Roundcube/bootstrap.php index b7e69cb2a..182ea1232 100644 --- a/program/lib/Roundcube/bootstrap.php +++ b/program/lib/Roundcube/bootstrap.php @@ -39,13 +39,13 @@ $config = array( if (php_sapi_name() != 'cli') { $config += array( 'suhosin.session.encrypt' => 0, - 'session.auto_start' => 0, 'file_uploads' => 1, ); } foreach ($config as $optname => $optval) { - if ($optval != ini_get($optname) && @ini_set($optname, $optval) === false) { + $ini_optval = filter_var(ini_get($optname), FILTER_VALIDATE_BOOLEAN); + if ($optval != $ini_optval && @ini_set($optname, $optval) === false) { $error = "ERROR: Wrong '$optname' option value and it wasn't possible to set it to required value ($optval).\n" . "Check your PHP configuration (including php_admin_flag)."; if (defined('STDERR')) fwrite(STDERR, $error); else echo $error; @@ -293,32 +293,6 @@ function is_ascii($str, $control_chars = true) /** - * Remove single and double quotes from a given string - * - * @param string Input value - * - * @return string Dequoted string - */ -function strip_quotes($str) -{ - return str_replace(array("'", '"'), '', $str); -} - - -/** - * Remove new lines characters from given string - * - * @param string $str Input value - * - * @return string Stripped string - */ -function strip_newlines($str) -{ - return preg_replace('/[\r\n]/', '', $str); -} - - -/** * Compose a valid representation of name and e-mail address * * @param string $email E-mail address diff --git a/program/lib/Roundcube/html.php b/program/lib/Roundcube/html.php index eb23c8b2e..3e6e47a56 100644 --- a/program/lib/Roundcube/html.php +++ b/program/lib/Roundcube/html.php @@ -360,8 +360,8 @@ class html_inputfield extends html protected $allowed = array( 'type','name','value','size','tabindex','autocapitalize', 'autocomplete','checked','onchange','onclick','disabled','readonly', - 'spellcheck','results','maxlength','src','multiple','placeholder', - 'autofocus', + 'spellcheck','results','maxlength','src','multiple','accept', + 'placeholder','autofocus', ); /** diff --git a/program/lib/Roundcube/rcube.php b/program/lib/Roundcube/rcube.php index eea2fde84..ce97cd0a5 100644 --- a/program/lib/Roundcube/rcube.php +++ b/program/lib/Roundcube/rcube.php @@ -99,20 +99,20 @@ class rcube protected $texts; protected $caches = array(); protected $shutdown_functions = array(); - protected $expunge_cache = false; /** * This implements the 'singleton' design pattern * * @param integer Options to initialize with this instance. See rcube::INIT_WITH_* constants + * @param string Environment name to run (e.g. live, dev, test) * * @return rcube The one and only instance */ - static function get_instance($mode = 0) + static function get_instance($mode = 0, $env = '') { if (!self::$instance) { - self::$instance = new rcube(); + self::$instance = new rcube($env); self::$instance->init($mode); } @@ -123,10 +123,10 @@ class rcube /** * Private constructor */ - protected function __construct() + protected function __construct($env = '') { // load configuration - $this->config = new rcube_config; + $this->config = new rcube_config($env); $this->plugins = new rcube_dummy_plugin_api; register_shutdown_function(array($this, 'shutdown')); @@ -258,6 +258,39 @@ class rcube /** + * Initialize and get shared cache object + * + * @param string $name Cache identifier + * @param bool $packed Enables/disables data serialization + * + * @return rcube_cache_shared Cache object + */ + public function get_cache_shared($name, $packed=true) + { + $shared_name = "shared_$name"; + + if (!array_key_exists($shared_name, $this->caches)) { + $opt = strtolower($name) . '_cache'; + $type = $this->config->get($opt); + $ttl = $this->config->get($opt . '_ttl'); + + if (!$type) { + // cache is disabled + return $this->caches[$shared_name] = null; + } + + if ($ttl === null) { + $ttl = $this->config->get('shared_cache_ttl', '10d'); + } + + $this->caches[$shared_name] = new rcube_cache_shared($type, $name, $ttl, $packed); + } + + return $this->caches[$shared_name]; + } + + + /** * Create SMTP object and connect to server * * @param boolean True if connection should be established @@ -345,6 +378,7 @@ class rcube 'auth_pw' => $this->config->get("{$driver}_auth_pw"), 'debug' => (bool) $this->config->get("{$driver}_debug"), 'force_caps' => (bool) $this->config->get("{$driver}_force_caps"), + 'disabled_caps' => $this->config->get("{$driver}_disabled_caps"), 'timeout' => (int) $this->config->get("{$driver}_timeout"), 'skip_deleted' => (bool) $this->config->get('skip_deleted'), 'driver' => $driver, @@ -424,30 +458,40 @@ class rcube ini_set('session.name', $sess_name ? $sess_name : 'roundcube_sessid'); ini_set('session.use_cookies', 1); ini_set('session.use_only_cookies', 1); - ini_set('session.serialize_handler', 'php'); ini_set('session.cookie_httponly', 1); // use database for storing session data $this->session = new rcube_session($this->get_dbh(), $this->config); - $this->session->register_gc_handler(array($this, 'temp_gc')); - $this->session->register_gc_handler(array($this, 'cache_gc')); - + $this->session->register_gc_handler(array($this, 'gc')); $this->session->set_secret($this->config->get('des_key') . dirname($_SERVER['SCRIPT_NAME'])); $this->session->set_ip_check($this->config->get('ip_check')); // start PHP session (if not in CLI mode) if ($_SERVER['REMOTE_ADDR']) { - session_start(); + $this->session->start(); } } /** + * Garbage collector - cache/temp cleaner + */ + public function gc() + { + rcube_cache::gc(); + rcube_cache_shared::gc(); + $this->get_storage()->cache_gc(); + + $this->gc_temp(); + } + + + /** * Garbage collector function for temp files. * Remove temp files older than two days */ - public function temp_gc() + public function gc_temp() { $tmp = unslashify($this->config->get('temp_dir')); $expire = time() - 172800; // expire in 48 hours @@ -469,14 +513,21 @@ class rcube /** - * Garbage collector for cache entries. - * Set flag to expunge caches on shutdown + * Runs garbage collector with probability based on + * session settings. This is intended for environments + * without a session. */ - public function cache_gc() + public function gc_run() { - // because this gc function is called before storage is initialized, - // we just set a flag to expunge storage cache on shutdown. - $this->expunge_cache = true; + $probability = (int) ini_get('session.gc_probability'); + $divisor = (int) ini_get('session.gc_divisor'); + + if ($divisor > 0 && $probability > 0) { + $random = mt_rand(1, $divisor); + if ($random <= $probability) { + $this->gc(); + } + } } @@ -860,6 +911,14 @@ class rcube call_user_func($function); } + // write session data as soon as possible and before + // closing database connection, don't do this before + // registered shutdown functions, they may need the session + // Note: this will run registered gc handlers (ie. cache gc) + if ($_SERVER['REMOTE_ADDR'] && is_object($this->session)) { + $this->session->write_close(); + } + if (is_object($this->smtp)) { $this->smtp->disconnect(); } @@ -871,9 +930,6 @@ class rcube } if (is_object($this->storage)) { - if ($this->expunge_cache) { - $this->storage->expunge_cache(); - } $this->storage->close(); } } @@ -1433,7 +1489,7 @@ class rcube $subject = str_replace("\r\n", $delim, $subject); } - if (ini_get('safe_mode')) + if (filter_var(ini_get('safe_mode'), FILTER_VALIDATE_BOOLEAN)) $sent = mail($to, $subject, $msg_body, $header_str); else $sent = mail($to, $subject, $msg_body, $header_str, "-f$from"); diff --git a/program/lib/Roundcube/rcube_addressbook.php b/program/lib/Roundcube/rcube_addressbook.php index d23ad3687..4ed139c45 100644 --- a/program/lib/Roundcube/rcube_addressbook.php +++ b/program/lib/Roundcube/rcube_addressbook.php @@ -539,10 +539,10 @@ abstract class rcube_addressbook // add email to a key to not skip contacts with the same name (#1488375) if (!empty($contact['email'])) { - $key .= ':' . implode(':', (array)$contact['email']); - } + $key .= ':' . implode(':', (array)$contact['email']); + } - return $key; + return $key; } /** diff --git a/program/lib/Roundcube/rcube_cache.php b/program/lib/Roundcube/rcube_cache.php index 92f12a8bf..a708cb292 100644 --- a/program/lib/Roundcube/rcube_cache.php +++ b/program/lib/Roundcube/rcube_cache.php @@ -38,6 +38,7 @@ class rcube_cache private $type; private $userid; private $prefix; + private $table; private $ttl; private $packed; private $index; @@ -71,8 +72,9 @@ class rcube_cache $this->db = function_exists('apc_exists'); // APC 3.1.4 required } else { - $this->type = 'db'; - $this->db = $rcube->get_dbh(); + $this->type = 'db'; + $this->db = $rcube->get_dbh(); + $this->table = $this->db->table_name('cache'); } // convert ttl string to seconds @@ -145,7 +147,7 @@ class rcube_cache */ function write($key, $data) { - return $this->write_record($key, $this->packed ? serialize($data) : $data); + return $this->write_record($key, $this->serialize($data)); } @@ -192,20 +194,31 @@ class rcube_cache */ function expunge() { - if ($this->type == 'db' && $this->db) { + if ($this->type == 'db' && $this->db && $this->ttl) { $this->db->query( - "DELETE FROM ".$this->db->table_name('cache'). + "DELETE FROM ".$this->table. " WHERE user_id = ?". " AND cache_key LIKE ?". - " AND " . $this->db->unixtimestamp('created')." < ?", + " AND expires < " . $this->db->now(), $this->userid, - $this->prefix.'.%', - time() - $this->ttl); + $this->prefix.'.%'); } } /** + * Remove expired records of all caches + */ + static function gc() + { + $rcube = rcube::get_instance(); + $db = $rcube->get_dbh(); + + $db->query("DELETE FROM " . $db->table_name('cache') . " WHERE expires < " . $db->now()); + } + + + /** * Writes the cache back to the DB. */ function close() @@ -219,7 +232,7 @@ class rcube_cache if ($this->cache_changes[$key]) { // Make sure we're not going to write unchanged data // by comparing current md5 sum with the sum calculated on DB read - $data = $this->packed ? serialize($data) : $data; + $data = $this->serialize($data); if (!$this->cache_sums[$key] || $this->cache_sums[$key] != md5($data)) { $this->write_record($key, $data); @@ -255,7 +268,7 @@ class rcube_cache if ($data) { $md5sum = md5($data); - $data = $this->packed ? unserialize($data) : $data; + $data = $this->unserialize($data); if ($nostore) { return $data; @@ -271,7 +284,7 @@ class rcube_cache else { $sql_result = $this->db->limitquery( "SELECT data, cache_key". - " FROM ".$this->db->table_name('cache'). + " FROM " . $this->table. " WHERE user_id = ?". " AND cache_key = ?". // for better performance we allow more records for one key @@ -283,7 +296,7 @@ class rcube_cache $key = substr($sql_arr['cache_key'], strlen($this->prefix)+1); $md5sum = $sql_arr['data'] ? md5($sql_arr['data']) : null; if ($sql_arr['data']) { - $data = $this->packed ? unserialize($sql_arr['data']) : $sql_arr['data']; + $data = $this->unserialize($sql_arr['data']); } if ($nostore) { @@ -326,7 +339,7 @@ class rcube_cache // Remove NULL rows (here we don't need to check if the record exist) if ($data == 'N;') { $this->db->query( - "DELETE FROM ".$this->db->table_name('cache'). + "DELETE FROM " . $this->table. " WHERE user_id = ?". " AND cache_key = ?", $this->userid, $key); @@ -337,8 +350,10 @@ class rcube_cache // update existing cache record if ($key_exists) { $result = $this->db->query( - "UPDATE ".$this->db->table_name('cache'). - " SET created = ". $this->db->now().", data = ?". + "UPDATE " . $this->table. + " SET created = " . $this->db->now(). + ", expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL'). + ", data = ?". " WHERE user_id = ?". " AND cache_key = ?", $data, $this->userid, $key); @@ -348,9 +363,9 @@ class rcube_cache // for better performance we allow more records for one key // so, no need to check if record exist (see rcube_cache::read_record()) $result = $this->db->query( - "INSERT INTO ".$this->db->table_name('cache'). - " (created, user_id, cache_key, data)". - " VALUES (".$this->db->now().", ?, ?, ?)", + "INSERT INTO " . $this->table. + " (created, expires, user_id, cache_key, data)". + " VALUES (" . $this->db->now() . ", " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?, ?, ?)", $this->userid, $key, $data); } @@ -364,7 +379,6 @@ class rcube_cache * @param string $key Cache key name or pattern * @param boolean $prefix_mode Enable it to clear all keys starting * with prefix specified in $key - * */ private function remove_record($key=null, $prefix_mode=false) { @@ -412,7 +426,7 @@ class rcube_cache } $this->db->query( - "DELETE FROM ".$this->db->table_name('cache'). + "DELETE FROM " . $this->table. " WHERE user_id = ?" . $where, $this->userid); } @@ -553,4 +567,28 @@ class rcube_cache // This way each cache will have its own index return sprintf('%d:%s%s', $this->userid, $this->prefix, 'INDEX'); } + + /** + * Serializes data for storing + */ + private function serialize($data) + { + if ($this->type == 'db') { + return $this->db->encode($data, $this->packed); + } + + return $this->packed ? serialize($data) : $data; + } + + /** + * Unserializes serialized data + */ + private function unserialize($data) + { + if ($this->type == 'db') { + return $this->db->decode($data, $this->packed); + } + + return $this->packed ? @unserialize($data) : $data; + } } diff --git a/program/lib/Roundcube/rcube_cache_shared.php b/program/lib/Roundcube/rcube_cache_shared.php new file mode 100644 index 000000000..8f2574046 --- /dev/null +++ b/program/lib/Roundcube/rcube_cache_shared.php @@ -0,0 +1,581 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | This file is part of the Roundcube Webmail client | + | Copyright (C) 2011-2013, The Roundcube Dev Team | + | Copyright (C) 2011-2013, Kolab Systems AG | + | | + | Licensed under the GNU General Public License version 3 or | + | any later version with exceptions for skins & plugins. | + | See the README file for a full license statement. | + | | + | PURPOSE: | + | Shared (cross-user) caching engine | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + | Author: Aleksander Machniak <alec@alec.pl> | + +-----------------------------------------------------------------------+ +*/ + + +/** + * Interface class for accessing Roundcube shared cache + * + * @package Framework + * @subpackage Cache + * @author Thomas Bruederli <roundcube@gmail.com> + * @author Aleksander Machniak <alec@alec.pl> + */ +class rcube_cache_shared +{ + /** + * Instance of database handler + * + * @var rcube_db|Memcache|bool + */ + private $db; + private $type; + private $prefix; + private $ttl; + private $packed; + private $index; + private $table; + private $cache = array(); + private $cache_changes = array(); + private $cache_sums = array(); + + + /** + * Object constructor. + * + * @param string $type Engine type ('db' or 'memcache' or 'apc') + * @param string $prefix Key name prefix + * @param string $ttl Expiration time of memcache/apc items + * @param bool $packed Enables/disabled data serialization. + * It's possible to disable data serialization if you're sure + * stored data will be always a safe string + */ + function __construct($type, $prefix='', $ttl=0, $packed=true) + { + $rcube = rcube::get_instance(); + $type = strtolower($type); + + if ($type == 'memcache') { + $this->type = 'memcache'; + $this->db = $rcube->get_memcache(); + } + else if ($type == 'apc') { + $this->type = 'apc'; + $this->db = function_exists('apc_exists'); // APC 3.1.4 required + } + else { + $this->type = 'db'; + $this->db = $rcube->get_dbh(); + $this->table = $this->db->table_name('cache_shared'); + } + + // convert ttl string to seconds + $ttl = get_offset_sec($ttl); + if ($ttl > 2592000) $ttl = 2592000; + + $this->ttl = $ttl; + $this->packed = $packed; + $this->prefix = $prefix; + } + + + /** + * Returns cached value. + * + * @param string $key Cache key name + * + * @return mixed Cached value + */ + function get($key) + { + if (!array_key_exists($key, $this->cache)) { + return $this->read_record($key); + } + + return $this->cache[$key]; + } + + + /** + * Sets (add/update) value in cache. + * + * @param string $key Cache key name + * @param mixed $data Cache data + */ + function set($key, $data) + { + $this->cache[$key] = $data; + $this->cache_changed = true; + $this->cache_changes[$key] = true; + } + + + /** + * Returns cached value without storing it in internal memory. + * + * @param string $key Cache key name + * + * @return mixed Cached value + */ + function read($key) + { + if (array_key_exists($key, $this->cache)) { + return $this->cache[$key]; + } + + return $this->read_record($key, true); + } + + + /** + * Sets (add/update) value in cache and immediately saves + * it in the backend, no internal memory will be used. + * + * @param string $key Cache key name + * @param mixed $data Cache data + * + * @param boolean True on success, False on failure + */ + function write($key, $data) + { + return $this->write_record($key, $this->serialize($data)); + } + + + /** + * Clears the cache. + * + * @param string $key Cache key name or pattern + * @param boolean $prefix_mode Enable it to clear all keys starting + * with prefix specified in $key + */ + function remove($key=null, $prefix_mode=false) + { + // Remove all keys + if ($key === null) { + $this->cache = array(); + $this->cache_changed = false; + $this->cache_changes = array(); + $this->cache_sums = array(); + } + // Remove keys by name prefix + else if ($prefix_mode) { + foreach (array_keys($this->cache) as $k) { + if (strpos($k, $key) === 0) { + $this->cache[$k] = null; + $this->cache_changes[$k] = false; + unset($this->cache_sums[$k]); + } + } + } + // Remove one key by name + else { + $this->cache[$key] = null; + $this->cache_changes[$key] = false; + unset($this->cache_sums[$key]); + } + + // Remove record(s) from the backend + $this->remove_record($key, $prefix_mode); + } + + + /** + * Remove cache records older than ttl + */ + function expunge() + { + if ($this->type == 'db' && $this->db && $this->ttl) { + $this->db->query( + "DELETE FROM " . $this->table + . " WHERE cache_key LIKE ?" + . " AND expires < " . $this->db->now(), + $this->prefix . '.%'); + } + } + + + /** + * Remove expired records of all caches + */ + static function gc() + { + $rcube = rcube::get_instance(); + $db = $rcube->get_dbh(); + + $db->query("DELETE FROM " . $db->table_name('cache_shared') . " WHERE expires < " . $db->now()); + } + + + /** + * Writes the cache back to the DB. + */ + function close() + { + if (!$this->cache_changed) { + return; + } + + foreach ($this->cache as $key => $data) { + // The key has been used + if ($this->cache_changes[$key]) { + // Make sure we're not going to write unchanged data + // by comparing current md5 sum with the sum calculated on DB read + $data = $this->serialize($data); + + if (!$this->cache_sums[$key] || $this->cache_sums[$key] != md5($data)) { + $this->write_record($key, $data); + } + } + } + + $this->write_index(); + } + + + /** + * Reads cache entry. + * + * @param string $key Cache key name + * @param boolean $nostore Enable to skip in-memory store + * + * @return mixed Cached value + */ + private function read_record($key, $nostore=false) + { + if (!$this->db) { + return null; + } + + if ($this->type != 'db') { + if ($this->type == 'memcache') { + $data = $this->db->get($this->ckey($key)); + } + else if ($this->type == 'apc') { + $data = apc_fetch($this->ckey($key)); + } + + if ($data) { + $md5sum = md5($data); + $data = $this->unserialize($data); + + if ($nostore) { + return $data; + } + + $this->cache_sums[$key] = $md5sum; + $this->cache[$key] = $data; + } + else { + $this->cache[$key] = null; + } + } + else { + $sql_result = $this->db->limitquery( + "SELECT data, cache_key". + " FROM " . $this->table . + " WHERE cache_key = ?". + // for better performance we allow more records for one key + // get the newer one + " ORDER BY created DESC", + 0, 1, $this->prefix . '.' . $key); + + if ($sql_arr = $this->db->fetch_assoc($sql_result)) { + $md5sum = $sql_arr['data'] ? md5($sql_arr['data']) : null; + if ($sql_arr['data']) { + $data = $this->unserialize($sql_arr['data']); + } + + if ($nostore) { + return $data; + } + + $this->cache[$key] = $data; + $this->cache_sums[$key] = $md5sum; + } + else { + $this->cache[$key] = null; + } + } + + return $this->cache[$key]; + } + + + /** + * Writes single cache record into DB. + * + * @param string $key Cache key name + * @param mxied $data Serialized cache data + * + * @param boolean True on success, False on failure + */ + private function write_record($key, $data) + { + if (!$this->db) { + return false; + } + + if ($this->type == 'memcache' || $this->type == 'apc') { + return $this->add_record($this->ckey($key), $data); + } + + $key_exists = array_key_exists($key, $this->cache_sums); + $key = $this->prefix . '.' . $key; + + // Remove NULL rows (here we don't need to check if the record exist) + if ($data == 'N;') { + $this->db->query("DELETE FROM " . $this->table . " WHERE cache_key = ?", $key); + return true; + } + + // update existing cache record + if ($key_exists) { + $result = $this->db->query( + "UPDATE " . $this->table . + " SET created = " . $this->db->now() . + ", expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . + ", data = ?". + " WHERE cache_key = ?", + $data, $key); + } + // add new cache record + else { + // for better performance we allow more records for one key + // so, no need to check if record exist (see rcube_cache::read_record()) + $result = $this->db->query( + "INSERT INTO ".$this->table. + " (created, expires, cache_key, data)". + " VALUES (".$this->db->now().", " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?, ?)", + $key, $data); + } + + return $this->db->affected_rows($result); + } + + + /** + * Deletes the cache record(s). + * + * @param string $key Cache key name or pattern + * @param boolean $prefix_mode Enable it to clear all keys starting + * with prefix specified in $key + */ + private function remove_record($key=null, $prefix_mode=false) + { + if (!$this->db) { + return; + } + + if ($this->type != 'db') { + $this->load_index(); + + // Remove all keys + if ($key === null) { + foreach ($this->index as $key) { + $this->delete_record($key, false); + } + $this->index = array(); + } + // Remove keys by name prefix + else if ($prefix_mode) { + foreach ($this->index as $k) { + if (strpos($k, $key) === 0) { + $this->delete_record($k); + } + } + } + // Remove one key by name + else { + $this->delete_record($key); + } + + return; + } + + // Remove all keys (in specified cache) + if ($key === null) { + $where = " WHERE cache_key LIKE " . $this->db->quote($this->prefix.'.%'); + } + // Remove keys by name prefix + else if ($prefix_mode) { + $where = " WHERE cache_key LIKE " . $this->db->quote($this->prefix.'.'.$key.'%'); + } + // Remove one key by name + else { + $where = " WHERE cache_key = " . $this->db->quote($this->prefix.'.'.$key); + } + + $this->db->query("DELETE FROM " . $this->table . $where); + } + + + /** + * Adds entry into memcache/apc DB. + * + * @param string $key Cache key name + * @param mxied $data Serialized cache data + * @param bollean $index Enables immediate index update + * + * @param boolean True on success, False on failure + */ + private function add_record($key, $data, $index=false) + { + if ($this->type == 'memcache') { + $result = $this->db->replace($key, $data, MEMCACHE_COMPRESSED, $this->ttl); + if (!$result) { + $result = $this->db->set($key, $data, MEMCACHE_COMPRESSED, $this->ttl); + } + } + else if ($this->type == 'apc') { + if (apc_exists($key)) { + apc_delete($key); + } + $result = apc_store($key, $data, $this->ttl); + } + + // Update index + if ($index && $result) { + $this->load_index(); + + if (array_search($key, $this->index) === false) { + $this->index[] = $key; + $data = serialize($this->index); + $this->add_record($this->ikey(), $data); + } + } + + return $result; + } + + + /** + * Deletes entry from memcache/apc DB. + */ + private function delete_record($key, $index=true) + { + if ($this->type == 'memcache') { + // #1488592: use 2nd argument + $this->db->delete($this->ckey($key), 0); + } + else { + apc_delete($this->ckey($key)); + } + + if ($index) { + if (($idx = array_search($key, $this->index)) !== false) { + unset($this->index[$idx]); + } + } + } + + + /** + * Writes the index entry into memcache/apc DB. + */ + private function write_index() + { + if (!$this->db) { + return; + } + + if ($this->type == 'db') { + return; + } + + $this->load_index(); + + // Make sure index contains new keys + foreach ($this->cache as $key => $value) { + if ($value !== null) { + if (array_search($key, $this->index) === false) { + $this->index[] = $key; + } + } + } + + $data = serialize($this->index); + $this->add_record($this->ikey(), $data); + } + + + /** + * Gets the index entry from memcache/apc DB. + */ + private function load_index() + { + if (!$this->db) { + return; + } + + if ($this->index !== null) { + return; + } + + $index_key = $this->ikey(); + + if ($this->type == 'memcache') { + $data = $this->db->get($index_key); + } + else if ($this->type == 'apc') { + $data = apc_fetch($index_key); + } + + $this->index = $data ? unserialize($data) : array(); + } + + + /** + * Creates cache key name (for memcache and apc) + * + * @param string $key Cache key name + * + * @return string Cache key + */ + private function ckey($key) + { + return $this->prefix . ':' . $key; + } + + + /** + * Creates index cache key name (for memcache and apc) + * + * @return string Cache key + */ + private function ikey() + { + // This way each cache will have its own index + return $this->prefix . 'INDEX'; + } + + /** + * Serializes data for storing + */ + private function serialize($data) + { + if ($this->type == 'db') { + return $this->db->encode($data, $this->packed); + } + + return $this->packed ? serialize($data) : $data; + } + + /** + * Unserializes serialized data + */ + private function unserialize($data) + { + if ($this->type == 'db') { + return $this->db->decode($data, $this->packed); + } + + return $this->packed ? @unserialize($data) : $data; + } +} diff --git a/program/lib/Roundcube/rcube_config.php b/program/lib/Roundcube/rcube_config.php index 2190dc4c2..62567a0e0 100644 --- a/program/lib/Roundcube/rcube_config.php +++ b/program/lib/Roundcube/rcube_config.php @@ -26,6 +26,8 @@ class rcube_config { const DEFAULT_SKIN = 'larry'; + private $env = ''; + private $basedir = 'config/'; private $prop = array(); private $errors = array(); private $userprefs = array(); @@ -43,14 +45,21 @@ class rcube_config 'reply_mode' => 'top_posting', 'refresh_interval' => 'keep_alive', 'min_refresh_interval' => 'min_keep_alive', + 'messages_cache_ttl' => 'message_cache_lifetime', + 'redundant_attachments_cache_ttl' => 'redundant_attachments_memcache_ttl', ); /** * Object constructor + * + * @param string Environment suffix for config files to load */ - public function __construct() + public function __construct($env = '') { + $this->env = $env; + $this->basedir = RCUBE_CONFIG_DIR; + $this->load(); // Defaults, that we do not require you to configure, @@ -67,16 +76,26 @@ class rcube_config */ private function load() { - // load main config file - if (!$this->load_from_file(RCUBE_CONFIG_DIR . 'main.inc.php')) - $this->errors[] = 'main.inc.php was not found.'; + // Load default settings + if (!$this->load_from_file('defaults.inc.php')) { + $this->errors[] = 'defaults.inc.php was not found.'; + } - // load database config - if (!$this->load_from_file(RCUBE_CONFIG_DIR . 'db.inc.php')) - $this->errors[] = 'db.inc.php was not found.'; + // load main config file + if (!$this->load_from_file('config.inc.php')) { + // Old configuration files + if (!$this->load_from_file('main.inc.php') || + !$this->load_from_file('db.inc.php')) { + $this->errors[] = 'config.inc.php was not found.'; + } + else if (rand(1,100) == 10) { // log warning on every 100th request (average) + trigger_error("config.inc.php was not found. Please migrate your config by running bin/update.sh", E_USER_WARNING); + } + } // load host-specific configuration - $this->load_host_config(); + if (!empty($_SERVER['HTTP_HOST'])) + $this->load_host_config(); // set skin (with fallback to old 'skin_path' property) if (empty($this->prop['skin'])) { @@ -153,7 +172,7 @@ class rcube_config } if ($fname) { - $this->load_from_file(RCUBE_CONFIG_DIR . $fname); + $this->load_from_file($fname); } } @@ -162,19 +181,25 @@ class rcube_config * Read configuration from a file * and merge with the already stored config values * - * @param string $fpath Full path to the config file to be loaded + * @param string $file Name of the config file to be loaded * @return booelan True on success, false on failure */ - public function load_from_file($fpath) + public function load_from_file($file) { - if (is_file($fpath) && is_readable($fpath)) { + $fpath = $this->resolve_path($file); + if ($fpath && is_file($fpath) && is_readable($fpath)) { // use output buffering, we don't need any output here ob_start(); include($fpath); ob_end_clean(); - if (is_array($rcmail_config)) { - $this->prop = array_merge($this->prop, $rcmail_config, $this->userprefs); + if (is_array($config)) { + $this->merge($config); + return true; + } + // deprecated name of config variable + else if (is_array($rcmail_config)) { + $this->merge($rcmail_config); return true; } } @@ -182,6 +207,26 @@ class rcube_config return false; } + /** + * Helper method to resolve the absolute path to the given config file. + * This also takes the 'env' property into account. + */ + public function resolve_path($file, $use_env = true) + { + if (strpos($file, '/') === false) { + $file = realpath($this->basedir . '/' . $file); + } + + // check if <file>-env.ini exists + if ($file && $use_env && !empty($this->env)) { + $envfile = preg_replace('/\.(inc.php)$/', '-' . $this->env . '.\\1', $file); + if (is_file($envfile)) + return $envfile; + } + + return $file; + } + /** * Getter for a specific config parameter @@ -195,9 +240,6 @@ class rcube_config if (isset($this->prop[$name])) { $result = $this->prop[$name]; } - else if (isset($this->legacy_props[$name])) { - return $this->get($this->legacy_props[$name], $def); - } else { $result = $def; } @@ -241,6 +283,7 @@ class rcube_config public function merge($prefs) { $this->prop = array_merge($this->prop, $prefs, $this->userprefs); + $this->fix_legacy_props(); } @@ -273,6 +316,8 @@ class rcube_config $this->userprefs = $prefs; $this->prop = array_merge($this->prop, $prefs); + $this->fix_legacy_props(); + // override timezone settings with client values if ($this->prop['timezone'] == 'auto') { $this->prop['_timezone_value'] = isset($_SESSION['timezone']) ? $this->client_timezone() : $this->prop['_timezone_value']; @@ -435,4 +480,18 @@ class rcube_config return date_default_timezone_get(); } + /** + * Convert legacy options into new ones + */ + private function fix_legacy_props() + { + foreach ($this->legacy_props as $new => $old) { + if (isset($this->prop[$old])) { + if (!isset($this->prop[$new])) { + $this->prop[$new] = $this->prop[$old]; + } + unset($this->prop[$old]); + } + } + } } diff --git a/program/lib/Roundcube/rcube_db.php b/program/lib/Roundcube/rcube_db.php index 5da38c899..852070073 100644 --- a/program/lib/Roundcube/rcube_db.php +++ b/program/lib/Roundcube/rcube_db.php @@ -100,27 +100,15 @@ class rcube_db $this->db_dsnw_array = self::parse_dsn($db_dsnw); $this->db_dsnr_array = self::parse_dsn($db_dsnr); - - // Initialize driver class - $this->init(); - } - - /** - * Initialization of the object with driver specific code - */ - protected function init() - { - // To be used by driver classes } /** * Connect to specific database * - * @param array $dsn DSN for DB connections - * - * @return PDO database handle + * @param array $dsn DSN for DB connections + * @param string $mode Connection mode (r|w) */ - protected function dsn_connect($dsn) + protected function dsn_connect($dsn, $mode) { $this->db_error = false; $this->db_error_msg = null; @@ -158,9 +146,10 @@ class rcube_db return null; } + $this->dbh = $dbh; + $this->db_mode = $mode; + $this->db_connected = true; $this->conn_configure($dsn, $dbh); - - return $dbh; } /** @@ -183,16 +172,6 @@ class rcube_db } /** - * Driver-specific database character set setting - * - * @param string $charset Character set name - */ - protected function set_charset($charset) - { - $this->query("SET NAMES 'utf8'"); - } - - /** * Connect to appropriate database depending on the operation * * @param string $mode Connection mode (r|w) @@ -219,23 +198,14 @@ class rcube_db $dsn = ($mode == 'r') ? $this->db_dsnr_array : $this->db_dsnw_array; - $this->dbh = $this->dsn_connect($dsn); - $this->db_connected = is_object($this->dbh); + $this->dsn_connect($dsn, $mode); // use write-master when read-only fails if (!$this->db_connected && $mode == 'r' && $this->is_replicated()) { - $mode = 'w'; - $this->dbh = $this->dsn_connect($this->db_dsnw_array); - $this->db_connected = is_object($this->dbh); + $this->dsn_connect($this->db_dsnw_array, 'w'); } - if ($this->db_connected) { - $this->db_mode = $mode; - $this->set_charset('utf8'); - } - else { - $this->conn_failure = true; - } + $this->conn_failure = !$this->db_connected; } /** @@ -368,8 +338,10 @@ class rcube_db */ protected function _query($query, $offset, $numrows, $params) { + $query = trim($query); + // Read or write ? - $mode = preg_match('/^(select|show)/i', ltrim($query)) ? 'r' : 'w'; + $mode = preg_match('/^(select|show|set)/i', $query) ? 'r' : 'w'; $this->db_connect($mode); @@ -415,13 +387,16 @@ class rcube_db if ($result === false) { $error = $this->dbh->errorInfo(); - $this->db_error = true; - $this->db_error_msg = sprintf('[%s] %s', $error[1], $error[2]); - rcube::raise_error(array('code' => 500, 'type' => 'db', - 'line' => __LINE__, 'file' => __FILE__, - 'message' => $this->db_error_msg . " (SQL Query: $query)" - ), true, false); + if (empty($this->options['ignore_key_errors']) || $error[0] != '23000') { + $this->db_error = true; + $this->db_error_msg = sprintf('[%s] %s', $error[1], $error[2]); + + rcube::raise_error(array('code' => 500, 'type' => 'db', + 'line' => __LINE__, 'file' => __FILE__, + 'message' => $this->db_error_msg . " (SQL Query: $query)" + ), true, false); + } } $this->last_result = $result; @@ -708,11 +683,19 @@ class rcube_db /** * Return SQL function for current time and date * + * @param int $interval Optional interval (in seconds) to add/subtract + * * @return string SQL function to use in query */ - public function now() + public function now($interval = 0) { - return "now()"; + if ($interval) { + $add = ' ' . ($interval > 0 ? '+' : '-') . ' INTERVAL '; + $add .= $interval > 0 ? intval($interval) : intval($interval) * -1; + $add .= ' SECOND'; + } + + return "now()" . $add; } /** @@ -795,12 +778,19 @@ class rcube_db /** * Encodes non-UTF-8 characters in string/array/object (recursive) * - * @param mixed $input Data to fix + * @param mixed $input Data to fix + * @param bool $serialized Enable serialization * * @return mixed Properly UTF-8 encoded data */ - public static function encode($input) + public static function encode($input, $serialized = false) { + // use Base64 encoding to workaround issues with invalid + // or null characters in serialized string (#1489142) + if ($serialized) { + return base64_encode(serialize($input)); + } + if (is_object($input)) { foreach (get_object_vars($input) as $idx => $value) { $input->$idx = self::encode($value); @@ -811,6 +801,7 @@ class rcube_db foreach ($input as $idx => $value) { $input[$idx] = self::encode($value); } + return $input; } @@ -820,12 +811,24 @@ class rcube_db /** * Decodes encoded UTF-8 string/object/array (recursive) * - * @param mixed $input Input data + * @param mixed $input Input data + * @param bool $serialized Enable serialization * * @return mixed Decoded data */ - public static function decode($input) + public static function decode($input, $serialized = false) { + // use Base64 encoding to workaround issues with invalid + // or null characters in serialized string (#1489142) + if ($serialized) { + // Keep backward compatybility where base64 wasn't used + if (strpos(substr($input, 0, 16), ':') !== false) { + return self::decode(@unserialize($input)); + } + + return @unserialize(base64_decode($input)); + } + if (is_object($input)) { foreach (get_object_vars($input) as $idx => $value) { $input->$idx = self::decode($value); @@ -862,6 +865,17 @@ class rcube_db } /** + * Set class option value + * + * @param string $name Option name + * @param mixed $value Option value + */ + public function set_option($name, $value) + { + $this->options[$name] = $value; + } + + /** * MDB2 DSN string parser * * @param string $sequence Secuence name diff --git a/program/lib/Roundcube/rcube_db_mssql.php b/program/lib/Roundcube/rcube_db_mssql.php index 37a42678a..3c1b9d71f 100644 --- a/program/lib/Roundcube/rcube_db_mssql.php +++ b/program/lib/Roundcube/rcube_db_mssql.php @@ -29,38 +29,52 @@ class rcube_db_mssql extends rcube_db public $db_provider = 'mssql'; /** - * Driver initialization + * Object constructor + * + * @param string $db_dsnw DSN for read/write operations + * @param string $db_dsnr Optional DSN for read only operations + * @param bool $pconn Enables persistent connections */ - protected function init() + public function __construct($db_dsnw, $db_dsnr = '', $pconn = false) { + parent::__construct($db_dsnw, $db_dsnr, $pconn); + $this->options['identifier_start'] = '['; $this->options['identifier_end'] = ']'; } /** - * Character setting + * Driver-specific configuration of database connection + * + * @param array $dsn DSN for DB connections + * @param PDO $dbh Connection handler */ - protected function set_charset($charset) + protected function conn_configure($dsn, $dbh) { - // UTF-8 is default + // Set date format in case of non-default language (#1488918) + $this->query("SET DATEFORMAT ymd"); } /** * Return SQL function for current time and date * + * @param int $interval Optional interval (in seconds) to add/subtract + * * @return string SQL function to use in query */ - public function now() + public function now($interval = 0) { + if ($interval) { + $interval = intval($interval); + return "dateadd(second, $interval, getdate())"; + } + return "getdate()"; } /** * Return SQL statement to convert a field value into a unix timestamp * - * This method is deprecated and should not be used anymore due to limitations - * of timestamp functions in Mysql (year 2038 problem) - * * @param string $field Field name * * @return string SQL statement to use in query diff --git a/program/lib/Roundcube/rcube_db_mysql.php b/program/lib/Roundcube/rcube_db_mysql.php index 2d42610b6..6fa5ad768 100644 --- a/program/lib/Roundcube/rcube_db_mysql.php +++ b/program/lib/Roundcube/rcube_db_mysql.php @@ -30,9 +30,13 @@ class rcube_db_mysql extends rcube_db public $db_provider = 'mysql'; /** - * Driver initialization/configuration + * Object constructor + * + * @param string $db_dsnw DSN for read/write operations + * @param string $db_dsnr Optional DSN for read only operations + * @param bool $pconn Enables persistent connections */ - protected function init() + public function __construct($db_dsnw, $db_dsnr = '', $pconn = false) { if (version_compare(PHP_VERSION, '5.3.0', '<')) { rcube::raise_error(array('code' => 600, 'type' => 'db', @@ -41,12 +45,25 @@ class rcube_db_mysql extends rcube_db true, true); } + parent::__construct($db_dsnw, $db_dsnr, $pconn); + // SQL identifiers quoting $this->options['identifier_start'] = '`'; $this->options['identifier_end'] = '`'; } /** + * Driver-specific configuration of database connection + * + * @param array $dsn DSN for DB connections + * @param PDO $dbh Connection handler + */ + protected function conn_configure($dsn, $dbh) + { + $this->query("SET NAMES 'utf8'"); + } + + /** * Abstract SQL statement for value concatenation * * @return string SQL statement to be used in query diff --git a/program/lib/Roundcube/rcube_db_pgsql.php b/program/lib/Roundcube/rcube_db_pgsql.php index adfd2207b..d72c9d6b3 100644 --- a/program/lib/Roundcube/rcube_db_pgsql.php +++ b/program/lib/Roundcube/rcube_db_pgsql.php @@ -29,6 +29,17 @@ class rcube_db_pgsql extends rcube_db public $db_provider = 'postgres'; /** + * Driver-specific configuration of database connection + * + * @param array $dsn DSN for DB connections + * @param PDO $dbh Connection handler + */ + protected function conn_configure($dsn, $dbh) + { + $this->query("SET NAMES 'utf8'"); + } + + /** * Get last inserted record ID * * @param string $table Table name (to find the incremented sequence) @@ -75,9 +86,6 @@ class rcube_db_pgsql extends rcube_db /** * Return SQL statement to convert a field value into a unix timestamp * - * This method is deprecated and should not be used anymore due to limitations - * of timestamp functions in Mysql (year 2038 problem) - * * @param string $field Field name * * @return string SQL statement to use in query @@ -89,6 +97,24 @@ class rcube_db_pgsql extends rcube_db } /** + * Return SQL function for current time and date + * + * @param int $interval Optional interval (in seconds) to add/subtract + * + * @return string SQL function to use in query + */ + public function now($interval = 0) + { + if ($interval) { + $add = ' ' . ($interval > 0 ? '+' : '-') . " interval '"; + $add .= $interval > 0 ? intval($interval) : intval($interval) * -1; + $add .= " seconds'"; + } + + return "now()" . $add; + } + + /** * Return SQL statement for case insensitive LIKE * * @param string $column Field name @@ -130,4 +156,38 @@ class rcube_db_pgsql extends rcube_db return isset($this->variables[$varname]) ? $this->variables[$varname] : $default; } + /** + * Returns PDO DSN string from DSN array + * + * @param array $dsn DSN parameters + * + * @return string DSN string + */ + protected function dsn_string($dsn) + { + $params = array(); + $result = 'pgsql:'; + + if ($dsn['hostspec']) { + $params[] = 'host=' . $dsn['hostspec']; + } + else if ($dsn['socket']) { + $params[] = 'host=' . $dsn['socket']; + } + + if ($dsn['port']) { + $params[] = 'port=' . $dsn['port']; + } + + if ($dsn['database']) { + $params[] = 'dbname=' . $dsn['database']; + } + + if (!empty($params)) { + $result .= implode(';', $params); + } + + return $result; + } + } diff --git a/program/lib/Roundcube/rcube_db_sqlite.php b/program/lib/Roundcube/rcube_db_sqlite.php index 145b8a371..b66c56097 100644 --- a/program/lib/Roundcube/rcube_db_sqlite.php +++ b/program/lib/Roundcube/rcube_db_sqlite.php @@ -29,13 +29,6 @@ class rcube_db_sqlite extends rcube_db public $db_provider = 'sqlite'; /** - * Database character set - */ - protected function set_charset($charset) - { - } - - /** * Prepare connection */ protected function conn_prepare($dsn) @@ -56,10 +49,6 @@ class rcube_db_sqlite extends rcube_db */ protected function conn_configure($dsn, $dbh) { - // we emulate via callback some missing functions - $dbh->sqliteCreateFunction('unix_timestamp', array('rcube_db_sqlite', 'sqlite_unix_timestamp'), 1); - $dbh->sqliteCreateFunction('now', array('rcube_db_sqlite', 'sqlite_now'), 0); - // Initialize database structure in file is empty if (!empty($dsn['database']) && !filesize($dsn['database'])) { $data = file_get_contents(RCUBE_INSTALL_PATH . 'SQL/sqlite.initial.sql'); @@ -83,30 +72,32 @@ class rcube_db_sqlite extends rcube_db } /** - * Callback for sqlite: unix_timestamp() + * Return SQL statement to convert a field value into a unix timestamp + * + * @param string $field Field name + * + * @return string SQL statement to use in query + * @deprecated */ - public static function sqlite_unix_timestamp($timestamp = '') + public function unixtimestamp($field) { - $timestamp = trim($timestamp); - if (!$timestamp) { - $ret = time(); - } - else if (!preg_match('/^[0-9]+$/s', $timestamp)) { - $ret = strtotime($timestamp); - } - else { - $ret = $timestamp; - } - - return $ret; + return "strftime('%s', $field)"; } /** - * Callback for sqlite: now() + * Return SQL function for current time and date + * + * @param int $interval Optional interval (in seconds) to add/subtract + * + * @return string SQL function to use in query */ - public static function sqlite_now() + public function now($interval = 0) { - return date("Y-m-d H:i:s"); + if ($interval) { + $add = ($interval > 0 ? '+' : '') . intval($interval) . ' seconds'; + } + + return "datetime('now'" . ($add ? ",'$add'" : "") . ")"; } /** diff --git a/program/lib/Roundcube/rcube_db_sqlsrv.php b/program/lib/Roundcube/rcube_db_sqlsrv.php index e5dfb1154..45c41cdaf 100644 --- a/program/lib/Roundcube/rcube_db_sqlsrv.php +++ b/program/lib/Roundcube/rcube_db_sqlsrv.php @@ -29,29 +29,46 @@ class rcube_db_sqlsrv extends rcube_db public $db_provider = 'mssql'; /** - * Driver initialization + * Object constructor + * + * @param string $db_dsnw DSN for read/write operations + * @param string $db_dsnr Optional DSN for read only operations + * @param bool $pconn Enables persistent connections */ - protected function init() + public function __construct($db_dsnw, $db_dsnr = '', $pconn = false) { + parent::__construct($db_dsnw, $db_dsnr, $pconn); + $this->options['identifier_start'] = '['; $this->options['identifier_end'] = ']'; } /** - * Database character set setting + * Driver-specific configuration of database connection + * + * @param array $dsn DSN for DB connections + * @param PDO $dbh Connection handler */ - protected function set_charset($charset) + protected function conn_configure($dsn, $dbh) { - // UTF-8 is default + // Set date format in case of non-default language (#1488918) + $this->query("SET DATEFORMAT ymd"); } /** * Return SQL function for current time and date * + * @param int $interval Optional interval (in seconds) to add/subtract + * * @return string SQL function to use in query */ - public function now() + public function now($interval = 0) { + if ($interval) { + $interval = intval($interval); + return "dateadd(second, $interval, getdate())"; + } + return "getdate()"; } diff --git a/program/lib/Roundcube/rcube_image.php b/program/lib/Roundcube/rcube_image.php index 735a0df01..09bb4e81b 100644 --- a/program/lib/Roundcube/rcube_image.php +++ b/program/lib/Roundcube/rcube_image.php @@ -93,6 +93,10 @@ class rcube_image $convert = $rcube->config->get('im_convert_path', false); $props = $this->props(); + if (empty($props)) { + return false; + } + if (!$filename) { $filename = $this->image_file; } @@ -148,6 +152,10 @@ class rcube_image return false; } + if ($image === false) { + return false; + } + $scale = $size / max($props['width'], $props['height']); // Imagemagick resize is implemented in shrinking mode (see -resize argument above) diff --git a/program/lib/Roundcube/rcube_imap.php b/program/lib/Roundcube/rcube_imap.php index 43c61fd81..b60aefc5f 100644 --- a/program/lib/Roundcube/rcube_imap.php +++ b/program/lib/Roundcube/rcube_imap.php @@ -308,14 +308,7 @@ class rcube_imap extends rcube_storage */ public function set_folder($folder) { - if ($this->folder == $folder) { - return; - } - $this->folder = $folder; - - // clear messagecount cache for this folder - $this->clear_messagecount($folder); } @@ -626,7 +619,7 @@ class rcube_imap extends rcube_storage } if ($mode == 'THREADS') { - $res = $this->fetch_threads($folder, $force); + $res = $this->threads($folder); $count = $res->count(); if ($status) { @@ -656,11 +649,11 @@ class rcube_imap extends rcube_storage $keys[] = 'ALL'; } if ($status) { - $keys[] = 'MAX'; + $keys[] = 'MAX'; } } - // @TODO: if $force==false && $mode == 'ALL' we could try to use cache index here + // @TODO: if $mode == 'ALL' we could try to use cache index here // get message count using (E)SEARCH // not very performant but more precise (using UNDELETED) @@ -791,7 +784,7 @@ class rcube_imap extends rcube_storage $threads = $mcache->get_thread($folder); } else { - $threads = $this->fetch_threads($folder); + $threads = $this->threads($folder); } return $this->fetch_thread_headers($folder, $threads, $page, $slice); @@ -800,32 +793,47 @@ class rcube_imap extends rcube_storage /** * Method for fetching threads data * - * @param string $folder Folder name - * @param bool $force Use IMAP server, no cache + * @param string $folder Folder name * * @return rcube_imap_thread Thread data object */ - function fetch_threads($folder, $force = false) + function threads($folder) { - if (!$force && ($mcache = $this->get_mcache_engine())) { + if ($mcache = $this->get_mcache_engine()) { // don't store in self's internal cache, cache has it's own internal cache return $mcache->get_thread($folder); } - if (empty($this->icache['threads'])) { - if (!$this->check_connection()) { - return new rcube_result_thread(); + if (!empty($this->icache['threads'])) { + if ($this->icache['threads']->get_parameters('MAILBOX') == $folder) { + return $this->icache['threads']; } + } - // get all threads - $result = $this->conn->thread($folder, $this->threading, - $this->options['skip_deleted'] ? 'UNDELETED' : '', true); + // get all threads + $result = $this->threads_direct($folder); - // add to internal (fast) cache - $this->icache['threads'] = $result; + // add to internal (fast) cache + return $this->icache['threads'] = $result; + } + + + /** + * Method for direct fetching of threads data + * + * @param string $folder Folder name + * + * @return rcube_imap_thread Thread data object + */ + function threads_direct($folder) + { + if (!$this->check_connection()) { + return new rcube_result_thread(); } - return $this->icache['threads']; + // get all threads + return $this->conn->thread($folder, $this->threading, + $this->options['skip_deleted'] ? 'UNDELETED' : '', true); } @@ -1180,12 +1188,15 @@ class rcube_imap extends rcube_storage * @param string $folder Folder to get index from * @param string $sort_field Sort column * @param string $sort_order Sort order [ASC, DESC] + * @param bool $no_threads Get not threaded index + * @param bool $no_search Get index not limited to search result (optionally) * * @return rcube_result_index|rcube_result_thread List of messages (UIDs) */ - public function index($folder = '', $sort_field = NULL, $sort_order = NULL) - { - if ($this->threading) { + public function index($folder = '', $sort_field = NULL, $sort_order = NULL, + $no_threads = false, $no_search = false + ) { + if (!$no_threads && $this->threading) { return $this->thread_index($folder, $sort_field, $sort_order); } @@ -1197,43 +1208,50 @@ class rcube_imap extends rcube_storage // we have a saved search result, get index from there if ($this->search_string) { - if ($this->search_threads) { - $this->search($folder, $this->search_string, $this->search_charset, $this->sort_field); + if ($this->search_set->is_empty()) { + return new rcube_result_index($folder, '* SORT'); } - // use message index sort as default sorting - if (!$this->sort_field || $this->search_sorted) { - if ($this->sort_field && $this->search_sort_field != $this->sort_field) { - $this->search($folder, $this->search_string, $this->search_charset, $this->sort_field); - } + // search result is an index with the same sorting? + if (($this->search_set instanceof rcube_result_index) + && ((!$this->sort_field && !$this->search_sorted) || + ($this->search_sorted && $this->search_sort_field == $this->sort_field)) + ) { $index = $this->search_set; } - else if (!$this->check_connection()) { - return new rcube_result_index(); - } - else { - $index = $this->conn->index($folder, $this->search_set->get(), - $this->sort_field, $this->options['skip_deleted'], true, true); + // $no_search is enabled when we are not interested in + // fetching index for search result, e.g. to sort + // threaded search result we can use full mailbox index. + // This makes possible to use index from cache + else if (!$no_search) { + if (!$this->sort_field) { + // No sorting needed, just build index from the search result + // @TODO: do we need to sort by UID here? + $search = $this->search_set->get_compressed(); + $index = new rcube_result_index($folder, '* ESEARCH ALL ' . $search); + } + else { + $index = $this->index_direct($folder, $this->search_charset, + $this->sort_field, $this->search_set); + } } - if ($this->sort_order != $index->get_parameters('ORDER')) { - $index->revert(); - } + if (isset($index)) { + if ($this->sort_order != $index->get_parameters('ORDER')) { + $index->revert(); + } - return $index; + return $index; + } } // check local cache if ($mcache = $this->get_mcache_engine()) { - $index = $mcache->get_index($folder, $this->sort_field, $this->sort_order); - } - // fetch from IMAP server - else { - $index = $this->index_direct( - $folder, $this->sort_field, $this->sort_order); + return $mcache->get_index($folder, $this->sort_field, $this->sort_order); } - return $index; + // fetch from IMAP server + return $this->index_direct($folder, $this->sort_field, $this->sort_order); } @@ -1241,22 +1259,24 @@ class rcube_imap extends rcube_storage * Return sorted list of message UIDs ignoring current search settings. * Doesn't uses cache by default. * - * @param string $folder Folder to get index from - * @param string $sort_field Sort column - * @param string $sort_order Sort order [ASC, DESC] - * @param bool $skip_cache Disables cache usage + * @param string $folder Folder to get index from + * @param string $sort_field Sort column + * @param string $sort_order Sort order [ASC, DESC] + * @param rcube_result_* $search Optional messages set to limit the result * * @return rcube_result_index Sorted list of message UIDs */ - public function index_direct($folder, $sort_field = null, $sort_order = null, $skip_cache = true) + public function index_direct($folder, $sort_field = null, $sort_order = null, $search = null) { - if (!$skip_cache && ($mcache = $this->get_mcache_engine())) { - $index = $mcache->get_index($folder, $sort_field, $sort_order); + if (!empty($search)) { + $search = $this->search_set->get_compressed(); } + // use message index sort as default sorting - else if (!$sort_field) { + if (!$sort_field) { // use search result from count() if possible - if ($this->options['skip_deleted'] && !empty($this->icache['undeleted_idx']) + if (empty($search) && $this->options['skip_deleted'] + && !empty($this->icache['undeleted_idx']) && $this->icache['undeleted_idx']->get_parameters('ALL') !== null && $this->icache['undeleted_idx']->get_parameters('MAILBOX') == $folder ) { @@ -1266,8 +1286,12 @@ class rcube_imap extends rcube_storage return new rcube_result_index(); } else { - $index = $this->conn->search($folder, - 'ALL' .($this->options['skip_deleted'] ? ' UNDELETED' : ''), true); + $query = $this->options['skip_deleted'] ? 'UNDELETED' : ''; + if ($search) { + $query = trim($query . ' UID ' . $search); + } + + $index = $this->conn->search($folder, $query, true); } } else if (!$this->check_connection()) { @@ -1276,13 +1300,18 @@ class rcube_imap extends rcube_storage // fetch complete message index else { if ($this->get_capability('SORT')) { - $index = $this->conn->sort($folder, $sort_field, - $this->options['skip_deleted'] ? 'UNDELETED' : '', true); + $query = $this->options['skip_deleted'] ? 'UNDELETED' : ''; + if ($search) { + $query = trim($query . ' UID ' . $search); + } + + $index = $this->conn->sort($folder, $sort_field, $query, true); } if (empty($index) || $index->is_error()) { - $index = $this->conn->index($folder, "1:*", $sort_field, - $this->options['skip_deleted'], false, true); + $index = $this->conn->index($folder, $search ? $search : "1:*", + $sort_field, $this->options['skip_deleted'], + $search ? true : false, true); } } @@ -1315,7 +1344,7 @@ class rcube_imap extends rcube_storage } else { // get all threads (default sort order) - $threads = $this->fetch_threads($folder); + $threads = $this->threads($folder); } $this->set_sort_order($sort_field, $sort_order); @@ -1326,9 +1355,10 @@ class rcube_imap extends rcube_storage /** - * Sort threaded result, using THREAD=REFS method + * Sort threaded result, using THREAD=REFS method if available. + * If not, use any method and re-sort the result in THREAD=REFS way. * - * @param rcube_result_thread $threads Threads result set + * @param rcube_result_thread $threads Threads result set */ protected function sort_threads($threads) { @@ -1340,17 +1370,16 @@ class rcube_imap extends rcube_storage // THREAD=REFERENCES: sorting by sent date of root message // THREAD=REFS: sorting by the most recent date in each thread - if ($this->sort_field && ($this->sort_field != 'date' || $this->get_capability('THREAD') != 'REFS')) { - $index = $this->index_direct($this->folder, $this->sort_field, $this->sort_order, false); + if ($this->threading != 'REFS' || ($this->sort_field && $this->sort_field != 'date')) { + $sortby = $this->sort_field ? $this->sort_field : 'date'; + $index = $this->index($this->folder, $sortby, $this->sort_order, true, true); if (!$index->is_empty()) { $threads->sort($index); } } - else { - if ($this->sort_order != $threads->get_parameters('ORDER')) { - $threads->revert(); - } + else if ($this->sort_order != $threads->get_parameters('ORDER')) { + $threads->revert(); } } @@ -2238,13 +2267,14 @@ class rcube_imap extends rcube_storage /** * Append a mail message (source) to a specific folder * - * @param string $folder Target folder - * @param string $message The message source string or filename - * @param string $headers Headers string if $message contains only the body - * @param boolean $is_file True if $message is a filename - * @param array $flags Message flags - * @param mixed $date Message internal date - * @param bool $binary Enables BINARY append + * @param string $folder Target folder + * @param string|array $message The message source string or filename + * or array (of strings and file pointers) + * @param string $headers Headers string if $message contains only the body + * @param boolean $is_file True if $message is a filename + * @param array $flags Message flags + * @param mixed $date Message internal date + * @param bool $binary Enables BINARY append * * @return int|bool Appended message UID or True on success, False on error */ @@ -2637,7 +2667,6 @@ class rcube_imap extends rcube_storage if ($list_extended) { // unsubscribe non-existent folders, remove from the list - // we can do this only when LIST response is available if (is_array($a_folders) && $name == '*' && !empty($this->conn->data['LIST'])) { foreach ($a_folders as $idx => $folder) { if (($opts = $this->conn->data['LIST'][$folder]) @@ -2650,19 +2679,14 @@ class rcube_imap extends rcube_storage } } else { - // unsubscribe non-existent folders, remove them from the list, - // we can do this only when LIST response is available - if (is_array($a_folders) && $name == '*' && !empty($this->conn->data['LIST'])) { - foreach ($a_folders as $idx => $folder) { - if (!isset($this->conn->data['LIST'][$folder]) - || in_array('\\Noselect', $this->conn->data['LIST'][$folder]) - ) { - // Some servers returns \Noselect for existing folders - if (!$this->folder_exists($folder)) { - $this->conn->unsubscribe($folder); - unset($a_folders[$idx]); - } - } + // unsubscribe non-existent folders, remove them from the list + if (is_array($a_folders) && !empty($a_folders) && $name == '*') { + $existing = $this->list_folders($root, $name); + $nonexisting = array_diff($a_folders, $existing); + $a_folders = array_diff($a_folders, $nonexisting); + + foreach ($nonexisting as $folder) { + $this->conn->unsubscribe($folder); } } } @@ -3691,7 +3715,7 @@ class rcube_imap extends rcube_storage { if ($this->caching && !$this->cache) { $rcube = rcube::get_instance(); - $ttl = $rcube->config->get('message_cache_lifetime', '10d'); + $ttl = $rcube->config->get('imap_cache_ttl', '10d'); $this->cache = $rcube->get_cache('IMAP', $this->caching, $ttl); } @@ -3739,21 +3763,6 @@ class rcube_imap extends rcube_storage } } - /** - * Delete outdated cache entries - */ - public function expunge_cache() - { - if ($this->mcache) { - $ttl = rcube::get_instance()->config->get('message_cache_lifetime', '10d'); - $this->mcache->expunge($ttl); - } - - if ($this->cache) { - $this->cache->expunge(); - } - } - /* -------------------------------- * message caching methods @@ -3787,8 +3796,9 @@ class rcube_imap extends rcube_storage if ($this->messages_caching && !$this->mcache) { $rcube = rcube::get_instance(); if (($dbh = $rcube->get_dbh()) && ($userid = $rcube->get_user_id())) { + $ttl = $rcube->config->get('messages_cache_ttl', '10d'); $this->mcache = new rcube_imap_cache( - $dbh, $this, $userid, $this->options['skip_deleted']); + $dbh, $this, $userid, $this->options['skip_deleted'], $ttl); } } @@ -3810,6 +3820,15 @@ class rcube_imap extends rcube_storage } + /** + * Delete outdated cache entries + */ + function cache_gc() + { + rcube_imap_cache::gc(); + } + + /* -------------------------------- * protected methods * --------------------------------*/ @@ -4103,9 +4122,9 @@ class rcube_imap extends rcube_storage return $this->index($folder, $sort_field, $sort_order); } - public function message_index_direct($folder, $sort_field = null, $sort_order = null, $skip_cache = true) + public function message_index_direct($folder, $sort_field = null, $sort_order = null) { - return $this->index_direct($folder, $sort_field, $sort_order, $skip_cache); + return $this->index_direct($folder, $sort_field, $sort_order); } public function list_mailboxes($root='', $name='*', $filter=null, $rights=null, $skip_sort=false) diff --git a/program/lib/Roundcube/rcube_imap_cache.php b/program/lib/Roundcube/rcube_imap_cache.php index 47d9aaf4a..061ac546d 100644 --- a/program/lib/Roundcube/rcube_imap_cache.php +++ b/program/lib/Roundcube/rcube_imap_cache.php @@ -49,6 +49,13 @@ class rcube_imap_cache private $userid; /** + * Expiration time in seconds + * + * @var int + */ + private $ttl; + + /** * Internal (in-memory) cache * * @var array @@ -83,13 +90,25 @@ class rcube_imap_cache /** * Object constructor. + * + * @param rcube_db $db DB handler + * @param rcube_imap $imap IMAP handler + * @param int $userid User identifier + * @param bool $skip_deleted skip_deleted flag + * @param string $ttl Expiration time of memcache/apc items + * */ - function __construct($db, $imap, $userid, $skip_deleted) + function __construct($db, $imap, $userid, $skip_deleted, $ttl=0) { + // convert ttl string to seconds + $ttl = get_offset_sec($ttl); + if ($ttl > 2592000) $ttl = 2592000; + $this->db = $db; $this->imap = $imap; $this->userid = $userid; $this->skip_deleted = $skip_deleted; + $this->ttl = $ttl; } @@ -215,9 +234,7 @@ class rcube_imap_cache * Return messages thread. * If threaded index doesn't exist or is invalid, will be updated. * - * @param string $mailbox Folder name - * @param string $sort_field Sorting column - * @param string $sort_order Sorting order (ASC|DESC) + * @param string $mailbox Folder name * * @return array Messages threaded index */ @@ -256,19 +273,11 @@ class rcube_imap_cache if ($index === null) { // Get mailbox data (UIDVALIDITY, counters, etc.) for status check $mbox_data = $this->imap->folder_data($mailbox); - - if ($mbox_data['EXISTS']) { - // get all threads (default sort order) - $threads = $this->imap->fetch_threads($mailbox, true); - } - else { - $threads = new rcube_result_thread($mailbox, '* THREAD'); - } - - $index['object'] = $threads; + // Get THREADS result + $index['object'] = $this->get_thread_data($mailbox, $mbox_data); // insert/update - $this->add_thread_row($mailbox, $threads, $mbox_data, $exists); + $this->add_thread_row($mailbox, $index['object'], $mbox_data, $exists); } $this->icache[$mailbox]['thread'] = $index; @@ -407,8 +416,8 @@ class rcube_imap_cache return; } - $msg = serialize($this->db->encode(clone $message)); $flags = 0; + $msg = clone $message; if (!empty($message->flags)) { foreach ($this->flags as $idx => $flag) { @@ -417,14 +426,16 @@ class rcube_imap_cache } } } + unset($msg->flags); + $msg = $this->db->encode($msg, true); // update cache record (even if it exists, the update // here will work as select, assume row exist if affected_rows=0) if (!$force) { $res = $this->db->query( "UPDATE ".$this->db->table_name('cache_messages') - ." SET flags = ?, data = ?, changed = ".$this->db->now() + ." SET flags = ?, data = ?, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') ." WHERE user_id = ?" ." AND mailbox = ?" ." AND uid = ?", @@ -435,12 +446,29 @@ class rcube_imap_cache } } + $this->db->set_option('ignore_key_errors', true); + // insert new record - $this->db->query( + $res = $this->db->query( "INSERT INTO ".$this->db->table_name('cache_messages') - ." (user_id, mailbox, uid, flags, changed, data)" - ." VALUES (?, ?, ?, ?, ".$this->db->now().", ?)", + ." (user_id, mailbox, uid, flags, expires, data)" + ." VALUES (?, ?, ?, ?, ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?)", $this->userid, $mailbox, (int) $message->uid, $flags, $msg); + + // race-condition, insert failed so try update (#1489146) + // thanks to ignore_key_errors "duplicate row" errors will be ignored + if ($force && !$res && !$this->db->is_error($res)) { + $this->db->query( + "UPDATE ".$this->db->table_name('cache_messages') + ." SET expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') + .", flags = ?, data = ?" + ." WHERE user_id = ?" + ." AND mailbox = ?" + ." AND uid = ?", + $flags, $msg, $this->userid, $mailbox, (int) $message->uid); + } + + $this->db->set_option('ignore_key_errors', false); } @@ -481,7 +509,7 @@ class rcube_imap_cache $this->db->query( "UPDATE ".$this->db->table_name('cache_messages') - ." SET changed = ".$this->db->now() + ." SET expires = ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL') .", flags = flags ".($enabled ? "+ $idx" : "- $idx") ." WHERE user_id = ?" ." AND mailbox = ?" @@ -604,23 +632,21 @@ class rcube_imap_cache /** - * Delete cache entries older than TTL - * - * @param string $ttl Lifetime of message cache entries + * Delete expired cache entries */ - function expunge($ttl) + static function gc() { - // get expiration timestamp - $ts = get_offset_time($ttl, -1); + $rcube = rcube::get_instance(); + $db = $rcube->get_dbh(); - $this->db->query("DELETE FROM ".$this->db->table_name('cache_messages') - ." WHERE changed < " . $this->db->fromunixtime($ts)); + $db->query("DELETE FROM ".$db->table_name('cache_messages') + ." WHERE expires < " . $db->now()); - $this->db->query("DELETE FROM ".$this->db->table_name('cache_index') - ." WHERE changed < " . $this->db->fromunixtime($ts)); + $db->query("DELETE FROM ".$db->table_name('cache_index') + ." WHERE expires < " . $db->now()); - $this->db->query("DELETE FROM ".$this->db->table_name('cache_thread') - ." WHERE changed < " . $this->db->fromunixtime($ts)); + $db->query("DELETE FROM ".$db->table_name('cache_thread') + ." WHERE expires < " . $db->now()); } @@ -639,7 +665,7 @@ class rcube_imap_cache if ($sql_arr = $this->db->fetch_assoc($sql_result)) { $data = explode('@', $sql_arr['data']); - $index = @unserialize($data[0]); + $index = $this->db->decode($data[0], true); unset($data[0]); if (empty($index)) { @@ -676,7 +702,7 @@ class rcube_imap_cache if ($sql_arr = $this->db->fetch_assoc($sql_result)) { $data = explode('@', $sql_arr['data']); - $thread = @unserialize($data[0]); + $thread = $this->db->decode($data[0], true); unset($data[0]); if (empty($thread)) { @@ -702,7 +728,7 @@ class rcube_imap_cache $data, $mbox_data = array(), $exists = false, $modseq = null) { $data = array( - serialize($data), + $this->db->encode($data, true), $sort_field, (int) $this->skip_deleted, (int) $mbox_data['UIDVALIDITY'], @@ -712,20 +738,38 @@ class rcube_imap_cache $data = implode('@', $data); if ($exists) { - $sql_result = $this->db->query( + $res = $this->db->query( "UPDATE ".$this->db->table_name('cache_index') - ." SET data = ?, valid = 1, changed = ".$this->db->now() + ." SET data = ?, valid = 1, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') ." WHERE user_id = ?" ." AND mailbox = ?", $data, $this->userid, $mailbox); + + if ($this->db->affected_rows($res)) { + return; + } } - else { - $sql_result = $this->db->query( - "INSERT INTO ".$this->db->table_name('cache_index') - ." (user_id, mailbox, data, valid, changed)" - ." VALUES (?, ?, ?, 1, ".$this->db->now().")", - $this->userid, $mailbox, $data); + + $this->db->set_option('ignore_key_errors', true); + + $res = $this->db->query( + "INSERT INTO ".$this->db->table_name('cache_index') + ." (user_id, mailbox, valid, expires, data)" + ." VALUES (?, ?, 1, ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL') .", ?)", + $this->userid, $mailbox, $data); + + // race-condition, insert failed so try update (#1489146) + // thanks to ignore_key_errors "duplicate row" errors will be ignored + if (!$exists && !$res && !$this->db->is_error($res)) { + $res = $this->db->query( + "UPDATE ".$this->db->table_name('cache_index') + ." SET data = ?, valid = 1, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') + ." WHERE user_id = ?" + ." AND mailbox = ?", + $data, $this->userid, $mailbox); } + + $this->db->set_option('ignore_key_errors', false); } @@ -735,28 +779,48 @@ class rcube_imap_cache private function add_thread_row($mailbox, $data, $mbox_data = array(), $exists = false) { $data = array( - serialize($data), + $this->db->encode($data, true), (int) $this->skip_deleted, (int) $mbox_data['UIDVALIDITY'], (int) $mbox_data['UIDNEXT'], ); $data = implode('@', $data); + $expires = ($this->ttl ? $this->db->now($this->ttl) : 'NULL'); + if ($exists) { - $sql_result = $this->db->query( + $res = $this->db->query( "UPDATE ".$this->db->table_name('cache_thread') - ." SET data = ?, changed = ".$this->db->now() + ." SET data = ?, expires = $expires" ." WHERE user_id = ?" ." AND mailbox = ?", $data, $this->userid, $mailbox); + + if ($this->db->affected_rows($res)) { + return; + } } - else { - $sql_result = $this->db->query( - "INSERT INTO ".$this->db->table_name('cache_thread') - ." (user_id, mailbox, data, changed)" - ." VALUES (?, ?, ?, ".$this->db->now().")", - $this->userid, $mailbox, $data); + + $this->db->set_option('ignore_key_errors', true); + + $res = $this->db->query( + "INSERT INTO ".$this->db->table_name('cache_thread') + ." (user_id, mailbox, expires, data)" + ." VALUES (?, ?, $expires, ?)", + $this->userid, $mailbox, $data); + + // race-condition, insert failed so try update (#1489146) + // thanks to ignore_key_errors "duplicate row" errors will be ignored + if (!$exists && !$res && !$this->db->is_error($res)) { + $this->db->query( + "UPDATE ".$this->db->table_name('cache_thread') + ." SET expires = $expires, data = ?" + ." WHERE user_id = ?" + ." AND mailbox = ?", + $data, $this->userid, $mailbox); } + + $this->db->set_option('ignore_key_errors', false); } @@ -1004,7 +1068,7 @@ class rcube_imap_cache $this->db->query( "UPDATE ".$this->db->table_name('cache_messages') - ." SET flags = ?, changed = ".$this->db->now() + ." SET flags = ?, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') ." WHERE user_id = ?" ." AND mailbox = ?" ." AND uid = ?" @@ -1032,17 +1096,18 @@ class rcube_imap_cache } } - // Invalidate thread index (?) - if (!$index['valid']) { - $this->remove_thread($mailbox); - } - $sort_field = $index['sort_field']; $sort_order = $index['object']->get_parameters('ORDER'); $exists = true; // Validate index if (!$this->validate($mailbox, $index, $exists)) { + // Invalidate (remove) thread index + // if $exists=false it was already removed in validate() + if ($exists) { + $this->remove_thread($mailbox); + } + // Update index $data = $this->get_index_data($mailbox, $sort_field, $sort_order, $mbox_data); } @@ -1067,7 +1132,7 @@ class rcube_imap_cache */ private function build_message($sql_arr) { - $message = $this->db->decode(unserialize($sql_arr['data'])); + $message = $this->db->decode($sql_arr['data'], true); if ($message) { $message->flags = array(); @@ -1150,6 +1215,25 @@ class rcube_imap_cache return $index; } + + + /** + * Fetches thread data from IMAP server + */ + private function get_thread_data($mailbox, $mbox_data = array()) + { + if (empty($mbox_data)) { + $mbox_data = $this->imap->folder_data($mailbox); + } + + if ($mbox_data['EXISTS']) { + // get all threads (default sort order) + return $this->imap->threads_direct($mailbox); + } + + return new rcube_result_thread($mailbox, '* THREAD'); + } + } // for backward compat. diff --git a/program/lib/Roundcube/rcube_imap_generic.php b/program/lib/Roundcube/rcube_imap_generic.php index 292b932e1..920c7184a 100644 --- a/program/lib/Roundcube/rcube_imap_generic.php +++ b/program/lib/Roundcube/rcube_imap_generic.php @@ -715,6 +715,10 @@ class rcube_imap_generic $auth_method = 'CHECK'; } + if (!empty($this->prefs['disabled_caps'])) { + $this->prefs['disabled_caps'] = array_map('strtoupper', (array)$this->prefs['disabled_caps']); + } + $result = false; // initialize connection @@ -1329,9 +1333,8 @@ class rcube_imap_generic $folders[$mailbox] = array(); } - // store LSUB options only if not empty, this way - // we can detect a situation when LIST doesn't return specified folder - if (!empty($opts) || $cmd == 'LIST') { + // store folder options + if ($cmd == 'LIST') { // Add to options array if (empty($this->data['LIST'][$mailbox])) $this->data['LIST'][$mailbox] = $opts; @@ -1563,11 +1566,12 @@ class rcube_imap_generic } // message IDs - if (!empty($add)) + if (!empty($add)) { $add = $this->compressMessageSet($add); + } list($code, $response) = $this->execute($return_uid ? 'UID SORT' : 'SORT', - array("($field)", $encoding, 'ALL' . (!empty($add) ? ' '.$add : ''))); + array("($field)", $encoding, !empty($add) ? $add : 'ALL')); if ($code != self::ERROR_OK) { $response = null; @@ -2158,14 +2162,18 @@ class rcube_imap_generic else if ($name == 'RFC822') { $result[$id]->body = $value; } - else if ($name == 'BODY') { - $body = $this->tokenizeResponse($line, 1); - if ($value[0] == 'HEADER.FIELDS') - $headers = $body; - else if (!empty($value)) - $result[$id]->bodypart[$value[0]] = $body; + else if (stripos($name, 'BODY[') === 0) { + $name = str_replace(']', '', substr($name, 5)); + + if ($name == 'HEADER.FIELDS') { + // skip ']' after headers list + $this->tokenizeResponse($line, 1); + $headers = $this->tokenizeResponse($line, 1); + } + else if (strlen($name)) + $result[$id]->bodypart[$name] = $value; else - $result[$id]->body = $body; + $result[$id]->body = $value; } } @@ -2505,6 +2513,7 @@ class rcube_imap_generic // handle one line response if ($line[0] == '(' && substr($line, -1) == ')') { // tokenize content inside brackets + // the content can be e.g.: (UID 9844 BODY[2.4] NIL) $tokens = $this->tokenizeResponse(preg_replace('/(^\(|\)$)/', '', $line)); for ($i=0; $i<count($tokens); $i+=2) { @@ -2533,7 +2542,11 @@ class rcube_imap_generic $prev = ''; $found = true; - while ($bytes > 0) { + // empty body + if (!$bytes) { + $result = ''; + } + else while ($bytes > 0) { $line = $this->readLine(8192); if ($line === NULL) { @@ -2615,11 +2628,11 @@ class rcube_imap_generic /** * Handler for IMAP APPEND command * - * @param string $mailbox Mailbox name - * @param string $message Message content - * @param array $flags Message flags - * @param string $date Message internal date - * @param bool $binary Enable BINARY append (RFC3516) + * @param string $mailbox Mailbox name + * @param string|array $message The message source string or array (of strings and file pointers) + * @param array $flags Message flags + * @param string $date Message internal date + * @param bool $binary Enable BINARY append (RFC3516) * * @return string|bool On success APPENDUID response (if available) or True, False on failure */ @@ -2633,13 +2646,28 @@ class rcube_imap_generic $binary = $binary && $this->getCapability('BINARY'); $literal_plus = !$binary && $this->prefs['literal+']; + $len = 0; + $msg = is_array($message) ? $message : array(&$message); + $chunk_size = 512000; + + for ($i=0, $cnt=count($msg); $i<$cnt; $i++) { + if (is_resource($msg[$i])) { + $stat = fstat($msg[$i]); + if ($stat === false) { + return false; + } + $len += $stat['size']; + } + else { + if (!$binary) { + $msg[$i] = str_replace("\r", '', $msg[$i]); + $msg[$i] = str_replace("\n", "\r\n", $msg[$i]); + } - if (!$binary) { - $message = str_replace("\r", '', $message); - $message = str_replace("\n", "\r\n", $message); + $len += strlen($msg[$i]); + } } - $len = strlen($message); if (!$len) { return false; } @@ -2664,7 +2692,32 @@ class rcube_imap_generic } } - if (!$this->putLine($message)) { + foreach ($msg as $msg_part) { + // file pointer + if (is_resource($msg_part)) { + rewind($msg_part); + while (!feof($msg_part) && $this->fp) { + $buffer = fread($msg_part, $chunk_size); + $this->putLine($buffer, false); + } + fclose($msg_part); + } + // string + else { + $size = strlen($msg_part); + + // Break up the data by sending one chunk (up to 512k) at a time. + // This approach reduces our peak memory usage + for ($offset = 0; $offset < $size; $offset += $chunk_size) { + $chunk = substr($msg_part, $offset, $chunk_size); + if (!$this->putLine($chunk, false)) { + return false; + } + } + } + } + + if (!$this->putLine('')) { // \r\n return false; } @@ -2703,94 +2756,23 @@ class rcube_imap_generic */ function appendFromFile($mailbox, $path, $headers=null, $flags = array(), $date = null, $binary = false) { - unset($this->data['APPENDUID']); - - if ($mailbox === null || $mailbox === '') { - return false; - } - // open message file - $in_fp = false; if (file_exists(realpath($path))) { - $in_fp = fopen($path, 'r'); + $fp = fopen($path, 'r'); } - if (!$in_fp) { + if (!$fp) { $this->setError(self::ERROR_UNKNOWN, "Couldn't open $path for reading"); return false; } - $body_separator = "\r\n\r\n"; - $len = filesize($path); - - if (!$len) { - return false; - } - + $message = array(); if ($headers) { - $headers = preg_replace('/[\r\n]+$/', '', $headers); - $len += strlen($headers) + strlen($body_separator); + $message[] = trim($headers, "\r\n") . "\r\n\r\n"; } + $message[] = $fp; - $binary = $binary && $this->getCapability('BINARY'); - $literal_plus = !$binary && $this->prefs['literal+']; - - // build APPEND command - $key = $this->nextTag(); - $request = "$key APPEND " . $this->escape($mailbox) . ' (' . $this->flagsToStr($flags) . ')'; - if (!empty($date)) { - $request .= ' ' . $this->escape($date); - } - $request .= ' ' . ($binary ? '~' : '') . '{' . $len . ($literal_plus ? '+' : '') . '}'; - - // send APPEND command - if ($this->putLine($request)) { - // Don't wait when LITERAL+ is supported - if (!$literal_plus) { - $line = $this->readReply(); - - if ($line[0] != '+') { - $this->parseResult($line, 'APPEND: '); - return false; - } - } - - // send headers with body separator - if ($headers) { - $this->putLine($headers . $body_separator, false); - } - - // send file - while (!feof($in_fp) && $this->fp) { - $buffer = fgets($in_fp, 4096); - $this->putLine($buffer, false); - } - fclose($in_fp); - - if (!$this->putLine('')) { // \r\n - return false; - } - - // read response - do { - $line = $this->readLine(); - } while (!$this->startsWith($line, $key, true, true)); - - // Clear internal status cache - unset($this->data['STATUS:'.$mailbox]); - - if ($this->parseResult($line, 'APPEND: ') != self::ERROR_OK) - return false; - else if (!empty($this->data['APPENDUID'])) - return $this->data['APPENDUID']; - else - return true; - } - else { - $this->setError(self::ERROR_COMMAND, "Unable to send command: $request"); - } - - return false; + return $this->append($mailbox, $message, $flags, $date, $binary); } /** @@ -3008,7 +2990,7 @@ class rcube_imap_generic } foreach ($entries as $name => $value) { - $entries[$name] = $this->escape($name) . ' ' . $this->escape($value); + $entries[$name] = $this->escape($name) . ' ' . $this->escape($value, true); } $entries = implode(' ', $entries); @@ -3505,25 +3487,24 @@ class rcube_imap_generic // Parenthesized list case '(': - case '[': $str = substr($str, 1); $result[] = self::tokenizeResponse($str); break; case ')': - case ']': $str = substr($str, 1); return $result; break; - // String atom, number, NIL, *, % + // String atom, number, astring, NIL, *, % default: // empty string if ($str === '' || $str === null) { break 2; } - // excluded chars: SP, CTL, ), [, ] - if (preg_match('/^([^\x00-\x20\x29\x5B\x5D\x7F]+)/', $str, $m)) { + // excluded chars: SP, CTL, ), DEL + // we do not exclude [ and ] (#1489223) + if (preg_match('/^([^\x00-\x20\x29\x7F]+)/', $str, $m)) { $result[] = $m[1] == 'NIL' ? NULL : $m[1]; $str = substr($str, strlen($m[1])); } @@ -3714,6 +3695,10 @@ class rcube_imap_generic $this->capability = explode(' ', strtoupper($str)); + if (!empty($this->prefs['disabled_caps'])) { + $this->capability = array_diff($this->capability, $this->prefs['disabled_caps']); + } + if (!isset($this->prefs['literal+']) && in_array('LITERAL+', $this->capability)) { $this->prefs['literal+'] = true; } diff --git a/program/lib/Roundcube/rcube_ldap.php b/program/lib/Roundcube/rcube_ldap.php index 70163b21c..555a56471 100644 --- a/program/lib/Roundcube/rcube_ldap.php +++ b/program/lib/Roundcube/rcube_ldap.php @@ -3,8 +3,8 @@ /* +-----------------------------------------------------------------------+ | This file is part of the Roundcube Webmail client | - | Copyright (C) 2006-2012, The Roundcube Dev Team | - | Copyright (C) 2011-2012, Kolab Systems AG | + | Copyright (C) 2006-2013, The Roundcube Dev Team | + | Copyright (C) 2011-2013, Kolab Systems AG | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -27,38 +27,50 @@ */ class rcube_ldap extends rcube_addressbook { - /** public properties */ + // public properties public $primary_key = 'ID'; - public $groups = false; - public $readonly = true; - public $ready = false; - public $group_id = 0; - public $coltypes = array(); - - /** private properties */ - protected $conn; - protected $prop = array(); + public $groups = false; + public $readonly = true; + public $ready = false; + public $group_id = 0; + public $coltypes = array(); + + // private properties + protected $ldap; + protected $prop = array(); protected $fieldmap = array(); + protected $filter = ''; protected $sub_filter; - protected $filter = ''; - protected $result = null; - protected $ldap_result = null; + protected $result; + protected $ldap_result; protected $mail_domain = ''; protected $debug = false; - private $base_dn = ''; + /** + * Group objectclass (lowercase) to member attribute mapping + * + * @var array + */ + private static $group_types = array( + 'group' => 'member', + 'groupofnames' => 'member', + 'kolabgroupofnames' => 'member', + 'groupofuniquenames' => 'uniqueMember', + 'kolabgroupofuniquenames' => 'uniqueMember', + 'univentiongroup' => 'uniqueMember', + 'groupofurls' => null, + ); + + private $base_dn = ''; private $groups_base_dn = ''; - private $group_url = null; + private $group_url; private $cache; - private $vlv_active = false; - private $vlv_count = 0; - /** * Object constructor * - * @param array $p LDAP connection properties + * @param array $p LDAP connection properties * @param boolean $debug Enables debug mode * @param string $mail_domain Current user mail domain name */ @@ -66,8 +78,7 @@ class rcube_ldap extends rcube_addressbook { $this->prop = $p; - if (isset($p['searchonly'])) - $this->searchonly = $p['searchonly']; + $fetch_attributes = array('objectClass'); // check if groups are configured if (is_array($p['groups']) && count($p['groups'])) { @@ -82,6 +93,21 @@ class rcube_ldap extends rcube_addressbook $this->prop['groups']['name_attr'] = 'cn'; if (empty($this->prop['groups']['scope'])) $this->prop['groups']['scope'] = 'sub'; + + // add group name attrib to the list of attributes to be fetched + $fetch_attributes[] = $this->prop['groups']['name_attr']; + } + if (is_array($p['group_filters']) && count($p['group_filters'])) { + $this->groups = true; + + foreach ($p['group_filters'] as $k => $group_filter) { + // set default name attribute to cn + if (empty($group_filter['name_attr']) && empty($this->prop['groups']['name_attr'])) + $this->prop['group_filters'][$k]['name_attr'] = $group_filter['name_attr'] = 'cn'; + + if ($group_filter['name_attr']) + $fetch_attributes[] = $group_filter['name_attr']; + } } // fieldmap property is given @@ -186,7 +212,24 @@ class rcube_ldap extends rcube_addressbook // initialize cache $rcube = rcube::get_instance(); - $this->cache = $rcube->get_cache('LDAP.' . asciiwords($this->prop['name']), 'db', 600); + if ($cache_type = $rcube->config->get('ldap_cache', 'db')) { + $cache_ttl = $rcube->config->get('ldap_cache_ttl', '10m'); + $cache_name = 'LDAP.' . asciiwords($this->prop['name']); + + $this->cache = $rcube->get_cache($cache_name, $cache_type, $cache_ttl); + } + + // determine which attributes to fetch + $this->prop['list_attributes'] = array_unique($fetch_attributes); + $this->prop['attributes'] = array_merge(array_values($this->fieldmap), $fetch_attributes); + foreach ($rcube->config->get('contactlist_fields') as $col) { + $this->prop['list_attributes'] = array_merge($this->prop['list_attributes'], $this->_map_field($col)); + } + + // initialize ldap wrapper object + $this->ldap = new rcube_ldap_generic($this->prop); + $this->ldap->set_cache($this->cache); + $this->ldap->set_debug($this->debug); $this->_connect(); } @@ -199,49 +242,18 @@ class rcube_ldap extends rcube_addressbook { $rcube = rcube::get_instance(); - if (!function_exists('ldap_connect')) - rcube::raise_error(array('code' => 100, 'type' => 'ldap', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "No ldap support in this installation of PHP"), - true, true); - - if (is_resource($this->conn)) + if ($this->ready) return true; if (!is_array($this->prop['hosts'])) $this->prop['hosts'] = array($this->prop['hosts']); - if (empty($this->prop['ldap_version'])) - $this->prop['ldap_version'] = 3; - // try to connect + bind for every host configured // with OpenLDAP 2.x ldap_connect() always succeeds but ldap_bind will fail if host isn't reachable // see http://www.php.net/manual/en/function.ldap-connect.php foreach ($this->prop['hosts'] as $host) { - $host = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host)); - $hostname = $host.($this->prop['port'] ? ':'.$this->prop['port'] : ''); - - $this->_debug("C: Connect [$hostname] [{$this->prop['name']}]"); - - if ($lc = @ldap_connect($host, $this->prop['port'])) { - if ($this->prop['use_tls'] === true) - if (!ldap_start_tls($lc)) - continue; - - $this->_debug("S: OK"); - - ldap_set_option($lc, LDAP_OPT_PROTOCOL_VERSION, $this->prop['ldap_version']); - $this->prop['host'] = $host; - $this->conn = $lc; - - if (!empty($this->prop['network_timeout'])) - ldap_set_option($lc, LDAP_OPT_NETWORK_TIMEOUT, $this->prop['network_timeout']); - - if (isset($this->prop['referrals'])) - ldap_set_option($lc, LDAP_OPT_REFERRALS, $this->prop['referrals']); - } - else { - $this->_debug("S: NOT OK"); + // skip host if connection failed + if (!$this->ldap->connect($host)) { continue; } @@ -256,7 +268,7 @@ class rcube_ldap extends rcube_addressbook $this->base_dn = $this->prop['base_dn']; $this->groups_base_dn = ($this->prop['groups']['base_dn']) ? - $this->prop['groups']['base_dn'] : $this->base_dn; + $this->prop['groups']['base_dn'] : $this->base_dn; // User specific access, generate the proper values to use. if ($this->prop['user_specific']) { @@ -275,29 +287,46 @@ class rcube_ldap extends rcube_addressbook $replaces = array('%dn' => '', '%dc' => $dc, '%d' => $d, '%fu' => $fu, '%u' => $u); + // Search for the dn to use to authenticate if ($this->prop['search_base_dn'] && $this->prop['search_filter']) { - if (!empty($this->prop['search_bind_dn']) && !empty($this->prop['search_bind_pw'])) { - $this->bind($this->prop['search_bind_dn'], $this->prop['search_bind_pw']); - } - - // Search for the dn to use to authenticate - $this->prop['search_base_dn'] = strtr($this->prop['search_base_dn'], $replaces); - $this->prop['search_filter'] = strtr($this->prop['search_filter'], $replaces); + $search_bind_dn = strtr($this->prop['search_bind_dn'], $replaces); + $search_base_dn = strtr($this->prop['search_base_dn'], $replaces); + $search_filter = strtr($this->prop['search_filter'], $replaces); - $this->_debug("S: searching with base {$this->prop['search_base_dn']} for {$this->prop['search_filter']}"); + $cache_key = 'DN.' . md5("$host:$search_bind_dn:$search_base_dn:$search_filter:" + .$this->prop['search_bind_pw']); - $res = @ldap_search($this->conn, $this->prop['search_base_dn'], $this->prop['search_filter'], array('uid')); - if ($res) { - if (($entry = ldap_first_entry($this->conn, $res)) - && ($bind_dn = ldap_get_dn($this->conn, $entry)) - ) { - $this->_debug("S: search returned dn: $bind_dn"); - $dn = ldap_explode_dn($bind_dn, 1); - $replaces['%dn'] = $dn[0]; - } + if ($this->cache && ($dn = $this->cache->get($cache_key))) { + $replaces['%dn'] = $dn; } else { - $this->_debug("S: ".ldap_error($this->conn)); + $ldap = $this->ldap; + if (!empty($search_bind_dn) && !empty($this->prop['search_bind_pw'])) { + // To protect from "Critical extension is unavailable" error + // we need to use a separate LDAP connection + if (!empty($this->prop['vlv'])) { + $ldap = new rcube_ldap_generic($this->prop); + $ldap->set_debug($this->debug); + $ldap->set_cache($this->cache); + if (!$ldap->connect($host)) { + continue; + } + } + + if (!$ldap->bind($search_bind_dn, $this->prop['search_bind_pw'])) { + continue; // bind failed, try next host + } + } + + $res = $ldap->search($search_base_dn, $search_filter, 'sub', array('uid')); + if ($res) { + $res->rewind(); + $replaces['%dn'] = $res->get_dn(); + } + + if ($ldap != $this->ldap) { + $ldap->close(); + } } // DN not found @@ -309,9 +338,13 @@ class rcube_ldap extends rcube_addressbook 'code' => 100, 'type' => 'ldap', 'file' => __FILE__, 'line' => __LINE__, 'message' => "DN not found using LDAP search."), true); - return false; + continue; } } + + if ($this->cache && !empty($replaces['%dn'])) { + $this->cache->set($cache_key, $replaces['%dn']); + } } // Replace the bind_dn and base_dn variables. @@ -329,13 +362,13 @@ class rcube_ldap extends rcube_addressbook } else { if (!empty($bind_dn)) { - $this->ready = $this->bind($bind_dn, $bind_pass); + $this->ready = $this->ldap->bind($bind_dn, $bind_pass); } else if (!empty($this->prop['auth_cid'])) { - $this->ready = $this->sasl_bind($this->prop['auth_cid'], $bind_pass, $bind_user); + $this->ready = $this->ldap->sasl_bind($this->prop['auth_cid'], $bind_pass, $bind_user); } else { - $this->ready = $this->sasl_bind($bind_user, $bind_pass); + $this->ready = $this->ldap->sasl_bind($bind_user, $bind_pass); } } @@ -346,10 +379,10 @@ class rcube_ldap extends rcube_addressbook } // end foreach hosts - if (!is_resource($this->conn)) { + if (!is_resource($this->ldap->conn)) { rcube::raise_error(array('code' => 100, 'type' => 'ldap', 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Could not connect to any LDAP server, last tried $hostname"), true); + 'message' => "Could not connect to any LDAP server, last tried $host"), true); return false; } @@ -359,112 +392,47 @@ class rcube_ldap extends rcube_addressbook /** - * Bind connection with (SASL-) user and password - * - * @param string $authc Authentication user - * @param string $pass Bind password - * @param string $authz Autorization user - * - * @return boolean True on success, False on error + * Close connection to LDAP server */ - public function sasl_bind($authc, $pass, $authz=null) + function close() { - if (!$this->conn) { - return false; - } - - if (!function_exists('ldap_sasl_bind')) { - rcube::raise_error(array('code' => 100, 'type' => 'ldap', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Unable to bind: ldap_sasl_bind() not exists"), - true, true); + if ($this->ldap) { + $this->ldap->close(); } - - if (!empty($authz)) { - $authz = 'u:' . $authz; - } - - if (!empty($this->prop['auth_method'])) { - $method = $this->prop['auth_method']; - } - else { - $method = 'DIGEST-MD5'; - } - - $this->_debug("C: Bind [mech: $method, authc: $authc, authz: $authz] [pass: $pass]"); - - if (ldap_sasl_bind($this->conn, NULL, $pass, $method, NULL, $authc, $authz)) { - $this->_debug("S: OK"); - return true; - } - - $this->_debug("S: ".ldap_error($this->conn)); - - rcube::raise_error(array( - 'code' => ldap_errno($this->conn), 'type' => 'ldap', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Bind failed for authcid=$authc ".ldap_error($this->conn)), - true); - - return false; } /** - * Bind connection with DN and password - * - * @param string Bind DN - * @param string Bind password + * Returns address book name * - * @return boolean True on success, False on error + * @return string Address book name */ - public function bind($dn, $pass) + function get_name() { - if (!$this->conn) { - return false; - } - - $this->_debug("C: Bind [dn: $dn] [pass: $pass]"); - - if (@ldap_bind($this->conn, $dn, $pass)) { - $this->_debug("S: OK"); - return true; - } - - $this->_debug("S: ".ldap_error($this->conn)); - - rcube::raise_error(array( - 'code' => ldap_errno($this->conn), 'type' => 'ldap', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Bind failed for dn=$dn: ".ldap_error($this->conn)), - true); - - return false; + return $this->prop['name']; } /** - * Close connection to LDAP server + * Set internal list page + * + * @param number Page number to list */ - function close() + function set_page($page) { - if ($this->conn) - { - $this->_debug("C: Close"); - ldap_unbind($this->conn); - $this->conn = null; - } + $this->list_page = (int)$page; + $this->ldap->set_vlv_page($this->list_page, $this->page_size); } - /** - * Returns address book name + * Set internal page size * - * @return string Address book name + * @param number Number of records to display on one page */ - function get_name() + function set_pagesize($size) { - return $this->prop['name']; + $this->page_size = (int)$size; + $this->ldap->set_vlv_page($this->list_page, $this->page_size); } @@ -524,16 +492,14 @@ class rcube_ldap extends rcube_addressbook */ function list_records($cols=null, $subset=0) { - if ($this->prop['searchonly'] && empty($this->filter) && !$this->group_id) - { + if ($this->prop['searchonly'] && empty($this->filter) && !$this->group_id) { $this->result = new rcube_result_set(0); $this->result->searchonly = true; return $this->result; } // fetch group members recursively - if ($this->group_id && $this->group_data['dn']) - { + if ($this->group_id && $this->group_data['dn']) { $entries = $this->list_group_members($this->group_data['dn']); // make list of entries unique and sort it @@ -547,34 +513,34 @@ class rcube_ldap extends rcube_addressbook $entries['count'] = count($entries); $this->result = new rcube_result_set($entries['count'], ($this->list_page-1) * $this->page_size); } - else - { - // add general filter to query - if (!empty($this->prop['filter']) && empty($this->filter)) - $this->set_search_set($this->prop['filter']); + else { + $prop = $this->group_id ? $this->group_data : $this->prop; + + // use global search filter + if (!empty($this->filter)) + $prop['filter'] = $this->filter; // exec LDAP search if no result resource is stored - if ($this->conn && !$this->ldap_result) - $this->_exec_search(); + if ($this->ready && !$this->ldap_result) + $this->ldap_result = $this->ldap->search($prop['base_dn'], $prop['filter'], $prop['scope'], $this->prop['attributes'], $prop); // count contacts for this user $this->result = $this->count(); // we have a search result resource - if ($this->ldap_result && $this->result->count > 0) - { + if ($this->ldap_result && $this->result->count > 0) { // sorting still on the ldap server - if ($this->sort_col && $this->prop['scope'] !== 'base' && !$this->vlv_active) - ldap_sort($this->conn, $this->ldap_result, $this->sort_col); + if ($this->sort_col && $prop['scope'] !== 'base' && !$this->ldap->vlv_active) + $this->ldap_result->sort($this->sort_col); // get all entries from the ldap server - $entries = ldap_get_entries($this->conn, $this->ldap_result); + $entries = $this->ldap_result->entries(); } } // end else // start and end of the page - $start_row = $this->vlv_active ? 0 : $this->result->first; + $start_row = $this->ldap->vlv_active ? 0 : $this->result->first; $start_row = $subset < 0 ? $start_row + $this->page_size + $subset : $start_row; $last_row = $this->result->first + $this->page_size; $last_row = $subset != 0 ? $start_row + abs($subset) : $last_row; @@ -599,43 +565,34 @@ class rcube_ldap extends rcube_addressbook // fetch group object if (empty($entries)) { - $result = @ldap_read($this->conn, $dn, '(objectClass=*)', array('dn','objectClass','member','uniqueMember','memberURL')); - if ($result === false) - { - $this->_debug("S: ".ldap_error($this->conn)); + $attribs = array('dn','objectClass','member','uniqueMember','memberURL'); + $entries = $this->ldap->read_entries($dn, '(objectClass=*)', $attribs); + if ($entries === false) { return $group_members; } - - $entries = @ldap_get_entries($this->conn, $result); } - for ($i=0; $i < $entries['count']; $i++) - { + for ($i=0; $i < $entries['count']; $i++) { $entry = $entries[$i]; + $attrs = array(); - if (empty($entry['objectclass'])) - continue; + foreach ((array)$entry['objectclass'] as $objectclass) { + if (strtolower($objectclass) == 'groupofurls') { + $members = $this->_list_group_memberurl($dn, $entry, $count); + $group_members = array_merge($group_members, $members); + } + else if (($member_attr = $this->get_group_member_attr(array($objectclass), '')) + && ($member_attr = strtolower($member_attr)) && !in_array($member_attr, $attrs) + ) { + $members = $this->_list_group_members($dn, $entry, $member_attr, $count); + $group_members = array_merge($group_members, $members); + $attrs[] = $member_attr; + } - foreach ((array)$entry['objectclass'] as $objectclass) - { - switch (strtolower($objectclass)) { - case "group": - case "groupofnames": - case "kolabgroupofnames": - $group_members = array_merge($group_members, $this->_list_group_members($dn, $entry, 'member', $count)); - break; - case "groupofuniquenames": - case "kolabgroupofuniquenames": - $group_members = array_merge($group_members, $this->_list_group_members($dn, $entry, 'uniquemember', $count)); - break; - case "groupofurls": - $group_members = array_merge($group_members, $this->_list_group_memberurl($dn, $entry, $count)); - break; + if ($this->prop['sizelimit'] && count($group_members) > $this->prop['sizelimit']) { + break 2; } } - - if ($this->prop['sizelimit'] && count($group_members) > $this->prop['sizelimit']) - break; } return array_filter($group_members); @@ -654,28 +611,24 @@ class rcube_ldap extends rcube_addressbook // Use the member attributes to return an array of member ldap objects // NOTE that the member attribute is supposed to contain a DN $group_members = array(); - if (empty($entry[$attr])) + if (empty($entry[$attr])) { return $group_members; + } // read these attributes for all members - $attrib = $count ? array('dn') : array_values($this->fieldmap); - $attrib[] = 'objectClass'; + $attrib = $count ? array('dn','objectClass') : $this->prop['list_attributes']; $attrib[] = 'member'; $attrib[] = 'uniqueMember'; $attrib[] = 'memberURL'; - for ($i=0; $i < $entry[$attr]['count']; $i++) - { + $filter = $this->prop['groups']['member_filter'] ? $this->prop['groups']['member_filter'] : '(objectclass=*)'; + + for ($i=0; $i < $entry[$attr]['count']; $i++) { if (empty($entry[$attr][$i])) continue; - $result = @ldap_read($this->conn, $entry[$attr][$i], '(objectclass=*)', - $attrib, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit']); - - $members = @ldap_get_entries($this->conn, $result); - if ($members == false) - { - $this->_debug("S: ".ldap_error($this->conn)); + $members = $this->ldap->read_entries($entry[$attr][$i], $filter, $attrib); + if ($members == false) { $members = array(); } @@ -701,34 +654,22 @@ class rcube_ldap extends rcube_addressbook { $group_members = array(); - for ($i=0; $i < $entry['memberurl']['count']; $i++) - { + for ($i=0; $i < $entry['memberurl']['count']; $i++) { // extract components from url if (!preg_match('!ldap:///([^\?]+)\?\?(\w+)\?(.*)$!', $entry['memberurl'][$i], $m)) continue; // add search filter if any $filter = $this->filter ? '(&(' . $m[3] . ')(' . $this->filter . '))' : $m[3]; - $func = $m[2] == 'sub' ? 'ldap_search' : ($m[2] == 'base' ? 'ldap_read' : 'ldap_list'); - - $attrib = $count ? array('dn') : array_values($this->fieldmap); - if ($result = @$func($this->conn, $m[1], $filter, - $attrib, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit']) - ) { - $this->_debug("S: ".ldap_count_entries($this->conn, $result)." record(s) for ".$m[1]); - } - else { - $this->_debug("S: ".ldap_error($this->conn)); - return $group_members; - } - - $entries = @ldap_get_entries($this->conn, $result); - for ($j = 0; $j < $entries['count']; $j++) - { - if ($nested_group_members = $this->list_group_members($entries[$j]['dn'], $count)) - $group_members = array_merge($group_members, $nested_group_members); - else - $group_members[] = $entries[$j]; + $attrs = $count ? array('dn','objectClass') : $this->prop['list_attributes']; + if ($result = $this->ldap->search($m[1], $filter, $m[2], $attrs, $this->group_data)) { + $entries = $result->entries(); + for ($j = 0; $j < $entries['count']; $j++) { + if (self::is_group_entry($entries[$j]) && ($nested_group_members = $this->list_group_members($entries[$j]['dn'], $count))) + $group_members = array_merge($group_members, $nested_group_members); + else + $group_members[] = $entries[$j]; + } } } @@ -764,14 +705,11 @@ class rcube_ldap extends rcube_addressbook $mode = intval($mode); // special treatment for ID-based search - if ($fields == 'ID' || $fields == $this->primary_key) - { + if ($fields == 'ID' || $fields == $this->primary_key) { $ids = !is_array($value) ? explode(',', $value) : $value; $result = new rcube_result_set(); - foreach ($ids as $id) - { - if ($rec = $this->get_record($id, true)) - { + foreach ($ids as $id) { + if ($rec = $this->get_record($id, true)) { $result->add($rec); $result->count++; } @@ -783,34 +721,20 @@ class rcube_ldap extends rcube_addressbook $rcube = rcube::get_instance(); $list_fields = $rcube->config->get('contactlist_fields'); - if ($this->prop['vlv_search'] && $this->conn && join(',', (array)$fields) == join(',', $list_fields)) - { - // add general filter to query - if (!empty($this->prop['filter']) && empty($this->filter)) - $this->set_search_set($this->prop['filter']); - - // set VLV controls with encoded search string - $this->_vlv_set_controls($this->prop, $this->list_page, $this->page_size, $value); - - $function = $this->_scope2func($this->prop['scope']); - $this->ldap_result = @$function($this->conn, $this->base_dn, $this->filter ? $this->filter : '(objectclass=*)', - array_values($this->fieldmap), 0, $this->page_size, (int)$this->prop['timelimit']); - + if ($this->prop['vlv_search'] && $this->ready && join(',', (array)$fields) == join(',', $list_fields)) { $this->result = new rcube_result_set(0); - if (!$this->ldap_result) { - $this->_debug("S: ".ldap_error($this->conn)); + $search_suffix = $this->prop['fuzzy_search'] && $mode != 1 ? '*' : ''; + $ldap_data = $this->ldap->search($this->base_dn, $this->prop['filter'], $this->prop['scope'], $this->prop['attributes'], + array('search' => $value . $search_suffix /*, 'sort' => $this->prop['sort'] */)); + if ($ldap_data === false) { return $this->result; } - $this->_debug("S: ".ldap_count_entries($this->conn, $this->ldap_result)." record(s)"); - // get all entries of this page and post-filter those that really match the query - $search = mb_strtolower($value); - $entries = ldap_get_entries($this->conn, $this->ldap_result); - - for ($i = 0; $i < $entries['count']; $i++) { - $rec = $this->_ldap2result($entries[$i]); + $search = mb_strtolower($value); + foreach ($ldap_data as $i => $entry) { + $rec = $this->_ldap2result($entry); foreach ($fields as $f) { foreach ((array)$rec[$f] as $val) { if ($this->compare_search_value($f, $val, $search, $mode)) { @@ -836,31 +760,27 @@ class rcube_ldap extends rcube_addressbook } } - if ($fields == '*') - { + if ($fields == '*') { // search_fields are required for fulltext search - if (empty($this->prop['search_fields'])) - { + if (empty($this->prop['search_fields'])) { $this->set_error(self::ERROR_SEARCH, 'nofulltextsearch'); $this->result = new rcube_result_set(); return $this->result; } - if (is_array($this->prop['search_fields'])) - { + if (is_array($this->prop['search_fields'])) { foreach ($this->prop['search_fields'] as $field) { - $filter .= "($field=$wp" . $this->_quote_string($value) . "$ws)"; + $filter .= "($field=$wp" . rcube_ldap_generic::quote_string($value) . "$ws)"; } } } - else - { + else { foreach ((array)$fields as $idx => $field) { $val = is_array($value) ? $value[$idx] : $value; if ($attrs = $this->_map_field($field)) { if (count($attrs) > 1) $filter .= '(|'; foreach ($attrs as $f) - $filter .= "($f=$wp" . $this->_quote_string($val) . "$ws)"; + $filter .= "($f=$wp" . rcube_ldap_generic::quote_string($val) . "$ws)"; if (count($attrs) > 1) $filter .= ')'; } @@ -871,6 +791,8 @@ class rcube_ldap extends rcube_addressbook // add required (non empty) fields filter $req_filter = ''; foreach ((array)$required as $field) { + if (in_array($field, (array)$fields)) // required field is already in search filter + continue; if ($attrs = $this->_map_field($field)) { if (count($attrs) > 1) $req_filter .= '(|'; @@ -893,7 +815,6 @@ class rcube_ldap extends rcube_addressbook // set filter string and execute search $this->set_search_set($filter); - $this->_exec_search(); if ($select) $this->list_records(); @@ -912,20 +833,20 @@ class rcube_ldap extends rcube_addressbook function count() { $count = 0; - if ($this->conn && $this->ldap_result) { - $count = $this->vlv_active ? $this->vlv_count : ldap_count_entries($this->conn, $this->ldap_result); + if ($this->ldap_result) { + $count = $this->ldap_result->count(); } else if ($this->group_id && $this->group_data['dn']) { $count = count($this->list_group_members($this->group_data['dn'], true)); } - else if ($this->conn) { - // We have a connection but no result set, attempt to get one. - if (empty($this->filter)) { - // The filter is not set, set it. - $this->filter = $this->prop['filter']; - } + // We have a connection but no result set, attempt to get one. + else if ($this->ready) { + $prop = $this->group_id ? $this->group_data : $this->prop; - $count = (int) $this->_exec_search(true); + if (!empty($this->filter)) { // Use global search filter + $prop['filter'] = $this->filter; + } + $count = $this->ldap->search($prop['base_dn'], $prop['filter'], $prop['scope'], array('dn'), $prop, true); } return new rcube_result_set($count, ($this->list_page-1) * $this->page_size); @@ -955,28 +876,16 @@ class rcube_ldap extends rcube_addressbook { $res = $this->result = null; - if ($this->conn && $dn) - { + if ($this->ready && $dn) { $dn = self::dn_decode($dn); - $this->_debug("C: Read [dn: $dn] [(objectclass=*)]"); - - if ($ldap_result = @ldap_read($this->conn, $dn, '(objectclass=*)', array_values($this->fieldmap))) { - $this->_debug("S: OK"); - - $entry = ldap_first_entry($this->conn, $ldap_result); - - if ($entry && ($rec = ldap_get_attributes($this->conn, $entry))) { - $rec = array_change_key_case($rec, CASE_LOWER); - } - } - else { - $this->_debug("S: ".ldap_error($this->conn)); + if ($rec = $this->ldap->get_entry($dn)) { + $rec = array_change_key_case($rec, CASE_LOWER); } // Use ldap_list to get subentries like country (c) attribute (#1488123) if (!empty($rec) && $this->sub_filter) { - if ($entries = $this->ldap_list($dn, $this->sub_filter, array_keys($this->prop['sub_fields']))) { + if ($entries = $this->ldap->list_entries($dn, $this->sub_filter, array_keys($this->prop['sub_fields']))) { foreach ($entries as $entry) { $lrec = array_change_key_case($entry, CASE_LOWER); $rec = array_merge($lrec, $rec); @@ -988,7 +897,7 @@ class rcube_ldap extends rcube_addressbook // Add in the dn for the entry. $rec['dn'] = $dn; $res = $this->_ldap2result($rec); - $this->result = new rcube_result_set(); + $this->result = new rcube_result_set(1); $this->result->add($res); } } @@ -1101,7 +1010,7 @@ class rcube_ldap extends rcube_addressbook } // Build the new entries DN. - $dn = $this->prop['LDAP_rdn'].'='.$this->_quote_string($newentry[$this->prop['LDAP_rdn']], true).','.$this->base_dn; + $dn = $this->prop['LDAP_rdn'].'='.rcube_ldap_generic::quote_string($newentry[$this->prop['LDAP_rdn']], true).','.$this->base_dn; // Remove attributes that need to be added separately (child objects) $xfields = array(); @@ -1114,19 +1023,19 @@ class rcube_ldap extends rcube_addressbook } } - if (!$this->ldap_add($dn, $newentry)) { + if (!$this->ldap->add($dn, $newentry)) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return false; } foreach ($xfields as $xidx => $xf) { - $xdn = $xidx.'='.$this->_quote_string($xf).','.$dn; + $xdn = $xidx.'='.rcube_ldap_generic::quote_string($xf).','.$dn; $xf = array( $xidx => $xf, 'objectClass' => (array) $this->prop['sub_fields'][$xidx], ); - $this->ldap_add($xdn, $xf); + $this->ldap->add($xdn, $xf); } $dn = self::dn_encode($dn); @@ -1232,7 +1141,7 @@ class rcube_ldap extends rcube_addressbook // Update the entry as required. if (!empty($deletedata)) { // Delete the fields. - if (!$this->ldap_mod_del($dn, $deletedata)) { + if (!$this->ldap->mod_del($dn, $deletedata)) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return false; } @@ -1242,17 +1151,17 @@ class rcube_ldap extends rcube_addressbook // Handle RDN change if ($replacedata[$this->prop['LDAP_rdn']]) { $newdn = $this->prop['LDAP_rdn'].'=' - .$this->_quote_string($replacedata[$this->prop['LDAP_rdn']], true) + .rcube_ldap_generic::quote_string($replacedata[$this->prop['LDAP_rdn']], true) .','.$this->base_dn; if ($dn != $newdn) { $newrdn = $this->prop['LDAP_rdn'].'=' - .$this->_quote_string($replacedata[$this->prop['LDAP_rdn']], true); + .rcube_ldap_generic::quote_string($replacedata[$this->prop['LDAP_rdn']], true); unset($replacedata[$this->prop['LDAP_rdn']]); } } // Replace the fields. if (!empty($replacedata)) { - if (!$this->ldap_mod_replace($dn, $replacedata)) { + if (!$this->ldap->mod_replace($dn, $replacedata)) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return false; } @@ -1268,8 +1177,8 @@ class rcube_ldap extends rcube_addressbook // remove sub-entries if (!empty($subdeldata)) { foreach ($subdeldata as $fld => $val) { - $subdn = $fld.'='.$this->_quote_string($val).','.$dn; - if (!$this->ldap_delete($subdn)) { + $subdn = $fld.'='.rcube_ldap_generic::quote_string($val).','.$dn; + if (!$this->ldap->delete($subdn)) { return false; } } @@ -1277,7 +1186,7 @@ class rcube_ldap extends rcube_addressbook if (!empty($newdata)) { // Add the fields. - if (!$this->ldap_mod_add($dn, $newdata)) { + if (!$this->ldap->mod_add($dn, $newdata)) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return false; } @@ -1285,7 +1194,7 @@ class rcube_ldap extends rcube_addressbook // Handle RDN change if (!empty($newrdn)) { - if (!$this->ldap_rename($dn, $newrdn, null, true)) { + if (!$this->ldap->rename($dn, $newrdn, null, true)) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return false; } @@ -1296,8 +1205,7 @@ class rcube_ldap extends rcube_addressbook // change the group membership of the contact if ($this->groups) { $group_ids = $this->get_record_groups($dn); - foreach ($group_ids as $group_id) - { + foreach (array_keys($group_ids) as $group_id) { $this->remove_from_group($group_id, $dn); $this->add_to_group($group_id, $newdn); } @@ -1309,12 +1217,12 @@ class rcube_ldap extends rcube_addressbook // add sub-entries if (!empty($subnewdata)) { foreach ($subnewdata as $fld => $val) { - $subdn = $fld.'='.$this->_quote_string($val).','.$dn; + $subdn = $fld.'='.rcube_ldap_generic::quote_string($val).','.$dn; $xf = array( $fld => $val, 'objectClass' => (array) $this->prop['sub_fields'][$fld], ); - $this->ldap_add($subdn, $xf); + $this->ldap->add($subdn, $xf); } } @@ -1342,9 +1250,9 @@ class rcube_ldap extends rcube_addressbook // Need to delete all sub-entries first if ($this->sub_filter) { - if ($entries = $this->ldap_list($dn, $this->sub_filter)) { + if ($entries = $this->ldap->list_entries($dn, $this->sub_filter)) { foreach ($entries as $entry) { - if (!$this->ldap_delete($entry['dn'])) { + if (!$this->ldap->delete($entry['dn'])) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return false; } @@ -1353,7 +1261,7 @@ class rcube_ldap extends rcube_addressbook } // Delete the record. - if (!$this->ldap_delete($dn)) { + if (!$this->ldap->delete($dn)) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return false; } @@ -1362,7 +1270,7 @@ class rcube_ldap extends rcube_addressbook if ($this->groups) { $dn = self::dn_encode($dn); $group_ids = $this->get_record_groups($dn); - foreach ($group_ids as $group_id) { + foreach (array_keys($group_ids) as $group_id) { $this->remove_from_group($group_id, $dn); } } @@ -1377,8 +1285,8 @@ class rcube_ldap extends rcube_addressbook */ function delete_all() { - //searching for contact entries - $dn_list = $this->ldap_list($this->base_dn, $this->prop['filter'] ? $this->prop['filter'] : '(objectclass=*)'); + // searching for contact entries + $dn_list = $this->ldap->list_entries($this->base_dn, $this->prop['filter'] ? $this->prop['filter'] : '(objectclass=*)'); if (!empty($dn_list)) { foreach ($dn_list as $idx => $entry) { @@ -1428,120 +1336,26 @@ class rcube_ldap extends rcube_addressbook } } - /** - * Execute the LDAP search based on the stored credentials - */ - private function _exec_search($count = false) - { - if ($this->ready) - { - $filter = $this->filter ? $this->filter : '(objectclass=*)'; - $function = $this->_scope2func($this->prop['scope'], $ns_function); - - $this->_debug("C: Search [$filter][dn: $this->base_dn]"); - - // when using VLV, we get the total count by... - if (!$count && $function != 'ldap_read' && $this->prop['vlv'] && !$this->group_id) { - // ...either reading numSubOrdinates attribute - if ($this->prop['numsub_filter'] && ($result_count = @$ns_function($this->conn, $this->base_dn, $this->prop['numsub_filter'], array('numSubOrdinates'), 0, 0, 0))) { - $counts = ldap_get_entries($this->conn, $result_count); - for ($this->vlv_count = $j = 0; $j < $counts['count']; $j++) - $this->vlv_count += $counts[$j]['numsubordinates'][0]; - $this->_debug("D: total numsubordinates = " . $this->vlv_count); - } - else if (!function_exists('ldap_parse_virtuallist_control')) // ...or by fetching all records dn and count them - $this->vlv_count = $this->_exec_search(true); - - $this->vlv_active = $this->_vlv_set_controls($this->prop, $this->list_page, $this->page_size); - } - - // only fetch dn for count (should keep the payload low) - $attrs = $count ? array('dn') : array_values($this->fieldmap); - if ($this->ldap_result = @$function($this->conn, $this->base_dn, $filter, - $attrs, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit']) - ) { - // when running on a patched PHP we can use the extended functions to retrieve the total count from the LDAP search result - if ($this->vlv_active && function_exists('ldap_parse_virtuallist_control')) { - if (ldap_parse_result($this->conn, $this->ldap_result, - $errcode, $matcheddn, $errmsg, $referrals, $serverctrls) - && $serverctrls // can be null e.g. in case of adm. limit error - ) { - ldap_parse_virtuallist_control($this->conn, $serverctrls, - $last_offset, $this->vlv_count, $vresult); - $this->_debug("S: VLV result: last_offset=$last_offset; content_count=$this->vlv_count"); - } - else { - $this->_debug("S: ".($errmsg ? $errmsg : ldap_error($this->conn))); - } - } - - $entries_count = ldap_count_entries($this->conn, $this->ldap_result); - $this->_debug("S: $entries_count record(s)"); - - return $count ? $entries_count : true; - } - else { - $this->_debug("S: ".ldap_error($this->conn)); - } - } - - return false; - } - - /** - * Choose the right PHP function according to scope property - */ - private function _scope2func($scope, &$ns_function = null) - { - switch ($scope) { - case 'sub': - $function = $ns_function = 'ldap_search'; - break; - case 'base': - $function = $ns_function = 'ldap_read'; - break; - default: - $function = 'ldap_list'; - $ns_function = 'ldap_read'; - break; - } - - return $function; - } - - /** - * Set server controls for Virtual List View (paginated listing) - */ - private function _vlv_set_controls($prop, $list_page, $page_size, $search = null) - { - $sort_ctrl = array('oid' => "1.2.840.113556.1.4.473", 'value' => $this->_sort_ber_encode((array)$prop['sort'])); - $vlv_ctrl = array('oid' => "2.16.840.1.113730.3.4.9", 'value' => $this->_vlv_ber_encode(($offset = ($list_page-1) * $page_size + 1), $page_size, $search), 'iscritical' => true); - - $sort = (array)$prop['sort']; - $this->_debug("C: set controls sort=" . join(' ', unpack('H'.(strlen($sort_ctrl['value'])*2), $sort_ctrl['value'])) . " ($sort[0]);" - . " vlv=" . join(' ', (unpack('H'.(strlen($vlv_ctrl['value'])*2), $vlv_ctrl['value']))) . " ($offset/$page_size)"); - - if (!ldap_set_option($this->conn, LDAP_OPT_SERVER_CONTROLS, array($sort_ctrl, $vlv_ctrl))) { - $this->_debug("S: ".ldap_error($this->conn)); - $this->set_error(self::ERROR_SEARCH, 'vlvnotsupported'); - return false; - } - - return true; - } - /** * Converts LDAP entry into an array */ private function _ldap2result($rec) { - $out = array(); + $out = array('_type' => 'person'); + $fieldmap = $this->fieldmap; if ($rec['dn']) $out[$this->primary_key] = self::dn_encode($rec['dn']); - foreach ($this->fieldmap as $rf => $lf) + // determine record type + if (self::is_group_entry($rec)) { + $out['_type'] = 'group'; + $out['readonly'] = true; + $fieldmap['name'] = $this->group_data['name_attr'] ? $this->group_data['name_attr'] : $this->prop['groups']['name_attr']; + } + + foreach ($fieldmap as $rf => $lf) { for ($i=0; $i < $rec[$lf]['count']; $i++) { if (!($value = $rec[$lf][$i])) @@ -1603,8 +1417,10 @@ class rcube_ldap extends rcube_addressbook if (is_array($colprop['serialized'])) { foreach ($colprop['serialized'] as $subtype => $delim) { $key = $col.':'.$subtype; - foreach ((array)$save_cols[$key] as $i => $val) - $save_cols[$key][$i] = join($delim, array($val['street'], $val['locality'], $val['zipcode'], $val['country'])); + foreach ((array)$save_cols[$key] as $i => $val) { + $values = array($val['street'], $val['locality'], $val['zipcode'], $val['country']); + $save_cols[$key][$i] = count(array_filter($values)) ? join($delim, $values) : null; + } } } } @@ -1642,11 +1458,11 @@ class rcube_ldap extends rcube_addressbook { // list of known attribute aliases static $aliases = array( - 'gn' => 'givenname', + 'gn' => 'givenname', 'rfc822mailbox' => 'email', - 'userid' => 'uid', - 'emailaddress' => 'email', - 'pkcs9email' => 'email', + 'userid' => 'uid', + 'emailaddress' => 'email', + 'pkcs9email' => 'email', ); list($name, $limit) = explode(':', $namev, 2); @@ -1655,6 +1471,15 @@ class rcube_ldap extends rcube_addressbook return (isset($aliases[$name]) ? $aliases[$name] : $name) . $suffix; } + /** + * Determines whether the given LDAP entry is a group record + */ + private static function is_group_entry($entry) + { + $classes = array_map('strtolower', (array)$entry['objectclass']); + + return count(array_intersect(array_keys(self::$group_types), $classes)) > 0; + } /** * Prints debug info to the log @@ -1671,55 +1496,27 @@ class rcube_ldap extends rcube_addressbook * Activate/deactivate debug mode * * @param boolean $dbg True if LDAP commands should be logged - * @access public */ function set_debug($dbg = true) { $this->debug = $dbg; - } - - - /** - * Quotes attribute value string - * - * @param string $str Attribute value - * @param bool $dn True if the attribute is a DN - * - * @return string Quoted string - */ - private static function _quote_string($str, $dn=false) - { - // take firt entry if array given - if (is_array($str)) - $str = reset($str); - - if ($dn) - $replace = array(','=>'\2c', '='=>'\3d', '+'=>'\2b', '<'=>'\3c', - '>'=>'\3e', ';'=>'\3b', '\\'=>'\5c', '"'=>'\22', '#'=>'\23'); - else - $replace = array('*'=>'\2a', '('=>'\28', ')'=>'\29', '\\'=>'\5c', - '/'=>'\2f'); - return strtr($str, $replace); + if ($this->ldap) { + $this->ldap->set_debug($dbg); + } } /** * Setter for the current group - * (empty, has to be re-implemented by extending class) */ function set_group($group_id) { - if ($group_id) - { - if (($group_cache = $this->cache->get('groups')) === null) - $group_cache = $this->_fetch_groups(); - + if ($group_id) { $this->group_id = $group_id; - $this->group_data = $group_cache[$group_id]; + $this->group_data = $this->get_group_entry($group_id); } - else - { + else { $this->group_id = 0; $this->group_data = null; } @@ -1738,15 +1535,13 @@ class rcube_ldap extends rcube_addressbook */ function list_groups($search = null, $mode = 0) { - if (!$this->groups) + if (!$this->groups) { return array(); + } - // use cached list for searching - $this->cache->expunge(); - if (!$search || ($group_cache = $this->cache->get('groups')) === null) - $group_cache = $this->_fetch_groups(); + $group_cache = $this->_fetch_groups(); + $groups = array(); - $groups = array(); if ($search) { foreach ($group_cache as $group) { if ($this->compare_search_value('name', $group['name'], $search, $mode)) { @@ -1754,8 +1549,9 @@ class rcube_ldap extends rcube_addressbook } } } - else + else { $groups = $group_cache; + } return array_values($groups); } @@ -1763,80 +1559,139 @@ class rcube_ldap extends rcube_addressbook /** * Fetch groups from server */ - private function _fetch_groups($vlv_page = 0) + private function _fetch_groups($vlv_page = null) { - $base_dn = $this->groups_base_dn; - $filter = $this->prop['groups']['filter']; - $name_attr = $this->prop['groups']['name_attr']; + // special case: list groups from 'group_filters' config + if ($vlv_page === null && !empty($this->prop['group_filters'])) { + $groups = array(); + + // list regular groups configuration as special filter + if (!empty($this->prop['groups']['filter'])) { + $id = '__groups__'; + $groups[$id] = array('ID' => $id, 'name' => rcube_label('groups'), 'virtual' => true) + $this->prop['groups']; + } + + foreach ($this->prop['group_filters'] as $id => $prop) { + $groups[$id] = $prop + array('ID' => $id, 'name' => ucfirst($id), 'virtual' => true, 'base_dn' => $this->base_dn); + } + + return $groups; + } + + if ($this->cache && $vlv_page === null && ($groups = $this->cache->get('groups')) !== null) { + return $groups; + } + + $base_dn = $this->groups_base_dn; + $filter = $this->prop['groups']['filter']; + $name_attr = $this->prop['groups']['name_attr']; $email_attr = $this->prop['groups']['email_attr'] ? $this->prop['groups']['email_attr'] : 'mail'; $sort_attrs = $this->prop['groups']['sort'] ? (array)$this->prop['groups']['sort'] : array($name_attr); - $sort_attr = $sort_attrs[0]; + $sort_attr = $sort_attrs[0]; - $this->_debug("C: Search [$filter][dn: $base_dn]"); + $ldap = $this->ldap; // use vlv to list groups if ($this->prop['groups']['vlv']) { $page_size = 200; - if (!$this->prop['groups']['sort']) + if (!$this->prop['groups']['sort']) { $this->prop['groups']['sort'] = $sort_attrs; - $vlv_active = $this->_vlv_set_controls($this->prop['groups'], $vlv_page+1, $page_size); + } + + $ldap = clone $this->ldap; + $ldap->set_config($this->prop['groups']); + $ldap->set_vlv_page($vlv_page+1, $page_size); } - $function = $this->_scope2func($this->prop['groups']['scope']); - $res = @$function($this->conn, $base_dn, $filter, array_unique(array('dn', 'objectClass', $name_attr, $email_attr, $sort_attr))); - if ($res === false) - { - $this->_debug("S: ".ldap_error($this->conn)); + $attrs = array_unique(array('dn', 'objectClass', $name_attr, $email_attr, $sort_attr)); + $ldap_data = $ldap->search($base_dn, $filter, $this->prop['groups']['scope'], $attrs, $this->prop['groups']); + + if ($ldap_data === false) { return array(); } - $ldap_data = ldap_get_entries($this->conn, $res); - $this->_debug("S: ".ldap_count_entries($this->conn, $res)." record(s)"); - - $groups = array(); + $groups = array(); $group_sortnames = array(); - $group_count = $ldap_data["count"]; - for ($i=0; $i < $group_count; $i++) - { - $group_name = is_array($ldap_data[$i][$name_attr]) ? $ldap_data[$i][$name_attr][0] : $ldap_data[$i][$name_attr]; - $group_id = self::dn_encode($group_name); + $group_count = $ldap_data->count(); + + foreach ($ldap_data as $entry) { + if (!$entry['dn']) // DN is mandatory + $entry['dn'] = $ldap_data->get_dn(); + + $group_name = is_array($entry[$name_attr]) ? $entry[$name_attr][0] : $entry[$name_attr]; + $group_id = self::dn_encode($entry['dn']); $groups[$group_id]['ID'] = $group_id; - $groups[$group_id]['dn'] = $ldap_data[$i]['dn']; + $groups[$group_id]['dn'] = $entry['dn']; $groups[$group_id]['name'] = $group_name; - $groups[$group_id]['member_attr'] = $this->get_group_member_attr($ldap_data[$i]['objectclass']); + $groups[$group_id]['member_attr'] = $this->get_group_member_attr($entry['objectclass']); // list email attributes of a group - for ($j=0; $ldap_data[$i][$email_attr] && $j < $ldap_data[$i][$email_attr]['count']; $j++) { - if (strpos($ldap_data[$i][$email_attr][$j], '@') > 0) - $groups[$group_id]['email'][] = $ldap_data[$i][$email_attr][$j]; + for ($j=0; $entry[$email_attr] && $j < $entry[$email_attr]['count']; $j++) { + if (strpos($entry[$email_attr][$j], '@') > 0) + $groups[$group_id]['email'][] = $entry[$email_attr][$j]; } - $group_sortnames[] = mb_strtolower($ldap_data[$i][$sort_attr][0]); + $group_sortnames[] = mb_strtolower($entry[$sort_attr][0]); } // recursive call can exit here - if ($vlv_page > 0) + if ($vlv_page > 0) { return $groups; + } // call recursively until we have fetched all groups - while ($vlv_active && $group_count == $page_size) - { - $next_page = $this->_fetch_groups(++$vlv_page); - $groups = array_merge($groups, $next_page); + while ($this->prop['groups']['vlv'] && $group_count == $page_size) { + $next_page = $this->_fetch_groups(++$vlv_page); + $groups = array_merge($groups, $next_page); $group_count = count($next_page); } // when using VLV the list of groups is already sorted - if (!$this->prop['groups']['vlv']) + if (!$this->prop['groups']['vlv']) { array_multisort($group_sortnames, SORT_ASC, SORT_STRING, $groups); + } // cache this - $this->cache->set('groups', $groups); + if ($this->cache) { + $this->cache->set('groups', $groups); + } return $groups; } /** + * Fetch a group entry from LDAP and save in local cache + */ + private function get_group_entry($group_id) + { + $group_cache = $this->_fetch_groups(); + + // add group record to cache if it isn't yet there + if (!isset($group_cache[$group_id])) { + $name_attr = $this->prop['groups']['name_attr']; + $dn = self::dn_decode($group_id); + + if ($list = $this->ldap->read_entries($dn, '(objectClass=*)', array('dn','objectClass','member','uniqueMember','memberURL',$name_attr,$this->fieldmap['email']))) { + $entry = $list[0]; + $group_name = is_array($entry[$name_attr]) ? $entry[$name_attr][0] : $entry[$name_attr]; + $group_cache[$group_id]['ID'] = $group_id; + $group_cache[$group_id]['dn'] = $dn; + $group_cache[$group_id]['name'] = $group_name; + $group_cache[$group_id]['member_attr'] = $this->get_group_member_attr($entry['objectclass']); + } + else { + $group_cache[$group_id] = false; + } + + if ($this->cache) { + $this->cache->set('groups', $group_cache); + } + } + + return $group_cache[$group_id]; + } + + /** * Get group properties such as name and email address(es) * * @param string Group identifier @@ -1844,10 +1699,7 @@ class rcube_ldap extends rcube_addressbook */ function get_group($group_id) { - if (($group_cache = $this->cache->get('groups')) === null) - $group_cache = $this->_fetch_groups(); - - $group_data = $group_cache[$group_id]; + $group_data = $this->get_group_entry($group_id); unset($group_data['dn'], $group_data['member_attr']); return $group_data; @@ -1861,24 +1713,24 @@ class rcube_ldap extends rcube_addressbook */ function create_group($group_name) { - $base_dn = $this->groups_base_dn; - $new_dn = "cn=$group_name,$base_dn"; - $new_gid = self::dn_encode($group_name); + $new_dn = 'cn=' . rcube_ldap_generic::quote_string($group_name, true) . ',' . $this->groups_base_dn; + $new_gid = self::dn_encode($new_dn); $member_attr = $this->get_group_member_attr(); - $name_attr = $this->prop['groups']['name_attr'] ? $this->prop['groups']['name_attr'] : 'cn'; - - $new_entry = array( + $name_attr = $this->prop['groups']['name_attr'] ? $this->prop['groups']['name_attr'] : 'cn'; + $new_entry = array( 'objectClass' => $this->prop['groups']['object_classes'], $name_attr => $group_name, $member_attr => '', ); - if (!$this->ldap_add($new_dn, $new_entry)) { + if (!$this->ldap->add($new_dn, $new_entry)) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return false; } - $this->cache->remove('groups'); + if ($this->cache) { + $this->cache->remove('groups'); + } return array('id' => $new_gid, 'name' => $group_name); } @@ -1891,19 +1743,18 @@ class rcube_ldap extends rcube_addressbook */ function delete_group($group_id) { - if (($group_cache = $this->cache->get('groups')) === null) - $group_cache = $this->_fetch_groups(); - - $base_dn = $this->groups_base_dn; - $group_name = $group_cache[$group_id]['name']; - $del_dn = "cn=$group_name,$base_dn"; + $group_cache = $this->_fetch_groups(); + $del_dn = $group_cache[$group_id]['dn']; - if (!$this->ldap_delete($del_dn)) { + if (!$this->ldap->delete($del_dn)) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return false; } - $this->cache->remove('groups'); + if ($this->cache) { + unset($group_cache[$group_id]); + $this->cache->set('groups', $group_cache); + } return true; } @@ -1918,21 +1769,19 @@ class rcube_ldap extends rcube_addressbook */ function rename_group($group_id, $new_name, &$new_gid) { - if (($group_cache = $this->cache->get('groups')) === null) - $group_cache = $this->_fetch_groups(); + $group_cache = $this->_fetch_groups(); + $old_dn = $group_cache[$group_id]['dn']; + $new_rdn = "cn=" . rcube_ldap_generic::quote_string($new_name, true); + $new_gid = self::dn_encode($new_rdn . ',' . $this->groups_base_dn); - $base_dn = $this->groups_base_dn; - $group_name = $group_cache[$group_id]['name']; - $old_dn = "cn=$group_name,$base_dn"; - $new_rdn = "cn=$new_name"; - $new_gid = self::dn_encode($new_name); - - if (!$this->ldap_rename($old_dn, $new_rdn, null, true)) { + if (!$this->ldap->rename($old_dn, $new_rdn, null, true)) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return false; } - $this->cache->remove('groups'); + if ($this->cache) { + $this->cache->remove('groups'); + } return $new_name; } @@ -1947,27 +1796,27 @@ class rcube_ldap extends rcube_addressbook */ function add_to_group($group_id, $contact_ids) { - if (($group_cache = $this->cache->get('groups')) === null) - $group_cache = $this->_fetch_groups(); - - if (!is_array($contact_ids)) - $contact_ids = explode(',', $contact_ids); - - $base_dn = $this->groups_base_dn; - $group_name = $group_cache[$group_id]['name']; + $group_cache = $this->_fetch_groups(); $member_attr = $group_cache[$group_id]['member_attr']; - $group_dn = "cn=$group_name,$base_dn"; + $group_dn = $group_cache[$group_id]['dn']; $new_attrs = array(); - foreach ($contact_ids as $id) + if (!is_array($contact_ids)) { + $contact_ids = explode(',', $contact_ids); + } + + foreach ($contact_ids as $id) { $new_attrs[$member_attr][] = self::dn_decode($id); + } - if (!$this->ldap_mod_add($group_dn, $new_attrs)) { + if (!$this->ldap->mod_add($group_dn, $new_attrs)) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return 0; } - $this->cache->remove('groups'); + if ($this->cache) { + $this->cache->remove('groups'); + } return count($new_attrs[$member_attr]); } @@ -1982,27 +1831,27 @@ class rcube_ldap extends rcube_addressbook */ function remove_from_group($group_id, $contact_ids) { - if (($group_cache = $this->cache->get('groups')) === null) - $group_cache = $this->_fetch_groups(); - - if (!is_array($contact_ids)) - $contact_ids = explode(',', $contact_ids); - - $base_dn = $this->groups_base_dn; - $group_name = $group_cache[$group_id]['name']; + $group_cache = $this->_fetch_groups(); $member_attr = $group_cache[$group_id]['member_attr']; - $group_dn = "cn=$group_name,$base_dn"; + $group_dn = $group_cache[$group_id]['dn']; $del_attrs = array(); - foreach ($contact_ids as $id) + if (!is_array($contact_ids)) { + $contact_ids = explode(',', $contact_ids); + } + + foreach ($contact_ids as $id) { $del_attrs[$member_attr][] = self::dn_decode($id); + } - if (!$this->ldap_mod_del($group_dn, $del_attrs)) { + if (!$this->ldap->mod_del($group_dn, $del_attrs)) { $this->set_error(self::ERROR_SAVING, 'errorsaving'); return 0; } - $this->cache->remove('groups'); + if ($this->cache) { + $this->cache->remove('groups'); + } return count($del_attrs[$member_attr]); } @@ -2017,206 +1866,63 @@ class rcube_ldap extends rcube_addressbook */ function get_record_groups($contact_id) { - if (!$this->groups) + if (!$this->groups) { return array(); + } $base_dn = $this->groups_base_dn; $contact_dn = self::dn_decode($contact_id); $name_attr = $this->prop['groups']['name_attr'] ? $this->prop['groups']['name_attr'] : 'cn'; $member_attr = $this->get_group_member_attr(); $add_filter = ''; + if ($member_attr != 'member' && $member_attr != 'uniqueMember') $add_filter = "($member_attr=$contact_dn)"; $filter = strtr("(|(member=$contact_dn)(uniqueMember=$contact_dn)$add_filter)", array('\\' => '\\\\')); - $this->_debug("C: Search [$filter][dn: $base_dn]"); - - $res = @ldap_search($this->conn, $base_dn, $filter, array($name_attr)); - if ($res === false) - { - $this->_debug("S: ".ldap_error($this->conn)); + $ldap_data = $this->ldap->search($base_dn, $filter, 'sub', array('dn', $name_attr)); + if ($res === false) { return array(); } - $ldap_data = ldap_get_entries($this->conn, $res); - $this->_debug("S: ".ldap_count_entries($this->conn, $res)." record(s)"); $groups = array(); - for ($i=0; $i<$ldap_data["count"]; $i++) - { - $group_name = $ldap_data[$i][$name_attr][0]; - $group_id = self::dn_encode($group_name); - $groups[$group_id] = $group_id; + foreach ($ldap_data as $entry) { + if (!$entry['dn']) + $entry['dn'] = $ldap_data->get_dn(); + $group_name = $entry[$name_attr][0]; + $group_id = self::dn_encode($entry['dn']); + $groups[$group_id] = $group_name; } + return $groups; } /** * Detects group member attribute name */ - private function get_group_member_attr($object_classes = array()) + private function get_group_member_attr($object_classes = array(), $default = 'member') { if (empty($object_classes)) { $object_classes = $this->prop['groups']['object_classes']; } + if (!empty($object_classes)) { foreach ((array)$object_classes as $oc) { - switch (strtolower($oc)) { - case 'group': - case 'groupofnames': - case 'kolabgroupofnames': - $member_attr = 'member'; - break; - - case 'groupofuniquenames': - case 'kolabgroupofuniquenames': - $member_attr = 'uniqueMember'; - break; + if ($attr = self::$group_types[strtolower($oc)]) { + return $attr; } } } - if (!empty($member_attr)) { - return $member_attr; - } - if (!empty($this->prop['groups']['member_attr'])) { return $this->prop['groups']['member_attr']; } - return 'member'; + return $default; } /** - * Generate BER encoded string for Virtual List View option - * - * @param integer List offset (first record) - * @param integer Records per page - * @return string BER encoded option value - */ - private function _vlv_ber_encode($offset, $rpp, $search = '') - { - # this string is ber-encoded, php will prefix this value with: - # 04 (octet string) and 10 (length of 16 bytes) - # the code behind this string is broken down as follows: - # 30 = ber sequence with a length of 0e (14) bytes following - # 02 = type integer (in two's complement form) with 2 bytes following (beforeCount): 01 00 (ie 0) - # 02 = type integer (in two's complement form) with 2 bytes following (afterCount): 01 18 (ie 25-1=24) - # a0 = type context-specific/constructed with a length of 06 (6) bytes following - # 02 = type integer with 2 bytes following (offset): 01 01 (ie 1) - # 02 = type integer with 2 bytes following (contentCount): 01 00 - - # whith a search string present: - # 81 = type context-specific/constructed with a length of 04 (4) bytes following (the length will change here) - # 81 indicates a user string is present where as a a0 indicates just a offset search - # 81 = type context-specific/constructed with a length of 06 (6) bytes following - - # the following info was taken from the ISO/IEC 8825-1:2003 x.690 standard re: the - # encoding of integer values (note: these values are in - # two-complement form so since offset will never be negative bit 8 of the - # leftmost octet should never by set to 1): - # 8.3.2: If the contents octets of an integer value encoding consist - # of more than one octet, then the bits of the first octet (rightmost) and bit 8 - # of the second (to the left of first octet) octet: - # a) shall not all be ones; and - # b) shall not all be zero - - if ($search) - { - $search = preg_replace('/[^-[:alpha:] ,.()0-9]+/', '', $search); - $ber_val = self::_string2hex($search); - $str = self::_ber_addseq($ber_val, '81'); - } - else - { - # construct the string from right to left - $str = "020100"; # contentCount - - $ber_val = self::_ber_encode_int($offset); // returns encoded integer value in hex format - - // calculate octet length of $ber_val - $str = self::_ber_addseq($ber_val, '02') . $str; - - // now compute length over $str - $str = self::_ber_addseq($str, 'a0'); - } - - // now tack on records per page - $str = "020100" . self::_ber_addseq(self::_ber_encode_int($rpp-1), '02') . $str; - - // now tack on sequence identifier and length - $str = self::_ber_addseq($str, '30'); - - return pack('H'.strlen($str), $str); - } - - - /** - * create ber encoding for sort control - * - * @param array List of cols to sort by - * @return string BER encoded option value - */ - private function _sort_ber_encode($sortcols) - { - $str = ''; - foreach (array_reverse((array)$sortcols) as $col) { - $ber_val = self::_string2hex($col); - - # 30 = ber sequence with a length of octet value - # 04 = octet string with a length of the ascii value - $oct = self::_ber_addseq($ber_val, '04'); - $str = self::_ber_addseq($oct, '30') . $str; - } - - // now tack on sequence identifier and length - $str = self::_ber_addseq($str, '30'); - - return pack('H'.strlen($str), $str); - } - - /** - * Add BER sequence with correct length and the given identifier - */ - private static function _ber_addseq($str, $identifier) - { - $len = dechex(strlen($str)/2); - if (strlen($len) % 2 != 0) - $len = '0'.$len; - - return $identifier . $len . $str; - } - - /** - * Returns BER encoded integer value in hex format - */ - private static function _ber_encode_int($offset) - { - $val = dechex($offset); - $prefix = ''; - - // check if bit 8 of high byte is 1 - if (preg_match('/^[89abcdef]/', $val)) - $prefix = '00'; - - if (strlen($val)%2 != 0) - $prefix .= '0'; - - return $prefix . $val; - } - - /** - * Returns ascii string encoded in hex - */ - private static function _string2hex($str) - { - $hex = ''; - for ($i=0; $i < strlen($str); $i++) - $hex .= dechex(ord($str[$i])); - return $hex; - } - - /** * HTML-safe DN string encoding * * @param string $str DN string @@ -2243,130 +1949,4 @@ class rcube_ldap extends rcube_addressbook return base64_decode($str); } - /** - * Wrapper for ldap_add() - */ - protected function ldap_add($dn, $entry) - { - $this->_debug("C: Add [dn: $dn]: ".print_r($entry, true)); - - $res = ldap_add($this->conn, $dn, $entry); - if ($res === false) { - $this->_debug("S: ".ldap_error($this->conn)); - return false; - } - - $this->_debug("S: OK"); - return true; - } - - /** - * Wrapper for ldap_delete() - */ - protected function ldap_delete($dn) - { - $this->_debug("C: Delete [dn: $dn]"); - - $res = ldap_delete($this->conn, $dn); - if ($res === false) { - $this->_debug("S: ".ldap_error($this->conn)); - return false; - } - - $this->_debug("S: OK"); - return true; - } - - /** - * Wrapper for ldap_mod_replace() - */ - protected function ldap_mod_replace($dn, $entry) - { - $this->_debug("C: Replace [dn: $dn]: ".print_r($entry, true)); - - if (!ldap_mod_replace($this->conn, $dn, $entry)) { - $this->_debug("S: ".ldap_error($this->conn)); - return false; - } - - $this->_debug("S: OK"); - return true; - } - - /** - * Wrapper for ldap_mod_add() - */ - protected function ldap_mod_add($dn, $entry) - { - $this->_debug("C: Add [dn: $dn]: ".print_r($entry, true)); - - if (!ldap_mod_add($this->conn, $dn, $entry)) { - $this->_debug("S: ".ldap_error($this->conn)); - return false; - } - - $this->_debug("S: OK"); - return true; - } - - /** - * Wrapper for ldap_mod_del() - */ - protected function ldap_mod_del($dn, $entry) - { - $this->_debug("C: Delete [dn: $dn]: ".print_r($entry, true)); - - if (!ldap_mod_del($this->conn, $dn, $entry)) { - $this->_debug("S: ".ldap_error($this->conn)); - return false; - } - - $this->_debug("S: OK"); - return true; - } - - /** - * Wrapper for ldap_rename() - */ - protected function ldap_rename($dn, $newrdn, $newparent = null, $deleteoldrdn = true) - { - $this->_debug("C: Rename [dn: $dn] [dn: $newrdn]"); - - if (!ldap_rename($this->conn, $dn, $newrdn, $newparent, $deleteoldrdn)) { - $this->_debug("S: ".ldap_error($this->conn)); - return false; - } - - $this->_debug("S: OK"); - return true; - } - - /** - * Wrapper for ldap_list() - */ - protected function ldap_list($dn, $filter, $attrs = array('')) - { - $list = array(); - $this->_debug("C: List [dn: $dn] [{$filter}]"); - - if ($result = ldap_list($this->conn, $dn, $filter, $attrs)) { - $list = ldap_get_entries($this->conn, $result); - - if ($list === false) { - $this->_debug("S: ".ldap_error($this->conn)); - return array(); - } - - $count = $list['count']; - unset($list['count']); - - $this->_debug("S: $count record(s)"); - } - else { - $this->_debug("S: ".ldap_error($this->conn)); - } - - return $list; - } - } diff --git a/program/lib/Roundcube/rcube_ldap_generic.php b/program/lib/Roundcube/rcube_ldap_generic.php new file mode 100644 index 000000000..88378dc22 --- /dev/null +++ b/program/lib/Roundcube/rcube_ldap_generic.php @@ -0,0 +1,1049 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | Roundcube/rcube_ldap_generic.php | + | | + | This file is part of the Roundcube Webmail client | + | Copyright (C) 2006-2013, The Roundcube Dev Team | + | Copyright (C) 2012-2013, Kolab Systems AG | + | | + | Licensed under the GNU General Public License version 3 or | + | any later version with exceptions for skins & plugins. | + | See the README file for a full license statement. | + | | + | PURPOSE: | + | Provide basic functionality for accessing LDAP directories | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + | Aleksander Machniak <machniak@kolabsys.com> | + +-----------------------------------------------------------------------+ +*/ + + +/* + LDAP connection properties + -------------------------- + + $prop = array( + 'host' => '<ldap-server-address>', + // or + 'hosts' => array('directory.verisign.com'), + 'port' => 389, + 'use_tls' => true|false, + 'ldap_version' => 3, // using LDAPv3 + 'auth_method' => '', // SASL authentication method (for proxy auth), e.g. DIGEST-MD5 + 'attributes' => array('dn'), // List of attributes to read from the server + 'vlv' => false, // Enable Virtual List View to more efficiently fetch paginated data (if server supports it) + 'config_root_dn' => 'cn=config', // Root DN to read config (e.g. vlv indexes) from + 'numsub_filter' => '(objectClass=organizationalUnit)', // with VLV, we also use numSubOrdinates to query the total number of records. Set this filter to get all numSubOrdinates attributes for counting + 'sizelimit' => '0', // Enables you to limit the count of entries fetched. Setting this to 0 means no limit. + 'timelimit' => '0', // Sets the number of seconds how long is spend on the search. Setting this to 0 means no limit. + 'network_timeout' => 10, // The timeout (in seconds) for connect + bind arrempts. This is only supported in PHP >= 5.3.0 with OpenLDAP 2.x + 'referrals' => true|false, // Sets the LDAP_OPT_REFERRALS option. Mostly used in multi-domain Active Directory setups + ); +*/ + +/** + * Model class to access an LDAP directories + * + * @package Framework + * @subpackage LDAP + */ +class rcube_ldap_generic +{ + const UPDATE_MOD_ADD = 1; + const UPDATE_MOD_DELETE = 2; + const UPDATE_MOD_REPLACE = 4; + const UPDATE_MOD_FULL = 7; + + public $conn; + public $vlv_active = false; + + /** private properties */ + protected $cache = null; + protected $config = array(); + protected $attributes = array('dn'); + protected $entries = null; + protected $result = null; + protected $debug = false; + protected $list_page = 1; + protected $page_size = 10; + protected $vlv_config = null; + + + /** + * Object constructor + * + * @param array $p LDAP connection properties + */ + function __construct($p) + { + $this->config = $p; + + if (is_array($p['attributes'])) + $this->attributes = $p['attributes']; + + if (!is_array($p['hosts']) && !empty($p['host'])) + $this->config['hosts'] = array($p['host']); + } + + /** + * Activate/deactivate debug mode + * + * @param boolean $dbg True if LDAP commands should be logged + */ + public function set_debug($dbg = true) + { + $this->debug = $dbg; + } + + /** + * Set connection options + * + * @param mixed $opt Option name as string or hash array with multiple options + * @param mixed $val Option value + */ + public function set_config($opt, $val = null) + { + if (is_array($opt)) + $this->config = array_merge($this->config, $opt); + else + $this->config[$opt] = $value; + } + + /** + * Enable caching by passing an instance of rcube_cache to be used by this object + * + * @param object rcube_cache Instance or False to disable caching + */ + public function set_cache($cache_engine) + { + $this->cache = $cache_engine; + } + + /** + * Set properties for VLV-based paging + * + * @param number $page Page number to list (starting at 1) + * @param number $size Number of entries to display on one page + */ + public function set_vlv_page($page, $size = 10) + { + $this->list_page = $page; + $this->page_size = $size; + } + + /** + * Establish a connection to the LDAP server + */ + public function connect($host = null) + { + if (!function_exists('ldap_connect')) { + rcube::raise_error(array('code' => 100, 'type' => 'ldap', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "No ldap support in this installation of PHP"), + true); + return false; + } + + if (is_resource($this->conn) && $this->config['host'] == $host) + return true; + + if (empty($this->config['ldap_version'])) + $this->config['ldap_version'] = 3; + + // iterate over hosts if none specified + if (!$host) { + if (!is_array($this->config['hosts'])) + $this->config['hosts'] = array($this->config['hosts']); + + foreach ($this->config['hosts'] as $host) { + if ($this->connect($host)) { + return true; + } + } + + return false; + } + + // open connection to the given $host + $host = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host)); + $hostname = $host . ($this->config['port'] ? ':'.$this->config['port'] : ''); + + $this->_debug("C: Connect to $hostname [{$this->config['name']}]"); + + if ($lc = @ldap_connect($host, $this->config['port'])) { + if ($this->config['use_tls'] === true) + if (!ldap_start_tls($lc)) + continue; + + $this->_debug("S: OK"); + + ldap_set_option($lc, LDAP_OPT_PROTOCOL_VERSION, $this->config['ldap_version']); + $this->config['host'] = $host; + $this->conn = $lc; + + if (!empty($this->config['network_timeout'])) + ldap_set_option($lc, LDAP_OPT_NETWORK_TIMEOUT, $this->config['network_timeout']); + + if (isset($this->config['referrals'])) + ldap_set_option($lc, LDAP_OPT_REFERRALS, $this->config['referrals']); + } + else { + $this->_debug("S: NOT OK"); + } + + if (!is_resource($this->conn)) { + rcube::raise_error(array('code' => 100, 'type' => 'ldap', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "Could not connect to any LDAP server, last tried $hostname"), + true); + return false; + } + + return true; + } + + /** + * Bind connection with (SASL-) user and password + * + * @param string $authc Authentication user + * @param string $pass Bind password + * @param string $authz Autorization user + * + * @return boolean True on success, False on error + */ + public function sasl_bind($authc, $pass, $authz=null) + { + if (!$this->conn) { + return false; + } + + if (!function_exists('ldap_sasl_bind')) { + rcube::raise_error(array('code' => 100, 'type' => 'ldap', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "Unable to bind: ldap_sasl_bind() not exists"), + true); + return false; + } + + if (!empty($authz)) { + $authz = 'u:' . $authz; + } + + if (!empty($this->config['auth_method'])) { + $method = $this->config['auth_method']; + } + else { + $method = 'DIGEST-MD5'; + } + + $this->_debug("C: SASL Bind [mech: $method, authc: $authc, authz: $authz, pass: $pass]"); + + if (ldap_sasl_bind($this->conn, NULL, $pass, $method, NULL, $authc, $authz)) { + $this->_debug("S: OK"); + return true; + } + + $this->_debug("S: ".ldap_error($this->conn)); + + rcube::raise_error(array( + 'code' => ldap_errno($this->conn), 'type' => 'ldap', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "SASL Bind failed for authcid=$authc ".ldap_error($this->conn)), + true); + return false; + } + + /** + * Bind connection with DN and password + * + * @param string $dn Bind DN + * @param string $pass Bind password + * + * @return boolean True on success, False on error + */ + public function bind($dn, $pass) + { + if (!$this->conn) { + return false; + } + + $this->_debug("C: Bind $dn [pass: $pass]"); + + if (@ldap_bind($this->conn, $dn, $pass)) { + $this->_debug("S: OK"); + return true; + } + + $this->_debug("S: ".ldap_error($this->conn)); + + rcube::raise_error(array( + 'code' => ldap_errno($this->conn), 'type' => 'ldap', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "Bind failed for dn=$dn: ".ldap_error($this->conn)), + true); + + return false; + } + + /** + * Close connection to LDAP server + */ + public function close() + { + if ($this->conn) { + $this->_debug("C: Close"); + ldap_unbind($this->conn); + $this->conn = null; + } + } + + /** + * Return the last result set + * + * @return object rcube_ldap_result Result object + */ + function get_result() + { + return $this->result; + } + + /** + * Get a specific LDAP entry, identified by its DN + * + * @param string $dn Record identifier + * @return array Hash array + */ + function get_entry($dn) + { + $rec = null; + + if ($this->conn && $dn) { + $this->_debug("C: Read $dn [(objectclass=*)]"); + + if ($ldap_result = @ldap_read($this->conn, $dn, '(objectclass=*)', $this->attributes)) { + $this->_debug("S: OK"); + + if ($entry = ldap_first_entry($this->conn, $ldap_result)) { + $rec = ldap_get_attributes($this->conn, $entry); + } + } + else { + $this->_debug("S: ".ldap_error($this->conn)); + } + + if (!empty($rec)) { + $rec['dn'] = $dn; // Add in the dn for the entry. + } + } + + return $rec; + } + + /** + * Execute the LDAP search based on the stored credentials + * + * @param string $base_dn The base DN to query + * @param string $filter The LDAP filter for search + * @param string $scope The LDAP scope (list|sub|base) + * @param array $attrs List of entry attributes to read + * @param array $prop Hash array with query configuration properties: + * - sort: array of sort attributes (has to be in sync with the VLV index) + * - search: search string used for VLV controls + * @param boolean $count_only Set to true if only entry count is requested + * + * @return mixed rcube_ldap_result object or number of entries (if count_only=true) or false on error + */ + public function search($base_dn, $filter = '', $scope = 'sub', $attrs = array('dn'), $prop = array(), $count_only = false) + { + if (!$this->conn) { + return false; + } + + if (empty($filter)) { + $filter = '(objectclass=*)'; + } + + $this->_debug("C: Search $base_dn for $filter"); + + $function = self::scope2func($scope, $ns_function); + + // find available VLV index for this query + if (!$count_only && ($vlv_sort = $this->_find_vlv($base_dn, $filter, $scope, $prop['sort']))) { + // when using VLV, we get the total count by... + // ...either reading numSubOrdinates attribute + if (($sub_filter = $this->config['numsub_filter']) && + ($result_count = @$ns_function($this->conn, $base_dn, $sub_filter, array('numSubOrdinates'), 0, 0, 0)) + ) { + $counts = ldap_get_entries($this->conn, $result_count); + for ($vlv_count = $j = 0; $j < $counts['count']; $j++) + $vlv_count += $counts[$j]['numsubordinates'][0]; + $this->_debug("D: total numsubordinates = " . $vlv_count); + } + // ...or by fetching all records dn and count them + else if (!function_exists('ldap_parse_virtuallist_control')) { + $vlv_count = $this->search($base_dn, $filter, $scope, array('dn'), $prop, true); + } + + $this->vlv_active = $this->_vlv_set_controls($vlv_sort, $this->list_page, $this->page_size, $prop['search']); + } + else { + $this->vlv_active = false; + } + + // only fetch dn for count (should keep the payload low) + if ($ldap_result = @$function($this->conn, $base_dn, $filter, + $attrs, 0, (int)$this->config['sizelimit'], (int)$this->config['timelimit']) + ) { + // when running on a patched PHP we can use the extended functions + // to retrieve the total count from the LDAP search result + if ($this->vlv_active && function_exists('ldap_parse_virtuallist_control')) { + if (ldap_parse_result($this->conn, $ldap_result, $errcode, $matcheddn, $errmsg, $referrals, $serverctrls)) { + ldap_parse_virtuallist_control($this->conn, $serverctrls, $last_offset, $vlv_count, $vresult); + $this->_debug("S: VLV result: last_offset=$last_offset; content_count=$vlv_count"); + } + else { + $this->_debug("S: ".($errmsg ? $errmsg : ldap_error($this->conn))); + } + } + else if ($this->debug) { + $this->_debug("S: ".ldap_count_entries($this->conn, $ldap_result)." record(s) found"); + } + + $this->result = new rcube_ldap_result($this->conn, $ldap_result, $base_dn, $filter, $vlv_count); + + return $count_only ? $this->result->count() : $this->result; + } + else { + $this->_debug("S: ".ldap_error($this->conn)); + } + + return false; + } + + /** + * Modify an LDAP entry on the server + * + * @param string $dn Entry DN + * @param array $params Hash array of entry attributes + * @param int $mode Update mode (UPDATE_MOD_ADD | UPDATE_MOD_DELETE | UPDATE_MOD_REPLACE) + */ + public function modify($dn, $parms, $mode = 255) + { + // TODO: implement this + + return false; + } + + /** + * Wrapper for ldap_add() + * + * @see ldap_add() + */ + public function add($dn, $entry) + { + $this->_debug("C: Add $dn: ".print_r($entry, true)); + + $res = ldap_add($this->conn, $dn, $entry); + if ($res === false) { + $this->_debug("S: ".ldap_error($this->conn)); + return false; + } + + $this->_debug("S: OK"); + return true; + } + + /** + * Wrapper for ldap_delete() + * + * @see ldap_delete() + */ + public function delete($dn) + { + $this->_debug("C: Delete $dn"); + + $res = ldap_delete($this->conn, $dn); + if ($res === false) { + $this->_debug("S: ".ldap_error($this->conn)); + return false; + } + + $this->_debug("S: OK"); + return true; + } + + /** + * Wrapper for ldap_mod_replace() + * + * @see ldap_mod_replace() + */ + public function mod_replace($dn, $entry) + { + $this->_debug("C: Replace $dn: ".print_r($entry, true)); + + if (!ldap_mod_replace($this->conn, $dn, $entry)) { + $this->_debug("S: ".ldap_error($this->conn)); + return false; + } + + $this->_debug("S: OK"); + return true; + } + + /** + * Wrapper for ldap_mod_add() + * + * @see ldap_mod_add() + */ + public function mod_add($dn, $entry) + { + $this->_debug("C: Add $dn: ".print_r($entry, true)); + + if (!ldap_mod_add($this->conn, $dn, $entry)) { + $this->_debug("S: ".ldap_error($this->conn)); + return false; + } + + $this->_debug("S: OK"); + return true; + } + + /** + * Wrapper for ldap_mod_del() + * + * @see ldap_mod_del() + */ + public function mod_del($dn, $entry) + { + $this->_debug("C: Delete $dn: ".print_r($entry, true)); + + if (!ldap_mod_del($this->conn, $dn, $entry)) { + $this->_debug("S: ".ldap_error($this->conn)); + return false; + } + + $this->_debug("S: OK"); + return true; + } + + /** + * Wrapper for ldap_rename() + * + * @see ldap_rename() + */ + public function rename($dn, $newrdn, $newparent = null, $deleteoldrdn = true) + { + $this->_debug("C: Rename $dn to $newrdn"); + + if (!ldap_rename($this->conn, $dn, $newrdn, $newparent, $deleteoldrdn)) { + $this->_debug("S: ".ldap_error($this->conn)); + return false; + } + + $this->_debug("S: OK"); + return true; + } + + /** + * Wrapper for ldap_list() + ldap_get_entries() + * + * @see ldap_list() + * @see ldap_get_entries() + */ + public function list_entries($dn, $filter, $attributes = array('dn')) + { + $list = array(); + $this->_debug("C: List $dn [{$filter}]"); + + if ($result = ldap_list($this->conn, $dn, $filter, $attributes)) { + $list = ldap_get_entries($this->conn, $result); + + if ($list === false) { + $this->_debug("S: ".ldap_error($this->conn)); + return array(); + } + + $count = $list['count']; + unset($list['count']); + + $this->_debug("S: $count record(s)"); + } + else { + $this->_debug("S: ".ldap_error($this->conn)); + } + + return $list; + } + + /** + * Wrapper for ldap_read() + ldap_get_entries() + * + * @see ldap_read() + * @see ldap_get_entries() + */ + public function read_entries($dn, $filter, $attributes = null) + { + $this->_debug("C: Read $dn [{$filter}]"); + + if ($this->conn && $dn) { + if (!$attributes) + $attributes = $this->attributes; + + $result = @ldap_read($this->conn, $dn, $filter, $attributes, 0, (int)$this->config['sizelimit'], (int)$this->config['timelimit']); + if ($result === false) { + $this->_debug("S: ".ldap_error($this->conn)); + return false; + } + + $this->_debug("S: OK"); + return ldap_get_entries($this->conn, $result); + } + + return false; + } + + /** + * Choose the right PHP function according to scope property + * + * @param string $scope The LDAP scope (sub|base|list) + * @param string $ns_function Function to be used for numSubOrdinates queries + * @return string PHP function to be used to query directory + */ + public static function scope2func($scope, &$ns_function = null) + { + switch ($scope) { + case 'sub': + $function = $ns_function = 'ldap_search'; + break; + case 'base': + $function = $ns_function = 'ldap_read'; + break; + default: + $function = 'ldap_list'; + $ns_function = 'ldap_read'; + break; + } + + return $function; + } + + /** + * Convert the given scope integer value to a string representation + */ + public static function scopeint2str($scope) + { + switch ($scope) { + case 2: return 'sub'; + case 1: return 'one'; + case 0: return 'base'; + default: $this->_debug("Scope $scope is not a valid scope integer"); + } + + return ''; + } + + /** + * Escapes the given value according to RFC 2254 so that it can be safely used in LDAP filters. + * + * @param string $val Value to quote + * @return string The escaped value + */ + public static function escape_value($val) + { + return strtr($str, array('*'=>'\2a', '('=>'\28', ')'=>'\29', + '\\'=>'\5c', '/'=>'\2f')); + } + + /** + * Escapes a DN value according to RFC 2253 + * + * @param string $dn DN value o quote + * @return string The escaped value + */ + public static function escape_dn($dn) + { + return strtr($str, array(','=>'\2c', '='=>'\3d', '+'=>'\2b', + '<'=>'\3c', '>'=>'\3e', ';'=>'\3b', '\\'=>'\5c', + '"'=>'\22', '#'=>'\23')); + } + + /** + * Normalize a LDAP result by converting entry attributes arrays into single values + * + * @param array $result LDAP result set fetched with ldap_get_entries() + * @return array Hash array with normalized entries, indexed by their DNs + */ + public static function normalize_result($result) + { + if (!is_array($result)) { + return array(); + } + + $entries = array(); + for ($i = 0; $i < $result['count']; $i++) { + $key = $result[$i]['dn'] ? $result[$i]['dn'] : $i; + $entries[$key] = self::normalize_entry($result[$i]); + } + + return $entries; + } + + /** + * Turn an LDAP entry into a regular PHP array with attributes as keys. + * + * @param array $entry Attributes array as retrieved from ldap_get_attributes() or ldap_get_entries() + * @return array Hash array with attributes as keys + */ + public static function normalize_entry($entry) + { + $rec = array(); + for ($i=0; $i < $entry['count']; $i++) { + $attr = $entry[$i]; + if ($entry[$attr]['count'] == 1) { + switch ($attr) { + case 'objectclass': + $rec[$attr] = array(strtolower($entry[$attr][0])); + break; + default: + $rec[$attr] = $entry[$attr][0]; + break; + } + } + else { + for ($j=0; $j < $entry[$attr]['count']; $j++) { + $rec[$attr][$j] = $entry[$attr][$j]; + } + } + } + + return $rec; + } + + /** + * Set server controls for Virtual List View (paginated listing) + */ + private function _vlv_set_controls($sort, $list_page, $page_size, $search = null) + { + $sort_ctrl = array('oid' => "1.2.840.113556.1.4.473", 'value' => self::_sort_ber_encode((array)$sort)); + $vlv_ctrl = array('oid' => "2.16.840.1.113730.3.4.9", 'value' => self::_vlv_ber_encode(($offset = ($list_page-1) * $page_size + 1), $page_size, $search), 'iscritical' => true); + + $this->_debug("C: Set controls sort=" . join(' ', unpack('H'.(strlen($sort_ctrl['value'])*2), $sort_ctrl['value'])) . " ($sort[0]);" + . " vlv=" . join(' ', (unpack('H'.(strlen($vlv_ctrl['value'])*2), $vlv_ctrl['value']))) . " ($offset/$page_size; $search)"); + + if (!ldap_set_option($this->conn, LDAP_OPT_SERVER_CONTROLS, array($sort_ctrl, $vlv_ctrl))) { + $this->_debug("S: ".ldap_error($this->conn)); + $this->set_error(self::ERROR_SEARCH, 'vlvnotsupported'); + return false; + } + + return true; + } + + /** + * Returns unified attribute name (resolving aliases) + */ + private static function _attr_name($namev) + { + // list of known attribute aliases + static $aliases = array( + 'gn' => 'givenname', + 'rfc822mailbox' => 'email', + 'userid' => 'uid', + 'emailaddress' => 'email', + 'pkcs9email' => 'email', + ); + + list($name, $limit) = explode(':', $namev, 2); + $suffix = $limit ? ':'.$limit : ''; + + return (isset($aliases[$name]) ? $aliases[$name] : $name) . $suffix; + } + + /** + * Quotes attribute value string + * + * @param string $str Attribute value + * @param bool $dn True if the attribute is a DN + * + * @return string Quoted string + */ + public static function quote_string($str, $dn=false) + { + // take firt entry if array given + if (is_array($str)) + $str = reset($str); + + if ($dn) + $replace = array(','=>'\2c', '='=>'\3d', '+'=>'\2b', '<'=>'\3c', + '>'=>'\3e', ';'=>'\3b', '\\'=>'\5c', '"'=>'\22', '#'=>'\23'); + else + $replace = array('*'=>'\2a', '('=>'\28', ')'=>'\29', '\\'=>'\5c', + '/'=>'\2f'); + + return strtr($str, $replace); + } + + /** + * Prints debug info to the log + */ + private function _debug($str) + { + if ($this->debug && class_exists('rcube')) { + rcube::write_log('ldap', $str); + } + } + + + /***************** Virtual List View (VLV) related utility functions **************** */ + + /** + * Return the search string value to be used in VLV controls + */ + private function _vlv_search($sort, $search) + { + foreach ($search as $attr => $value) { + if (!in_array(strtolower($attr), $sort)) { + $this->_debug("d: Cannot use VLV search using attribute not indexed: $attr (not in " . var_export($sort, true) . ")"); + return null; + } else { + return $value; + } + } + } + + /** + * Find a VLV index matching the given query attributes + * + * @return string Sort attribute or False if no match + */ + private function _find_vlv($base_dn, $filter, $scope, $sort_attrs = null) + { + if (!$this->config['vlv'] || $scope == 'base') { + return false; + } + + // get vlv config + $vlv_config = $this->_read_vlv_config(); + + if ($vlv = $vlv_config[$base_dn]) { + $this->_debug("D: Found a VLV for $base_dn"); + + if ($vlv['filter'] == strtolower($filter) || stripos($filter, '(&'.$vlv['filter'].'(') === 0) { + $this->_debug("D: Filter matches"); + if ($vlv['scope'] == $scope) { + // Not passing any sort attributes means you don't care + if (empty($sort_attrs) || in_array($sort_attrs, $vlv['sort'])) { + return $vlv['sort'][0]; + } + } + else { + $this->_debug("D: Scope does not match"); + } + } + else { + $this->_debug("D: Filter does not match"); + } + } + else { + $this->_debug("D: No VLV for $base_dn"); + } + + return false; + } + + /** + * Return VLV indexes and searches including necessary configuration + * details. + */ + private function _read_vlv_config() + { + if (empty($this->config['vlv']) || empty($this->config['config_root_dn'])) { + return array(); + } + // return hard-coded VLV config + else if (is_array($this->config['vlv'])) { + return $this->config['vlv']; + } + + // return cached result + if (is_array($this->vlv_config)) { + return $this->vlv_config; + } + + if ($this->cache && ($cached_config = $this->cache->get('vlvconfig'))) { + $this->vlv_config = $cached_config; + return $this->vlv_config; + } + + $this->vlv_config = array(); + + $ldap_result = ldap_search($this->conn, $this->config['config_root_dn'], '(objectclass=vlvsearch)', array('*'), 0, 0, 0); + $vlv_searches = new rcube_ldap_result($this->conn, $ldap_result, $this->config['config_root_dn'], '(objectclass=vlvsearch)'); + + if ($vlv_searches->count() < 1) { + $this->_debug("D: Empty result from search for '(objectclass=vlvsearch)' on '$config_root_dn'"); + return array(); + } + + foreach ($vlv_searches->entries(true) as $vlv_search_dn => $vlv_search_attrs) { + // Multiple indexes may exist + $ldap_result = ldap_search($this->conn, $vlv_search_dn, '(objectclass=vlvindex)', array('*'), 0, 0, 0); + $vlv_indexes = new rcube_ldap_result($this->conn, $ldap_result, $vlv_search_dn, '(objectclass=vlvindex)'); + + // Reset this one for each VLV search. + $_vlv_sort = array(); + foreach ($vlv_indexes->entries(true) as $vlv_index_dn => $vlv_index_attrs) { + $_vlv_sort[] = explode(' ', $vlv_index_attrs['vlvsort']); + } + + $this->vlv_config[$vlv_search_attrs['vlvbase']] = array( + 'scope' => self::scopeint2str($vlv_search_attrs['vlvscope']), + 'filter' => strtolower($vlv_search_attrs['vlvfilter']), + 'sort' => $_vlv_sort, + ); + } + + // cache this + if ($this->cache) + $this->cache->set('vlvconfig', $this->vlv_config); + + $this->_debug("D: Refreshed VLV config: " . var_export($this->vlv_config, true)); + + return $this->vlv_config; + } + + /** + * Generate BER encoded string for Virtual List View option + * + * @param integer List offset (first record) + * @param integer Records per page + * + * @return string BER encoded option value + */ + private static function _vlv_ber_encode($offset, $rpp, $search = '') + { + /* + this string is ber-encoded, php will prefix this value with: + 04 (octet string) and 10 (length of 16 bytes) + the code behind this string is broken down as follows: + 30 = ber sequence with a length of 0e (14) bytes following + 02 = type integer (in two's complement form) with 2 bytes following (beforeCount): 01 00 (ie 0) + 02 = type integer (in two's complement form) with 2 bytes following (afterCount): 01 18 (ie 25-1=24) + a0 = type context-specific/constructed with a length of 06 (6) bytes following + 02 = type integer with 2 bytes following (offset): 01 01 (ie 1) + 02 = type integer with 2 bytes following (contentCount): 01 00 + + with a search string present: + 81 = type context-specific/constructed with a length of 04 (4) bytes following (the length will change here) + 81 indicates a user string is present where as a a0 indicates just a offset search + 81 = type context-specific/constructed with a length of 06 (6) bytes following + + The following info was taken from the ISO/IEC 8825-1:2003 x.690 standard re: the + encoding of integer values (note: these values are in + two-complement form so since offset will never be negative bit 8 of the + leftmost octet should never by set to 1): + 8.3.2: If the contents octets of an integer value encoding consist + of more than one octet, then the bits of the first octet (rightmost) + and bit 8 of the second (to the left of first octet) octet: + a) shall not all be ones; and + b) shall not all be zero + */ + + if ($search) { + $search = preg_replace('/[^-[:alpha:] ,.()0-9]+/', '', $search); + $ber_val = self::_string2hex($search); + $str = self::_ber_addseq($ber_val, '81'); + } + else { + // construct the string from right to left + $str = "020100"; # contentCount + + $ber_val = self::_ber_encode_int($offset); // returns encoded integer value in hex format + + // calculate octet length of $ber_val + $str = self::_ber_addseq($ber_val, '02') . $str; + + // now compute length over $str + $str = self::_ber_addseq($str, 'a0'); + } + + // now tack on records per page + $str = "020100" . self::_ber_addseq(self::_ber_encode_int($rpp-1), '02') . $str; + + // now tack on sequence identifier and length + $str = self::_ber_addseq($str, '30'); + + return pack('H'.strlen($str), $str); + } + + /** + * create ber encoding for sort control + * + * @param array List of cols to sort by + * @return string BER encoded option value + */ + private static function _sort_ber_encode($sortcols) + { + $str = ''; + foreach (array_reverse((array)$sortcols) as $col) { + $ber_val = self::_string2hex($col); + + // 30 = ber sequence with a length of octet value + // 04 = octet string with a length of the ascii value + $oct = self::_ber_addseq($ber_val, '04'); + $str = self::_ber_addseq($oct, '30') . $str; + } + + // now tack on sequence identifier and length + $str = self::_ber_addseq($str, '30'); + + return pack('H'.strlen($str), $str); + } + + /** + * Add BER sequence with correct length and the given identifier + */ + private static function _ber_addseq($str, $identifier) + { + $len = dechex(strlen($str)/2); + if (strlen($len) % 2 != 0) + $len = '0'.$len; + + return $identifier . $len . $str; + } + + /** + * Returns BER encoded integer value in hex format + */ + private static function _ber_encode_int($offset) + { + $val = dechex($offset); + $prefix = ''; + + // check if bit 8 of high byte is 1 + if (preg_match('/^[89abcdef]/', $val)) + $prefix = '00'; + + if (strlen($val)%2 != 0) + $prefix .= '0'; + + return $prefix . $val; + } + + /** + * Returns ascii string encoded in hex + */ + private static function _string2hex($str) + { + $hex = ''; + for ($i=0; $i < strlen($str); $i++) { + $hex .= dechex(ord($str[$i])); + } + return $hex; + } + +} diff --git a/program/lib/Roundcube/rcube_ldap_result.php b/program/lib/Roundcube/rcube_ldap_result.php new file mode 100644 index 000000000..efc3331bc --- /dev/null +++ b/program/lib/Roundcube/rcube_ldap_result.php @@ -0,0 +1,130 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | Roundcube/rcube_ldap_result.php | + | | + | This file is part of the Roundcube Webmail client | + | Copyright (C) 2006-2013, The Roundcube Dev Team | + | Copyright (C) 2013, Kolab Systems AG | + | | + | Licensed under the GNU General Public License version 3 or | + | any later version with exceptions for skins & plugins. | + | See the README file for a full license statement. | + | | + | PURPOSE: | + | Model class that represents an LDAP search result | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ +*/ + + +/** + * Model class representing an LDAP search result + * + * @package Framework + * @subpackage LDAP + */ +class rcube_ldap_result implements Iterator +{ + public $conn; + public $ldap; + public $base_dn; + public $filter; + + private $count = null; + private $current = null; + private $iteratorkey = 0; + + /** + * Default constructor + * + * @param resource $conn LDAP link identifier + * @param resource $ldap LDAP result entry identifier + * @param string $base_dn Base DN used to get this result + * @param string $filter Filter query used to get this result + * @param integer $count Record count value (pre-calculated) + */ + function __construct($conn, $ldap, $base_dn, $filter, $count = null) + { + $this->conn = $conn; + $this->ldap = $ldap; + $this->base_dn = $base_dn; + $this->filter = $filter; + $this->count = $count; + } + + /** + * Wrapper for ldap_sort() + */ + public function sort($attr) + { + return ldap_sort($this->conn, $this->ldap, $attr); + } + + /** + * Get entries count + */ + public function count() + { + if (!isset($this->count)) + $this->count = ldap_count_entries($this->conn, $this->ldap); + + return $this->count; + } + + /** + * Wrapper for ldap_get_entries() + * + * @param boolean $normalize Optionally normalize the entries to a list of hash arrays + * @return array List of LDAP entries + */ + public function entries($normalize = false) + { + $entries = ldap_get_entries($this->conn, $this->ldap); + return $normalize ? rcube_ldap_generic::normalize_result($entries) : $entries; + } + + /** + * Wrapper for ldap_get_dn() using the current entry pointer + */ + public function get_dn() + { + return $this->current ? ldap_get_dn($this->conn, $this->current) : null; + } + + + /*** Implements the PHP 5 Iterator interface to make foreach work ***/ + + function current() + { + $attrib = ldap_get_attributes($this->conn, $this->current); + $attrib['dn'] = ldap_get_dn($this->conn, $this->current); + return $attrib; + } + + function key() + { + return $this->iteratorkey; + } + + function rewind() + { + $this->iteratorkey = 0; + $this->current = ldap_first_entry($this->conn, $this->ldap); + } + + function next() + { + $this->iteratorkey++; + $this->current = ldap_next_entry($this->conn, $this->current); + } + + function valid() + { + return (bool)$this->current; + } + +} diff --git a/program/lib/Roundcube/rcube_mime.php b/program/lib/Roundcube/rcube_mime.php index 5258af5bf..572540f47 100644 --- a/program/lib/Roundcube/rcube_mime.php +++ b/program/lib/Roundcube/rcube_mime.php @@ -587,23 +587,20 @@ class rcube_mime */ public static function wordwrap($string, $width=75, $break="\n", $cut=false, $charset=null, $wrap_quoted=true) { - if (!$charset) { - $charset = RCUBE_CHARSET; - } + // Note: Never try to use iconv instead of mbstring functions here + // Iconv's substr/strlen are 100x slower (#1489113) - // detect available functions - $strlen_func = function_exists('iconv_strlen') ? 'iconv_strlen' : 'mb_strlen'; - $strpos_func = function_exists('iconv_strpos') ? 'iconv_strpos' : 'mb_strpos'; - $strrpos_func = function_exists('iconv_strrpos') ? 'iconv_strrpos' : 'mb_strrpos'; - $substr_func = function_exists('iconv_substr') ? 'iconv_substr' : 'mb_substr'; + if ($charset && $charset != RCUBE_CHARSET && function_exists('mb_internal_encoding')) { + mb_internal_encoding($charset); + } // Convert \r\n to \n, this is our line-separator $string = str_replace("\r\n", "\n", $string); $separator = "\n"; // must be 1 character length $result = array(); - while (($stringLength = $strlen_func($string, $charset)) > 0) { - $breakPos = $strpos_func($string, $separator, 0, $charset); + while (($stringLength = mb_strlen($string)) > 0) { + $breakPos = mb_strpos($string, $separator, 0); // quoted line (do not wrap) if ($wrap_quoted && $string[0] == '>') { @@ -612,7 +609,7 @@ class rcube_mime $cutLength = null; } else { - $subString = $substr_func($string, 0, $breakPos, $charset); + $subString = mb_substr($string, 0, $breakPos); $cutLength = $breakPos + 1; } } @@ -623,39 +620,34 @@ class rcube_mime $cutLength = null; } else { - $subString = $substr_func($string, 0, $breakPos, $charset); + $subString = mb_substr($string, 0, $breakPos); $cutLength = $breakPos + 1; } } else { - $subString = $substr_func($string, 0, $width, $charset); + $subString = mb_substr($string, 0, $width); // last line if ($breakPos === false && $subString === $string) { $cutLength = null; } else { - $nextChar = $substr_func($string, $width, 1, $charset); + $nextChar = mb_substr($string, $width, 1); if ($nextChar === ' ' || $nextChar === $separator) { - $afterNextChar = $substr_func($string, $width + 1, 1, $charset); + $afterNextChar = mb_substr($string, $width + 1, 1); if ($afterNextChar === false) { $subString .= $nextChar; } - $cutLength = $strlen_func($subString, $charset) + 1; + $cutLength = mb_strlen($subString) + 1; } else { - if ($strrpos_func[0] == 'm') { - $spacePos = $strrpos_func($subString, ' ', 0, $charset); - } - else { - $spacePos = $strrpos_func($subString, ' ', $charset); - } + $spacePos = mb_strrpos($subString, ' ', 0); if ($spacePos !== false) { - $subString = $substr_func($subString, 0, $spacePos, $charset); + $subString = mb_substr($subString, 0, $spacePos); $cutLength = $spacePos + 1; } else if ($cut === false && $breakPos === false) { @@ -663,19 +655,19 @@ class rcube_mime $cutLength = null; } else if ($cut === false) { - $spacePos = $strpos_func($string, ' ', 0, $charset); + $spacePos = mb_strpos($string, ' ', 0); if ($spacePos !== false && $spacePos < $breakPos) { - $subString = $substr_func($string, 0, $spacePos, $charset); + $subString = mb_substr($string, 0, $spacePos); $cutLength = $spacePos + 1; } else { - $subString = $substr_func($string, 0, $breakPos, $charset); + $subString = mb_substr($string, 0, $breakPos); $cutLength = $breakPos + 1; } } else { - $subString = $substr_func($subString, 0, $width, $charset); + $subString = mb_substr($subString, 0, $width); $cutLength = $width; } } @@ -685,13 +677,17 @@ class rcube_mime $result[] = $subString; if ($cutLength !== null) { - $string = $substr_func($string, $cutLength, ($stringLength - $cutLength), $charset); + $string = mb_substr($string, $cutLength, ($stringLength - $cutLength)); } else { break; } } + if ($charset && $charset != RCUBE_CHARSET && function_exists('mb_internal_encoding')) { + mb_internal_encoding(RCUBE_CHARSET); + } + return implode($break, $result); } diff --git a/program/lib/Roundcube/rcube_session.php b/program/lib/Roundcube/rcube_session.php index dedde2284..646933b71 100644 --- a/program/lib/Roundcube/rcube_session.php +++ b/program/lib/Roundcube/rcube_session.php @@ -32,6 +32,7 @@ class rcube_session private $ip; private $start; private $changed; + private $time_diff = 0; private $reloaded = false; private $unsets = array(); private $gc_handlers = array(); @@ -42,6 +43,7 @@ class rcube_session private $secret = ''; private $ip_check = false; private $logging = false; + private $storage; private $memcache; @@ -52,18 +54,21 @@ class rcube_session { $this->db = $db; $this->start = microtime(true); - $this->ip = $_SERVER['REMOTE_ADDR']; + $this->ip = rcube_utils::remote_addr(); $this->logging = $config->get('log_session', false); $lifetime = $config->get('session_lifetime', 1) * 60; $this->set_lifetime($lifetime); // use memcache backend - if ($config->get('session_storage', 'db') == 'memcache') { + $this->storage = $config->get('session_storage', 'db'); + if ($this->storage == 'memcache') { $this->memcache = rcube::get_instance()->get_memcache(); // set custom functions for PHP session management if memcache is available if ($this->memcache) { + ini_set('session.serialize_handler', 'php'); + session_set_save_handler( array($this, 'open'), array($this, 'close'), @@ -79,7 +84,9 @@ class rcube_session true, true); } } - else { + else if ($this->storage != 'php') { + ini_set('session.serialize_handler', 'php'); + // set custom functions for PHP session management session_set_save_handler( array($this, 'open'), @@ -87,7 +94,23 @@ class rcube_session array($this, 'db_read'), array($this, 'db_write'), array($this, 'db_destroy'), - array($this, 'db_gc')); + array($this, 'gc')); + } + } + + + /** + * Wrapper for session_start() + */ + public function start() + { + session_start(); + + // copy some session properties to object vars + if ($this->storage == 'php') { + $this->key = session_id(); + $this->ip = $_SESSION['__IP']; + $this->changed = $_SESSION['__MTIME']; } } @@ -116,6 +139,25 @@ class rcube_session /** + * Wrapper for session_write_close() + */ + public function write_close() + { + if ($this->storage == 'php') { + $_SESSION['__IP'] = $this->ip; + $_SESSION['__MTIME'] = time(); + } + + session_write_close(); + + // write_close() is called on script shutdown, see rcube::shutdown() + // execute cleanup functionality if enabled by session gc handler + // we do this after closing the session for better performance + $this->gc_shutdown(); + } + + + /** * Read session data from database * * @param string Session ID @@ -125,14 +167,16 @@ class rcube_session public function db_read($key) { $sql_result = $this->db->query( - "SELECT vars, ip, changed FROM ".$this->db->table_name('session') - ." WHERE sess_id = ?", $key); + "SELECT vars, ip, changed, " . $this->db->now() . " AS ts" + . " FROM " . $this->db->table_name('session') + . " WHERE sess_id = ?", $key); if ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) { - $this->changed = strtotime($sql_arr['changed']); - $this->ip = $sql_arr['ip']; - $this->vars = base64_decode($sql_arr['vars']); - $this->key = $key; + $this->time_diff = time() - strtotime($sql_arr['ts']); + $this->changed = strtotime($sql_arr['changed']); + $this->ip = $sql_arr['ip']; + $this->vars = base64_decode($sql_arr['vars']); + $this->key = $key; return !empty($this->vars) ? (string) $this->vars : ''; } @@ -152,8 +196,9 @@ class rcube_session */ public function db_write($key, $vars) { - $ts = microtime(true); - $now = $this->db->fromunixtime((int)$ts); + $now = $this->db->now(); + $table = $this->db->table_name('session'); + $ts = microtime(true); // no session row in DB (db_read() returns false) if (!$this->key) { @@ -171,22 +216,19 @@ class rcube_session $newvars = $this->_fixvars($vars, $oldvars); if ($newvars !== $oldvars) { - $this->db->query( - sprintf("UPDATE %s SET vars=?, changed=%s WHERE sess_id=?", - $this->db->table_name('session'), $now), - base64_encode($newvars), $key); + $this->db->query("UPDATE $table " + . "SET changed = $now, vars = ? WHERE sess_id = ?", + base64_encode($newvars), $key); } - else if ($ts - $this->changed > $this->lifetime / 2) { - $this->db->query("UPDATE ".$this->db->table_name('session') - ." SET changed=$now WHERE sess_id=?", $key); + else if ($ts - $this->changed + $this->time_diff > $this->lifetime / 2) { + $this->db->query("UPDATE $table SET changed = $now" + . " WHERE sess_id = ?", $key); } } else { - $this->db->query( - sprintf("INSERT INTO %s (sess_id, vars, ip, created, changed) ". - "VALUES (?, ?, ?, %s, %s)", - $this->db->table_name('session'), $now, $now), - $key, base64_encode($vars), (string)$this->ip); + $this->db->query("INSERT INTO $table (sess_id, vars, ip, created, changed)" + . " VALUES (?, ?, ?, $now, $now)", + $key, base64_encode($vars), (string)$this->ip); } return true; @@ -246,25 +288,6 @@ class rcube_session /** - * Garbage collecting function - * - * @param string Session lifetime in seconds - * @return boolean True on success - */ - public function db_gc($maxlifetime) - { - // just delete all expired sessions - $this->db->query( - sprintf("DELETE FROM %s WHERE changed < %s", - $this->db->table_name('session'), $this->db->fromunixtime(time() - $maxlifetime))); - - $this->gc(); - - return true; - } - - - /** * Read session data from memcache * * @param string Session ID @@ -340,11 +363,11 @@ class rcube_session /** * Execute registered garbage collector routines */ - public function gc() + public function gc($maxlifetime) { - foreach ($this->gc_handlers as $fct) { - call_user_func($fct); - } + // move gc execution to the script shutdown function + // see rcube::shutdown() and rcube_session::write_close() + return $this->gc_enabled = $maxlifetime; } @@ -366,6 +389,25 @@ class rcube_session /** + * Garbage collector handler to run on script shutdown + */ + protected function gc_shutdown() + { + if ($this->gc_enabled) { + // just delete all expired sessions + if ($this->storage == 'db') { + $this->db->query("DELETE FROM " . $this->db->table_name('session') + . " WHERE changed < " . $this->db->now(-$this->gc_enabled)); + } + + foreach ($this->gc_handlers as $fct) { + call_user_func($fct); + } + } + } + + + /** * Generate and set new session id * * @param boolean $destroy If enabled the current session will be destroyed @@ -438,7 +480,7 @@ class rcube_session public function kill() { $this->vars = null; - $this->ip = $_SERVER['REMOTE_ADDR']; // update IP (might have changed) + $this->ip = rcube_utils::remote_addr(); // update IP (might have changed) $this->destroy(session_id()); rcube_utils::setcookie($this->cookiename, '-del-', time() - 60); } @@ -652,10 +694,10 @@ class rcube_session function check_auth() { $this->cookie = $_COOKIE[$this->cookiename]; - $result = $this->ip_check ? $_SERVER['REMOTE_ADDR'] == $this->ip : true; + $result = $this->ip_check ? rcube_utils::remote_addr() == $this->ip : true; if (!$result) { - $this->log("IP check failed for " . $this->key . "; expected " . $this->ip . "; got " . $_SERVER['REMOTE_ADDR']); + $this->log("IP check failed for " . $this->key . "; expected " . $this->ip . "; got " . rcube_utils::remote_addr()); } if ($result && $this->_mkcookie($this->now) != $this->cookie) { diff --git a/program/lib/Roundcube/rcube_spellchecker.php b/program/lib/Roundcube/rcube_spellchecker.php index 60aec500f..df4365223 100644 --- a/program/lib/Roundcube/rcube_spellchecker.php +++ b/program/lib/Roundcube/rcube_spellchecker.php @@ -84,6 +84,9 @@ class rcube_spellchecker if ($this->engine == 'pspell') { $this->matches = $this->_pspell_check($this->content); } + else if ($this->engine == 'enchant') { + $this->matches = $this->_enchant_check($this->content); + } else { $this->matches = $this->_googie_check($this->content); } @@ -115,6 +118,9 @@ class rcube_spellchecker if ($this->engine == 'pspell') { return $this->_pspell_suggestions($word); } + else if ($this->engine == 'enchant') { + return $this->_enchant_suggestions($word); + } return $this->_googie_suggestions($word); } @@ -133,6 +139,9 @@ class rcube_spellchecker if ($this->engine == 'pspell') { return $this->_pspell_words($text, $is_html); } + else if ($this->engine == 'enchant') { + return $this->_enchant_words($text, $is_html); + } return $this->_googie_words($text, $is_html); } @@ -326,6 +335,141 @@ class rcube_spellchecker } + /** + * Checks the text using enchant + * + * @param string $text Text content for spellchecking + */ + private function _enchant_check($text) + { + // init spellchecker + $this->_enchant_init(); + + if (!$this->enchant_dictionary) { + return array(); + } + + // tokenize + $text = preg_split($this->separator, $text, NULL, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE); + + $diff = 0; + $matches = array(); + + foreach ($text as $w) { + $word = trim($w[0]); + $pos = $w[1] - $diff; + $len = mb_strlen($word); + + // skip exceptions + if ($this->is_exception($word)) { + } + else if (!enchant_dict_check($this->enchant_dictionary, $word)) { + $suggestions = enchant_dict_suggest($this->enchant_dictionary, $word); + + if (sizeof($suggestions) > self::MAX_SUGGESTIONS) { + $suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS); + } + + $matches[] = array($word, $pos, $len, null, $suggestions); + } + + $diff += (strlen($word) - $len); + } + + return $matches; + } + + + /** + * Returns the misspelled words + */ + private function _enchant_words($text = null, $is_html=false) + { + $result = array(); + + if ($text) { + // init spellchecker + $this->_enchant_init(); + + if (!$this->enchant_dictionary) { + return array(); + } + + // With Enchant we don't need to get suggestions to return misspelled words + if ($is_html) { + $text = $this->html2text($text); + } + + $text = preg_split($this->separator, $text, NULL, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE); + + foreach ($text as $w) { + $word = trim($w[0]); + + // skip exceptions + if ($this->is_exception($word)) { + continue; + } + + if (!enchant_dict_check($this->enchant_dictionary, $word)) { + $result[] = $word; + } + } + + return $result; + } + + foreach ($this->matches as $m) { + $result[] = $m[0]; + } + + return $result; + } + + + /** + * Returns suggestions for misspelled word + */ + private function _enchant_suggestions($word) + { + // init spellchecker + $this->_enchant_init(); + + if (!$this->enchant_dictionary) { + return array(); + } + + $suggestions = enchant_dict_suggest($this->enchant_dictionary, $word); + + if (sizeof($suggestions) > self::MAX_SUGGESTIONS) + $suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS); + + return is_array($suggestions) ? $suggestions : array(); + } + + + /** + * Initializes PSpell dictionary + */ + private function _enchant_init() + { + if (!$this->enchant_broker) { + if (!extension_loaded('enchant')) { + $this->error = "Enchant extension not available"; + return; + } + + $this->enchant_broker = enchant_broker_init(); + } + + if (!enchant_broker_dict_exists($this->enchant_broker, $this->lang)) { + $this->error = "Unable to load dictionary for selected language using Enchant"; + return; + } + + $this->enchant_dictionary = enchant_broker_request_dict($this->enchant_broker, $this->lang); + } + + private function _googie_check($text) { // spell check uri is configured @@ -377,7 +521,7 @@ class rcube_spellchecker if (!$store) { $this->error = "Empty result from spelling engine"; } - else if (preg_match('/<spellresult error="([^"]+)"/', $store, $m)) { + else if (preg_match('/<spellresult error="([^"]+)"/', $store, $m) && $m[1]) { $this->error = "Error code $m[1] returned"; } diff --git a/program/lib/Roundcube/rcube_storage.php b/program/lib/Roundcube/rcube_storage.php index 700d12ffb..4b336f210 100644 --- a/program/lib/Roundcube/rcube_storage.php +++ b/program/lib/Roundcube/rcube_storage.php @@ -540,12 +540,13 @@ abstract class rcube_storage /** * Append a mail message (source) to a specific folder. * - * @param string $folder Target folder - * @param string $message The message source string or filename - * @param string $headers Headers string if $message contains only the body - * @param boolean $is_file True if $message is a filename - * @param array $flags Message flags - * @param mixed $date Message internal date + * @param string $folder Target folder + * @param string|array $message The message source string or filename + * or array (of strings and file pointers) + * @param string $headers Headers string if $message contains only the body + * @param boolean $is_file True if $message is a filename + * @param array $flags Message flags + * @param mixed $date Message internal date * * @return int|bool Appended message UID or True on success, False on error */ @@ -986,6 +987,6 @@ abstract class rcube_storage /** * Delete outdated cache entries */ - abstract function expunge_cache(); + abstract function cache_gc(); } // end class rcube_storage diff --git a/program/lib/Roundcube/rcube_user.php b/program/lib/Roundcube/rcube_user.php index 505b190d1..5e9c9af80 100644 --- a/program/lib/Roundcube/rcube_user.php +++ b/program/lib/Roundcube/rcube_user.php @@ -495,9 +495,9 @@ class rcube_user "INSERT INTO ".$dbh->table_name('users'). " (created, last_login, username, mail_host, language)". " VALUES (".$dbh->now().", ".$dbh->now().", ?, ?, ?)", - strip_newlines($data['user']), - strip_newlines($data['host']), - strip_newlines($data['language'])); + $data['user'], + $data['host'], + $data['language']); if ($user_id = $dbh->insert_id('users')) { // create rcube_user instance to make plugin hooks work @@ -517,7 +517,7 @@ class rcube_user if (empty($user_email)) { $user_email = strpos($data['user'], '@') ? $user : sprintf('%s@%s', $data['user'], $mail_domain); } - $email_list[] = strip_newlines($user_email); + $email_list[] = $user_email; } // identities_level check else if (count($email_list) > 1 && $rcube->config->get('identities_level', 0) > 1) { @@ -547,7 +547,6 @@ class rcube_user $record['name'] = $user_name != $record['email'] ? $user_name : ''; } - $record['name'] = strip_newlines($record['name']); $record['user_id'] = $user_id; $record['standard'] = $standard; diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php index 8467107fe..cf87dedb7 100644 --- a/program/lib/Roundcube/rcube_utils.php +++ b/program/lib/Roundcube/rcube_utils.php @@ -360,12 +360,8 @@ class rcube_utils return $value; } - // strip single quotes if magic_quotes_sybase is enabled - if (ini_get('magic_quotes_sybase')) { - $value = str_replace("''", "'", $value); - } // strip slashes if magic_quotes enabled - else if (get_magic_quotes_gpc() || get_magic_quotes_runtime()) { + if (get_magic_quotes_gpc() || get_magic_quotes_runtime()) { $value = stripslashes($value); } @@ -510,17 +506,24 @@ class rcube_utils */ public static function file2class($mimetype, $filename) { + $mimetype = strtolower($mimetype); + $filename = strtolower($filename); + list($primary, $secondary) = explode('/', $mimetype); $classes = array($primary ? $primary : 'unknown'); + if ($secondary) { $classes[] = $secondary; } - if (preg_match('/\.([a-z0-9]+)$/i', $filename, $m)) { - $classes[] = $m[1]; + + if (preg_match('/\.([a-z0-9]+)$/', $filename, $m)) { + if (!in_array($m[1], $classes)) { + $classes[] = $m[1]; + } } - return strtolower(join(" ", $classes)); + return join(" ", $classes); } @@ -663,6 +666,21 @@ class rcube_utils /** + * Returns the real remote IP address + * + * @return string Remote IP address + */ + public static function remote_addr() + { + foreach (array('HTTP_X_FORWARDED_FOR','HTTP_X_REAL_IP','REMOTE_ADDR') as $prop) { + if (!empty($_SERVER[$prop])) + return $_SERVER[$prop]; + } + + return ''; + } + + /** * Read a specific HTTP request header. * * @param string $name Header name @@ -726,7 +744,7 @@ class rcube_utils return mktime(0,0,0, intval($matches[2]), intval($matches[3]), intval($matches[1])); } else if (is_numeric($date)) { - return $date; + return (int) $date; } // Clean malformed data @@ -755,7 +773,7 @@ class rcube_utils $date = implode(' ', $d); } - return $ts; + return (int) $ts; } diff --git a/program/lib/Roundcube/rcube_vcard.php b/program/lib/Roundcube/rcube_vcard.php index 90acb2110..a71305c4b 100644 --- a/program/lib/Roundcube/rcube_vcard.php +++ b/program/lib/Roundcube/rcube_vcard.php @@ -714,9 +714,15 @@ class rcube_vcard $value[] = $attrvalues; } else if (is_bool($attrvalues)) { - // true means just tag, not tag=value, as in PHOTO;BASE64:... + // true means just a tag, not tag=value, as in PHOTO;BASE64:... if ($attrvalues) { - $attr .= strtoupper(";$attrname"); + // vCard v3 uses ENCODING=B (#1489183) + if ($attrname == 'base64') { + $attr .= ";ENCODING=B"; + } + else { + $attr .= strtoupper(";$attrname"); + } } } else { diff --git a/program/lib/Roundcube/rcube_washtml.php b/program/lib/Roundcube/rcube_washtml.php index a11371c61..6b2efcc78 100644 --- a/program/lib/Roundcube/rcube_washtml.php +++ b/program/lib/Roundcube/rcube_washtml.php @@ -113,10 +113,9 @@ class rcube_washtml 'type', 'rows', 'cols', 'disabled', 'readonly', 'checked', 'multiple', 'value' ); - /* Block elements which could be empty but cannot be returned in short form (<tag />) */ - static $block_elements = array('div', 'p', 'pre', 'blockquote', 'a', 'font', 'center', - 'table', 'ul', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'dl', 'strong', - 'i', 'b', 'u', 'span', + /* Elements which could be empty and be returned in short form (<tag />) */ + static $void_elements = array('area', 'base', 'br', 'col', 'command', 'embed', 'hr', + 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr' ); /* State for linked objects in HTML */ @@ -134,8 +133,8 @@ class rcube_washtml /* Ignore these HTML tags but process their content */ private $_ignore_elements = array(); - /* Block elements which could be empty but cannot be returned in short form (<tag />) */ - private $_block_elements = array(); + /* Elements which could be empty and be returned in short form (<tag />) */ + private $_void_elements = array(); /* Allowed HTML attributes */ private $_html_attribs = array(); @@ -152,9 +151,9 @@ class rcube_washtml $this->_html_elements = array_flip((array)$p['html_elements']) + array_flip(self::$html_elements) ; $this->_html_attribs = array_flip((array)$p['html_attribs']) + array_flip(self::$html_attribs); $this->_ignore_elements = array_flip((array)$p['ignore_elements']) + array_flip(self::$ignore_elements); - $this->_block_elements = array_flip((array)$p['block_elements']) + array_flip(self::$block_elements); + $this->_void_elements = array_flip((array)$p['void_elements']) + array_flip(self::$void_elements); - unset($p['html_elements'], $p['html_attribs'], $p['ignore_elements'], $p['block_elements']); + unset($p['html_elements'], $p['html_attribs'], $p['ignore_elements'], $p['void_elements']); $this->config = $p + array('show_washed' => true, 'allow_remote' => false, 'cid_map' => array()); } @@ -321,7 +320,7 @@ class rcube_washtml else if (isset($this->_html_elements[$tagName])) { $content = $this->dumpHtml($node, $level); $dump .= '<' . $tagName . $this->wash_attribs($node) . - ($content != '' || isset($this->_block_elements[$tagName]) ? ">$content</$tagName>" : ' />'); + ($content === '' && isset($this->_void_elements[$tagName]) ? ' />' : ">$content</$tagName>"); } else if (isset($this->_ignore_elements[$tagName])) { $dump .= '<!-- ' . htmlspecialchars($tagName, ENT_QUOTES) . ' not allowed -->'; diff --git a/program/localization/ar_SA/labels.inc b/program/localization/ar_SA/labels.inc index af08cc301..bc1764b0f 100644 --- a/program/localization/ar_SA/labels.inc +++ b/program/localization/ar_SA/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'المسودات'; $labels['sent'] = 'المرسل'; $labels['trash'] = 'المهملات'; $labels['junk'] = 'غير المرغوب'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'الموضوع'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'وضع طريقة السرد'; $labels['folderactions'] = 'إجراءات المجلد...'; $labels['compact'] = 'ضغط'; $labels['empty'] = 'تÙريغ'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'المساØØ© المستخدمة'; $labels['unknown'] = 'مجهول'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'استعادة البØØ« للاÙتراضي'; $labels['searchmod'] = 'أماكن البØØ«'; $labels['msgtext'] = 'كامل الرسالة'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'اÙØªØ ÙÙŠ ناÙذة جديدة'; $labels['emlsave'] = 'تنزيل (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'عرض المجموعة الأخيرة'; $labels['group'] = 'مجموعة'; $labels['groups'] = 'المجموعات'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'العناوين الشخصية'; $labels['searchsave'] = 'ØÙظ البØØ«'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'تجاهل الكلمات التي تØتوي $labels['spellcheckignorecaps'] = 'تجاهل الكلمات التي بها Ø£Øر٠كبيرة'; $labels['addtodict'] = 'إضاÙØ© إلى القامس'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/ast/labels.inc b/program/localization/ast/labels.inc index 49f85689b..8c1985eef 100644 --- a/program/localization/ast/labels.inc +++ b/program/localization/ast/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Borradores'; $labels['sent'] = 'Unviaos'; $labels['trash'] = 'Papelera'; $labels['junk'] = 'Puxarra'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Asuntu'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'Compautar'; $labels['empty'] = 'Vaciar'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Espaciu en discu'; $labels['unknown'] = 'desconocÃu'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Anovar la búsqueda'; $labels['searchmod'] = 'Guetar modificadores'; $labels['msgtext'] = 'Mensax completu'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Abrir en una ventana nueva'; $labels['emlsave'] = 'Baxar (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Amosar l\'últimu grupu'; $labels['group'] = 'Group'; $labels['groups'] = 'Grupos'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Direiciones personales'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/az_AZ/labels.inc b/program/localization/az_AZ/labels.inc index 0cb4b3e82..129315ec0 100644 --- a/program/localization/az_AZ/labels.inc +++ b/program/localization/az_AZ/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Qaralamalar'; $labels['sent'] = 'GöndÉ™rilÉ™nlÉ™r'; $labels['trash'] = 'SÉ™bÉ™t'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Mövzu'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Görünüş rejimi'; $labels['folderactions'] = 'Qovluq iÅŸlÉ™ri...'; $labels['compact'] = 'Sıx'; $labels['empty'] = 'BoÅŸalt'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Disk istifadÉ™si'; $labels['unknown'] = 'namÉ™lum'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Axtarışı yenilÉ™'; $labels['searchmod'] = 'Axtarış variantları'; $labels['msgtext'] = 'Bütün mÉ™ktub'; $labels['body'] = 'MÉ™tn'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Yeni pÉ™ncÉ™rÉ™dÉ™ aç'; $labels['emlsave'] = 'Saxla (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Sonuncunu göstÉ™r'; $labels['group'] = 'Qrup'; $labels['groups'] = 'Qruplar'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Şəxsi ünvanlar'; $labels['searchsave'] = 'SorÄŸunu saxla'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'RÉ™qÉ™mlÉ™r ilÉ™ sözlÉ™ri keç'; $labels['spellcheckignorecaps'] = 'Böyük hÉ™rflÉ™ri olan sözlÉ™rdÉ™n keç'; $labels['addtodict'] = 'LüğətÉ™ É™lavÉ™ et'; $labels['mailtoprotohandler'] = 'mailto: keçid üçün protokol qeyd et'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'MÉ™ktubların yönÉ™ldilmÉ™si'; $labels['inline'] = 'mÉ™tndÉ™'; $labels['asattachment'] = 'fayl kimi'; diff --git a/program/localization/be_BE/labels.inc b/program/localization/be_BE/labels.inc index a5489a454..56339a926 100644 --- a/program/localization/be_BE/labels.inc +++ b/program/localization/be_BE/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Чарнавікі'; $labels['sent'] = 'ДаÑланыÑ'; $labels['trash'] = 'Сметніца'; $labels['junk'] = 'Спам'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'ТÑма'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'Compact'; $labels['empty'] = 'Empty'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Disk usage'; $labels['unknown'] = 'unknown'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reset search'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Open in new window'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Show last page'; $labels['group'] = 'Group'; $labels['groups'] = 'Groups'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Personal Addresses'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/bg_BG/labels.inc b/program/localization/bg_BG/labels.inc index 6542cfc53..dd5be6e64 100644 --- a/program/localization/bg_BG/labels.inc +++ b/program/localization/bg_BG/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Чернови'; $labels['sent'] = 'Изпратени'; $labels['trash'] = 'Кошче'; $labels['junk'] = 'Спам'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Заглавие'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Кратък ÑпиÑък'; $labels['folderactions'] = 'ДейÑÑ‚Ð²Ð¸Ñ Ð·Ð° папки...'; $labels['compact'] = 'Свиване'; $labels['empty'] = 'Изпразни'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Използвано мÑÑто'; $labels['unknown'] = 'нÑма информациÑ'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ИзчиÑти Ñ‚ÑŠÑ€Ñенето и покажи Ð²Ñ $labels['searchmod'] = 'ТърÑене във'; $labels['msgtext'] = 'ЦÑлото Ñъобщение'; $labels['body'] = 'ОÑновен текÑÑ‚'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Отвори в нов прозорец'; $labels['emlsave'] = 'Изтегли като .eml'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'ПоÑледна Ñтраница'; $labels['group'] = 'Група'; $labels['groups'] = 'Групи'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Лични адреÑи'; $labels['searchsave'] = 'Запази Ñ‚ÑŠÑ€Ñенето'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Игнорирай думи ÑъдържащР$labels['spellcheckignorecaps'] = 'Игнорирай думи Ñъдържащи единÑтвено главни букви'; $labels['addtodict'] = 'Добави в речника'; $labels['mailtoprotohandler'] = 'РегиÑтриран протокол за mailto: връзките'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Препращане на ÑъобщениÑ'; $labels['inline'] = 'вградено'; $labels['asattachment'] = 'като прикачен файл'; diff --git a/program/localization/bn_BD/labels.inc b/program/localization/bn_BD/labels.inc index a0866a3a7..1273ef192 100644 --- a/program/localization/bn_BD/labels.inc +++ b/program/localization/bn_BD/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'খসড়া'; $labels['sent'] = 'পà§à¦°à§‡à¦°à¦¿à¦¤(পাঠানো মেইল)'; $labels['trash'] = 'ডাসà§à¦Ÿà¦¬à¦¿à¦¨'; $labels['junk'] = 'আজেবাজে মেইল'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'বিষয়'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'টাইটকরà§à¦¨'; $labels['empty'] = 'খালিকরà§à¦¨'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'ডিসà§à¦• ঠখালি যায়গা'; $labels['unknown'] = 'অজানা'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'নতà§à¦¨à¦•à¦°à§‡ খà§à¦œà§à¦¨'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'নতà§à¦¨ উইনà§à¦¡à§‹ তে দেখà§à¦¨'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'শেষের গà§à¦²à§‹ দেখান'; $labels['group'] = 'Group'; $labels['groups'] = 'গà§à¦°à§à¦ª'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'নিজের ঠিকানা'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/br/labels.inc b/program/localization/br/labels.inc index 537a887df..c88fd92a6 100644 --- a/program/localization/br/labels.inc +++ b/program/localization/br/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Brouilhedoù'; $labels['sent'] = 'Kaset'; $labels['trash'] = 'Pod-lastez'; $labels['junk'] = 'Stroboù'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Sujed'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'Stummaat'; $labels['empty'] = 'Skarzhañ'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Implijadur pladenn'; $labels['unknown'] = 'Dianav'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Aderaouekaat ar glask'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Open in new window'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Gwelout ar bajenn diwezhañ'; $labels['group'] = 'Group'; $labels['groups'] = 'Strolladoù'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Chomlec\'h personel'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/bs_BA/labels.inc b/program/localization/bs_BA/labels.inc index 5afdcad1f..61989e6b3 100644 --- a/program/localization/bs_BA/labels.inc +++ b/program/localization/bs_BA/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Skice'; $labels['sent'] = 'Poslano'; $labels['trash'] = 'Smeće'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Prikaži prava imena specijalnih foldera'; // message listing $labels['subject'] = 'Naslov'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'NaÄin prikaza liste'; $labels['folderactions'] = 'Akcije za foldere...'; $labels['compact'] = 'Optimiziraj'; $labels['empty'] = 'Isprazni'; +$labels['importmessages'] = 'Uvezi poruke'; $labels['quota'] = 'Zauzeće diska'; $labels['unknown'] = 'nepoznato'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Resetuj pretragu'; $labels['searchmod'] = 'Modifikacija pretrage'; $labels['msgtext'] = 'Cijela poruka'; $labels['body'] = 'Tijelo'; +$labels['type'] = 'Vrsta'; $labels['openinextwin'] = 'Otvori u novom prozoru'; $labels['emlsave'] = 'Preuzmi (.eml)'; @@ -223,7 +226,7 @@ $labels['mailreplyintro'] = '$date, $sender je napisao/la:'; $labels['originalmessage'] = 'Originalna poruka'; $labels['editidents'] = 'Uredi identitete'; -$labels['spellcheck'] = 'Spelovanje'; +$labels['spellcheck'] = 'Pravopis'; $labels['checkspelling'] = 'Provjera pravopisa'; $labels['resumeediting'] = 'Nastavi ureÄ‘ivanje'; $labels['revertto'] = 'Vrati na'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Prikaži zadnju stranicu'; $labels['group'] = 'Grupa'; $labels['groups'] = 'Grupe'; +$labels['listgroup'] = 'Izlistaj Älanove grupe'; $labels['personaladrbook'] = 'LiÄne adrese'; $labels['searchsave'] = 'SaÄuvaj pretragu'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Zanemari rijeÄi sa brojevima'; $labels['spellcheckignorecaps'] = 'Zanemari rijeÄi napisane velikim slovima'; $labels['addtodict'] = 'Dodaj u rjeÄnik'; $labels['mailtoprotohandler'] = 'Registruj upravljaÄ protokola za mailto: linkovi'; +$labels['standardwindows'] = 'Tretiraj popup-ove kao standardne prozore'; $labels['forwardmode'] = 'ProsljeÄ‘ivanje poruka'; $labels['inline'] = 'u istom redu'; $labels['asattachment'] = 'kao prilog'; diff --git a/program/localization/ca_ES/labels.inc b/program/localization/ca_ES/labels.inc index 3be753b68..ca0129de4 100644 --- a/program/localization/ca_ES/labels.inc +++ b/program/localization/ca_ES/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Esborranys'; $labels['sent'] = 'Enviats'; $labels['trash'] = 'Paperera'; $labels['junk'] = 'Correu brossa'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Assumpte'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Mode de vista de llista'; $labels['folderactions'] = 'Accions de carpeta'; $labels['compact'] = 'Compacta'; $labels['empty'] = 'Buida'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Ús del disc'; $labels['unknown'] = 'desconegut'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Neteja cerca'; $labels['searchmod'] = 'Cerca modificadors'; $labels['msgtext'] = 'Missatge sencer'; $labels['body'] = 'Cos'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Obre a una nova finestra'; $labels['emlsave'] = 'Descarrega (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Mostra la darrera pà gina'; $labels['group'] = 'Grup'; $labels['groups'] = 'Grups'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Llibreta d\'adreces'; $labels['searchsave'] = 'Desa la cerca'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignora paraules amb números'; $labels['spellcheckignorecaps'] = 'Ignora paraules amb lletres capitalitzades'; $labels['addtodict'] = 'Afegeix al diccionari'; $labels['mailtoprotohandler'] = 'Registra controlador de protocol pels enllaços mailto:'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Reenviament de missatges'; $labels['inline'] = 'en lÃnia'; $labels['asattachment'] = 'com adjunt'; diff --git a/program/localization/cs_CZ/labels.inc b/program/localization/cs_CZ/labels.inc index 8fb7ffade..b5cc093d8 100644 --- a/program/localization/cs_CZ/labels.inc +++ b/program/localization/cs_CZ/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Rozepsané'; $labels['sent'] = 'Odeslané'; $labels['trash'] = 'KoÅ¡'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Zobrazit skuteÄná jména speciálnÃch složek'; // message listing $labels['subject'] = 'PÅ™edmÄ›t'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Režim zobrazenà seznamu'; $labels['folderactions'] = 'Akce se složkou...'; $labels['compact'] = 'ZmenÅ¡it'; $labels['empty'] = 'Vymazat'; +$labels['importmessages'] = 'Import zpráv'; $labels['quota'] = 'Využità schránky'; $labels['unknown'] = 'neznámý'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ZruÅ¡it vyhledávánÃ'; $labels['searchmod'] = 'Parametry hledánÃ'; $labels['msgtext'] = 'Celá zpráva'; $labels['body'] = 'TÄ›lo'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'OtevÅ™Ãt v novém oknÄ›'; $labels['emlsave'] = 'Stáhnout (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Zobrazit poslednà zprávy'; $labels['group'] = 'Skupina'; $labels['groups'] = 'Skupiny'; +$labels['listgroup'] = ' Seznam Älenů skupiny'; $labels['personaladrbook'] = 'Osobnà kontakty'; $labels['searchsave'] = 'Uložit hledánÃ'; @@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Vytvářet HTML zprávy'; $labels['htmlonreply'] = 'jen pÅ™i odpovÄ›di na HTML zprávy'; $labels['htmlonreplyandforward'] = 'pÅ™i pÅ™eposlánà nebo odpovÄ›di na HTML zprávu'; $labels['htmlsignature'] = 'HTML podpis'; -$labels['showemail'] = 'Show email address with display name'; +$labels['showemail'] = 'Zobrazit e-mailovou adresu se skuteÄným jménem'; $labels['previewpane'] = 'Zobrazit panel náhledu'; $labels['skin'] = 'Vzhled'; $labels['logoutclear'] = 'Vyprázdnit koÅ¡ pÅ™i odhlášenÃ'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorovat slova obsahujÃcà ÄÃsla'; $labels['spellcheckignorecaps'] = 'Ignorovat slova psaná velkými pÃsmeny'; $labels['addtodict'] = 'PÅ™idat do slovnÃku'; $labels['mailtoprotohandler'] = 'Zaregistrovat handler pro odkazy „mailto:“'; +$labels['standardwindows'] = 'Zacházet s vyskakovacÃmi okny jako se standardnÃmi okny'; $labels['forwardmode'] = 'PÅ™eposlat zprávu'; $labels['inline'] = 'vloženÄ›'; $labels['asattachment'] = 'jako pÅ™Ãlohu'; diff --git a/program/localization/cs_CZ/messages.inc b/program/localization/cs_CZ/messages.inc index 9800b2412..59b2c6bd6 100644 --- a/program/localization/cs_CZ/messages.inc +++ b/program/localization/cs_CZ/messages.inc @@ -24,7 +24,7 @@ $messages['sessionerror'] = 'VaÅ¡e pÅ™ihlášenà je neplatné nebo vyprÅ¡elo'; $messages['storageerror'] = 'PÅ™ipojenà na IMAP server selhalo'; $messages['servererror'] = 'Chyba serveru!'; $messages['servererrormsg'] = 'Chyba serveru: $msg'; -$messages['dberror'] = 'Chyba v databázi!'; +$messages['dberror'] = 'Chyba databáze!'; $messages['requesttimedout'] = 'DoÅ¡lo k vyprÅ¡enà požadavku'; $messages['errorreadonly'] = 'PÅ™Ãkaz nelze provést, složka je urÄena jen ke ÄtenÃ.'; $messages['errornoperm'] = 'PÅ™Ãkaz nelze provést, nemáte oprávnÄ›nÃ.'; @@ -33,7 +33,7 @@ $messages['erroroverquotadelete'] = 'Nenà volné mÃsto na disku. Použijte SHI $messages['invalidrequest'] = 'Nesprávný požadavek. Data nebyla uložena.'; $messages['invalidhost'] = 'Å patné jméno serveru.'; $messages['nomessagesfound'] = 'Ve schránce nebyla nalezena žádná zpráva'; -$messages['loggedout'] = 'Byli jste úspěšnÄ› odhlášeni. Nashledanou!'; +$messages['loggedout'] = 'Byli jste úspěšnÄ› odhlášeni. Na shledanou!'; $messages['mailboxempty'] = 'Schránka je prázdná'; $messages['refreshing'] = 'Obnovuji...'; $messages['loading'] = 'NaÄÃtám...'; @@ -126,6 +126,8 @@ $messages['importwait'] = 'Importuji, prosÃm Äekejte...'; $messages['importformaterror'] = 'Import se nezdaÅ™il! Typ souboru nenà podporován.'; $messages['importconfirm'] = 'ÚspěšnÄ› naimportováno $inserted kontaktů, $skipped existujÃcÃch záznamů pÅ™eskoÄeno: $names'; $messages['importconfirmskipped'] = '<b>PÅ™eskoÄeno $skipped existujÃcÃch položek</b>'; +$messages['importmessagesuccess'] = 'ÚspěšnÄ› naimportováno $nr zpráv'; +$messages['importmessageerror'] = 'Import se nezdaÅ™il! Nahraný soubor nenà platnou zprávou nebo souborem mailboxu'; $messages['opnotpermitted'] = 'Operace nenà povolena!'; $messages['nofromaddress'] = 'ChybÄ›jÃcà e-mailová adresa v oznaÄeném profilu'; $messages['editorwarning'] = 'PÅ™epnutÃm do režimu prostého textu ztratÃte veÅ¡keré formátovánÃ. Chcete pokraÄovat?'; diff --git a/program/localization/cy_GB/labels.inc b/program/localization/cy_GB/labels.inc index 3e4f136bc..ca1f17426 100644 --- a/program/localization/cy_GB/labels.inc +++ b/program/localization/cy_GB/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Drafftiau'; $labels['sent'] = 'Danfonwyd'; $labels['trash'] = 'Sbwriel'; $labels['junk'] = 'Sothach'; +$labels['show_real_foldernames'] = 'Dangos enwau go-iawn ar gyfer ffolderi arbennig'; // message listing $labels['subject'] = 'Pwnc'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Golwg rhestr'; $labels['folderactions'] = 'Gweithredoedd ffolder...'; $labels['compact'] = 'Crynhoi'; $labels['empty'] = 'Gwagio'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Defnydd'; $labels['unknown'] = 'anhysbys'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Ail-osod chwiliad'; $labels['searchmod'] = 'Addasyddion chwilio'; $labels['msgtext'] = 'Y neges yn llawn'; $labels['body'] = 'Corff'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Agor mewn ffenest newydd'; $labels['emlsave'] = 'Llwytho lawr (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Dangos y set olaf'; $labels['group'] = 'Grŵp'; $labels['groups'] = 'Grwpiau'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Cyfeiriadau Personol'; $labels['searchsave'] = 'Cadw chwiliad'; @@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Ysgrifennu negeseuon HTML'; $labels['htmlonreply'] = 'wrth ateb i neges HTML yn unig'; $labels['htmlonreplyandforward'] = 'wrth ddanfon ymlaen neu ymateb i neges HTML'; $labels['htmlsignature'] = 'Llofnod HTML'; -$labels['showemail'] = 'Show email address with display name'; +$labels['showemail'] = 'Dangos cyfeiriad ebost gyda\'r enw gweledig'; $labels['previewpane'] = 'Dangos ffenest rhagolwg'; $labels['skin'] = 'Croen rhyngwyneb'; $labels['logoutclear'] = 'Clirio\'r Sbwriel wrth allgofnodi'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Anwybyddu geiriau gyda rhifau'; $labels['spellcheckignorecaps'] = 'Anwybyddu geiriau sy\'n briflythrennau yn gyfangwbl'; $labels['addtodict'] = 'Ychwanegu i\'r geiriadur'; $labels['mailtoprotohandler'] = 'Cofrestru trafodwr protocol ar gyfer dolenni mailto:'; +$labels['standardwindows'] = 'Trin ffenestri naid fel ffenestri arferol'; $labels['forwardmode'] = 'Danfon neges ymlaen'; $labels['inline'] = 'mewnlin'; $labels['asattachment'] = 'fel atodiad'; diff --git a/program/localization/da_DK/labels.inc b/program/localization/da_DK/labels.inc index 02d7dd9e3..a5b9b3bc8 100644 --- a/program/localization/da_DK/labels.inc +++ b/program/localization/da_DK/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Kladder'; $labels['sent'] = 'Sendt post'; $labels['trash'] = 'Papirkurv'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Emne'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Listevisningsmode'; $labels['folderactions'] = 'Mappehandlinger...'; $labels['compact'] = 'Ryd op'; $labels['empty'] = 'Tøm'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Diskforbrug'; $labels['unknown'] = 'ukendt'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Nulstil søgning'; $labels['searchmod'] = 'Søgeparametre'; $labels['msgtext'] = 'Hele beskeden'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Ã…bn i nyt vindue'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Vis sidste side'; $labels['group'] = 'Gruppe'; $labels['groups'] = 'Grupper'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Personlige adresser'; $labels['searchsave'] = 'Gem søgning'; @@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Skriv HTML-besked'; $labels['htmlonreply'] = 'kun nÃ¥r jeg besvarer HTML-beskeder'; $labels['htmlonreplyandforward'] = 'ved videresendelse eller besvarelse af HTML beskeder'; $labels['htmlsignature'] = 'HTML-signatur'; -$labels['showemail'] = 'Show email address with display name'; +$labels['showemail'] = 'Vis email-adresse med vist navn'; $labels['previewpane'] = 'ForhÃ¥ndsvisning'; $labels['skin'] = 'Brugerflade'; $labels['logoutclear'] = 'Tøm Papirkurv nÃ¥r jeg logger af'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorer ord med tal'; $labels['spellcheckignorecaps'] = 'Ignorer ord hvor alle bogstaver er versaler'; $labels['addtodict'] = 'Tilføj til ordbog'; $labels['mailtoprotohandler'] = 'Registrer hÃ¥ndtering af \'mailto:\' links'; +$labels['standardwindows'] = 'Behandl popups som standardvinduer'; $labels['forwardmode'] = 'Videresendelse af besked'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'som vedhæftning'; diff --git a/program/localization/de_CH/labels.inc b/program/localization/de_CH/labels.inc index e64859d2c..67d42bb05 100644 --- a/program/localization/de_CH/labels.inc +++ b/program/localization/de_CH/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Entwürfe'; $labels['sent'] = 'Gesendet'; $labels['trash'] = 'Gelöscht'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Spezialordner nicht übersetzen'; // message listing $labels['subject'] = 'Betreff'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Anzeigemodus'; $labels['folderactions'] = 'Ordneraktionen...'; $labels['compact'] = 'Packen'; $labels['empty'] = 'Leeren'; +$labels['importmessages'] = 'Nachrichten importieren'; $labels['quota'] = 'Verwendeter Speicherplatz'; $labels['unknown'] = 'unbekannt'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Löschen'; $labels['searchmod'] = 'Suchkriterien ändern'; $labels['msgtext'] = 'Ganze Nachricht'; $labels['body'] = 'Inhalt'; +$labels['type'] = 'Typ'; $labels['openinextwin'] = 'In neuem Fenster öffnen'; $labels['emlsave'] = 'Herunterladen (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Letzte Seite'; $labels['group'] = 'Gruppe'; $labels['groups'] = 'Gruppen'; +$labels['listgroup'] = 'Gruppenmitglieder anzeigen'; $labels['personaladrbook'] = 'Persönliches Adressbuch'; $labels['searchsave'] = 'Suche speichern'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Wörter mit Ziffern überspringen'; $labels['spellcheckignorecaps'] = 'Wörter überspringen, die nur aus Grossbuchstaben bestehen'; $labels['addtodict'] = 'Zum Wörterbuch hinzufügen'; $labels['mailtoprotohandler'] = 'Als Empfänger für mailto: Links einrichten'; +$labels['standardwindows'] = 'Popups als normale Browserfenster öffnen'; $labels['forwardmode'] = 'Weiterleiten einer Nachricht'; $labels['inline'] = 'eingebettet'; $labels['asattachment'] = 'als Anhang'; diff --git a/program/localization/de_CH/messages.inc b/program/localization/de_CH/messages.inc index f3697a825..27175be9e 100644 --- a/program/localization/de_CH/messages.inc +++ b/program/localization/de_CH/messages.inc @@ -126,6 +126,8 @@ $messages['importwait'] = 'Daten werden importiert, bitte warten...'; $messages['importformaterror'] = 'Import fehlgeschlagen! Die hochgeladene Datei enthält keines der unterstützten Datenformate.'; $messages['importconfirm'] = '<b>Es wurden $inserted Adressen erfolgreich importiert</b>'; $messages['importconfirmskipped'] = '<b>$skipped bestehende Einträge wurden übersprungen</b>'; +$messages['importmessagesuccess'] = '$nr Nachricht(n) erfolgreich importiert'; +$messages['importmessageerror'] = 'Import fehlgeschlagen! Die hochgeladene Datei ist keine E-Mail-Nachricht oder Mailbox-Datei.'; $messages['opnotpermitted'] = 'Operation nicht erlaubt!'; $messages['nofromaddress'] = 'Fehlende E-Mail-Adresse in ausgewählter Identität.'; $messages['editorwarning'] = 'Beim Wechseln in den Texteditor gehen alle Textformatierungen verloren. Möchten Sie fortfahren?'; diff --git a/program/localization/de_DE/labels.inc b/program/localization/de_DE/labels.inc index d497a6bc6..662ad2c70 100644 --- a/program/localization/de_DE/labels.inc +++ b/program/localization/de_DE/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Entwürfe'; $labels['sent'] = 'Gesendet'; $labels['trash'] = 'Gelöscht'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Echte Namen für Spezialordner anzeigen'; // message listing $labels['subject'] = 'Betreff'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Anzeigemodus'; $labels['folderactions'] = 'Ordneraktionen...'; $labels['compact'] = 'Packen'; $labels['empty'] = 'Leeren'; +$labels['importmessages'] = 'Nachrichten importieren'; $labels['quota'] = 'Speicherplatz'; $labels['unknown'] = 'unbekannt'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Suche zurücksetzen'; $labels['searchmod'] = 'Suchkriterien ändern'; $labels['msgtext'] = 'Nachricht'; $labels['body'] = 'Inhalt'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'In neuem Fenster öffnen'; $labels['emlsave'] = 'Lokal speichern (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Letzte Seite'; $labels['group'] = 'Gruppe'; $labels['groups'] = 'Gruppen'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Persönliches Adressbuch'; $labels['searchsave'] = 'Suchergebnisse speichern'; @@ -402,7 +406,7 @@ $labels['htmleditor'] = 'HTML-Nachrichten verfassen'; $labels['htmlonreply'] = 'nur Antworten auf HTML-Nachrichten'; $labels['htmlonreplyandforward'] = 'beim Weiterleiten und Beantworten auf HTML-Nachrichten'; $labels['htmlsignature'] = 'HTML-Signatur'; -$labels['showemail'] = 'Show email address with display name'; +$labels['showemail'] = 'E-Mail-Adresse mit dem Display Namen anzeigen'; $labels['previewpane'] = 'Nachrichtenvorschau anzeigen'; $labels['skin'] = 'Oberflächendesign'; $labels['logoutclear'] = 'Papierkorb beim Abmelden leeren'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Wörter mit Ziffern überspringen'; $labels['spellcheckignorecaps'] = 'Wörter überspringen, die nur aus Großbuchstaben bestehen'; $labels['addtodict'] = 'Zum Wörterbuch hinzufügen'; $labels['mailtoprotohandler'] = 'Als Empfänger für mailto: Links einrichten'; +$labels['standardwindows'] = 'Popups als Standard Windows behandeln'; $labels['forwardmode'] = 'Nachrichtenweiterleitung'; $labels['inline'] = 'eingebettet'; $labels['asattachment'] = 'als Anhang'; diff --git a/program/localization/el_GR/labels.inc b/program/localization/el_GR/labels.inc index 9f5d81839..d3030e574 100644 --- a/program/localization/el_GR/labels.inc +++ b/program/localization/el_GR/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Î ÏόχειÏα'; $labels['sent'] = 'ΑπεσταλμÎνα'; $labels['trash'] = 'Κάδος ΑποÏÏιμάτων'; $labels['junk'] = 'ΑνεπιθÏμητα'; +$labels['show_real_foldernames'] = 'Εμφάνιση Ï€Ïαγματικών ονομάτων για ειδικοÏÏ‚ φακÎλους'; // message listing $labels['subject'] = 'ΘÎμα'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Î Ïοβολή σε λίστα'; $labels['folderactions'] = 'ΕνÎÏγειες στους φακÎλους'; $labels['compact'] = 'Συμπίεση'; $labels['empty'] = 'Άδειασμα'; +$labels['importmessages'] = 'Εισαγωγή μηνυμάτων'; $labels['quota'] = 'ΧÏήση δίσκου'; $labels['unknown'] = 'άγνωστο'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ΕπαναφοÏά Αναζήτησης'; $labels['searchmod'] = 'Aλλαγή αναζήτησης'; $labels['msgtext'] = 'Σε όλο το μήνυμα'; $labels['body'] = 'Σώμα'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Άνοιγμα σε νÎο παÏάθυÏο'; $labels['emlsave'] = 'Λήψη αÏχείου (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Εμφάνιση της τελευταίας σελ $labels['group'] = 'Ομάδα'; $labels['groups'] = 'Ομάδες'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Î ÏοσωπικÎÏ‚ ΔιυθÏνσεις'; $labels['searchsave'] = 'Αποθήκευση αναζήτησης'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Οι λÎξεις που πεÏιÎχουν Î $labels['spellcheckignorecaps'] = 'Οι λÎξεις γÏαμμÎνες με ΚΕΦΑΛΑΙΑ να αγνοοÏνται'; $labels['addtodict'] = 'Î Ïοσθήκη στο λεξικό'; $labels['mailtoprotohandler'] = 'ΚαταχώÏηση διαχείÏισης Ï€Ïωτοκόλλου δεσμών mailto:'; +$labels['standardwindows'] = 'ΧειÏιστείτε τα αναδυόμενα παÏάθυÏα ως Ï€Ïότυπο των Windows'; $labels['forwardmode'] = 'Î Ïοώθηση μηνυμάτων'; $labels['inline'] = 'με εσνωμάτωση'; $labels['asattachment'] = 'σαν επισÏναψη'; diff --git a/program/localization/en_GB/labels.inc b/program/localization/en_GB/labels.inc index 275208a98..f903b0cf5 100644 --- a/program/localization/en_GB/labels.inc +++ b/program/localization/en_GB/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Drafts'; $labels['sent'] = 'Sent'; $labels['trash'] = 'Deleted Items'; $labels['junk'] = 'Junk'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Subject'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'Compact'; $labels['empty'] = 'Empty'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Disk usage'; $labels['unknown'] = 'unknown'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reset search'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Open in new window'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Show last set'; $labels['group'] = 'Group'; $labels['groups'] = 'Groups'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Personal Addresses'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalised'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc index ab57007dd..1865bcb3d 100644 --- a/program/localization/en_US/labels.inc +++ b/program/localization/en_US/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Drafts'; $labels['sent'] = 'Sent'; $labels['trash'] = 'Trash'; $labels['junk'] = 'Junk'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Subject'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'Compact'; $labels['empty'] = 'Empty'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Disk usage'; $labels['unknown'] = 'unknown'; @@ -203,6 +205,8 @@ $labels['resetsearch'] = 'Reset search'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; +$labels['namex'] = 'Name'; $labels['openinextwin'] = 'Open in new window'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +358,7 @@ $labels['lastpage'] = 'Show last page'; $labels['group'] = 'Group'; $labels['groups'] = 'Groups'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Personal Addresses'; $labels['searchsave'] = 'Save search'; @@ -472,6 +477,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/en_US/messages.inc b/program/localization/en_US/messages.inc index f9b5e00a6..47b0f797d 100644 --- a/program/localization/en_US/messages.inc +++ b/program/localization/en_US/messages.inc @@ -101,13 +101,16 @@ $messages['converting'] = 'Removing formatting...'; $messages['messageopenerror'] = 'Could not load message from server.'; $messages['fileuploaderror'] = 'File upload failed.'; $messages['filesizeerror'] = 'The uploaded file exceeds the maximum size of $size.'; -$messages['copysuccess'] = 'Successfully copied $nr addresses.'; -$messages['copyerror'] = 'Could not copy any addresses.'; +$messages['copysuccess'] = 'Successfully copied $nr contacts.'; +$messages['movesuccess'] = 'Successfully moved $nr contacts.'; +$messages['copyerror'] = 'Could not copy any contacts.'; +$messages['moveerror'] = 'Could not move any contacts.'; $messages['sourceisreadonly'] = 'This address source is read only.'; $messages['errorsavingcontact'] = 'Could not save the contact address.'; $messages['movingmessage'] = 'Moving message(s)...'; $messages['copyingmessage'] = 'Copying message(s)...'; $messages['copyingcontact'] = 'Copying contact(s)...'; +$messages['movingcontact'] = 'Moving contact(s)...'; $messages['deletingmessage'] = 'Deleting message(s)...'; $messages['markingmessage'] = 'Marking message(s)...'; $messages['addingmember'] = 'Adding contact(s) to the group...'; @@ -126,6 +129,8 @@ $messages['importwait'] = 'Importing, please wait...'; $messages['importformaterror'] = 'Import failed! The uploaded file is not a valid import data file.'; $messages['importconfirm'] = '<b>Successfully imported $inserted contacts</b>'; $messages['importconfirmskipped'] = '<b>Skipped $skipped existing entries</b>'; +$messages['importmessagesuccess'] = 'Successfully imported $nr messages'; +$messages['importmessageerror'] = 'Import failed! The uploaded file is not a valid message or mailbox file'; $messages['opnotpermitted'] = 'Operation not permitted!'; $messages['nofromaddress'] = 'Missing e-mail address in selected identity.'; $messages['editorwarning'] = 'Switching to the plain text editor will cause all text formatting to be lost. Do you wish to continue?'; diff --git a/program/localization/eo/labels.inc b/program/localization/eo/labels.inc index c088fc50e..3c2930c89 100644 --- a/program/localization/eo/labels.inc +++ b/program/localization/eo/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Malnetujo'; $labels['sent'] = 'Senditujo'; $labels['trash'] = 'Rubujo'; $labels['junk'] = 'Spamujo'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Temo'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Dosierujo-agoj'; $labels['compact'] = 'Kompakta'; $labels['empty'] = 'Malplena'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Diskuzo'; $labels['unknown'] = 'nekonata'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Vakigu serĉon'; $labels['searchmod'] = 'Serĉ-opcioj'; $labels['msgtext'] = 'Tuta mesaÄo'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Malfermu en nova fenestro'; $labels['emlsave'] = 'ElÅutu (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Montru lastan'; $labels['group'] = 'Group'; $labels['groups'] = 'Grupoj'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Persona Adresoj'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/es_AR/labels.inc b/program/localization/es_AR/labels.inc index d9a83be75..5bc53f7f0 100644 --- a/program/localization/es_AR/labels.inc +++ b/program/localization/es_AR/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Borradores'; $labels['sent'] = 'Enviados'; $labels['trash'] = 'Papelera'; $labels['junk'] = 'Basura'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Asunto'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Acciones de carpeta...'; $labels['compact'] = 'Compactar'; $labels['empty'] = 'Vaciar'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Uso de disco'; $labels['unknown'] = 'desconocido'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reajustar la búsqueda'; $labels['searchmod'] = 'Opciones de búsqueda'; $labels['msgtext'] = 'Mensaje completo'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Abrir en ventana nueva'; $labels['emlsave'] = 'Guardar (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Mostrar último grupo'; $labels['group'] = 'Grupo'; $labels['groups'] = 'Grupos'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Direcciones personales'; $labels['searchsave'] = 'Guardar búsqueda'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/es_ES/labels.inc b/program/localization/es_ES/labels.inc index 03f6b489a..11d14fa08 100644 --- a/program/localization/es_ES/labels.inc +++ b/program/localization/es_ES/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Borradores'; $labels['sent'] = 'Enviados'; $labels['trash'] = 'Papelera'; $labels['junk'] = 'SPAM'; +$labels['show_real_foldernames'] = 'Mostrar nombres reales para carpetas especiales'; // message listing $labels['subject'] = 'Asunto'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Modo de vista de lista'; $labels['folderactions'] = 'Acciones de bandeja...'; $labels['compact'] = 'Compactar'; $labels['empty'] = 'Vaciar'; +$labels['importmessages'] = 'Importar mensajes'; $labels['quota'] = 'Uso de disco'; $labels['unknown'] = 'desconocido'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reiniciar la búsqueda'; $labels['searchmod'] = 'Opciones de búsqueda'; $labels['msgtext'] = 'Mensaje completo'; $labels['body'] = 'Cuerpo'; +$labels['type'] = 'Tipo'; $labels['openinextwin'] = 'Abrir en nueva ventana'; $labels['emlsave'] = 'Descargar (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Mostrar último grupo'; $labels['group'] = 'Grupo'; $labels['groups'] = 'Grupos'; +$labels['listgroup'] = 'Listar miembros del grupo'; $labels['personaladrbook'] = 'Direcciones personales'; $labels['searchsave'] = 'Guardar búsqueda'; @@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Componer mensaje en HTML'; $labels['htmlonreply'] = 'sólo en respuesta a un mensaje HTML'; $labels['htmlonreplyandforward'] = 'en reenvÃo o respuesta al mensaje HTML'; $labels['htmlsignature'] = 'Firma HTML'; -$labels['showemail'] = 'Show email address with display name'; +$labels['showemail'] = 'Mostrar dirección de correo electrónico al visualizar el nombre'; $labels['previewpane'] = 'Mostrar vista preliminar'; $labels['skin'] = 'Apariencia de la interfaz'; $labels['logoutclear'] = 'Vaciar papelera al cerrar sesión'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorar palabras con números'; $labels['spellcheckignorecaps'] = 'Ignorar palabras con todo mayúsculas'; $labels['addtodict'] = 'Añadir al diccionario'; $labels['mailtoprotohandler'] = 'Registrar controlador de protocolo para enlaces mailto:'; +$labels['standardwindows'] = 'Gestionar ventanas emergentes como ventanas estándar'; $labels['forwardmode'] = 'ReenvÃo de mensajes'; $labels['inline'] = 'en lÃnea'; $labels['asattachment'] = 'como adjunto'; diff --git a/program/localization/es_ES/messages.inc b/program/localization/es_ES/messages.inc index 6c031df29..d4bd81402 100644 --- a/program/localization/es_ES/messages.inc +++ b/program/localization/es_ES/messages.inc @@ -126,6 +126,8 @@ $messages['importwait'] = 'Importando, espere...'; $messages['importformaterror'] = '¡La importación falló! El fichero enviado no es un fichero válido de importación de datos'; $messages['importconfirm'] = '<b>Se han importado $inserted contactos correctamente</b>'; $messages['importconfirmskipped'] = '<b>Ignoradas $skipped entradas existentes</b>'; +$messages['importmessagesuccess'] = '$nr mensajes importados con éxito'; +$messages['importmessageerror'] = '¡Ha fallado la importación! El fichero subido no es un fichero válido de mensaje o buzón de correo'; $messages['opnotpermitted'] = '¡Operación no permitida!'; $messages['nofromaddress'] = 'El contacto seleccionado no tiene dirección de e-mail'; $messages['editorwarning'] = 'Cambiando a texto plano perderá el formato del mensaje. ¿Desea continuar?'; diff --git a/program/localization/et_EE/labels.inc b/program/localization/et_EE/labels.inc index c3b3aa954..a8bc28403 100644 --- a/program/localization/et_EE/labels.inc +++ b/program/localization/et_EE/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Mustandid'; $labels['sent'] = 'Saadetud'; $labels['trash'] = 'Prügikast'; $labels['junk'] = 'Rämps'; +$labels['show_real_foldernames'] = 'Näita eriliste kaustade päris nimesid'; // message listing $labels['subject'] = 'Pealkiri'; @@ -64,7 +65,7 @@ $labels['copy'] = 'Kopeeri'; $labels['move'] = 'Liiguta'; $labels['moveto'] = 'liiguta kausta...'; $labels['download'] = 'laadi arvutisse'; -$labels['open'] = 'Open'; +$labels['open'] = 'Ava'; $labels['showattachment'] = 'Näita'; $labels['showanyway'] = 'Näita ikka'; @@ -162,7 +163,7 @@ $labels['currpage'] = 'Praegune leht'; $labels['unread'] = 'Lugemata'; $labels['flagged'] = 'Märgistatud'; $labels['unanswered'] = 'Vastamata'; -$labels['withattachment'] = 'With attachment'; +$labels['withattachment'] = 'Koos manusega'; $labels['deleted'] = 'Kustutatud'; $labels['undeleted'] = 'Pole kustutatud'; $labels['invert'] = 'Vaheta'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Nimekirja vaatamise režiim'; $labels['folderactions'] = 'Kausta tegevused...'; $labels['compact'] = 'Tihenda'; $labels['empty'] = 'Tühjenda'; +$labels['importmessages'] = 'Impordi kirju'; $labels['quota'] = 'Kettakasutus'; $labels['unknown'] = 'teadmata'; @@ -203,11 +205,12 @@ $labels['resetsearch'] = 'Lähtesta otsing'; $labels['searchmod'] = 'Otsingu laiendid'; $labels['msgtext'] = 'Kogu kirjast'; $labels['body'] = 'Keha'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Ava uues aknas'; $labels['emlsave'] = 'Salvesta (.eml)'; -$labels['changeformattext'] = 'Display in plain text format'; -$labels['changeformathtml'] = 'Display in HTML format'; +$labels['changeformattext'] = 'Näita lihttekstina'; +$labels['changeformathtml'] = 'Näita HTMLis'; // message compose $labels['editasnew'] = 'Kasuta uue kirja põhjana'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Näita viimast komplekti'; $labels['group'] = 'Grupp'; $labels['groups'] = 'Grupid'; +$labels['listgroup'] = 'Näita grupi liikmeid'; $labels['personaladrbook'] = 'Isiklikud aadressid'; $labels['searchsave'] = 'Salvesta otsing'; @@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Kasuta HTML redaktorit'; $labels['htmlonreply'] = 'vaid HTML-vormingus kirjale vastamisel'; $labels['htmlonreplyandforward'] = 'edastamisel või HTML kirjale vastates'; $labels['htmlsignature'] = 'HTML allkiri'; -$labels['showemail'] = 'Show email address with display name'; +$labels['showemail'] = 'Näita nime juures e-posti aadressi'; $labels['previewpane'] = 'Näita eelvaate akent'; $labels['skin'] = 'Kliendi välimus'; $labels['logoutclear'] = 'Tühjenda väljumisel prügikast'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignoreeri sõnu, milles on numbreid'; $labels['spellcheckignorecaps'] = 'Ignoreeri suurte tähtedega kirjutatud sõnu'; $labels['addtodict'] = 'Lisa sõnastikku'; $labels['mailtoprotohandler'] = 'Kasuta mailto: linkide avamisel'; +$labels['standardwindows'] = 'Käsitle hüpikaknaid tavaliste akendena'; $labels['forwardmode'] = 'Kirja edastamine'; $labels['inline'] = 'kirja sees'; $labels['asattachment'] = 'manusena'; diff --git a/program/localization/et_EE/messages.inc b/program/localization/et_EE/messages.inc index 0064eaf9d..4d58b0a75 100644 --- a/program/localization/et_EE/messages.inc +++ b/program/localization/et_EE/messages.inc @@ -28,8 +28,8 @@ $messages['dberror'] = 'Andmebaasi tõrge!'; $messages['requesttimedout'] = 'Päring aegus'; $messages['errorreadonly'] = 'Operatsioon nurjus. Kaustale on vaid lugemisõigus'; $messages['errornoperm'] = 'Operatsioon nurjus. Ligipääsu õigused puuduvad'; -$messages['erroroverquota'] = 'Unable to perform operation. No free disk space.'; -$messages['erroroverquotadelete'] = 'No free disk space. Use SHIFT+DEL to delete a message.'; +$messages['erroroverquota'] = 'Operatsioon nurjus. Ketas on täis.'; +$messages['erroroverquotadelete'] = 'Ketas on täis. Kirja kustutamiseks vajuta SHIFT+DEL.'; $messages['invalidrequest'] = 'Lubamatu päring! Andmeid ei salvestatud.'; $messages['invalidhost'] = 'Lubamatu serveri nimi.'; $messages['nomessagesfound'] = 'Postkast paistab tühi olevat'; @@ -126,6 +126,8 @@ $messages['importwait'] = 'Impordin, palun oota...'; $messages['importformaterror'] = 'Import nurjus! Laaditud fail ei sisalda sobilikke andmeid.'; $messages['importconfirm'] = '<b>Edukalt imporditud $inserted kontakti, $skipped olemasolevat sissekannet vahele jäetud</b>:<p><em>$names</em></p>'; $messages['importconfirmskipped'] = '<b> $skipped olemasolevat kirjet jäeti vahele</b>'; +$messages['importmessagesuccess'] = '$nr kirja edukalt imporditud'; +$messages['importmessageerror'] = 'Import nurjus! Laaditud fail ei ole kirja ega postkasti fail'; $messages['opnotpermitted'] = 'Tegevus pole lubatud!'; $messages['nofromaddress'] = 'Valitud identiteedil puudub e-posti aadress'; $messages['editorwarning'] = 'Klaarteksti redaktorile lülitamine kaotab kogu teksti vorminduse. Soovid jätkata?'; diff --git a/program/localization/eu_ES/labels.inc b/program/localization/eu_ES/labels.inc index 8052d69e8..fedce7de5 100644 --- a/program/localization/eu_ES/labels.inc +++ b/program/localization/eu_ES/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Zirriborroak'; $labels['sent'] = 'Bidalitakoak'; $labels['trash'] = 'Zakarrontzia'; $labels['junk'] = 'Zabor-posta'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Gaia'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'Trinkotu'; $labels['empty'] = 'Hustu'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Disko erabilera'; $labels['unknown'] = 'ezezaguna'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Bilaketa berrabiarazi'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Lehio berrian ireki'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Azken sorta ikusi'; $labels['group'] = 'Group'; $labels['groups'] = 'Taldeak'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Helbide pertsonalak'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/fa_AF/labels.inc b/program/localization/fa_AF/labels.inc index 70113bc49..38154c23c 100644 --- a/program/localization/fa_AF/labels.inc +++ b/program/localization/fa_AF/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'نامه های ناتکمیل'; $labels['sent'] = 'ارسال شده'; $labels['trash'] = 'اشغال دانی'; $labels['junk'] = 'بیکاره'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'مضمون'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'خلاصه'; $labels['empty'] = 'خالي'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = '‌طريقه استعمال ديسک'; $labels['unknown'] = 'نامعلوم'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'بازنشاندن جستجو'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'در پینجره ای جدید باز کنید'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'بسته اخير را نشان دهيد'; $labels['group'] = 'Group'; $labels['groups'] = 'گروه ها'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'ادرس های شخصي'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/fa_IR/labels.inc b/program/localization/fa_IR/labels.inc index 221e4b891..79bfbbe9d 100644 --- a/program/localization/fa_IR/labels.inc +++ b/program/localization/fa_IR/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'پیش‌نویس‌ها'; $labels['sent'] = 'Ùرستاده شده'; $labels['trash'] = 'سطل آشغال'; $labels['junk'] = 'بنجل'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'موضوع'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'نوع مشاهده Ùهرست'; $labels['folderactions'] = 'اعمال پوشه...'; $labels['compact'] = 'Ùشرده'; $labels['empty'] = 'خالی'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Ùضای استÙاده شده'; $labels['unknown'] = 'ناشناخته'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'جستجوی دوباره'; $labels['searchmod'] = 'اصلاØات جستجو'; $labels['msgtext'] = 'Ú©Ù„ پیغام'; $labels['body'] = 'بدنه'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'باز کردن در پنجره‌ی جدید'; $labels['emlsave'] = 'بارگیری (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'نمایش صÙØÙ‡ آخر'; $labels['group'] = 'گروه'; $labels['groups'] = 'گروه‌ها'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'نشانی‌های شخصی'; $labels['searchsave'] = 'ذخیره جستجو'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'نادیده گرÙتن کلمات دارای $labels['spellcheckignorecaps'] = 'نادیده گرÙتن کلمات با Øرو٠بزرگ'; $labels['addtodict'] = 'اضاÙÙ‡ کردن به واژه‌نامه'; $labels['mailtoprotohandler'] = 'ثبت نگه‌دارنده پروتوکل برای mailto: پیوندها'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'بازگردانی پیغام'; $labels['inline'] = 'خطی'; $labels['asattachment'] = 'به عنوان پیوست'; diff --git a/program/localization/fi_FI/labels.inc b/program/localization/fi_FI/labels.inc index 006f62947..ef0f0bff0 100644 --- a/program/localization/fi_FI/labels.inc +++ b/program/localization/fi_FI/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Luonnokset'; $labels['sent'] = 'Lähetetyt'; $labels['trash'] = 'Roskakori'; $labels['junk'] = 'Roskaposti'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Aihe'; @@ -162,7 +163,7 @@ $labels['currpage'] = 'Nykyinen sivu'; $labels['unread'] = 'Lukemattomat'; $labels['flagged'] = 'Korostettu'; $labels['unanswered'] = 'Vastaamaton'; -$labels['withattachment'] = 'With attachment'; +$labels['withattachment'] = 'Liitteen kera'; $labels['deleted'] = 'Poistettu'; $labels['undeleted'] = 'Ei poistettu'; $labels['invert'] = 'Käännä'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Listausnäkymä'; $labels['folderactions'] = 'Kansiotoiminnot...'; $labels['compact'] = 'Tiivistä'; $labels['empty'] = 'Tyhjennä'; +$labels['importmessages'] = 'Tuo viestejä'; $labels['quota'] = 'Levytila'; $labels['unknown'] = 'tuntematon'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Nollaa haku'; $labels['searchmod'] = 'Hakukriteerit'; $labels['msgtext'] = 'Koko viesti'; $labels['body'] = 'Runko'; +$labels['type'] = 'Tyyppi'; $labels['openinextwin'] = 'Avaa uudessa ikkunassa'; $labels['emlsave'] = 'Tallenna (.eml)'; @@ -245,9 +248,9 @@ $labels['nosubject'] = '(ei otsikkoa)'; $labels['showimages'] = 'Näytä kuvat'; $labels['alwaysshow'] = 'Näytä aina lähettäjältä $sender saapuneet kuvat'; $labels['isdraft'] = 'Tämä on luonnosviesti.'; -$labels['andnmore'] = '$nr more...'; +$labels['andnmore'] = '$nr lisää...'; $labels['togglemoreheaders'] = 'Näytä lisää viestiotsakkeita'; -$labels['togglefullheaders'] = 'Toggle raw message headers'; +$labels['togglefullheaders'] = 'Viestin otsakkeet päällä/pois'; $labels['htmltoggle'] = 'HTML'; $labels['plaintoggle'] = 'Tavallinen teksti'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Näytä viimeinen luettelo'; $labels['group'] = 'Ryhmä'; $labels['groups'] = 'Ryhmät'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Henkilökohtaiset osoitteet'; $labels['searchsave'] = 'Tallenna haku'; @@ -400,7 +404,7 @@ $labels['showinextwin'] = 'Avaa viesti uudessa ikkunassa'; $labels['composeextwin'] = 'Lähetä viesti uudessa ikkunassa'; $labels['htmleditor'] = 'Kirjoita HTML-muodossa'; $labels['htmlonreply'] = 'Vain vastatessa HTML-viesteihin'; -$labels['htmlonreplyandforward'] = 'on forward or reply to HTML message'; +$labels['htmlonreplyandforward'] = 'välittäessä tai vastatessa HTML-viestiin'; $labels['htmlsignature'] = 'HTML-allekirjoitus'; $labels['showemail'] = 'Näytä sähköpostiosoite näyttönimen kanssa'; $labels['previewpane'] = 'Näytä esikatselulehti'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Jätä huomiotta sanat, joissa on numeroita'; $labels['spellcheckignorecaps'] = 'Jätä huomiotta sanat, joissa kaikki kirjaimet on isoja'; $labels['addtodict'] = 'Lisää sanakirjaan'; $labels['mailtoprotohandler'] = 'Rekisteröi mailto:-linkkien protokollakäsitteljä'; +$labels['standardwindows'] = 'Käsittele popup-ikkunoita tavallisina ikkunoina'; $labels['forwardmode'] = 'Viestin välitys'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'liitteenä'; diff --git a/program/localization/fr_FR/labels.inc b/program/localization/fr_FR/labels.inc index 6731ecc3f..2a4f3a169 100644 --- a/program/localization/fr_FR/labels.inc +++ b/program/localization/fr_FR/labels.inc @@ -26,9 +26,9 @@ $labels['server'] = 'Serveur'; $labels['login'] = 'Connexion'; // taskbar -$labels['logout'] = 'Quitter'; +$labels['logout'] = 'Déconnexion'; $labels['mail'] = 'Courriel'; -$labels['settings'] = 'Préférences'; +$labels['settings'] = 'Paramètres'; $labels['addressbook'] = 'Carnet d\'adresses'; // mailbox names @@ -37,6 +37,7 @@ $labels['drafts'] = 'Brouillons'; $labels['sent'] = 'Messages envoyés'; $labels['trash'] = 'Corbeille'; $labels['junk'] = 'Indésirables'; +$labels['show_real_foldernames'] = 'Montrer les noms réels pour les dossiers spéciaux'; // message listing $labels['subject'] = 'Objet'; @@ -127,7 +128,7 @@ $labels['checkmail'] = 'Vérification des nouveaux messages'; $labels['compose'] = 'Composer un nouveau message'; $labels['writenewmessage'] = 'Écrire un nouveau message'; $labels['reply'] = 'Répondre'; -$labels['replytomessage'] = 'Répondre au message'; +$labels['replytomessage'] = 'Répondre à l\'expéditeur'; $labels['replytoallmessage'] = 'Répondre à tous'; $labels['replyall'] = 'Répondre à tous'; $labels['replylist'] = 'Répondre à la liste'; @@ -146,10 +147,10 @@ $labels['backtolist'] = 'Retourner à la liste des messages'; $labels['viewsource'] = 'Voir la source'; $labels['mark'] = 'Marquer'; $labels['markmessages'] = 'Marquer les messages'; -$labels['markread'] = 'Comme lus'; -$labels['markunread'] = 'Comme non lus'; -$labels['markflagged'] = 'Comme suivi'; -$labels['markunflagged'] = 'Comme non-suivi'; +$labels['markread'] = 'Comme lu(s)'; +$labels['markunread'] = 'Comme non lu(s)'; +$labels['markflagged'] = 'Comme suivi(s)'; +$labels['markunflagged'] = 'Comme non-suivi(s)'; $labels['moreactions'] = 'Plus d\'actions...'; $labels['more'] = 'Plus'; $labels['back'] = 'Retour'; @@ -159,19 +160,19 @@ $labels['select'] = 'Sélectionner'; $labels['all'] = 'Tous'; $labels['none'] = 'Aucun'; $labels['currpage'] = 'Page courante'; -$labels['unread'] = 'Non lus'; -$labels['flagged'] = 'Marqué'; -$labels['unanswered'] = 'Non répondu'; +$labels['unread'] = 'Non lu(s)'; +$labels['flagged'] = 'Marqué(s)'; +$labels['unanswered'] = 'Non répondu(s)'; $labels['withattachment'] = 'Avec pièce jointe'; -$labels['deleted'] = 'Supprimé'; -$labels['undeleted'] = 'Non supprimé'; +$labels['deleted'] = 'Supprimé(s)'; +$labels['undeleted'] = 'Non supprimé(s)'; $labels['invert'] = 'Inverser'; $labels['filter'] = 'Filtre'; $labels['list'] = 'Lister'; $labels['threads'] = 'Sujets'; -$labels['expand-all'] = 'Afficher Tous'; -$labels['expand-unread'] = 'Afficher Non-lus'; -$labels['collapse-all'] = 'Fermer Tous'; +$labels['expand-all'] = 'Tout afficher'; +$labels['expand-unread'] = 'Afficher non-lu(s)'; +$labels['collapse-all'] = 'Fermer tous'; $labels['threaded'] = 'Par sujet'; $labels['autoexpand_threads'] = 'Développer les sujets'; @@ -190,9 +191,10 @@ $labels['listsorting'] = 'Colonne de tri'; $labels['listorder'] = 'Ordre de tri'; $labels['listmode'] = 'Mode d\'affichage de la liste'; -$labels['folderactions'] = 'Actions du dossier'; +$labels['folderactions'] = 'Actions du dossier...'; $labels['compact'] = 'Compacter'; $labels['empty'] = 'Vider'; +$labels['importmessages'] = 'Importer des messages'; $labels['quota'] = 'Occupation disque'; $labels['unknown'] = 'inconnue'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Réinitialiser la recherche'; $labels['searchmod'] = 'Portée de la recherche'; $labels['msgtext'] = 'Message entier'; $labels['body'] = 'Corps'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Ouvrir dans une nouvelle fenêtre'; $labels['emlsave'] = 'Télécharger (.eml)'; @@ -212,8 +215,8 @@ $labels['changeformathtml'] = 'Afficher au format HTML'; // message compose $labels['editasnew'] = 'Éditer en tant que nouveau message'; $labels['send'] = 'Envoyer'; -$labels['sendmessage'] = 'Envoyer'; -$labels['savemessage'] = 'Enregistrer'; +$labels['sendmessage'] = 'Envoyer un message'; +$labels['savemessage'] = 'Sauvegarder comme brouillon'; $labels['addattachment'] = 'Joindre un fichier'; $labels['charset'] = 'Encodage'; $labels['editortype'] = 'Type d\'éditeur'; @@ -223,14 +226,14 @@ $labels['mailreplyintro'] = 'Le $date, $sender a écrit :'; $labels['originalmessage'] = 'Message original'; $labels['editidents'] = 'Modifier les identités'; -$labels['spellcheck'] = 'Vérifier l\'orthographe'; +$labels['spellcheck'] = 'Orthographe'; $labels['checkspelling'] = 'Vérifier l\'orthographe'; $labels['resumeediting'] = 'Retourner à l\'édition'; $labels['revertto'] = 'Revenir à '; $labels['attach'] = 'Joindre'; $labels['attachments'] = 'Fichiers joints'; -$labels['upload'] = 'Joindre'; +$labels['upload'] = 'Transférer'; $labels['uploadprogress'] = '$percent ($current sur $total)'; $labels['close'] = 'Fermer'; $labels['messageoptions'] = 'Options du message'; @@ -250,7 +253,7 @@ $labels['togglemoreheaders'] = 'Afficher plus d\'en-têtes du message'; $labels['togglefullheaders'] = 'Afficher/Cacher l\'entête du message'; $labels['htmltoggle'] = 'HTML'; -$labels['plaintoggle'] = 'texte brut'; +$labels['plaintoggle'] = 'Texte brut'; $labels['savesentmessagein'] = 'Enregistrer le message envoyé dans'; $labels['dontsave'] = 'ne pas enregistrer'; $labels['maxuploadsize'] = 'La taille maximum autorisée pour un fichier est $size'; @@ -264,7 +267,7 @@ $labels['addfollowupto'] = 'Ajouter Faire suivre à '; $labels['mdnrequest'] = 'L\'expéditeur de ce message a demandé d\'être prévenu quand vous lirez ce message. Souhaitez-vous prévenir l\'expéditeur ?'; $labels['receiptread'] = 'Accusé de réception (lu)'; $labels['yourmessage'] = 'Ceci est un accusé de réception pour votre message'; -$labels['receiptnote'] = 'Note : Cet accusé de réception indique seulement que le message a été affiché sur l\'ordinateur du destinataire. Il n\'y a aucune garantie que le destinataire a lu ou compris le contenu du message.'; +$labels['receiptnote'] = 'Note : Cet accusé de réception indique seulement que le message a été affiché sur l\'ordinateur du destinataire. Il n\'y a aucune garantie que le destinataire ait lu ou compris le contenu du message.'; // address boook $labels['name'] = 'Nom à afficher'; @@ -275,9 +278,9 @@ $labels['nameprefix'] = 'Préfixe'; $labels['namesuffix'] = 'Suffixe'; $labels['nickname'] = 'Surnom'; $labels['jobtitle'] = 'Fonction'; -$labels['department'] = 'Département'; +$labels['department'] = 'Service'; $labels['gender'] = 'Sexe'; -$labels['maidenname'] = 'Nom de naissance'; +$labels['maidenname'] = 'Nom de jeune fille'; $labels['email'] = 'Courriel'; $labels['phone'] = 'Téléphone'; $labels['address'] = 'Adresse'; @@ -318,7 +321,7 @@ $labels['typeblog'] = 'Blog'; $labels['typeprofile'] = 'Profil'; $labels['addfield'] = 'Ajouter un champ...'; -$labels['addcontact'] = 'Ajouter le contact sélectionné à votre Carnet d\'adresses'; +$labels['addcontact'] = 'Ajouter le contact sélectionné à votre carnet d\'adresses'; $labels['editcontact'] = 'Modifier le contact'; $labels['contacts'] = 'Contacts'; $labels['contactproperties'] = 'Propriétés du contact'; @@ -331,7 +334,7 @@ $labels['delete'] = 'Supprimer'; $labels['rename'] = 'Renommer'; $labels['addphoto'] = 'Ajouter'; $labels['replacephoto'] = 'Remplacer'; -$labels['uploadphoto'] = 'Envoyer une photo'; +$labels['uploadphoto'] = 'Transférer une photo'; $labels['newcontact'] = 'Créer un nouveau contact'; $labels['deletecontact'] = 'Supprimer les contacts sélectionnés'; @@ -345,7 +348,7 @@ $labels['exportvcards'] = 'Exporter les contacts au format vCard'; $labels['newcontactgroup'] = 'Créer un nouveau groupe de contacts'; $labels['grouprename'] = 'Renommer le groupe'; $labels['groupdelete'] = 'Supprimer le groupe'; -$labels['groupremoveselected'] = 'Retiré les contacts sélectionnés du groupe'; +$labels['groupremoveselected'] = 'Retirer les contacts sélectionnés du groupe'; $labels['previouspage'] = 'Montrer page précédente'; $labels['firstpage'] = 'Voir la première page'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Voir la dernière page'; $labels['group'] = 'Groupe'; $labels['groups'] = 'Groupes'; +$labels['listgroup'] = 'Liste des membres du groupe'; $labels['personaladrbook'] = 'Adresses personnelles'; $labels['searchsave'] = 'Enregistrer la recherche'; @@ -362,9 +366,9 @@ $labels['searchdelete'] = 'Supprimer la recherche'; $labels['import'] = 'Importer'; $labels['importcontacts'] = 'Importer les contacts'; $labels['importfromfile'] = 'Importer depuis un fichier :'; -$labels['importtarget'] = 'Ajouter de nouveaux contact au carnet d’adresse :'; -$labels['importreplace'] = 'Remplacer le carnet d\'adresse entier'; -$labels['importdesc'] = 'Vous pouvez télécharger des contacts à partir d\'un carnet d\'adresses existant.<br/>Nous supportons actuellement l\'importation d\'adresses à partir des format de données <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> ou CSV (comma -séparés).'; +$labels['importtarget'] = 'Ajouter de nouveaux contact au carnet d’adresses :'; +$labels['importreplace'] = 'Remplacer le carnet d\'adresses entier'; +$labels['importdesc'] = 'Vous pouvez transférer des contacts à partir d\'un carnet d\'adresses existant.<br/>Nous supportons actuellement l\'importation d\'adresses à partir des format de données <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> ou CSV (champs séparés par une virgule).'; $labels['done'] = 'Terminé'; // settings @@ -402,13 +406,13 @@ $labels['htmleditor'] = 'Composer un message au format HTML'; $labels['htmlonreply'] = 'en réponse aux messages HTML uniquement'; $labels['htmlonreplyandforward'] = 'Transférer ou répondre au message HTML'; $labels['htmlsignature'] = 'Signature HTML'; -$labels['showemail'] = 'Show email address with display name'; +$labels['showemail'] = 'Montrer l\'adresse de courriel avec le nom complet'; $labels['previewpane'] = 'Afficher le panneau d\'aperçu'; $labels['skin'] = 'Thème de l\'interface'; $labels['logoutclear'] = 'Vider la corbeille à la déconnexion'; $labels['logoutcompact'] = 'Compacter la boite de réception à la déconnexion'; $labels['uisettings'] = 'Interface utilisateur'; -$labels['serversettings'] = 'Préférences du serveur'; +$labels['serversettings'] = 'Paramètres du serveur'; $labels['mailboxview'] = 'Vue du courrier'; $labels['mdnrequests'] = 'Notifications à l\'expéditeur'; $labels['askuser'] = 'demander à l\'utilisateur'; @@ -452,7 +456,7 @@ $labels['whenreplying'] = 'En répondant'; $labels['replyempty'] = 'Ne pas citer le message original'; $labels['replytopposting'] = 'commencer le nouveau message au-dessus de l\'original'; $labels['replybottomposting'] = 'commencer le nouveau message en-dessous de l\'original'; -$labels['replyremovesignature'] = 'En répondant, supprimer la signature d\'origine du message'; +$labels['replyremovesignature'] = 'Supprimer la signature d\'origine du message lors de la réponse'; $labels['autoaddsignature'] = 'Ajouter la signature automatiquement'; $labels['newmessageonly'] = 'nouveau message uniquement'; $labels['replyandforwardonly'] = 'réponses et transferts uniquement'; @@ -462,16 +466,17 @@ $labels['afternseconds'] = 'après $n secondes'; $labels['reqmdn'] = 'Toujours demander un avis de réception'; $labels['reqdsn'] = 'Toujours demander une notification d\'état de distribution'; $labels['replysamefolder'] = 'Placer les réponses dans le dossier du message auquel il est répondu'; -$labels['defaultabook'] = 'Carnet d\'adresse par défaut'; -$labels['autocompletesingle'] = 'Ne pas tenir compte des adresses emails alternatives dans l\'autoremplissage'; +$labels['defaultabook'] = 'Carnet d\'adresses par défaut'; +$labels['autocompletesingle'] = 'Ne pas tenir compte des adresses de courriel alternatives dans l\'autoremplissage'; $labels['listnamedisplay'] = 'Lister les contacts comme'; -$labels['spellcheckbeforesend'] = 'Vérifier l’orthographe avant l’envoie d’un message'; +$labels['spellcheckbeforesend'] = 'Vérifier l’orthographe avant l’envoi d’un message'; $labels['spellcheckoptions'] = 'Options du vérificateur d\'orthographe'; $labels['spellcheckignoresyms'] = 'Ignorer les mots avec des symboles'; $labels['spellcheckignorenums'] = 'Ignorer les mots avec des nombres'; $labels['spellcheckignorecaps'] = 'Ignorer les mots entièrement en majuscule'; $labels['addtodict'] = 'Ajouter au dictionnaire'; $labels['mailtoprotohandler'] = 'Enregistrer le gestionnaire de protocole pour les liens mailto:'; +$labels['standardwindows'] = 'Manipuler les menus surgissants comme des fenêtres standards'; $labels['forwardmode'] = 'Transfert des messages'; $labels['inline'] = 'dans le corps'; $labels['asattachment'] = 'en pièce jointe'; @@ -507,7 +512,7 @@ $labels['plugin'] = 'Plugin'; $labels['version'] = 'Version'; $labels['source'] = 'Source'; $labels['license'] = 'Licence'; -$labels['support'] = 'Support'; +$labels['support'] = 'Obtenir un support technique'; // units $labels['B'] = 'o'; diff --git a/program/localization/fy_NL/labels.inc b/program/localization/fy_NL/labels.inc index 891371f58..5ffd906eb 100644 --- a/program/localization/fy_NL/labels.inc +++ b/program/localization/fy_NL/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Konsepten'; $labels['sent'] = 'Stjoerd'; $labels['trash'] = 'Jiskefet'; $labels['junk'] = 'Junk'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Ûnderwerp'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'Compact'; $labels['empty'] = 'Empty'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Disk usage'; $labels['unknown'] = 'unknown'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reset search'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Open in new window'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Show last page'; $labels['group'] = 'Group'; $labels['groups'] = 'Groups'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Personal Addresses'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/fy_NL/messages.inc b/program/localization/fy_NL/messages.inc index 1dacf4adc..16f4c67bf 100644 --- a/program/localization/fy_NL/messages.inc +++ b/program/localization/fy_NL/messages.inc @@ -2,15 +2,172 @@ /* +-----------------------------------------------------------------------+ - | localization/fy_NL/messages.inc | + | localization/<lang>/messages.inc | | | - | Language file of the Roundcube Webmail client | - | Copyright (C) 2012, The Roundcube Dev Team | - | Licensed under the GNU General Public License | + | Localization file of the Roundcube Webmail client | + | Copyright (C) 2005-2013, The Roundcube Dev Team | + | | + | Licensed under the GNU General Public License version 3 or | + | any later version with exceptions for skins & plugins. | + | See the README file for a full license statement. | | | +-----------------------------------------------------------------------+ - | Author: unknown | - +-----------------------------------------------------------------------+ + + For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/messages/ */ -$messages = array();
\ No newline at end of file +$messages = array(); +$messages['errortitle'] = 'An error occurred!'; +$messages['loginfailed'] = 'Login failed.'; +$messages['cookiesdisabled'] = 'Your browser does not accept cookies.'; +$messages['sessionerror'] = 'Your session is invalid or expired.'; +$messages['storageerror'] = 'Connection to storage server failed.'; +$messages['servererror'] = 'Server Error!'; +$messages['servererrormsg'] = 'Server Error: $msg'; +$messages['dberror'] = 'Database Error!'; +$messages['requesttimedout'] = 'Request timed out'; +$messages['errorreadonly'] = 'Unable to perform operation. Folder is read-only.'; +$messages['errornoperm'] = 'Unable to perform operation. Permission denied.'; +$messages['erroroverquota'] = 'Unable to perform operation. No free disk space.'; +$messages['erroroverquotadelete'] = 'No free disk space. Use SHIFT+DEL to delete a message.'; +$messages['invalidrequest'] = 'Invalid request! No data was saved.'; +$messages['invalidhost'] = 'Invalid server name.'; +$messages['nomessagesfound'] = 'No messages found in this mailbox.'; +$messages['loggedout'] = 'You have successfully terminated the session. Good bye!'; +$messages['mailboxempty'] = 'Mailbox is empty.'; +$messages['refreshing'] = 'Refreshing...'; +$messages['loading'] = 'Loading...'; +$messages['uploading'] = 'Uploading file...'; +$messages['uploadingmany'] = 'Uploading files...'; +$messages['loadingdata'] = 'Loading data...'; +$messages['checkingmail'] = 'Checking for new messages...'; +$messages['sendingmessage'] = 'Sending message...'; +$messages['messagesent'] = 'Message sent successfully.'; +$messages['savingmessage'] = 'Saving message...'; +$messages['messagesaved'] = 'Message saved to Drafts.'; +$messages['successfullysaved'] = 'Successfully saved.'; +$messages['addedsuccessfully'] = 'Contact added successfully to address book.'; +$messages['contactexists'] = 'A contact with the same e-mail address already exists.'; +$messages['contactnameexists'] = 'A contact with the same name already exists.'; +$messages['blockedimages'] = 'To protect your privacy, remote images are blocked in this message.'; +$messages['encryptedmessage'] = 'This is an encrypted message and can not be displayed. Sorry!'; +$messages['nocontactsfound'] = 'No contacts found.'; +$messages['contactnotfound'] = 'The requested contact was not found.'; +$messages['contactsearchonly'] = 'Enter some search terms to find contacts'; +$messages['sendingfailed'] = 'Failed to send message.'; +$messages['senttooquickly'] = 'Please wait $sec sec(s). before sending this message.'; +$messages['errorsavingsent'] = 'An error occured while saving sent message.'; +$messages['errorsaving'] = 'An error occured while saving.'; +$messages['errormoving'] = 'Could not move the message(s).'; +$messages['errorcopying'] = 'Could not copy the message(s).'; +$messages['errordeleting'] = 'Could not delete the message(s).'; +$messages['errormarking'] = 'Could not mark the message(s).'; +$messages['deletecontactconfirm'] = 'Do you really want to delete selected contact(s)?'; +$messages['deletegroupconfirm'] = 'Do you really want to delete selected group?'; +$messages['deletemessagesconfirm'] = 'Do you really want to delete selected message(s)?'; +$messages['deletefolderconfirm'] = 'Do you really want to delete this folder?'; +$messages['purgefolderconfirm'] = 'Do you really want to delete all messages in this folder?'; +$messages['contactdeleting'] = 'Deleting contact(s)...'; +$messages['groupdeleting'] = 'Deleting group...'; +$messages['folderdeleting'] = 'Deleting folder...'; +$messages['foldermoving'] = 'Moving folder...'; +$messages['foldersubscribing'] = 'Subscribing folder...'; +$messages['folderunsubscribing'] = 'Unsubscribing folder...'; +$messages['formincomplete'] = 'The form was not completely filled out.'; +$messages['noemailwarning'] = 'Please enter a valid email address.'; +$messages['nonamewarning'] = 'Please enter a name.'; +$messages['nopagesizewarning'] = 'Please enter a page size.'; +$messages['nosenderwarning'] = 'Please enter sender e-mail address.'; +$messages['norecipientwarning'] = 'Please enter at least one recipient.'; +$messages['nosubjectwarning'] = 'The "Subject" field is empty. Would you like to enter one now?'; +$messages['nobodywarning'] = 'Send this message without text?'; +$messages['notsentwarning'] = 'Message has not been sent. Do you want to discard your message?'; +$messages['noldapserver'] = 'Please select an ldap server to search.'; +$messages['nosearchname'] = 'Please enter a contact name or email address.'; +$messages['notuploadedwarning'] = 'Not all attachments have been uploaded yet. Please wait or cancel the upload.'; +$messages['searchsuccessful'] = '$nr messages found.'; +$messages['contactsearchsuccessful'] = '$nr contacts found.'; +$messages['searchnomatch'] = 'Search returned no matches.'; +$messages['searching'] = 'Searching...'; +$messages['checking'] = 'Checking...'; +$messages['nospellerrors'] = 'No spelling errors found.'; +$messages['folderdeleted'] = 'Folder successfully deleted.'; +$messages['foldersubscribed'] = 'Folder successfully subscribed.'; +$messages['folderunsubscribed'] = 'Folder successfully unsubscribed.'; +$messages['folderpurged'] = 'Folder has successfully been emptied.'; +$messages['folderexpunged'] = 'Folder has successfully been compacted.'; +$messages['deletedsuccessfully'] = 'Successfully deleted.'; +$messages['converting'] = 'Removing formatting...'; +$messages['messageopenerror'] = 'Could not load message from server.'; +$messages['fileuploaderror'] = 'File upload failed.'; +$messages['filesizeerror'] = 'The uploaded file exceeds the maximum size of $size.'; +$messages['copysuccess'] = 'Successfully copied $nr addresses.'; +$messages['copyerror'] = 'Could not copy any addresses.'; +$messages['sourceisreadonly'] = 'This address source is read only.'; +$messages['errorsavingcontact'] = 'Could not save the contact address.'; +$messages['movingmessage'] = 'Moving message(s)...'; +$messages['copyingmessage'] = 'Copying message(s)...'; +$messages['copyingcontact'] = 'Copying contact(s)...'; +$messages['deletingmessage'] = 'Deleting message(s)...'; +$messages['markingmessage'] = 'Marking message(s)...'; +$messages['addingmember'] = 'Adding contact(s) to the group...'; +$messages['removingmember'] = 'Removing contact(s) from the group...'; +$messages['receiptsent'] = 'Successfully sent a read receipt.'; +$messages['errorsendingreceipt'] = 'Could not send the receipt.'; +$messages['deleteidentityconfirm'] = 'Do you really want to delete this identity?'; +$messages['nodeletelastidentity'] = 'You cannot delete this identity, it\'s your last one.'; +$messages['forbiddencharacter'] = 'Folder name contains a forbidden character.'; +$messages['selectimportfile'] = 'Please select a file to upload.'; +$messages['addresswriterror'] = 'The selected address book is not writeable.'; +$messages['contactaddedtogroup'] = 'Successfully added the contacts to this group.'; +$messages['contactremovedfromgroup'] = 'Successfully removed contacts from this group.'; +$messages['nogroupassignmentschanged'] = 'No group assignments changed.'; +$messages['importwait'] = 'Importing, please wait...'; +$messages['importformaterror'] = 'Import failed! The uploaded file is not a valid import data file.'; +$messages['importconfirm'] = '<b>Successfully imported $inserted contacts</b>'; +$messages['importconfirmskipped'] = '<b>Skipped $skipped existing entries</b>'; +$messages['importmessagesuccess'] = 'Successfully imported $nr messages'; +$messages['importmessageerror'] = 'Import failed! The uploaded file is not a valid message or mailbox file'; +$messages['opnotpermitted'] = 'Operation not permitted!'; +$messages['nofromaddress'] = 'Missing e-mail address in selected identity.'; +$messages['editorwarning'] = 'Switching to the plain text editor will cause all text formatting to be lost. Do you wish to continue?'; +$messages['httpreceivedencrypterror'] = 'A fatal configuration error occurred. Contact your administrator immediately. <b>Your message can not be sent.</b>'; +$messages['smtpconnerror'] = 'SMTP Error ($code): Connection to server failed.'; +$messages['smtpautherror'] = 'SMTP Error ($code): Authentication failed.'; +$messages['smtpfromerror'] = 'SMTP Error ($code): Failed to set sender "$from" ($msg).'; +$messages['smtptoerror'] = 'SMTP Error ($code): Failed to add recipient "$to" ($msg).'; +$messages['smtprecipientserror'] = 'SMTP Error: Unable to parse recipients list.'; +$messages['smtperror'] = 'SMTP Error: $msg'; +$messages['emailformaterror'] = 'Invalid e-mail address: $email'; +$messages['toomanyrecipients'] = 'Too many recipients. Reduce the number of recipients to $max.'; +$messages['maxgroupmembersreached'] = 'The number of group members exceeds the maximum of $max.'; +$messages['internalerror'] = 'An internal error occured. Please try again.'; +$messages['contactdelerror'] = 'Could not delete contact(s).'; +$messages['contactdeleted'] = 'Contact(s) deleted successfully.'; +$messages['contactrestoreerror'] = 'Could not restore deleted contact(s).'; +$messages['contactrestored'] = 'Contact(s) restored successfully.'; +$messages['groupdeleted'] = 'Group deleted successfully.'; +$messages['grouprenamed'] = 'Group renamed successfully.'; +$messages['groupcreated'] = 'Group created successfully.'; +$messages['savedsearchdeleted'] = 'Saved search deleted successfully.'; +$messages['savedsearchdeleteerror'] = 'Could not delete saved search.'; +$messages['savedsearchcreated'] = 'Saved search created successfully.'; +$messages['savedsearchcreateerror'] = 'Could not create saved search.'; +$messages['messagedeleted'] = 'Message(s) deleted successfully.'; +$messages['messagemoved'] = 'Message(s) moved successfully.'; +$messages['messagecopied'] = 'Message(s) copied successfully.'; +$messages['messagemarked'] = 'Message(s) marked successfully.'; +$messages['autocompletechars'] = 'Enter at least $min characters for autocompletion.'; +$messages['autocompletemore'] = 'More matching entries found. Please type more characters.'; +$messages['namecannotbeempty'] = 'Name cannot be empty.'; +$messages['nametoolong'] = 'Name is too long.'; +$messages['folderupdated'] = 'Folder updated successfully.'; +$messages['foldercreated'] = 'Folder created successfully.'; +$messages['invalidimageformat'] = 'Not a valid image format.'; +$messages['mispellingsfound'] = 'Spelling errors detected in the message.'; +$messages['parentnotwritable'] = 'Unable to create/move folder into selected parent folder. No access rights.'; +$messages['messagetoobig'] = 'The message part is too big to process it.'; +$messages['attachmentvalidationerror'] = 'WARNING! This attachment is suspicious because its type doesn\'t match the type declared in the message. If you do not trust the sender, you shouldn\'t open it in the browser because it may contain malicious contents.<br/><br/><em>Expected: $expected; found: $detected</em>'; +$messages['noscriptwarning'] = 'Warning: This webmail service requires Javascript! In order to use it please enable Javascript in your browser\'s settings.'; + +?> diff --git a/program/localization/ga_IE/labels.inc b/program/localization/ga_IE/labels.inc index 9f0da6550..9fffaf42a 100755 --- a/program/localization/ga_IE/labels.inc +++ b/program/localization/ga_IE/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'DréachtaÃ'; $labels['sent'] = 'Amach'; $labels['trash'] = 'Bosca bruscair'; $labels['junk'] = 'DramhaÃl'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Ãbhair'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'Comhbhrúigh'; $labels['empty'] = 'Folmhaigh'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Toilleadh diosca atá athláimhe'; $labels['unknown'] = 'gan aithne'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Athshocraigh an cuardach'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Open in new window'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Taispeáin an foireann deireanach'; $labels['group'] = 'Group'; $labels['groups'] = 'GrúpaÃ'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Seoltaà Pearsanta'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/gl_ES/labels.inc b/program/localization/gl_ES/labels.inc index 5905ea4b9..c624c462e 100644 --- a/program/localization/gl_ES/labels.inc +++ b/program/localization/gl_ES/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Borradores'; $labels['sent'] = 'Enviados'; $labels['trash'] = 'Cubo do lixo'; $labels['junk'] = 'Correo lixo'; +$labels['show_real_foldernames'] = 'Amosar nomes reáis para cartafois especiáis'; // message listing $labels['subject'] = 'Asunto'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Modo de vista da lista'; $labels['folderactions'] = 'Accións cos cartafoles'; $labels['compact'] = 'Compactar'; $labels['empty'] = 'Baleirar'; +$labels['importmessages'] = 'Importar mensaxes'; $labels['quota'] = 'Uso de disco'; $labels['unknown'] = 'descoñecido'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Restablecer a busca'; $labels['searchmod'] = 'Modificadores de busca'; $labels['msgtext'] = 'Mensaxe enteira'; $labels['body'] = 'Corpo'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Abrir nunha nova fiestra'; $labels['emlsave'] = 'Gardar (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Amosar o último grupo'; $labels['group'] = 'Grupo'; $labels['groups'] = 'Grupos'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Enderezos persoais'; $labels['searchsave'] = 'Gardar procura'; @@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Redactar mensaxes HTML'; $labels['htmlonreply'] = 'só cando se resposte a unha mensaxe HTML'; $labels['htmlonreplyandforward'] = 'ao reenviar ou respostar a unha mensaxe HTML'; $labels['htmlsignature'] = 'Sinatura HTML'; -$labels['showemail'] = 'Show email address with display name'; +$labels['showemail'] = 'Amosar enderezo de correo co nome en pantalla'; $labels['previewpane'] = 'Amosar previsualización'; $labels['skin'] = 'Aspecto da interface'; $labels['logoutclear'] = 'Baleirar o cubo do lixo ao saÃr'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorar as palabras con números'; $labels['spellcheckignorecaps'] = 'Ignorar as palabras escritas en maiúsculas'; $labels['addtodict'] = 'Engadir ao diccionario'; $labels['mailtoprotohandler'] = 'Rexistrar o manexador de protocolo para as ligazóns "mailto:"'; +$labels['standardwindows'] = 'Manexar avisos emerxentes como xanelas estándar'; $labels['forwardmode'] = 'Reenvio de mensaxes'; $labels['inline'] = 'inserido'; $labels['asattachment'] = 'coma anexo'; diff --git a/program/localization/gl_ES/messages.inc b/program/localization/gl_ES/messages.inc index 207a016a1..8fc2cb424 100644 --- a/program/localization/gl_ES/messages.inc +++ b/program/localization/gl_ES/messages.inc @@ -126,6 +126,8 @@ $messages['importwait'] = 'A importar. Por favor, agarde...'; $messages['importformaterror'] = 'Fallou a importación! O ficheiro cargado non contén datos válidos.'; $messages['importconfirm'] = '<b>Importáronse correctamente $inserted contactos. Ignoráronse $skipped contactos que xa existÃan</b>:<p><em>$names</em></p>'; $messages['importconfirmskipped'] = '<b>Ignoráronse $skipped existing entradas</b>'; +$messages['importmessagesuccess'] = 'Importados $nr mensaxes con éxito'; +$messages['importmessageerror'] = 'Fallou a importación! O arquivo subido non é unha mensaxe válida ou un ficheiro de caixa de correo'; $messages['opnotpermitted'] = 'Operación non permitida!'; $messages['nofromaddress'] = 'Falta o enderezo de correo electrónico na identidade que escolleu.'; $messages['editorwarning'] = 'Se troca neste intre ao editor de texto plano, vai perder todo o formato do texto. Quere continuar?'; diff --git a/program/localization/he_IL/labels.inc b/program/localization/he_IL/labels.inc index bfb9e2fef..7ad04ab4a 100644 --- a/program/localization/he_IL/labels.inc +++ b/program/localization/he_IL/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'טיוטות'; $labels['sent'] = '× ×©×œ×—'; $labels['trash'] = '×שפה'; $labels['junk'] = 'זבל'; +$labels['show_real_foldernames'] = 'הצגת שמות ××ž×™×ª×™×™× ×©×œ תיקיות מיוחדות'; // message listing $labels['subject'] = '× ×•×©×'; @@ -193,6 +194,7 @@ $labels['listmode'] = '×ופן הצגת רשימה'; $labels['folderactions'] = 'פעולות על תיקי×'; $labels['compact'] = '×¤×™× ×•×™ שטח ×œ× ×ž× ×•×¦×œ'; $labels['empty'] = 'ריקון'; +$labels['importmessages'] = '×™×™×‘×•× ×”×•×“×¢×•×ª'; $labels['quota'] = '× ×™×¦×•×œ קיבולת'; $labels['unknown'] = '×œ× ×™×“×•×¢'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = '× ×™×§×•×™ תיבת החיפוש'; $labels['searchmod'] = 'מ××¤×™×™× ×™ חיפוש'; $labels['msgtext'] = 'כל ההודעה'; $labels['body'] = 'גוף ההודעה'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'פתיחה בחלון חדש'; $labels['emlsave'] = 'הורדת הודעה בפורמט EML'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'הצגת הקבוצה ×”××—×¨×•× ×”'; $labels['group'] = 'קבוצה'; $labels['groups'] = 'קבוצות'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'כתובות פרטיות'; $labels['searchsave'] = 'שמירת החיפוש'; @@ -474,6 +478,7 @@ $labels['spellcheckignorenums'] = 'התעלמות ×ž×ž×™×œ×™× ×”×ž×›×™×œ×•×ª מ $labels['spellcheckignorecaps'] = 'התעלמות ×ž×ž×™×œ×™× ×¢× ×ותציות ר×שיות'; $labels['addtodict'] = 'הוספה למילון'; $labels['mailtoprotohandler'] = 'קביעת הפרוטוקול לטיפול בקישור מסוג mailto:links'; +$labels['standardwindows'] = '×—×œ×•× ×•×ª ×§×•×¤×¦×™× ×™×˜×•×¤×œ×• ×›×—×œ×•× ×•×ª רגילי×'; $labels['forwardmode'] = '×”×¤× ×™×ª הודעות'; $labels['inline'] = 'חלק מההודעה'; $labels['asattachment'] = 'כצרופה'; diff --git a/program/localization/he_IL/messages.inc b/program/localization/he_IL/messages.inc index 7d9b87c06..37ebcea01 100644 --- a/program/localization/he_IL/messages.inc +++ b/program/localization/he_IL/messages.inc @@ -126,6 +126,8 @@ $messages['importwait'] = 'ייבו×, × × ×œ×”×ž×ª×™×Ÿ..'; $messages['importformaterror'] = '×”×™×‘×•× × ×›×©×œ ! הקובץ שהועלה ××™× ×• מת××™×.'; $messages['importconfirm'] = '<b>יוב×ו $inserted ×× ×©×™ קשר, $skipped היו ×§×™×™×ž×™× </b>:<p><em>$names</em></p>'; $messages['importconfirmskipped'] = '<b> דילוג של $skipped × ×ª×•× ×™× ×§×™×™×ž×™× <b>'; +$messages['importmessagesuccess'] = 'יוב×ו בהצלחה $nr הודעות '; +$messages['importmessageerror'] = '×”×™×‘×•× × ×›×©×œ ! הקובץ שהועלה ××™× ×• הודעה ×ו קובץ הודעות ×‘×ž×‘× ×” מת××™×'; $messages['opnotpermitted'] = 'פעולה ×סורה!'; $messages['nofromaddress'] = 'לזהות ×©× ×‘×—×¨×” חסרה כתובת דו×ר'; $messages['editorwarning'] = 'המעבר לעורך רגיל ×™×’×¨×•× ×œ×יבוד ×ת העריכה הקיימת. ×”×× ×œ×”×ž×©×™×š?'; diff --git a/program/localization/hi_IN/labels.inc b/program/localization/hi_IN/labels.inc index 3b8279f71..303e0b5fb 100644 --- a/program/localization/hi_IN/labels.inc +++ b/program/localization/hi_IN/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'डà¥à¤°à¤¾à¤«à¤¼à¤Ÿ'; $labels['sent'] = 'à¤à¥‡à¤œà¤¾ गया'; $labels['trash'] = 'रदà¥à¤¦à¥€'; $labels['junk'] = 'सà¥à¤ªà¥ˆà¤®'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'विशय'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'छोटा करें'; $labels['empty'] = 'मेल रदà¥à¤¦à¥€ में डालें'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'डिसà¥à¤• उपयोग'; $labels['unknown'] = 'अजà¥à¤žà¤¾à¤¤'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'खोज खाली करें'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Open in new window'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'आखिरी बनà¥à¤¡à¤² दिखाà¤à¤‚' $labels['group'] = 'Group'; $labels['groups'] = 'Groups'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Personal Addresses'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/hr_HR/labels.inc b/program/localization/hr_HR/labels.inc index 506d50f1f..4578fed2b 100644 --- a/program/localization/hr_HR/labels.inc +++ b/program/localization/hr_HR/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'PredloÅ¡ci'; $labels['sent'] = 'Poslano'; $labels['trash'] = 'Smeće'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Naslov'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Model pregleda listi'; $labels['folderactions'] = 'Akcije mapa'; $labels['compact'] = 'Kompresiranje'; $labels['empty'] = 'Isprazni'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Kvota'; $labels['unknown'] = 'nepoznato'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Prikaži sve poruke'; $labels['searchmod'] = 'Postavke pretrage'; $labels['msgtext'] = 'Cijela poruka'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Otvori u novom prozoru'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Zadnja strana'; $labels['group'] = 'Grupa'; $labels['groups'] = 'Grupe'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Privatna adresa'; $labels['searchsave'] = 'Pohrani pretragu'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignoriraj rijeÄi koje sadrže brojeve'; $labels['spellcheckignorecaps'] = 'Ignoriraj rijeÄi sa sa svim velikim slovima'; $labels['addtodict'] = 'Dodaj u rjeÄnik'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/hu_HU/labels.inc b/program/localization/hu_HU/labels.inc index 3cc5da1aa..abdc7e891 100644 --- a/program/localization/hu_HU/labels.inc +++ b/program/localization/hu_HU/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Piszkozatok'; $labels['sent'] = 'Küldött levelek'; $labels['trash'] = 'Törölt elemek'; $labels['junk'] = 'Kéretlen levelek'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Tárgy'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'MegjelenÃtési mód'; $labels['folderactions'] = 'Mappaműveletek...'; $labels['compact'] = 'TömörÃtés'; $labels['empty'] = 'KiürÃtés'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Helyfoglalás'; $labels['unknown'] = 'ismeretlen'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Alapállapot'; $labels['searchmod'] = 'Keresési opciók'; $labels['msgtext'] = 'Teljes üzenet'; $labels['body'] = 'Törzs'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Megnyitás új ablakban'; $labels['emlsave'] = 'Letöltés (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Utolsó oldal'; $labels['group'] = 'Csoport'; $labels['groups'] = 'Csoportok'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Személyes cÃmjegyzék'; $labels['searchsave'] = 'Keresés mentése'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Számot tartalmazó szavak kihagyása'; $labels['spellcheckignorecaps'] = 'Csak nagybetűt tartalmazó szavak kihagyása'; $labels['addtodict'] = 'Hozzáadás a szótárhoz'; $labels['mailtoprotohandler'] = 'BeállÃtás a mailto: linkek kezelÅ‘jeként'; +$labels['standardwindows'] = 'A felugró ablakok használata szokásos ablakként'; $labels['forwardmode'] = 'Ãœzenet továbbÃtás'; $labels['inline'] = 'beágyazott'; $labels['asattachment'] = 'csatolmányként'; diff --git a/program/localization/hy_AM/labels.inc b/program/localization/hy_AM/labels.inc index 99cee4ab9..8ee9316c4 100644 --- a/program/localization/hy_AM/labels.inc +++ b/program/localization/hy_AM/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'ÕÖ‡Õ¡Õ£Ö€Õ¥Ö€'; $labels['sent'] = 'ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¾Õ¡Õ®'; $labels['trash'] = 'Ô±Õ²Õ¢Õ¡Ö€Õ¯Õ²'; $labels['junk'] = 'Ô¹Õ¡ÖƒÕ¸Õ¶'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'ÕŽÕ¥Ö€Õ¶Õ¡Õ£Õ«Ö€'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Õ‘Õ¸Ö‚ÖÕ¡Õ¯Õ¸Õ¾ Õ¿Õ¥Õ½Ö„Õ« Õ¿Õ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯Õ¨'; $labels['folderactions'] = 'ÕŠÕ¡Õ¶Õ¡Õ¯Õ« գործողություններ…'; $labels['compact'] = 'ÕÕ¥Õ²Õ´Õ¥Õ¬'; $labels['empty'] = 'Ô´Õ¡Õ¿Õ¡Ö€Õ¯Õ¥Õ¬'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Ô´Õ«Õ½Õ¯Õ¡ÕµÕ«Õ¶ Õ¿Õ¡Ö€Õ¡Õ®Ö„'; $labels['unknown'] = 'Õ¡Õ¶Õ°Õ¡ÕµÕ¿'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ÕŽÕ¥Ö€Õ½Õ¯Õ½Õ¥Õ¬ Õ¸Ö€Õ¸Õ¶Õ¸Ö‚Õ´Õ¨'; $labels['searchmod'] = 'ÕˆÖ€Õ¸Õ¶Õ´Õ¡Õ¶ ÖƒÕ¸ÖƒÕ¸ÕÕ«Õ¹Õ¶Õ¥Ö€'; $labels['msgtext'] = 'ÕˆÕ²Õ» Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Ô²Õ¡ÖÕ¥Õ¬ Õ¶Õ¸Ö€ ÕºÕ¡Õ¿Õ¸Ö‚Õ°Õ¡Õ¶Õ¸Ö‚Õ´'; $labels['emlsave'] = 'Õ†Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¾Õ¥Ö€Õ»Õ«Õ¶ Õ§Õ»Õ¨'; $labels['group'] = 'Ô½Õ¸Ö‚Õ´Õ¢'; $labels['groups'] = 'Ô½Õ´Õ¢Õ¥Ö€'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Ô±Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ°Õ¡Õ½ÖÕ¥Õ¶Õ¥Ö€'; $labels['searchsave'] = 'ÕŠÕ¡Õ°ÕºÕ¡Õ¶Õ¥Õ¬ Õ¸Ö€Õ¸Õ¶Õ¸Ö‚Õ´Õ¨'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ô±Õ¶Õ¿Õ¥Õ½Õ¥Õ¬ Õ©Õ¾Õ¥Ö€Õ¸Õ¾ Õ¢Õ¡Õ¼Õ¥Ö€Õ¨'; $labels['spellcheckignorecaps'] = 'Ô±Õ¶Õ¿Õ¥Õ½Õ¥Õ¬ Õ¬Ö€Õ«Õ¾ Õ´Õ¥Õ®Õ¡Õ¿Õ¡Õ¼ Õ¢Õ¡Õ¼Õ¥Ö€Õ¨'; $labels['addtodict'] = 'Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¢Õ¡Õ¼Õ¡Ö€Õ¡Õ¶Õ¸Ö‚Õ´'; $labels['mailtoprotohandler'] = 'mailto: Õ°Õ²Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ¸Õ²'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/ia/labels.inc b/program/localization/ia/labels.inc index 2a9501168..1cd614d35 100644 --- a/program/localization/ia/labels.inc +++ b/program/localization/ia/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Drafts'; $labels['sent'] = 'Inviate'; $labels['trash'] = 'Trash'; $labels['junk'] = 'Junk'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Subjecto'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Actiones de dossier...'; $labels['compact'] = 'Compacte'; $labels['empty'] = 'Vacue'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Disk usage'; $labels['unknown'] = 'incognite'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reinitialisar cerca'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Message complete'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Aperir in nove fenestra'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Show last page'; $labels['group'] = 'Gruppo'; $labels['groups'] = 'Gruppos'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Adresses personal'; $labels['searchsave'] = 'Salveguardar cerca'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Adder al dictionario'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/id_ID/labels.inc b/program/localization/id_ID/labels.inc index eea3132cd..73bb0156d 100644 --- a/program/localization/id_ID/labels.inc +++ b/program/localization/id_ID/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Daftar tunggu'; $labels['sent'] = 'Terkirim'; $labels['trash'] = 'Surat Terhapus'; $labels['junk'] = 'Sampah'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Judul'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Perlihatkan mode tinjauan'; $labels['folderactions'] = 'Tindakan pada folder...'; $labels['compact'] = 'Rampingkan'; $labels['empty'] = 'Kosong'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Penggunaan ruang'; $labels['unknown'] = 'Tidak dikenal'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Atur ulang pencarian'; $labels['searchmod'] = 'Peubah pencarian'; $labels['msgtext'] = 'Seluruh pesan'; $labels['body'] = 'Badan'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Buka dalam jendela baru'; $labels['emlsave'] = 'Unduh (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Perlihatkan himpunan terakhir'; $labels['group'] = 'Kelompok'; $labels['groups'] = 'Kelompok'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Alamat pribadi'; $labels['searchsave'] = 'Simpan pencarian'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Abaikan kata-kata yang bernomor'; $labels['spellcheckignorecaps'] = 'Abaikan kata-kata dengan huruf besar semua'; $labels['addtodict'] = 'Tambahkan ke kamus'; $labels['mailtoprotohandler'] = 'Daftarkan pengampu protokol untuk link mailto:'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Meneruskan pesan'; $labels['inline'] = 'dalam surat'; $labels['asattachment'] = 'sebagai sisipan'; diff --git a/program/localization/index.inc b/program/localization/index.inc index bfb770cac..4b848dc49 100644 --- a/program/localization/index.inc +++ b/program/localization/index.inc @@ -70,6 +70,7 @@ $rcube_languages = array( 'ku' => 'Kurdish (Kurmancî)', 'lv_LV' => 'Latvian (LatvieÅ¡u)', 'lt_LT' => 'Lithuanian (LietuviÅ¡kai)', + 'lb_LU' => 'Luxembourgish (Lëtzebuergesch)', 'mk_MK' => 'Macedonian (МакедонÑки)', 'ms_MY' => 'Malay (Bahasa Melayu)', 'ml_IN' => 'Malayalam (മലയാളം)', @@ -133,6 +134,7 @@ $rcube_language_aliases = array( 'kh' => 'km_KH', 'kh_KH' => 'km_KH', 'km' => 'km_KH', + 'lb' => 'lb_LU', 'ne' => 'ne_NP', 'no' => 'nn_NO', 'ms' => 'ms_MY', diff --git a/program/localization/is_IS/labels.inc b/program/localization/is_IS/labels.inc index 80443dd3a..c2859ce75 100644 --- a/program/localization/is_IS/labels.inc +++ b/program/localization/is_IS/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Drög'; $labels['sent'] = 'Sent'; $labels['trash'] = 'Rusl'; $labels['junk'] = 'Ruslpóstur'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Titill'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Listayfirlit'; $labels['folderactions'] = 'Möppuaðgerðir...'; $labels['compact'] = 'Pakka'; $labels['empty'] = 'Tæma'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Gagnamagn'; $labels['unknown'] = 'óþekkt'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Tæma leit'; $labels['searchmod'] = 'Leitarskilyrði'; $labels['msgtext'] = 'Allt skeytið'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Opna à nýjum glugga'; $labels['emlsave'] = 'Niðurhlaða (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Sýna sÃðustu sÃðu'; $labels['group'] = 'Hópur'; $labels['groups'] = 'Hópar'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Persónuleg heimilisföng'; $labels['searchsave'] = 'Vista leit'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Hunsa orð með tölum'; $labels['spellcheckignorecaps'] = 'Hunsa orð sem eru à hástöfum'; $labels['addtodict'] = 'Bæta við orðalista'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/it_IT/labels.inc b/program/localization/it_IT/labels.inc index 75a24c5fd..55cd432f7 100644 --- a/program/localization/it_IT/labels.inc +++ b/program/localization/it_IT/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Bozze'; $labels['sent'] = 'Inviata'; $labels['trash'] = 'Cestino'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Oggetto'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Modalità di visualizzazione'; $labels['folderactions'] = 'Operazioni cartella'; $labels['compact'] = 'Compatta'; $labels['empty'] = 'Svuota'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Spazio utilizzato'; $labels['unknown'] = 'sconosciuto'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Annulla ricerca'; $labels['searchmod'] = 'Ambito di ricerca'; $labels['msgtext'] = 'Intero messaggio'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Apri in una nuova finestra'; $labels['emlsave'] = 'Scarica (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Ultima pagina'; $labels['group'] = 'Gruppo'; $labels['groups'] = 'Gruppi'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Rubrica Personale'; $labels['searchsave'] = 'Salva ricerca'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignora le parole contenenti numeri'; $labels['spellcheckignorecaps'] = 'Ignora le parole con tutte le lettere maiuscole'; $labels['addtodict'] = 'Aggiungi al dizionario'; $labels['mailtoprotohandler'] = 'Registra gestore per mailto:'; +$labels['standardwindows'] = 'Gestisci i popup come finestre standard'; $labels['forwardmode'] = 'Inoltro messaggi'; $labels['inline'] = 'In linea'; $labels['asattachment'] = 'come allegato'; diff --git a/program/localization/ja_JP/labels.inc b/program/localization/ja_JP/labels.inc index 6998f0623..767aff23a 100644 --- a/program/localization/ja_JP/labels.inc +++ b/program/localization/ja_JP/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = '下書ã'; $labels['sent'] = 'é€ä¿¡æ¸ˆã¿'; $labels['trash'] = 'ã”ã¿ç®±'; $labels['junk'] = '迷惑メール'; +$labels['show_real_foldernames'] = '特殊フォルダーã®å®Ÿéš›ã®åå‰ã‚’表示'; // message listing $labels['subject'] = '件å'; @@ -193,6 +194,7 @@ $labels['listmode'] = '一覧表示モード'; $labels['folderactions'] = 'フォルダーã®æ“作...'; $labels['compact'] = '圧縮'; $labels['empty'] = '空'; +$labels['importmessages'] = 'メッセージをインãƒãƒ¼ãƒˆ'; $labels['quota'] = 'ディスクã®ä½¿ç”¨çŠ¶æ³'; $labels['unknown'] = 'ä¸æ˜Ž'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = '検索を解除'; $labels['searchmod'] = '検索ã®æ¡ä»¶'; $labels['msgtext'] = 'メッセージ全体'; $labels['body'] = '本文'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'æ–°ã—ã„ウィンドウã§é–‹ã'; $labels['emlsave'] = 'ダウンãƒãƒ¼ãƒ‰(.emlå½¢å¼)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = '最後ã®ãƒšãƒ¼ã‚¸ã‚’表示'; $labels['group'] = 'グループ'; $labels['groups'] = 'グループ'; +$labels['listgroup'] = 'グループã®ãƒ¡ãƒ³ãƒãƒ¼ã‚’一覧'; $labels['personaladrbook'] = '個人ã®ä½æ‰€'; $labels['searchsave'] = 'æ¤œç´¢æƒ…å ±ã‚’ä¿å˜'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'æ•°å—ã‚’å«ã‚€å˜èªžã‚’無視'; $labels['spellcheckignorecaps'] = 'ã™ã¹ã¦å¤§æ–‡å—ã®å˜èªžã‚’無視'; $labels['addtodict'] = '辞書ã«è¿½åŠ '; $labels['mailtoprotohandler'] = 'mailto: ã®ãƒªãƒ³ã‚¯ã‚’扱ã†ãƒ—ãƒãƒˆã‚³ãƒ«å‡¦ç†ã®ç™»éŒ²'; +$labels['standardwindows'] = 'ãƒãƒƒãƒ—アップを通常ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã¨ã—ã¦å‡¦ç†'; $labels['forwardmode'] = 'メッセージã®è»¢é€å½¢å¼'; $labels['inline'] = 'インライン'; $labels['asattachment'] = '添付ファイル'; diff --git a/program/localization/ka_GE/labels.inc b/program/localization/ka_GE/labels.inc index 3ab3b6e63..b0126c44e 100755 --- a/program/localization/ka_GE/labels.inc +++ b/program/localization/ka_GE/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'დრáƒáƒ”ბითი'; $labels['sent'] = 'გáƒáƒ’ზáƒáƒ•áƒœáƒ˜áƒšáƒ˜'; $labels['trash'] = 'წáƒáƒ¨áƒšáƒ˜áƒšáƒ˜'; $labels['junk'] = 'სპáƒáƒ›áƒ˜'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'სáƒáƒ—áƒáƒ£áƒ ი'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'შეკუმშვáƒ'; $labels['empty'] = 'გáƒáƒªáƒáƒ იელებáƒ'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'შეზღუდვáƒ'; $labels['unknown'] = 'უცნáƒáƒ‘ი'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ძიების გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ”ბáƒ' $labels['searchmod'] = 'ძებნის ვáƒáƒ იáƒáƒœáƒ¢áƒ”ბი'; $labels['msgtext'] = 'ყველრშეტყáƒáƒ‘ინებáƒ'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'გáƒáƒ®áƒ¡áƒœáƒ áƒáƒ®áƒáƒš ფáƒáƒœáƒ¯áƒáƒ áƒáƒ¨áƒ˜'; $labels['emlsave'] = 'გáƒáƒ“მáƒáƒ¬áƒ”რრ(.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'ბáƒáƒšáƒáƒ¡ ჩვენებáƒ'; $labels['group'] = 'ჯგუფი'; $labels['groups'] = 'ჯგუფები'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'პერსáƒáƒœáƒáƒšáƒ£áƒ ი მისáƒáƒ›áƒáƒ თები'; $labels['searchsave'] = 'ძებნის შენáƒáƒ®áƒ•áƒ'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'ლექსიკáƒáƒœáƒ¨áƒ˜ დáƒáƒ›áƒáƒ¢áƒ”ბáƒ'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/km_KH/labels.inc b/program/localization/km_KH/labels.inc index 7b10b5f7f..bc2836a53 100644 --- a/program/localization/km_KH/labels.inc +++ b/program/localization/km_KH/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'សំបុážáŸ’រពង្រៀង'; $labels['sent'] = 'សំបុážáŸ’រដែលបានបញ្ជូន'; $labels['trash'] = 'ធុងសំរាម'; $labels['junk'] = 'សំបុážáŸ’រមិនល្អ'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'ចំណងជើង'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'បង្ហាញជាážáž¶ážšáž¶áž„'; $labels['folderactions'] = 'មុážáž„ារážáž'; $labels['compact'] = 'បង្រួម'; $labels['empty'] = 'áž‘áž‘áŸážš'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'ទំហំសំបុážáŸ’រទាំងអស់ដែលមាន'; $labels['unknown'] = 'មិនស្គាល់'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'កំណážáŸ‹áž›áž€áŸ’ážážáŸážŽáŸ’ឌស្វ០$labels['searchmod'] = 'កែសំរួលលក្ážážáŸážŽáŸ’ឌស្វែងរក'; $labels['msgtext'] = 'សំបុážáŸ’រទាំងមូល'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'បើកក្នុងវីនដូវážáŸ’មី'; $labels['emlsave'] = 'រក្សាទុកទិន្ននáŸáž™áž‡áž¶áž¯áž€ážŸáž¶ážšáž”្រភáŸáž‘(.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'ទំពáŸážšáž…ុងក្រោយ'; $labels['group'] = 'ក្រុម'; $labels['groups'] = 'ក្រុម'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'អាសយដ្ឋានផ្ទាល់ážáŸ’លួន'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/ko_KR/labels.inc b/program/localization/ko_KR/labels.inc index 950928767..60a9275ac 100644 --- a/program/localization/ko_KR/labels.inc +++ b/program/localization/ko_KR/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'ìž„ì‹œ 보관함'; $labels['sent'] = '보낸 편지함'; $labels['trash'] = '휴지통'; $labels['junk'] = '스팸 편지함'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'ì œëª©'; @@ -193,6 +194,7 @@ $labels['listmode'] = '화면 모드 ëª©ë¡ ë³´ê¸°'; $labels['folderactions'] = 'í´ë” ëª…ë ¹'; $labels['compact'] = '간단하게'; $labels['empty'] = '비어 있ìŒ'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'ë””ìŠ¤í¬ ì‚¬ìš©ëŸ‰'; $labels['unknown'] = 'ì•Œ 수 ì—†ìŒ'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = '검색 ìž¬ì„¤ì •'; $labels['searchmod'] = 'ìˆ˜ì •ìž ê²€ìƒ‰'; $labels['msgtext'] = 'ì „ì²´ 메시지'; $labels['body'] = '본문'; +$labels['type'] = 'Type'; $labels['openinextwin'] = '새 ì°½ì—ì„œ 열기'; $labels['emlsave'] = '다운로드(.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = '마지막 페ì´ì§€ 보기'; $labels['group'] = '그룹'; $labels['groups'] = '그룹'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'ê°œì¸ ì£¼ì†Œ'; $labels['searchsave'] = '검색 ì €ìž¥'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = '숫ìžê°€ í¬í•¨ëœ 단어 무시'; $labels['spellcheckignorecaps'] = 'ëª¨ë‘ ëŒ€ë¬¸ìžë¡œ í‘œê¸°ëœ ë‹¨ì–´ 무시'; $labels['addtodict'] = 'ì‚¬ì „ì— ì¶”ê°€'; $labels['mailtoprotohandler'] = 'mailto: ë§í¬ì˜ í”„ë¡œí† ì½œ ì²˜ë¦¬ìž ë“±ë¡'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = '메시지 ì „ë‹¬'; $labels['inline'] = '본문 내용으로'; $labels['asattachment'] = '첨부파ì¼ë¡œ'; diff --git a/program/localization/ku/labels.inc b/program/localization/ku/labels.inc index a4f6cb568..6a3c16a5f 100644 --- a/program/localization/ku/labels.inc +++ b/program/localization/ku/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Hilanînî'; $labels['sent'] = 'Åžandî'; $labels['trash'] = 'Çop'; $labels['junk'] = 'Biikêrnehatî'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Mijar'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'Kompakt'; $labels['empty'] = 'Vala Bike'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Bikaranîna dîskê'; $labels['unknown'] = 'nayê zanîn'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Lêgerînê reset bike'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Open in new window'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Seta dawî nîşan bide'; $labels['group'] = 'Group'; $labels['groups'] = 'Kom'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Navnîşanên Takekesî'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/lb_LU/labels.inc b/program/localization/lb_LU/labels.inc new file mode 100644 index 000000000..1dff3a9e7 --- /dev/null +++ b/program/localization/lb_LU/labels.inc @@ -0,0 +1,544 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | localization/<lang>/labels.inc | + | | + | Localization file of the Roundcube Webmail client | + | Copyright (C) 2005-2013, The Roundcube Dev Team | + | | + | Licensed under the GNU General Public License version 3 or | + | any later version with exceptions for skins & plugins. | + | See the README file for a full license statement. | + | | + +-----------------------------------------------------------------------+ + + For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/labels/ +*/ + +$labels = array(); + +// login page +$labels['welcome'] = 'Wëllkomm bei $product'; +$labels['username'] = 'Benotzernumm'; +$labels['password'] = 'Passwuert'; +$labels['server'] = 'Server'; +$labels['login'] = 'Aloggen'; + +// taskbar +$labels['logout'] = 'Ausloggen'; +$labels['mail'] = 'Mailen'; +$labels['settings'] = 'Astellungen'; +$labels['addressbook'] = 'Adressbuch'; + +// mailbox names +$labels['inbox'] = 'Mailbox'; +$labels['drafts'] = 'Brouillonen'; +$labels['sent'] = 'Verschéckt'; +$labels['trash'] = 'Poubelle'; +$labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Richteg Nimm vu de speziellen Dossieren uweisen'; + +// message listing +$labels['subject'] = 'Sujet'; +$labels['from'] = 'Vun'; +$labels['sender'] = 'Geschéckt vun'; +$labels['to'] = 'Un'; +$labels['cc'] = 'CC'; +$labels['bcc'] = 'BCC'; +$labels['replyto'] = 'Äntwert un'; +$labels['followupto'] = 'Noverfollgung un'; +$labels['date'] = 'Datum'; +$labels['size'] = 'Gréisst'; +$labels['priority'] = 'Prioritéit'; +$labels['organization'] = 'Organisatioun'; +$labels['readstatus'] = 'Lies-Status'; +$labels['listoptions'] = 'Optiounen oplëschten'; + +$labels['mailboxlist'] = 'Dossieren'; +$labels['messagesfromto'] = 'Messagen $from bis $to vun $count'; +$labels['threadsfromto'] = 'Diskussiounen $from bis $to vun $count'; +$labels['messagenrof'] = 'Message $nr vun $count'; +$labels['fromtoshort'] = '$from bis $to vun $count'; + +$labels['copy'] = 'Kopéieren'; +$labels['move'] = 'Réckelen'; +$labels['moveto'] = 'Réckelen an...'; +$labels['download'] = 'Eroflueden'; +$labels['open'] = 'Opmaachen'; +$labels['showattachment'] = 'Weisen'; +$labels['showanyway'] = 'Trotzdeem weisen'; + +$labels['filename'] = 'Numm vum Fichier'; +$labels['filesize'] = 'Gréisst vum Fichier'; + +$labels['addtoaddressbook'] = 'An d\'Adressbuch setzen'; + +// weekdays short +$labels['sun'] = 'Son'; +$labels['mon'] = 'Méi'; +$labels['tue'] = 'Dën'; +$labels['wed'] = 'Don'; +$labels['thu'] = 'Fre'; +$labels['fri'] = 'Sam'; +$labels['sat'] = 'Son'; + +// weekdays long +$labels['sunday'] = 'Sonndeg'; +$labels['monday'] = 'Méindeg'; +$labels['tuesday'] = 'Dënschdeg'; +$labels['wednesday'] = 'Mëttwoch'; +$labels['thursday'] = 'Donneschdeg'; +$labels['friday'] = 'Freideg'; +$labels['saturday'] = 'Samschdeg'; + +// months short +$labels['jan'] = 'Jan'; +$labels['feb'] = 'Feb'; +$labels['mar'] = 'Mäe'; +$labels['apr'] = 'Abr'; +$labels['may'] = 'Mee'; +$labels['jun'] = 'Jun'; +$labels['jul'] = 'Jul'; +$labels['aug'] = 'Aug'; +$labels['sep'] = 'Sep'; +$labels['oct'] = 'Okt'; +$labels['nov'] = 'Nov'; +$labels['dec'] = 'Dez'; + +// months long +$labels['longjan'] = 'Januar'; +$labels['longfeb'] = 'Februar'; +$labels['longmar'] = 'Mäerz'; +$labels['longapr'] = 'Abrëll'; +$labels['longmay'] = 'Mee'; +$labels['longjun'] = 'Juni'; +$labels['longjul'] = 'Juli'; +$labels['longaug'] = 'August'; +$labels['longsep'] = 'September'; +$labels['longoct'] = 'Oktober'; +$labels['longnov'] = 'November'; +$labels['longdec'] = 'Dezember'; + +$labels['today'] = 'Haut'; + +// toolbar buttons +$labels['refresh'] = 'Nei lueden'; +$labels['checkmail'] = 'Nei Messagen ofruffen'; +$labels['compose'] = 'Schreiwen'; +$labels['writenewmessage'] = 'Neie Message schreiwen'; +$labels['reply'] = 'Äntweren'; +$labels['replytomessage'] = 'Dem Ofsender äntweren'; +$labels['replytoallmessage'] = 'Dem Ofsender an allen Empfänger äntweren'; +$labels['replyall'] = 'U jiddwereen äntweren'; +$labels['replylist'] = 'Äntwert-Lëscht'; +$labels['forward'] = 'Weiderleeden'; +$labels['forwardinline'] = 'Am Message weiderleeden'; +$labels['forwardattachment'] = 'Als Unhank weiderleeden'; +$labels['forwardmessage'] = 'De Message weiderleeden'; +$labels['deletemessage'] = 'Message läschen'; +$labels['movemessagetotrash'] = 'Message an d\'Poubelle réckelen'; +$labels['printmessage'] = 'Dëse Message drécken'; +$labels['previousmessage'] = 'Message virdru weisen'; +$labels['firstmessage'] = 'Éischte Message weisen'; +$labels['nextmessage'] = 'Nächste Message weisen'; +$labels['lastmessage'] = 'Leschte Message weisen'; +$labels['backtolist'] = 'Zréck bei d\'Lëscht vun de Messagen'; +$labels['viewsource'] = 'Source weisen'; +$labels['mark'] = 'Markéieren'; +$labels['markmessages'] = 'Messagë markéieren'; +$labels['markread'] = 'Als gelies'; +$labels['markunread'] = 'Als ongelies'; +$labels['markflagged'] = 'Mat Fändel'; +$labels['markunflagged'] = 'Ouni Fändel'; +$labels['moreactions'] = 'Mei Aktiounen...'; +$labels['more'] = 'Méi'; +$labels['back'] = 'Zréck'; +$labels['options'] = 'Optiounen'; + +$labels['select'] = 'Auswielen'; +$labels['all'] = 'All'; +$labels['none'] = 'Keng'; +$labels['currpage'] = 'Aktuell Säit'; +$labels['unread'] = 'Ongelies'; +$labels['flagged'] = 'Mat Fändel'; +$labels['unanswered'] = 'Net beäntwert'; +$labels['withattachment'] = 'Mat Unhank'; +$labels['deleted'] = 'Geläscht'; +$labels['undeleted'] = 'Net geläscht'; +$labels['invert'] = 'Ëmdréinen'; +$labels['filter'] = 'Filter'; +$labels['list'] = 'Lëscht'; +$labels['threads'] = 'Diskussiounen'; +$labels['expand-all'] = 'All opfächeren'; +$labels['expand-unread'] = 'Ongelies opfächeren'; +$labels['collapse-all'] = 'All zesummefächeren'; +$labels['threaded'] = 'Diskussiounen zesummefaassen'; + +$labels['autoexpand_threads'] = 'Diskussiounen auserneefächeren'; +$labels['do_expand'] = 'All d\'Diskussiounen'; +$labels['expand_only_unread'] = 'just ongeliese Messagen'; +$labels['fromto'] = 'Vun/Un'; +$labels['flag'] = 'Fändel'; +$labels['attachment'] = 'Unhank'; +$labels['nonesort'] = 'Keng'; +$labels['sentdate'] = 'Verschéckt'; +$labels['arrival'] = 'Ukomm'; +$labels['asc'] = 'opsteigend'; +$labels['desc'] = 'ofsteigend'; +$labels['listcolumns'] = 'Kolonnen oplëschten'; +$labels['listsorting'] = 'Kolonne sortéieren'; +$labels['listorder'] = 'Sortéier-Reiefolleg'; +$labels['listmode'] = 'Oplëschtungs-Modus'; + +$labels['folderactions'] = 'Dossiers-Aktiounen...'; +$labels['compact'] = 'Kompaktéieren'; +$labels['empty'] = 'Eidel'; +$labels['importmessages'] = 'Messagen importéieren'; + +$labels['quota'] = 'Plazverbrauch'; +$labels['unknown'] = 'onbekannt'; +$labels['unlimited'] = 'onlimitéiert'; + +$labels['quicksearch'] = 'Séier Sich'; +$labels['resetsearch'] = 'Sich zerécksetzen'; +$labels['searchmod'] = 'Sich-Parameter'; +$labels['msgtext'] = 'Ganze Message'; +$labels['body'] = 'Kierper'; +$labels['type'] = 'Typ'; +$labels['namex'] = 'Numm'; + +$labels['openinextwin'] = 'An enger neier Fënster opmaachen'; +$labels['emlsave'] = 'Eroflueden (.eml)'; +$labels['changeformattext'] = 'Als Text ouni Formatéierungen uweisen'; +$labels['changeformathtml'] = 'Als formatéierten Text uweisen'; + +// message compose +$labels['editasnew'] = 'Als nei editéieren'; +$labels['send'] = 'Schécken'; +$labels['sendmessage'] = 'Message schécken'; +$labels['savemessage'] = 'Als Brouillon späicheren'; +$labels['addattachment'] = 'E Fichier drunhänken'; +$labels['charset'] = 'Zeechesaz'; +$labels['editortype'] = 'Editor-Typ'; +$labels['returnreceipt'] = 'Empfanksbestätegung'; +$labels['dsn'] = 'Empfanks-Status-Meldung'; +$labels['mailreplyintro'] = 'Den $date, $sender schreift:'; +$labels['originalmessage'] = 'Original-Message'; + +$labels['editidents'] = 'Identitéiten editéieren'; +$labels['spellcheck'] = 'Orthographie'; +$labels['checkspelling'] = 'Orthographie kontrolléieren'; +$labels['resumeediting'] = 'Weider editéieren'; +$labels['revertto'] = 'Zréck bei'; + +$labels['attach'] = 'Drunhänken'; +$labels['attachments'] = 'Unhäng'; +$labels['upload'] = 'Eroplueden'; +$labels['uploadprogress'] = '$percent ($current vun $total)'; +$labels['close'] = 'Zoumaachen'; +$labels['messageoptions'] = 'Message-Optiounen...'; + +$labels['low'] = 'Niddreg'; +$labels['lowest'] = 'Am niddregsten'; +$labels['normal'] = 'Normal'; +$labels['high'] = 'Héich'; +$labels['highest'] = 'Am héchsten'; + +$labels['nosubject'] = '(kee Sujet)'; +$labels['showimages'] = 'Biller uweisen'; +$labels['alwaysshow'] = 'Biller vun $sender ëmmer uweisen'; +$labels['isdraft'] = 'Dëst ass e Brouillon.'; +$labels['andnmore'] = '$nr more...'; +$labels['togglemoreheaders'] = 'Méi Message-Headeren uweisen'; +$labels['togglefullheaders'] = 'Réi Message-Headeren an-/ausblenden'; + +$labels['htmltoggle'] = 'Text mat Formatéierungen'; +$labels['plaintoggle'] = 'Text ouni Formatéierungen'; +$labels['savesentmessagein'] = 'Dee verschéckte Message späicheren an'; +$labels['dontsave'] = 'net späicheren'; +$labels['maxuploadsize'] = 'Déi maximal erlaabte Fichiers-Gréisst ass $size'; + +$labels['addcc'] = 'CC dobäisetzen'; +$labels['addbcc'] = 'BCC dobäisetzen'; +$labels['addreplyto'] = '"Äntwert un" dobäisetzen'; +$labels['addfollowupto'] = '"Noverfollgung un" dobäisetzen'; + +// mdn +$labels['mdnrequest'] = 'De Sender vun dësem Message huet gefrot fir informéiert ze gi wann de Message gelies gëtt. Wëlls du de Sender informéieren?'; +$labels['receiptread'] = 'Empfanksbestätegung (gelies)'; +$labels['yourmessage'] = 'Dëst ass eng Empfanksbestätegung fir Äre Message.'; +$labels['receiptnote'] = 'Bemierkung: Dës Bestätegung bezeit just datt de Message beim Empfänger ugewise ginn ass. Et gëtt keng Garantie dass den Empfänger den Inhalt vum Message gelies oder verstanen huet.'; + +// address boook +$labels['name'] = 'Ganzen Numm'; +$labels['firstname'] = 'Virnumm'; +$labels['surname'] = 'Nonumm'; +$labels['middlename'] = 'Mëttelnumm'; +$labels['nameprefix'] = 'Präfix'; +$labels['namesuffix'] = 'Suffix'; +$labels['nickname'] = 'Spëtznumm'; +$labels['jobtitle'] = 'Job-Titel'; +$labels['department'] = 'Departement'; +$labels['gender'] = 'Geschlecht'; +$labels['maidenname'] = 'Meedechersnumm'; +$labels['email'] = 'E-Mail'; +$labels['phone'] = 'Telefon'; +$labels['address'] = 'Adress'; +$labels['street'] = 'Strooss'; +$labels['locality'] = 'Uertschaft'; +$labels['zipcode'] = 'Postleitzuel'; +$labels['region'] = 'Staat'; +$labels['country'] = 'Land'; +$labels['birthday'] = 'Gebuertsdatum'; +$labels['anniversary'] = 'Anniversaire'; +$labels['website'] = 'Websäit'; +$labels['instantmessenger'] = 'Instant-Messenger'; +$labels['notes'] = 'Notizen'; +$labels['male'] = 'männlech'; +$labels['female'] = 'weiblech'; +$labels['manager'] = 'Manager'; +$labels['assistant'] = 'Assistent'; +$labels['spouse'] = 'Liewenspartner'; +$labels['allfields'] = 'All d\'Felder'; +$labels['search'] = 'Sichen'; +$labels['advsearch'] = 'Avancéiert Sich'; +$labels['advanced'] = 'Avancéiert'; +$labels['other'] = 'Aneres'; + +$labels['typehome'] = 'Doheem'; +$labels['typework'] = 'Aarbecht'; +$labels['typeother'] = 'Aneres'; +$labels['typemobile'] = 'Mobil'; +$labels['typemain'] = 'Haapt'; +$labels['typehomefax'] = 'Fax Doheem'; +$labels['typeworkfax'] = 'Fax Aarbecht'; +$labels['typecar'] = 'Auto'; +$labels['typepager'] = 'Pager'; +$labels['typevideo'] = 'Video'; +$labels['typeassistant'] = 'Assistent'; +$labels['typehomepage'] = 'Websäit'; +$labels['typeblog'] = 'Blog'; +$labels['typeprofile'] = 'Profil'; + +$labels['addfield'] = 'Feld dobäisetzen...'; +$labels['addcontact'] = 'Neie Kontakt dobäisetzen'; +$labels['editcontact'] = 'Kontakt editéieren'; +$labels['contacts'] = 'Kontakter'; +$labels['contactproperties'] = 'Kontakt-Eegeschaften'; +$labels['personalinfo'] = 'Perséinlech Informatioun'; + +$labels['edit'] = 'Änneren'; +$labels['cancel'] = 'Ofbriechen'; +$labels['save'] = 'Späicheren'; +$labels['delete'] = 'Läschen'; +$labels['rename'] = 'Ëmbenennen'; +$labels['addphoto'] = 'Dobäisetzen'; +$labels['replacephoto'] = 'Ersetzen'; +$labels['uploadphoto'] = 'Foto eroplueden'; + +$labels['newcontact'] = 'Nei Kontakt-Kaart erstellen'; +$labels['deletecontact'] = 'Déi ausgewielte Kontakter läschen'; +$labels['composeto'] = 'Mail schreiwen un'; +$labels['contactsfromto'] = 'Kontakter $from bis $to vun $count'; +$labels['print'] = 'Drécke'; +$labels['export'] = 'Exportéieren'; +$labels['exportall'] = 'All exportéieren'; +$labels['exportsel'] = 'Déi ausgewielten exportéieren'; +$labels['exportvcards'] = 'Kontakter am vCard-Format exportéieren'; +$labels['newcontactgroup'] = 'Nei Kontakt-Grupp erstellen'; +$labels['grouprename'] = 'Grupp ëmbenennen'; +$labels['groupdelete'] = 'Grupp läschen'; +$labels['groupremoveselected'] = 'Ausgewielte Kontakter aus Grupp eraushuele'; + +$labels['previouspage'] = 'Säit virdru weisen'; +$labels['firstpage'] = 'Éischt Säit weisen'; +$labels['nextpage'] = 'Nächst Säit weisen'; +$labels['lastpage'] = 'Lescht Säit weisen'; + +$labels['group'] = 'Grup'; +$labels['groups'] = 'Gruppen'; +$labels['listgroup'] = 'Gruppe-Memberen oplëschten'; +$labels['personaladrbook'] = 'Perséinlech Adressen'; + +$labels['searchsave'] = 'Sich späicheren'; +$labels['searchdelete'] = 'Sich läschen'; + +$labels['import'] = 'Importéieren'; +$labels['importcontacts'] = 'Kontakter importéieren'; +$labels['importfromfile'] = 'Aus Fichier importéieren:'; +$labels['importtarget'] = 'Nei Kontakter an d\'Adressbuch setzen:'; +$labels['importreplace'] = 'Dat ganzt Adressbuch ersetzen'; +$labels['importdesc'] = 'Du kanns Kontakter aus engem existéierenden Adressbuch eroplueden.<br/>Mir ënnerstëtze momentan en Adress-Import vum <a href="http://en.wikipedia.org/wiki/VCard">vCard</a>- oder CSV (mat Komma getrennt)-Date-Format.'; +$labels['done'] = 'Erleedegt'; + +// settings +$labels['settingsfor'] = 'Astellunge fir'; +$labels['about'] = 'Iwwert'; +$labels['preferences'] = 'Astellungen'; +$labels['userpreferences'] = 'Benotzer-Astellungen'; +$labels['editpreferences'] = 'Benotzer-Astellungen änneren'; + +$labels['identities'] = 'Identitéiten'; +$labels['manageidentities'] = 'Identitéite fir dësen Account geréieren'; +$labels['newidentity'] = 'Nei Identitéit'; + +$labels['newitem'] = 'Neit Element'; +$labels['edititem'] = 'Element änneren'; + +$labels['preferhtml'] = 'HTML uweisen'; +$labels['defaultcharset'] = 'Standard Zeechesaz'; +$labels['htmlmessage'] = 'HTML-Message'; +$labels['messagepart'] = 'Deel'; +$labels['digitalsig'] = 'Digital Signatur'; +$labels['dateformat'] = 'Datums-Format'; +$labels['timeformat'] = 'Zäit-Format'; +$labels['prettydate'] = 'Schéin Daten'; +$labels['setdefault'] = 'Als standard definéieren'; +$labels['autodetect'] = 'Automatesch'; +$labels['language'] = 'Sprooch'; +$labels['timezone'] = 'Zäitzon'; +$labels['pagesize'] = 'Reie pro Säit'; +$labels['signature'] = 'Ënnerschrëft'; +$labels['dstactive'] = 'Summerzäit'; +$labels['showinextwin'] = 'Message an neier Fënster opmaache'; +$labels['composeextwin'] = 'An enger neier Fënster schreiwen'; +$labels['htmleditor'] = 'HTML-Messagë schreiwen'; +$labels['htmlonreply'] = 'bei Äntwert op e Message mat Formatéierungen'; +$labels['htmlonreplyandforward'] = 'bei Weiderleedung oder Äntwert op e Message mat Formatéierungen'; +$labels['htmlsignature'] = 'Formatéiert Ënnerschrëft'; +$labels['showemail'] = 'Email-Adress mat ganzem Numm uweisen'; +$labels['previewpane'] = 'Virschau-Panneau uweisen'; +$labels['skin'] = 'Opmaachung vum Interface'; +$labels['logoutclear'] = 'Poubelle beim Logout eidelmaachen'; +$labels['logoutcompact'] = 'Mailbox beim Logout eidelmaachen'; +$labels['uisettings'] = 'Benotzer-Interface'; +$labels['serversettings'] = 'Server-Astellungen'; +$labels['mailboxview'] = 'Mailbox-Usiicht'; +$labels['mdnrequests'] = 'Bei Ufro no Empfanksbestätegung'; +$labels['askuser'] = 'mech froen'; +$labels['autosend'] = 'Bestätegung schécken'; +$labels['autosendknown'] = 'Bestätegung u meng Kontakter schécken, anerefalls nofroen'; +$labels['autosendknownignore'] = 'Bestätegung u meng Kontakter schécken, anerefalls ignoréieren'; +$labels['ignore'] = 'ignoréieren'; +$labels['readwhendeleted'] = 'Beim Läschen de Message als gelies markéieren'; +$labels['flagfordeletion'] = 'De Message als "läschbar" markéieren amplaz en ze läschen'; +$labels['skipdeleted'] = 'Geläschte Messagen net uweisen'; +$labels['deletealways'] = 'Falls Messagen net an d\'Poubelle kënne geréckelt ginn, läsch se'; +$labels['deletejunk'] = 'Messagen am Spam-Dossier direkt läschen'; +$labels['showremoteimages'] = 'Biller an de Maile vun externe Serveren nolueden'; +$labels['fromknownsenders'] = 'vu bekannte Senderen'; +$labels['always'] = 'ëmmer'; +$labels['showinlineimages'] = 'Biller déi drunhänken ënnert dem Message uweisen'; +$labels['autosavedraft'] = 'Brouillon automatesch späicheren'; +$labels['everynminutes'] = 'all $n Minutt(en)'; +$labels['refreshinterval'] = 'Frësch lueden (nei Messagen ofruffen, etc.)'; +$labels['never'] = 'ni'; +$labels['immediately'] = 'direkt'; +$labels['messagesdisplaying'] = 'Messagen uweisen'; +$labels['messagescomposition'] = 'Messagë schreiwen'; +$labels['mimeparamfolding'] = 'Nimm vun den Unhäng'; +$labels['2231folding'] = 'Kompletten RFC 2231 (Thunderbird)'; +$labels['miscfolding'] = 'RFC 2047/2231 (Microsoft Outlook)'; +$labels['2047folding'] = 'Kompletten RFC 2047 (anerer)'; +$labels['force7bit'] = 'MIME-Kodéierung fir 8-Bit-Zeeche benotzen'; +$labels['advancedoptions'] = 'Avancéiert Optiounen'; +$labels['focusonnewmessage'] = 'Browser-Fënster fokusséiere wann en neie Message ukënnt'; +$labels['checkallfolders'] = 'Nei Messagen an allen Dossieren opruffen'; +$labels['displaynext'] = 'Nom Réckelen/Läsche vun engem Message deen nächsten uweisen'; +$labels['defaultfont'] = 'Standard-Schrëft fir e Message mat Formatéierungen'; +$labels['mainoptions'] = 'Haapt-Optiounen'; +$labels['browseroptions'] = 'Browser-Optiounen'; +$labels['section'] = 'Beräich'; +$labels['maintenance'] = 'Maintenance'; +$labels['newmessage'] = 'Neie Message'; +$labels['signatureoptions'] = 'Optioune vun der Ënnerschrëft'; +$labels['whenreplying'] = 'Bei enger Äntwert'; +$labels['replyempty'] = 'den Original-Message net zitéieren'; +$labels['replytopposting'] = 'neie Message iwwert dem Zitat ufänken'; +$labels['replybottomposting'] = 'neie Message ënnert dem Zitat ufänken'; +$labels['replyremovesignature'] = 'Bei enger Äntwert d\'Original-Ënnerschrëft aus dem Message huelen'; +$labels['autoaddsignature'] = 'Ënnerschrëft automatesch drasetzen'; +$labels['newmessageonly'] = 'just bei neie Messagen'; +$labels['replyandforwardonly'] = 'just bei Äntwerten a Weiderleedungen'; +$labels['insertsignature'] = 'Ënnerschrëft drasetzen'; +$labels['previewpanemarkread'] = 'D\'Messagen an der Virschau als gelies markéieren'; +$labels['afternseconds'] = 'no $n Sekonnen'; +$labels['reqmdn'] = 'Ëmmer eng Empfanksbestätegung ufroen'; +$labels['reqdsn'] = 'Ëmmer eng Empfanks-Status-Meldung ufroen'; +$labels['replysamefolder'] = 'Äntwert an de selweschten Dossier setze wéi de Message op dee geäntwert gëtt'; +$labels['defaultabook'] = 'Standard Adress-Buch'; +$labels['autocompletesingle'] = 'Alternativ Email-Adressen bei der automatescher Vervollstänneung iwwersprangen'; +$labels['listnamedisplay'] = 'Kontakter oplëschten als'; +$labels['spellcheckbeforesend'] = 'Orthographie kontrolléieren bevir de Message verschéckt gëtt'; +$labels['spellcheckoptions'] = 'Orthographie-Korrektur-Optiounen'; +$labels['spellcheckignoresyms'] = 'Wierder mat Symboler ignoréieren'; +$labels['spellcheckignorenums'] = 'Wierder mat Zuelen ignoréieren'; +$labels['spellcheckignorecaps'] = 'Wierder mat just Groussbuschtawen ignoréieren'; +$labels['addtodict'] = 'An den Dictionnaire setzen'; +$labels['mailtoprotohandler'] = 'Protokoll-Handhaber fir "mailto:"-Links registréieren'; +$labels['standardwindows'] = 'Popup-Fënstere wéi normal Fënstere behandelen'; +$labels['forwardmode'] = 'Messagë-Weiderleedung'; +$labels['inline'] = 'am Message'; +$labels['asattachment'] = 'als Unhank'; + +$labels['folder'] = 'Dossier'; +$labels['folders'] = 'Dossieren'; +$labels['foldername'] = 'Dossiersnumm'; +$labels['subscribed'] = 'Abonnéiert'; +$labels['messagecount'] = 'Messagen'; +$labels['create'] = 'Erstellen'; +$labels['createfolder'] = 'Neien Dossier erstellen'; +$labels['managefolders'] = 'Dossieren geréieren'; +$labels['specialfolders'] = 'Speziell Dossieren'; +$labels['properties'] = 'Astellungen'; +$labels['folderproperties'] = 'Dossiers-Astellungen'; +$labels['parentfolder'] = 'Elteren-Dossier'; +$labels['location'] = 'Plaz'; +$labels['info'] = 'Informatioun'; +$labels['getfoldersize'] = 'Klick fir d\'Dossiers-Gréisst ze kréien'; +$labels['changesubscription'] = 'Klick fir den Abonnement ze änneren'; +$labels['foldertype'] = 'Dossiers-Typ'; +$labels['personalfolder'] = 'Privaten Dossier'; +$labels['otherfolder'] = 'Dossier vun anerem Benotzer'; +$labels['sharedfolder'] = 'Ëffentlechen Dossier'; + +$labels['sortby'] = 'Sortéieren no'; +$labels['sortasc'] = 'Opsteigend sortéieren'; +$labels['sortdesc'] = 'Ofsteigend sortéieren'; +$labels['undo'] = 'Réckgängeg maachen'; + +$labels['installedplugins'] = 'Installéiert Plugins'; +$labels['plugin'] = 'Plugin'; +$labels['version'] = 'Versioun'; +$labels['source'] = 'Source'; +$labels['license'] = 'Lizenz'; +$labels['support'] = 'Support ufroen'; + +// units +$labels['B'] = 'B'; +$labels['KB'] = 'kB'; +$labels['MB'] = 'MB'; +$labels['GB'] = 'GB'; + +// character sets +$labels['unicode'] = 'Unicode'; +$labels['english'] = 'Englesch'; +$labels['westerneuropean'] = 'West-Europäesch'; +$labels['easterneuropean'] = 'Ost-Europäesch'; +$labels['southeasterneuropean'] = 'Süd-Ost-Europäesch'; +$labels['baltic'] = 'Baltesch'; +$labels['cyrillic'] = 'Kyrilesch'; +$labels['arabic'] = 'Arabesch'; +$labels['greek'] = 'Griechesch'; +$labels['hebrew'] = 'Häbräesch'; +$labels['turkish'] = 'Türkesch'; +$labels['nordic'] = 'Nordesch'; +$labels['thai'] = 'Thai'; +$labels['celtic'] = 'Keltesch'; +$labels['vietnamese'] = 'Vietnamesesch'; +$labels['japanese'] = 'Japanesch'; +$labels['korean'] = 'Koreanesch'; +$labels['chinese'] = 'Chinesesch'; + +?> diff --git a/program/localization/lb_LU/messages.inc b/program/localization/lb_LU/messages.inc new file mode 100644 index 000000000..5599f227b --- /dev/null +++ b/program/localization/lb_LU/messages.inc @@ -0,0 +1,176 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | localization/<lang>/messages.inc | + | | + | Localization file of the Roundcube Webmail client | + | Copyright (C) 2005-2013, The Roundcube Dev Team | + | | + | Licensed under the GNU General Public License version 3 or | + | any later version with exceptions for skins & plugins. | + | See the README file for a full license statement. | + | | + +-----------------------------------------------------------------------+ + + For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/messages/ +*/ + +$messages = array(); +$messages['errortitle'] = 'Ee Feeler ass opgetrueden!'; +$messages['loginfailed'] = 'Login feelgeschloen.'; +$messages['cookiesdisabled'] = 'Däi Browser acceptéiert keng Cookien.'; +$messages['sessionerror'] = 'Deng Sessioun ass ongëlteg oder verfall.'; +$messages['storageerror'] = 'D\'Verbindung mam Späicher-Server ass feelgeschloen.'; +$messages['servererror'] = 'Server-Feeler!'; +$messages['servererrormsg'] = 'Server-Feeler: $msg'; +$messages['dberror'] = 'Datebank-Feeler!'; +$messages['requesttimedout'] = 'D\'Ufro huet ze laang gedauert'; +$messages['errorreadonly'] = 'D\'Operatioun kann net ofgeschloss ginn. Den Dossier ass schreifgeschützt.'; +$messages['errornoperm'] = 'D\'Operatioun kann net ofgeschloss ginn. Zougrëff verweigert.'; +$messages['erroroverquota'] = 'D\'Operatioun konnt net ausgefouert ginn. Et ass net méi genuch Plaz um Disk.'; +$messages['erroroverquotadelete'] = 'Et ass net méi genuch Plaz um Disk. Benotz Shift+Delete fir e message ze läschen.'; +$messages['invalidrequest'] = 'Ongëlteg Ufro! Et goufe keng Date gespäichert.'; +$messages['invalidhost'] = 'Ongëltege Server-Numm.'; +$messages['nomessagesfound'] = 'Keng Messagen an der Mailbox fonnt.'; +$messages['loggedout'] = 'Du hues dech erfollegräich ofgemellt. Äddi!'; +$messages['mailboxempty'] = 'D\'Mailbox ass eidel.'; +$messages['refreshing'] = 'Lueden nei...'; +$messages['loading'] = 'Lueden...'; +$messages['uploading'] = 'Fichier gëtt eropgelueden...'; +$messages['uploadingmany'] = 'Fichiere ginn eropgelueden...'; +$messages['loadingdata'] = 'Date gi gelueden..'; +$messages['checkingmail'] = 'Nei Messagë ginn ofgeruff...'; +$messages['sendingmessage'] = 'Message gëtt geschéckt...'; +$messages['messagesent'] = 'Message erfollegräich verschéckt.'; +$messages['savingmessage'] = 'Message gëtt gespäichert...'; +$messages['messagesaved'] = 'Message als Brouillon gespäichert.'; +$messages['successfullysaved'] = 'Erfollegräich gespäichert.'; +$messages['addedsuccessfully'] = 'Kontakt erfollegräich an d\'Adressbuch gesat.'; +$messages['contactexists'] = 'Et existéiert schon e Kontakt mat der selweschter E-Mail-Adress.'; +$messages['contactnameexists'] = 'Et existéiert schon e Kontakt mam selweschten Numm.'; +$messages['blockedimages'] = 'Fir deng Privatsphär ze schütze, gi Biller vun externe Serveren an dësem Message net gelueden.'; +$messages['encryptedmessage'] = 'Dëst ass e verschlësselte Message a kann net ugewise ginn. Et deet eis Leed!'; +$messages['nocontactsfound'] = 'Keng Kontakter fonnt.'; +$messages['contactnotfound'] = 'Den ugefrotene Kontakt gouf net fonnt.'; +$messages['contactsearchonly'] = 'Gëff e puer Sichbegrëffer a fir Kontakter ze fannen'; +$messages['sendingfailed'] = 'De Message konnt net verschéckt ginn.'; +$messages['senttooquickly'] = 'Waart wann ech gelift $sec Sekonn(en) bevir s du de Message verschécks. '; +$messages['errorsavingsent'] = 'Beim Späichere vum verschéckte Message ass e Feeler opgetrueden'; +$messages['errorsaving'] = 'Beim Späicheren ass e Feeler opgetrueden.'; +$messages['errormoving'] = 'D\'Messagë konnten net verréckelt ginn.'; +$messages['errorcopying'] = 'D\'Messagë konnten net kopéiert ginn.'; +$messages['errordeleting'] = 'D\'Messagë konnten net geläscht ginn.'; +$messages['errormarking'] = 'D\'Messagë konnten net markéiert ginn.'; +$messages['deletecontactconfirm'] = 'Wëlls du wierklech déi ausgewielte Kontakter läschen?'; +$messages['deletegroupconfirm'] = 'Wëlls du wierklech déi ausgewielte Gruppe läschen?'; +$messages['deletemessagesconfirm'] = 'Wëlls du wierklech déi ausgewielte Messagë läschen?'; +$messages['deletefolderconfirm'] = 'Wëlls du dësen Dossier wierklech läschen?'; +$messages['purgefolderconfirm'] = 'Wëlls du wierklech all d\'Messagen an dësem Dossier läschen?'; +$messages['contactdeleting'] = 'Kontakter gi geläscht...'; +$messages['groupdeleting'] = 'Grupp gëtt geläscht...'; +$messages['folderdeleting'] = 'Dossier gëtt geläscht...'; +$messages['foldermoving'] = 'Dossier gëtt geréckelt...'; +$messages['foldersubscribing'] = 'Dossier gëtt abonnéiert...'; +$messages['folderunsubscribing'] = 'Dossier gëtt desabonnéiert...'; +$messages['formincomplete'] = 'De Formular war net komplett ausgefëlt.'; +$messages['noemailwarning'] = 'Gëff w.e.gl eng gëlteg Email-Adress an.'; +$messages['nonamewarning'] = 'Gëff w.e.gl en Numm an.'; +$messages['nopagesizewarning'] = 'Gëff w.e.gl eng Säitegréisst an.'; +$messages['nosenderwarning'] = 'Gëff w.e.gl d\'Adress vum Ofsender an.'; +$messages['norecipientwarning'] = 'Gëff w.e.gl op mannst een Empfänger an.'; +$messages['nosubjectwarning'] = 'D\'Feld "Sujet" ass eidel. Wëlls du elo eent uginn?'; +$messages['nobodywarning'] = 'Soll dëse Message ouni Text verschéckt ginn?'; +$messages['notsentwarning'] = 'De Message gouf net verschéckt. Wëlls du e verwerfen?'; +$messages['noldapserver'] = 'Wiel w.e.gl en LDAP-Server fir d\'Sich aus.'; +$messages['nosearchname'] = 'Gëff w.e.gl en Numm oder eng E-Mail-Adress fir de Kontakt an.'; +$messages['notuploadedwarning'] = 'Net all d\'Unhäng goufen eropgelueden. Waart w.e.gl e Moment oder briech den Upload of.'; +$messages['searchsuccessful'] = '$nr Messagë fonnt.'; +$messages['contactsearchsuccessful'] = '$nr Kontakter fonnt.'; +$messages['searchnomatch'] = 'D\'Sich huet keng Treffer bruecht.'; +$messages['searching'] = 'Sichen...'; +$messages['checking'] = 'Kontrolléieren...'; +$messages['nospellerrors'] = 'Et goufe keng Schreiffeeler fonnt.'; +$messages['folderdeleted'] = 'Dossier erfollegräich geläscht.'; +$messages['foldersubscribed'] = 'Dossier erfollegräich abonnéiert.'; +$messages['folderunsubscribed'] = 'Dossier erfollegräich desabonnéiert.'; +$messages['folderpurged'] = 'Dossier erfollegräich eidelgemaach.'; +$messages['folderexpunged'] = 'Dossier erfollegräich kompaktéiert.'; +$messages['deletedsuccessfully'] = 'Erfollegräich geläscht.'; +$messages['converting'] = 'Formatéierunge gi geläscht...'; +$messages['messageopenerror'] = 'Message konnt net vum Server geluede ginn.'; +$messages['fileuploaderror'] = 'Upload vum Fichier feelgeschloen.'; +$messages['filesizeerror'] = 'Den eropgeluedene Fichier ass méi grouss wéi déi maximal erlaabte Gréisst vun $size.'; +$messages['copysuccess'] = 'Et goufen erfollegräich $nr Kontakter kopéiert.'; +$messages['movesuccess'] = 'Et goufen erfollegräich $nr Kontakter geréckelt.'; +$messages['copyerror'] = 'Konnt d\'Kontakter net kopéieren'; +$messages['moveerror'] = 'Konnt d\'Kontakter net réckelen.'; +$messages['sourceisreadonly'] = 'D\'Adresse-Quell ass schreifgeschützt.'; +$messages['errorsavingcontact'] = 'D\'Kontakt-Adress konnt net gespäichert ginn.'; +$messages['movingmessage'] = 'Messagë gi geréckelt...'; +$messages['copyingmessage'] = 'Messagë gi kopéiert...'; +$messages['copyingcontact'] = 'Kontakter gi kopéiert...'; +$messages['movingcontact'] = 'Kontakter gi geréckelt...'; +$messages['deletingmessage'] = 'Messagë gi geläscht...'; +$messages['markingmessage'] = 'Messagë gi markéiert...'; +$messages['addingmember'] = 'Kontakter ginn an d\'grupp gesat...'; +$messages['removingmember'] = 'Kontakter ginn aus der Grupp erausgeholl...'; +$messages['receiptsent'] = 'Empfanksbestätegung erfollegräich verschéckt.'; +$messages['errorsendingreceipt'] = 'Konnt d\'Bestätegung net verschécken.'; +$messages['deleteidentityconfirm'] = 'Wëlls du dës Identitéit wierklech läschen?'; +$messages['nodeletelastidentity'] = 'Du kanns dës Identitéit net läschen, well et deng lescht ass.'; +$messages['forbiddencharacter'] = 'Den Numm vum Dossier enthält verbueden Zeechen.'; +$messages['selectimportfile'] = 'Wuel w.e.gl e Fichier aus fir eropzelueden.'; +$messages['addresswriterror'] = 'Dat ausgewieltent Adressbucht ass schreifgeschützt.'; +$messages['contactaddedtogroup'] = 'Kontakter erfollegräich an d\'Grupp gesat.'; +$messages['contactremovedfromgroup'] = 'Kontakter erfollegräich aus der Grupp erausgeholl.'; +$messages['nogroupassignmentschanged'] = 'Keng Gruppen-Zouuerdnung geännert.'; +$messages['importwait'] = 'Import leeft, ee Moment w.e.gl...'; +$messages['importformaterror'] = 'Import feelgeschloen! Den eropgeluedene Fichier ass kee gëltegen Date-Fichier.'; +$messages['importconfirm'] = '<b>$inserted Kontakter erfollegräich importéiert</b>'; +$messages['importconfirmskipped'] = '<b>$skipped existéierend Anträg iwwersprongen</b>'; +$messages['importmessagesuccess'] = 'Erfollegräich $nr Messagen importéiert'; +$messages['importmessageerror'] = 'Import feelgeschloen! Den eropgeluedene Fichier ass kee gëltege Message oder kee Mailbox-Fichier.'; +$messages['opnotpermitted'] = 'Operatioun net zougelooss!'; +$messages['nofromaddress'] = 'An der ausgewieltener Identitéit feelt d\'E-Mail-Adress.'; +$messages['editorwarning'] = 'Bei engem Wiessel op den Text-Editor ginn all d\'Formatéierunge verluer. Wëlls du sécher weidermaachen?'; +$messages['httpreceivedencrypterror'] = 'E fatale Konfiguratiouns-Feeler ass opgetrueden. Kontaktéier w.e.gl. den Administrator esou séier ewéi méiglech. <b>Däi Message kann net geschéckt ginn.</b> '; +$messages['smtpconnerror'] = 'SMTP-Feeler ($code): Et konnt keng Verbindung mam Server hirgestallt ginn.'; +$messages['smtpautherror'] = 'SMTP-Feeler ($code): Authentifizéierung feelgeschloen.'; +$messages['smtpfromerror'] = 'SMTP-Feeler ($code): Den Ofsender "$from" konnt net gesat ginn ($msg).'; +$messages['smtptoerror'] = 'SMTP-Feeler ($code): Den Empfänger "$to" konnt net dobäigesat ginn ($msg).'; +$messages['smtprecipientserror'] = 'SMTP-Feeler: D\'Empfänger-Lëscht kann net verschafft ginn.'; +$messages['smtperror'] = 'SMTP-Feeler: $msg'; +$messages['emailformaterror'] = 'Ongëlteg E-Mail-Adress: $email'; +$messages['toomanyrecipients'] = 'Zevill Empfänger. Reduzéier d\'Zuel vun den Empfänger op $max.'; +$messages['maxgroupmembersreached'] = 'D\'Unzuel vu Gruppememberen iwwersteigt de Maximum vun $max.'; +$messages['internalerror'] = 'En interne Feeler ass opgetrueden. Probéier w.e.gl nach eng Kéier.'; +$messages['contactdelerror'] = 'Kontakter konnten net geläscht ginn.'; +$messages['contactdeleted'] = 'Kontakter erfollegräich geläscht.'; +$messages['contactrestoreerror'] = 'Déi geläschte Kontakter konnten net recuperéiert ginn.'; +$messages['contactrestored'] = 'Kontakter erfollegräich recuperéiert.'; +$messages['groupdeleted'] = 'Grupp erfollegräich geläscht.'; +$messages['grouprenamed'] = 'Grupp erfollegräich ëmbenannt.'; +$messages['groupcreated'] = 'Grupp erfollegräich creéiert.'; +$messages['savedsearchdeleted'] = 'Déi gespäicherte Sich gouf erfollegräich geläscht.'; +$messages['savedsearchdeleteerror'] = 'Déi gespäicherte Sich konnt net geläscht ginn.'; +$messages['savedsearchcreated'] = 'Déi gespäicherte Sich gouf erfollegräich erstallt.'; +$messages['savedsearchcreateerror'] = 'Déi gespäicherte Sich konnt net erstallt ginn.'; +$messages['messagedeleted'] = 'Messagen erfollegräich geläscht.'; +$messages['messagemoved'] = 'Messagen erfollegräich geréckelt.'; +$messages['messagecopied'] = 'Messagen erfollegräich kopéiert.'; +$messages['messagemarked'] = 'Messagen erfollegräich markéiert.'; +$messages['autocompletechars'] = 'Gëff e mimumum vun $min Zeechen u fir déi automatesch Vervollstänegung.'; +$messages['autocompletemore'] = 'Et goufe méi passend Treffer fonnt. Tipp w.e.gl. nach e puer Buschtawe méi.'; +$messages['namecannotbeempty'] = 'Den Numm kann net eidel sinn.'; +$messages['nametoolong'] = 'Den Numm ass ze laang.'; +$messages['folderupdated'] = 'Dossier erfollegräich aktualiséiert.'; +$messages['foldercreated'] = 'Dossier erfollegräich ugeluecht.'; +$messages['invalidimageformat'] = 'Kee gëltegt Bild-Format'; +$messages['mispellingsfound'] = 'Et goufe Schreiffeeler am Message fonnt.'; +$messages['parentnotwritable'] = 'Den Dossier konnt net am ausgewielten Dossier erstallt oder an den Dossier erageréckelt ginn. Keng Zougrëffsrechter.'; +$messages['messagetoobig'] = 'Den Messagen-Deel ass ze grouss fir verschafft ze ginn.'; +$messages['attachmentvalidationerror'] = 'WARNUNG! Dësen Unhank ass verdächteg well den tatsächlechen Typ vum Fichier net mam Typ deen am Message deklaréiert ass iwwertenee stëmmt. Falls du dem Ofsender net traus sollts du den Unhank net am Browser opmaache well e béisaartegen Inhalt enthaale kéint.<br/><br/><em>Erwaart: $expected; fonnt: $detected</em>'; +$messages['noscriptwarning'] = 'Warnung: Dëse Webmail brauch JavaScript! Fir de Service benotzen ze kënnen, aktivéier w.e.gl JavaScript an denge Browser-Astellungen.'; + +?> diff --git a/program/localization/lt_LT/labels.inc b/program/localization/lt_LT/labels.inc index 6398a3683..31cb44d27 100644 --- a/program/localization/lt_LT/labels.inc +++ b/program/localization/lt_LT/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'JuodraÅ¡Äiai'; $labels['sent'] = 'IÅ¡siųsti laiÅ¡kai'; $labels['trash'] = 'Å iukÅ¡linÄ—'; $labels['junk'] = 'Brukalas'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Tema'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'SÄ…raÅ¡o rodymo veiksena'; $labels['folderactions'] = 'Veiksmai su aplankais…'; $labels['compact'] = 'Suglaudinti'; $labels['empty'] = 'IÅ¡tuÅ¡tinti'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Disko naudojimas'; $labels['unknown'] = 'nežinomas'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'AtÅ¡aukti paieÅ¡kÄ…'; $labels['searchmod'] = 'PaieÅ¡kos modifikatoriai'; $labels['msgtext'] = 'Visas laiÅ¡kas'; $labels['body'] = 'LaiÅ¡ko tekstas'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Atverti naujame lange'; $labels['emlsave'] = 'Parsisiųsti (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Rodyti paskutinį puslapį'; $labels['group'] = 'GrupÄ—'; $labels['groups'] = 'GrupÄ—s'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Asmeniniai adresai'; $labels['searchsave'] = 'Ä®raÅ¡yti kaip radinių aplankÄ…'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Nepaisyti žodžių su skaitmenimis'; $labels['spellcheckignorecaps'] = 'Nepaisyti žodžių vien iÅ¡ didžiųjų raidžių'; $labels['addtodict'] = 'Ä®traukti į žodynÄ…'; $labels['mailtoprotohandler'] = 'Užregistruoti svetainÄ™ kaip dirbanÄiÄ… su „mailto:“ saitais'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'LaiÅ¡kų persiuntimo bÅ«das'; $labels['inline'] = 'kaip citatÄ…'; $labels['asattachment'] = 'kaip priedas'; diff --git a/program/localization/lv_LV/labels.inc b/program/localization/lv_LV/labels.inc index 7d4de2564..0fe5b0faf 100644 --- a/program/localization/lv_LV/labels.inc +++ b/program/localization/lv_LV/labels.inc @@ -23,50 +23,51 @@ $labels['welcome'] = 'Esiet laipni lÅ«gti $product'; $labels['username'] = 'LietotÄjvÄrds'; $labels['password'] = 'Parole'; $labels['server'] = 'Serveris'; -$labels['login'] = 'PieslÄ“gties'; +$labels['login'] = 'AutorizÄ“ties'; // taskbar -$labels['logout'] = 'AtslÄ“gties'; +$labels['logout'] = 'Iziet'; $labels['mail'] = 'E-pasts'; -$labels['settings'] = 'PersonÄ«gie iestatÄ«jumi'; +$labels['settings'] = 'IestatÄ«jumi'; $labels['addressbook'] = 'AdreÅ¡u grÄmata'; // mailbox names $labels['inbox'] = 'IenÄkoÅ¡Äs'; $labels['drafts'] = 'Uzmetumi'; $labels['sent'] = 'NosÅ«tÄ«tÄs'; -$labels['trash'] = 'Miskaste'; +$labels['trash'] = 'PapÄ«rgrozs'; $labels['junk'] = 'MÄ“stules'; +$labels['show_real_foldernames'] = 'SistÄ“mas mapÄ“m rÄdÄ«t Ä«stos nosaukumus'; // message listing $labels['subject'] = 'Temats'; $labels['from'] = 'No'; -$labels['sender'] = 'Sender'; +$labels['sender'] = 'SÅ«tÄ«tÄjs'; $labels['to'] = 'Kam'; $labels['cc'] = 'Cc'; $labels['bcc'] = 'Bcc'; -$labels['replyto'] = 'Reply-To'; -$labels['followupto'] = 'Followup-To'; +$labels['replyto'] = 'AtbildÄ“t-Uz'; +$labels['followupto'] = 'Sekot-Uz'; $labels['date'] = 'Datums'; $labels['size'] = 'IzmÄ“rs'; $labels['priority'] = 'PrioritÄte'; $labels['organization'] = 'Uzņēmums'; $labels['readstatus'] = 'IzlasÄ«Å¡anas statuss'; -$labels['listoptions'] = 'List options...'; +$labels['listoptions'] = 'VÄ“stuļu saraksta attÄ“loÅ¡anas iestatÄ«jumi...'; $labels['mailboxlist'] = 'Mapes'; $labels['messagesfromto'] = 'VÄ“stules $from lÄ«dz $to no $count'; $labels['threadsfromto'] = 'Vijumi $from lÄ«dz $to no $count'; -$labels['messagenrof'] = '$nr. vÄ“stule no $count'; -$labels['fromtoshort'] = '$from – $to of $count'; +$labels['messagenrof'] = '$nr. vÄ“stule no $count'; +$labels['fromtoshort'] = '$from – $to no $count'; $labels['copy'] = 'KopÄ“t'; $labels['move'] = 'PÄrvietot'; -$labels['moveto'] = 'pÄrvietot uz...'; +$labels['moveto'] = 'PÄrvietot uz...'; $labels['download'] = 'lejupielÄdÄ“t'; -$labels['open'] = 'Open'; -$labels['showattachment'] = 'Show'; -$labels['showanyway'] = 'Show it anyway'; +$labels['open'] = 'AtvÄ“rt'; +$labels['showattachment'] = 'RÄdÄ«t'; +$labels['showanyway'] = 'Vienalga rÄdÄ«t'; $labels['filename'] = 'Faila nosaukums'; $labels['filesize'] = 'Faila izmÄ“rs'; @@ -122,77 +123,78 @@ $labels['longdec'] = 'Decembris'; $labels['today'] = 'Å odien'; // toolbar buttons -$labels['refresh'] = 'Refresh'; -$labels['checkmail'] = 'PÄrbaudÄ«t pastu'; +$labels['refresh'] = 'Atjaunot'; +$labels['checkmail'] = 'PÄrbaudÄ«t e-pastu'; $labels['compose'] = 'RakstÄ«t vÄ“stuli'; $labels['writenewmessage'] = 'RakstÄ«t jaunu vÄ“stuli'; -$labels['reply'] = 'Reply'; -$labels['replytomessage'] = 'AtbildÄ“t'; -$labels['replytoallmessage'] = 'AtbildÄ“t sÅ«tÄ«tÄjam un visiem saņēmÄ“jiem'; +$labels['reply'] = 'AtbildÄ“t'; +$labels['replytomessage'] = 'AtbildÄ“t sÅ«tÄ«tÄjam'; +$labels['replytoallmessage'] = 'AtbildÄ“t sÅ«tÄ«tÄjam vai listei un visiem adresÄtiem'; $labels['replyall'] = 'AtbildÄ“t visiem'; $labels['replylist'] = 'AtbildÄ“t listei'; -$labels['forward'] = 'Forward'; +$labels['forward'] = 'PÄrsÅ«tÄ«t'; $labels['forwardinline'] = 'PÄrsÅ«tÄ«t iekļaujot vÄ“stulÄ“'; $labels['forwardattachment'] = 'PÄrsÅ«tÄ«t kÄ pielikumu'; $labels['forwardmessage'] = 'PÄrsÅ«tÄ«t vÄ“stuli'; $labels['deletemessage'] = 'DzÄ“st vÄ“stuli'; -$labels['movemessagetotrash'] = 'PÄrvietot vÄ“stuli uz miskasti'; -$labels['printmessage'] = 'izdrukÄt'; +$labels['movemessagetotrash'] = 'PÄrvietot vÄ“stuli uz papÄ«rgrozu'; +$labels['printmessage'] = 'IzdrukÄt Å¡o vÄ“stuli'; $labels['previousmessage'] = 'ParÄdÄ«t iepriekÅ¡Ä“jo vÄ“stuli'; $labels['firstmessage'] = 'ParÄdÄ«t pirmo vÄ“stuli'; $labels['nextmessage'] = 'ParÄdÄ«t nÄkamo vÄ“stuli'; $labels['lastmessage'] = 'ParÄdÄ«t pÄ“dÄ“jo vÄ“stuli'; $labels['backtolist'] = 'Atpakaļ uz vÄ“stuļu sarakstu'; -$labels['viewsource'] = 'parÄdÄ«t pirmtekstu'; -$labels['mark'] = 'Mark'; -$labels['markmessages'] = 'MarÄ·Ä“t vÄ“stules kÄ:'; -$labels['markread'] = 'lasÄ«tas'; -$labels['markunread'] = 'nelasÄ«tas'; -$labels['markflagged'] = 'iezÄ«mÄ“tas'; -$labels['markunflagged'] = 'neiezÄ«mÄ“tas'; -$labels['moreactions'] = 'Citas darbÄ«bas...'; -$labels['more'] = 'More'; -$labels['back'] = 'Back'; -$labels['options'] = 'Options'; - -$labels['select'] = 'IezÄ«mÄ“t'; -$labels['all'] = 'visas'; -$labels['none'] = 'Neviens'; +$labels['viewsource'] = 'ParÄdÄ«t pirmtekstu'; +$labels['mark'] = 'AtzÄ«mÄ“t'; +$labels['markmessages'] = 'AtzÄ«mÄ“t vÄ“stules kÄ:'; +$labels['markread'] = 'KÄ lasÄ«tas'; +$labels['markunread'] = 'KÄ nelasÄ«tas'; +$labels['markflagged'] = 'KÄ atÄ«mÄ“tas'; +$labels['markunflagged'] = 'KÄ neatzÄ«mÄ“tas'; +$labels['moreactions'] = 'Papildus darbÄ«bas...'; +$labels['more'] = 'VairÄk'; +$labels['back'] = 'Atpakaļ'; +$labels['options'] = 'Opcijas'; + +$labels['select'] = 'AtzÄ«mÄ“t'; +$labels['all'] = 'Visas'; +$labels['none'] = 'Nevienu'; $labels['currpage'] = 'PaÅ¡reizÄ“jÄ lapa'; -$labels['unread'] = 'nelasÄ«tÄs'; -$labels['flagged'] = 'iezÄ«mÄ“tÄs'; -$labels['unanswered'] = 'neatbildÄ“tÄs'; -$labels['withattachment'] = 'With attachment'; -$labels['deleted'] = 'dzÄ“stÄs'; -$labels['undeleted'] = 'Not deleted'; -$labels['invert'] = 'invertÄ“t'; +$labels['unread'] = 'NelasÄ«tÄs'; +$labels['flagged'] = 'AtzÄ«mÄ“tÄs'; +$labels['unanswered'] = 'NeatbildÄ“tÄs'; +$labels['withattachment'] = 'Ar pielikumu'; +$labels['deleted'] = 'DzÄ“stÄs'; +$labels['undeleted'] = 'Nav izdzÄ“stas'; +$labels['invert'] = 'PretÄ“ji'; $labels['filter'] = 'FiltrÄ“t'; -$labels['list'] = 'Saraksts'; -$labels['threads'] = 'Vijumi'; +$labels['list'] = 'RÄdÄ«t kÄ sarakstu'; +$labels['threads'] = 'RÄdÄ«t kÄ vijumus'; $labels['expand-all'] = 'IzvÄ“rst visus'; -$labels['expand-unread'] = 'IzvÄ“rst neizlasÄ«tos'; -$labels['collapse-all'] = 'SavÄ“rst visu'; -$labels['threaded'] = 'SavÄ«ts'; +$labels['expand-unread'] = 'IzvÄ“rst neizlasÄ«tÄs'; +$labels['collapse-all'] = 'Sakļaut visas'; +$labels['threaded'] = 'RÄdÄ«t vijumus'; $labels['autoexpand_threads'] = 'IzvÄ“rst vÄ“stuļu vijumus'; -$labels['do_expand'] = 'visiem vijumiem'; -$labels['expand_only_unread'] = 'tikai tad, ja ir neizlasÄ«tas vÄ“stules'; -$labels['fromto'] = 'SÅ«tÄ«tÄjs/SaņēmÄ“js'; -$labels['flag'] = 'IezÄ«mÄ“ts'; +$labels['do_expand'] = 'visus vijumus'; +$labels['expand_only_unread'] = 'tikai ar neizlasÄ«tÄm vÄ“stulÄ“m'; +$labels['fromto'] = 'No/Kam'; +$labels['flag'] = 'AtzÄ«mÄ“t'; $labels['attachment'] = 'Pielikums'; -$labels['nonesort'] = 'Neviens'; +$labels['nonesort'] = 'Neviena'; $labels['sentdate'] = 'NosÅ«tÄ«Å¡anas datums'; $labels['arrival'] = 'PienÄkÅ¡anas datums'; $labels['asc'] = 'augoÅ¡a'; $labels['desc'] = 'dilstoÅ¡a'; $labels['listcolumns'] = 'Saraksta kolonnas'; -$labels['listsorting'] = 'KÄrtot pÄ“c kolonnas'; +$labels['listsorting'] = 'KÄrtoÅ¡anas kolonnas'; $labels['listorder'] = 'KÄrtoÅ¡anas secÄ«ba'; -$labels['listmode'] = 'Saraksta režīms'; +$labels['listmode'] = 'AttÄ“loÅ¡anas veids'; $labels['folderactions'] = 'DarbÄ«bas ar mapÄ“m...'; -$labels['compact'] = 'saspiest'; -$labels['empty'] = 'iztukÅ¡ot'; +$labels['compact'] = 'Saspiest'; +$labels['empty'] = 'IztukÅ¡ot'; +$labels['importmessages'] = 'ImportÄ“t vÄ“stules'; $labels['quota'] = 'Kvota'; $labels['unknown'] = 'nezinÄms'; @@ -200,35 +202,36 @@ $labels['unlimited'] = 'neierobežots'; $labels['quicksearch'] = 'Ä€rtÄ meklÄ“Å¡ana'; $labels['resetsearch'] = 'AtstatÄ«t meklÄ“Å¡anu'; -$labels['searchmod'] = 'MeklÄ“t laukos:'; -$labels['msgtext'] = 'VÄ“stules tekstÄ'; -$labels['body'] = 'Body'; +$labels['searchmod'] = 'MeklÄ“Å¡anas modifikatori:'; +$labels['msgtext'] = 'VisÄ vÄ“stulÄ“'; +$labels['body'] = 'Pamatteksts'; +$labels['type'] = 'Tips'; -$labels['openinextwin'] = 'atvÄ“rt jaunÄ logÄ'; +$labels['openinextwin'] = 'AtvÄ“rt jaunÄ logÄ'; $labels['emlsave'] = 'lejupielÄdÄ“t (.eml)'; -$labels['changeformattext'] = 'Display in plain text format'; -$labels['changeformathtml'] = 'Display in HTML format'; +$labels['changeformattext'] = 'RÄdÄ«t kÄ neformatÄ“tu tekstu'; +$labels['changeformathtml'] = 'RÄdÄ«t kÄ HTML formatÄ“tu'; // message compose -$labels['editasnew'] = 'rediģēt kÄ jaunu'; -$labels['send'] = 'Send'; +$labels['editasnew'] = 'Rediģēt kÄ jaunu'; +$labels['send'] = 'SÅ«tÄ«t'; $labels['sendmessage'] = 'SÅ«tÄ«t vÄ“stuli'; -$labels['savemessage'] = 'SaglabÄt uzmetumu'; +$labels['savemessage'] = 'SaglabÄt kÄ uzmetumu'; $labels['addattachment'] = 'Pievienot failu'; $labels['charset'] = 'RakstzÄ«mju kopa'; $labels['editortype'] = 'Redaktora tips'; $labels['returnreceipt'] = 'SaņemÅ¡anas apstiprinÄjums'; -$labels['dsn'] = 'Atskaite par piegÄdi'; +$labels['dsn'] = 'PiegÄdes atskaite'; $labels['mailreplyintro'] = '$sender @ $date rakstÄ«ja:'; $labels['originalmessage'] = 'SÄkotnÄ“jÄ vÄ“stule'; $labels['editidents'] = 'Rediģēt identitÄtes'; -$labels['spellcheck'] = 'Spell'; +$labels['spellcheck'] = 'IzrunÄt'; $labels['checkspelling'] = 'PÄrbaudÄ«t pareizrakstÄ«bu'; $labels['resumeediting'] = 'TurpinÄt rediģēšanu'; $labels['revertto'] = 'Atgriezt uz'; -$labels['attach'] = 'Attach'; +$labels['attach'] = 'Pievienot'; $labels['attachments'] = 'Pielikumi'; $labels['upload'] = 'AugÅ¡upielÄdÄ“t'; $labels['uploadprogress'] = '$percent ($current no $total)'; @@ -241,13 +244,13 @@ $labels['normal'] = 'NormÄla'; $labels['high'] = 'Augsta'; $labels['highest'] = 'AugstÄkÄ'; -$labels['nosubject'] = '(no subject)'; +$labels['nosubject'] = '(bez tÄ“mas)'; $labels['showimages'] = 'RÄdÄ«t attÄ“lus'; -$labels['alwaysshow'] = 'VienmÄ“r rÄdÄ«t attÄ“lus no $sender'; +$labels['alwaysshow'] = 'VienmÄ“r rÄdÄ«t attÄ“lus vÄ“stulÄ“s, kuras sÅ«tÄ«jis $sender'; $labels['isdraft'] = 'Å is ir melnraksts.'; -$labels['andnmore'] = '$nr more...'; -$labels['togglemoreheaders'] = 'Show more message headers'; -$labels['togglefullheaders'] = 'Toggle raw message headers'; +$labels['andnmore'] = '$nr vairÄk...'; +$labels['togglemoreheaders'] = 'RÄdÄ«t galvenes papildus informÄciju'; +$labels['togglefullheaders'] = 'SlÄ“pt galvenes papildus informÄciju'; $labels['htmltoggle'] = 'HTML'; $labels['plaintoggle'] = 'VienkÄrÅ¡s teksts'; @@ -257,14 +260,14 @@ $labels['maxuploadsize'] = 'MaksimÄlais atļautais faila izmÄ“rs ir $size'; $labels['addcc'] = 'Pievienot Cc'; $labels['addbcc'] = 'Pievienot Bcc'; -$labels['addreplyto'] = 'Pievienot Reply-To'; +$labels['addreplyto'] = 'Pievienot AtbildÄ“t-Uz'; $labels['addfollowupto'] = 'Pievienot Followup-To'; // mdn -$labels['mdnrequest'] = 'Å Ä«s vÄ“stules sÅ«tÄ«tÄjs vÄ“las redzÄ“t vÄ“stules saņemÅ¡anas apstiprinÄjumu. Vai jÅ«s vÄ“laties nosÅ«tÄ«t apstiprinÄjumu?'; +$labels['mdnrequest'] = 'Å Ä«s vÄ“stules sÅ«tÄ«tÄjs vÄ“las redzÄ“t vÄ“stules saņemÅ¡anas apstiprinÄjumu. Vai JÅ«s vÄ“laties nosÅ«tÄ«t Å¡o apstiprinÄjumu?'; $labels['receiptread'] = 'SaņemÅ¡anas apstiprinÄjums'; -$labels['yourmessage'] = 'Å Ä«s ir jÅ«su vÄ“stules saņemÅ¡anas apstiprinÄjums'; -$labels['receiptnote'] = 'PiezÄ«me: Å Ä«s apsiprinÄjums nozÄ«mÄ“ tikai to, ka vÄ“stule tika parÄdÄ«ta uz saņēmÄja datora. Tas nenozÄ«mÄ“, ka saņēmÄ“js ir izlasÄ«jis vai izpratis vÄ“stules saturu.'; +$labels['yourmessage'] = 'Å is ir JÅ«su nosÅ«tÄ«tÄs vÄ“stules saņemÅ¡anas apstiprinÄjums'; +$labels['receiptnote'] = 'PiezÄ«me: Å is apsiprinÄjums nozÄ«mÄ“ tikai to, ka vÄ“stule tika parÄdÄ«ta uz saņēmÄja datora. Tas nenozÄ«mÄ“, ka saņēmÄ“js ir izlasÄ«jis vai sapratis vÄ“stules saturu.'; // address boook $labels['name'] = 'UzrÄdÄ«tais vÄrds'; @@ -273,33 +276,33 @@ $labels['surname'] = 'UzvÄrds'; $labels['middlename'] = 'Otrais vÄrds'; $labels['nameprefix'] = 'Prefikss'; $labels['namesuffix'] = 'Sufikss'; -$labels['nickname'] = 'Iesauka (nick)'; +$labels['nickname'] = 'SegvÄrds'; $labels['jobtitle'] = 'Amats'; $labels['department'] = 'Nodaļa'; $labels['gender'] = 'Dzimums'; -$labels['maidenname'] = 'PirmslaulÄ«bu uzvÄrds'; +$labels['maidenname'] = 'PirmslaulÄ«bas uzvÄrds'; $labels['email'] = 'E-pasts'; $labels['phone'] = 'TÄlrunis'; $labels['address'] = 'Adrese'; $labels['street'] = 'Iela'; $labels['locality'] = 'PilsÄ“ta'; -$labels['zipcode'] = 'Pasta kods'; +$labels['zipcode'] = 'Pasta indekss'; $labels['region'] = 'Novads'; $labels['country'] = 'PilsÄ“ta'; $labels['birthday'] = 'DzimÅ¡anas diena'; $labels['anniversary'] = 'Gadadiena'; -$labels['website'] = 'Web lapa'; +$labels['website'] = 'MÄjaslapa'; $labels['instantmessenger'] = 'IM'; $labels['notes'] = 'PiezÄ«mes'; $labels['male'] = 'vÄ«rietis'; $labels['female'] = 'sieviete'; $labels['manager'] = 'Menedžeris'; $labels['assistant'] = 'Asistents'; -$labels['spouse'] = 'LaulÄtais draugs'; +$labels['spouse'] = 'LaulÄtais'; $labels['allfields'] = 'Visi lauki'; $labels['search'] = 'MeklÄ“t'; $labels['advsearch'] = 'PaplaÅ¡inÄtÄ meklÄ“Å¡ana'; -$labels['advanced'] = 'Advanced'; +$labels['advanced'] = 'PaplaÅ¡inÄtie iestatÄ«jumi'; $labels['other'] = 'Cits'; $labels['typehome'] = 'MÄjas'; @@ -307,22 +310,22 @@ $labels['typework'] = 'Darbs'; $labels['typeother'] = 'Cits'; $labels['typemobile'] = 'Mobilais tÄlrunis'; $labels['typemain'] = 'Galvenais'; -$labels['typehomefax'] = 'MÄjas Fax'; -$labels['typeworkfax'] = 'Darba Fax'; +$labels['typehomefax'] = 'Fakss mÄjÄs'; +$labels['typeworkfax'] = 'Fakss darbÄ'; $labels['typecar'] = 'Auto'; $labels['typepager'] = 'Peidžeris'; $labels['typevideo'] = 'Video'; $labels['typeassistant'] = 'Asistents'; -$labels['typehomepage'] = 'Web lapa'; +$labels['typehomepage'] = 'MÄjaslapa'; $labels['typeblog'] = 'Blogs'; $labels['typeprofile'] = 'Profils'; $labels['addfield'] = 'Pievienot lauku...'; -$labels['addcontact'] = 'Pievienot iezÄ«mÄ“to ierakstu adreÅ¡u grÄmatai'; -$labels['editcontact'] = 'Rediģēt adreÅ¡u grÄmatas ierakstu'; +$labels['addcontact'] = 'Pievienot jaunu kontaktu'; +$labels['editcontact'] = 'Rediģēt kontaktu'; $labels['contacts'] = 'Kontakti'; $labels['contactproperties'] = 'Kontakta Ä«paÅ¡Ä«bas'; -$labels['personalinfo'] = 'PersoniskÄ informÄcija'; +$labels['personalinfo'] = 'PersonÄ«gÄ informÄcija'; $labels['edit'] = 'Rediģēt'; $labels['cancel'] = 'Atcelt'; @@ -331,29 +334,30 @@ $labels['delete'] = 'DzÄ“st'; $labels['rename'] = 'PÄrdÄ“vÄ“t'; $labels['addphoto'] = 'Pievienot'; $labels['replacephoto'] = 'Aizvietot'; -$labels['uploadphoto'] = 'Upload photo'; +$labels['uploadphoto'] = 'AugÅ¡upielÄdÄ“t fotogrÄfiju'; -$labels['newcontact'] = 'Izveidot jaunu ierakstu'; -$labels['deletecontact'] = 'DzÄ“st iezÄ«mÄ“tos ierakstus'; +$labels['newcontact'] = 'Izveidot jaunu kontaktu'; +$labels['deletecontact'] = 'DzÄ“st atzÄ«mÄ“tos kontaktus'; $labels['composeto'] = 'RakstÄ«t vÄ“stuli'; -$labels['contactsfromto'] = 'Ieraksti $from lÄ«dz $to no $count'; +$labels['contactsfromto'] = 'Ieraksti no $from lÄ«dz $to - kopÄ $count'; $labels['print'] = 'DrukÄt'; $labels['export'] = 'EksportÄ“t'; -$labels['exportall'] = 'Export all'; -$labels['exportsel'] = 'Export selected'; +$labels['exportall'] = 'EksportÄ“t visu'; +$labels['exportsel'] = 'EksportÄ“t atzÄ«mÄ“to'; $labels['exportvcards'] = 'EksportÄ“t kontaktus vCard formÄtÄ'; $labels['newcontactgroup'] = 'Izveidot jaunu kontaktu grupu'; $labels['grouprename'] = 'PÄrdÄ“vÄ“t grupu'; $labels['groupdelete'] = 'IzdzÄ“st grupu'; -$labels['groupremoveselected'] = 'Remove selected contacts from group'; +$labels['groupremoveselected'] = 'DzÄ“st atzÄ«mÄ“tos kontaktus no grupas'; -$labels['previouspage'] = 'ParÄdÄ«t iepriekÅ¡Ä“jo kopu'; -$labels['firstpage'] = 'ParÄdÄ«t pirmo kopu'; -$labels['nextpage'] = 'ParÄdÄ«t nÄkamo kopu'; -$labels['lastpage'] = 'ParÄdÄ«t pÄ“dÄ“jo kopu'; +$labels['previouspage'] = 'ParÄdÄ«t iepriekÅ¡Ä“jo lapu'; +$labels['firstpage'] = 'ParÄdÄ«t pirmo lapu'; +$labels['nextpage'] = 'ParÄdÄ«t nÄkamo lapu'; +$labels['lastpage'] = 'ParÄdÄ«t pÄ“dÄ“jo lapu'; $labels['group'] = 'Grupa'; $labels['groups'] = 'Grupas'; +$labels['listgroup'] = 'RÄdÄ«t grupas kontaktus'; $labels['personaladrbook'] = 'PersonÄ«gÄs adreses'; $labels['searchsave'] = 'SaglabÄt meklÄ“Å¡anas pieprasÄ«jumu'; @@ -362,72 +366,72 @@ $labels['searchdelete'] = 'DzÄ“st saglabÄto meklÄ“Å¡anas pieprasÄ«jumu'; $labels['import'] = 'ImportÄ“t'; $labels['importcontacts'] = 'ImportÄ“t kontaktus'; $labels['importfromfile'] = 'ImportÄ“t no faila:'; -$labels['importtarget'] = 'Pievienot jaunus kontaktus adreÅ¡u grÄmatai'; +$labels['importtarget'] = 'Pievienot jaunus kontaktus adreÅ¡u grÄmatai:'; $labels['importreplace'] = 'Aizvietot visu adreÅ¡u grÄmatu'; -$labels['importdesc'] = 'You can upload contacts from an existing address book.<br/>We currently support importing addresses from the <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> or CSV (comma-separated) data format.'; +$labels['importdesc'] = 'JÅ«s varat ieimportÄ“t kontaktus no jau esoÅ¡as adreÅ¡u grÄmatas.<br/>Uz doto brÄ«di tiek atbalstÄ«ti <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> vai CSV (ar komatu atdalÄ«tie) datu formÄti.'; $labels['done'] = 'Pabeigts'; // settings $labels['settingsfor'] = 'IestatÄ«jumi'; $labels['about'] = 'Par'; $labels['preferences'] = 'IestatÄ«jumi'; -$labels['userpreferences'] = 'LietotÄja preferences'; -$labels['editpreferences'] = 'Rediģēt lietotÄja preferences'; +$labels['userpreferences'] = 'LietotÄja iestatÄ«jumi'; +$labels['editpreferences'] = 'Rediģēt iestatÄ«jumus'; $labels['identities'] = 'IdentitÄtes'; -$labels['manageidentities'] = 'Rediģēt Å¡Ä« konta identitÄtes'; +$labels['manageidentities'] = 'Rediģēt identitÄtes'; $labels['newidentity'] = 'Jauna identitÄte'; $labels['newitem'] = 'Jauns'; $labels['edititem'] = 'Rediģēt'; -$labels['preferhtml'] = 'Dot priekÅ¡roku HTML formatÄ“tÄm vÄ“stulÄ“m'; +$labels['preferhtml'] = 'RÄdÄ«t HTML formatÄ“tÄs vÄ“stules'; $labels['defaultcharset'] = 'NoklusÄ“tÄ rakstzÄ«mju kopa'; -$labels['htmlmessage'] = 'HTML vÄ“stule'; -$labels['messagepart'] = 'Part'; -$labels['digitalsig'] = 'Digital Signature'; +$labels['htmlmessage'] = 'HTML formatÄ“ta vÄ“stule'; +$labels['messagepart'] = 'Daļa'; +$labels['digitalsig'] = 'DigitÄlais paraksts'; $labels['dateformat'] = 'Datuma formÄts'; $labels['timeformat'] = 'Laika formÄts'; -$labels['prettydate'] = 'FormatÄ“t datumus'; +$labels['prettydate'] = 'RÄdÄ«t Ä«sos datumus'; $labels['setdefault'] = 'Uzlikt kÄ noklusÄ“to'; -$labels['autodetect'] = 'AutomÄtiski'; +$labels['autodetect'] = 'AutomÄtiska'; $labels['language'] = 'Valoda'; $labels['timezone'] = 'Laika zona'; $labels['pagesize'] = 'Rindas lapÄ'; $labels['signature'] = 'Paraksts'; $labels['dstactive'] = 'Vasaras/ziemas laiks'; -$labels['showinextwin'] = 'Open message in a new window'; -$labels['composeextwin'] = 'Compose in a new window'; -$labels['htmleditor'] = 'RakstÄ«t HTML vÄ“stules'; +$labels['showinextwin'] = 'VÄ“stules atvÄ“rt jaunÄ logÄ'; +$labels['composeextwin'] = 'VÄ“stuli rakstÄ«t jaunÄ logÄ'; +$labels['htmleditor'] = 'RakstÄ«t HTML formatÄ“tas vÄ“stules'; $labels['htmlonreply'] = 'tikai atbildot uz HTML formatÄ“tÄm vÄ“stulÄ“m'; -$labels['htmlonreplyandforward'] = 'on forward or reply to HTML message'; -$labels['htmlsignature'] = 'HTML paraksts'; -$labels['showemail'] = 'Show email address with display name'; +$labels['htmlonreplyandforward'] = 'tikai pÄrsÅ«tot vai atbildot uz HTML formatÄ“tu vÄ“stuli'; +$labels['htmlsignature'] = 'HTML formatÄ“ts paraksts'; +$labels['showemail'] = 'Pie vÄrda rÄdÄ«t arÄ« e-pasta adresi'; $labels['previewpane'] = 'RÄdÄ«t priekÅ¡skatÄ«juma paneli'; -$labels['skin'] = 'Interfeisa izskats'; -$labels['logoutclear'] = 'Izejot no sistÄ“mas, iztÄ«rÄ«t miskasti'; -$labels['logoutcompact'] = 'Izejot no sistÄ“mas, saspiest iesÅ«tni'; +$labels['skin'] = 'Saskarnes izskats'; +$labels['logoutclear'] = 'Izejot no e-pasta, iztÄ«rÄ«t papÄ«rgrozu'; +$labels['logoutcompact'] = 'Izejot no e-pasta, saspiest iesÅ«tni'; $labels['uisettings'] = 'LietotÄja saskarne'; $labels['serversettings'] = 'Servera iestatÄ«jumi'; $labels['mailboxview'] = 'Pastkastes skats'; $labels['mdnrequests'] = 'VÄ“stules izlasÄ«Å¡anas atskaites sÅ«tÄ«Å¡ana'; -$labels['askuser'] = 'jautÄt lietotÄjam'; +$labels['askuser'] = 'jautÄt man vai sÅ«tÄ«t'; $labels['autosend'] = 'sÅ«tÄ«t automÄtiski'; -$labels['autosendknown'] = 'automÄtiski sÅ«tÄ«t maniem kontaktiem, par citiem jautÄt'; -$labels['autosendknownignore'] = 'automÄtiski sÅ«tÄ«t maniem kontaktiem, citiem nesÅ«tÄ«t'; -$labels['ignore'] = 'ignorÄ“t'; -$labels['readwhendeleted'] = 'AtzÄ«mÄ“t dzÄ“stÄs vÄ“stules kÄ izlasÄ«tas'; -$labels['flagfordeletion'] = 'DzÄ“Å¡ot marÄ·Ä“t vÄ“stules kÄ dzÄ“stas, bet nedzÄ“st'; +$labels['autosendknown'] = 'automÄtiski sÅ«tÄ«t ja pieprasÄ«tÄjs ir manos kontaktos, par citiem jautÄt'; +$labels['autosendknownignore'] = 'automÄtiski sÅ«tÄ«t ja pieprasÄ«tÄjs ir manos kontaktos, citiem ignorÄ“t un nesÅ«tÄ«t'; +$labels['ignore'] = 'ignorÄ“t un nesÅ«tÄ«t'; +$labels['readwhendeleted'] = 'DzÄ“Å¡ot vÄ“stules tÄs atzÄ«mÄ“t kÄ izlasÄ«tas'; +$labels['flagfordeletion'] = 'DzÄ“Å¡ot vÄ“stules tÄs nedzÄ“st, bet marÄ·Ä“t kÄ dzÄ“Å¡amas'; $labels['skipdeleted'] = 'NerÄdÄ«t dzÄ“stÄs vÄ“stules'; -$labels['deletealways'] = 'IzdzÄ“st vÄ“stules, ja tÄs neizdodas pÄrvietot uz miskasti'; -$labels['deletejunk'] = 'Directly delete messages in Junk'; -$labels['showremoteimages'] = 'RÄdÄ«t attÄ“lus, kas atrodas uz cita servera'; -$labels['fromknownsenders'] = 'no zinÄmiem sÅ«tÄ«tÄjiem'; +$labels['deletealways'] = 'IzdzÄ“st vÄ“stules, ja tÄs neizdodas pÄrvietot uz papÄ«rgrozu'; +$labels['deletejunk'] = 'AutomÄtiski dzÄ“st vÄ“stules no mÄ“stuļu mapÄ«tes'; +$labels['showremoteimages'] = 'RÄdÄ«t vÄ“stulÄ“s attÄ“lus, kuri atrodas uz cita servera'; +$labels['fromknownsenders'] = 'tikai no zinÄmiem sÅ«tÄ«tÄjiem'; $labels['always'] = 'vienmÄ“r'; $labels['showinlineimages'] = 'RÄdÄ«t pielikuma attÄ“lus zem vÄ“stules'; -$labels['autosavedraft'] = 'AutomÄtiski saglabÄt uzmetumu'; -$labels['everynminutes'] = 'ik pa $n minÅ«ti(Ä“m)'; -$labels['refreshinterval'] = 'Refresh (check for new messages, etc.)'; +$labels['autosavedraft'] = 'AutomÄtiski saglabÄt vÄ“stules uzmetumu'; +$labels['everynminutes'] = 'ik pÄ“c $n minÅ«tes(Ä“m)'; +$labels['refreshinterval'] = 'PÄrbaudÄ«t jaunÄs vÄ“stules'; $labels['never'] = 'nekad'; $labels['immediately'] = 'nekavÄ“joties'; $labels['messagesdisplaying'] = 'VÄ“stuļu attÄ“loÅ¡ana'; @@ -437,44 +441,45 @@ $labels['2231folding'] = 'Pilns RFC 2231 (Thunderbird)'; $labels['miscfolding'] = 'RFC 2047/2231 (MS Outlook)'; $labels['2047folding'] = 'Pilns RFC 2047 (citi)'; $labels['force7bit'] = 'Izmantot MIME kodÄ“jumu 8-bitu simboliem'; -$labels['advancedoptions'] = 'PaplaÅ¡inÄti iestatÄ«jumi'; -$labels['focusonnewmessage'] = 'UztÄdÄ«t pÄrlÅ«ka fokusu uz jaunu vÄ“stuli'; -$labels['checkallfolders'] = 'PÄrbaudÄ«t visas mapes pÄ“c jaunÄm vÄ“stulÄ“m'; -$labels['displaynext'] = 'RÄdÄ«t nÄkamo vÄ“stuli pÄ“c dzÄ“Å¡anas/pÄrvietoÅ¡anas'; -$labels['defaultfont'] = 'NoklusÄ“tais fonts vÄ“stulei HTML formÄtÄ'; +$labels['advancedoptions'] = 'PaplaÅ¡inÄtie iestatÄ«jumi'; +$labels['focusonnewmessage'] = 'UzstÄdÄ«t pÄrlÅ«ka fokusu uz jaunu vÄ“stuli'; +$labels['checkallfolders'] = 'MeklÄ“t visÄs mapÄ“s jaunÄs vÄ“stules'; +$labels['displaynext'] = 'PÄ“c vÄ“stules dzÄ“Å¡anas/pÄrvietoÅ¡anas rÄdÄ«t nÄkamo vÄ“stuli'; +$labels['defaultfont'] = 'NoklusÄ“tais fonts vÄ“stulÄ“m HTML formÄtÄ'; $labels['mainoptions'] = 'Galvenie iestatÄ«jumi'; -$labels['browseroptions'] = 'Browser Options'; -$labels['section'] = 'Kategorija'; +$labels['browseroptions'] = 'PÄrlÅ«ka iestatÄ«jumi'; +$labels['section'] = 'Sadaļa'; $labels['maintenance'] = 'UzturÄ“Å¡ana'; $labels['newmessage'] = 'VÄ“stuļu pienÄkÅ¡ana'; $labels['signatureoptions'] = 'Paraksta iestatÄ«jumi'; $labels['whenreplying'] = 'Atbildot'; -$labels['replyempty'] = 'do not quote the original message'; +$labels['replyempty'] = 'neiekļaut vÄ“stules sÄkotnÄ“jo tekstu'; $labels['replytopposting'] = 'sÄkt jaunu vÄ“stuli virs oriÄ£inÄla'; $labels['replybottomposting'] = 'sÄkt jaunu vÄ“stuli zem oriÄ£inÄla'; $labels['replyremovesignature'] = 'Atbildot izņemt oriÄ£inÄlo parakstu no vÄ“stules'; $labels['autoaddsignature'] = 'AutomÄtiski pievienot parakstu'; -$labels['newmessageonly'] = 'tikai jaunas vÄ“stules'; -$labels['replyandforwardonly'] = 'tikai atbildes un pÄrsÅ«tÄ«jumi'; +$labels['newmessageonly'] = 'tikai jaunÄm vÄ“stulÄ“m'; +$labels['replyandforwardonly'] = 'tikai atbildÄ“m un pÄrsÅ«tÄ«jumiem'; $labels['insertsignature'] = 'Ievietot parakstu'; $labels['previewpanemarkread'] = 'AtzÄ«mÄ“t priekÅ¡skatÄ«tÄs vÄ“stules kÄ lasÄ«tas'; $labels['afternseconds'] = 'pÄ“c $n sekundÄ“m'; -$labels['reqmdn'] = 'VienmÄ“r pieprasÄ«t atskati par vÄ“stules izlasÄ«Å¡anu'; -$labels['reqdsn'] = 'VienmÄ“r pieprasÄ«t atskati par vÄ“stules piegÄdÄÅ¡anu saņēmÄ“ja serverim'; +$labels['reqmdn'] = 'VienmÄ“r pieprasÄ«t saņemÅ¡anas apstiprinÄjumu'; +$labels['reqdsn'] = 'VienmÄ“r pieprasÄ«t atskati par piegÄdi'; $labels['replysamefolder'] = 'GlabÄt atbildes tajÄ paÅ¡Ä mapÄ“, kurÄ ir vÄ“stule, uz kuru tika atbildÄ“ts'; -$labels['defaultabook'] = 'Default address book'; -$labels['autocompletesingle'] = 'AutomÄtiski aizpildot, izlaist alternatÄ«vÄs e-pasta adreses'; -$labels['listnamedisplay'] = 'List contacts as'; -$labels['spellcheckbeforesend'] = 'PÄrbaudÄ«t pareizrakstÄ«bu pirms vÄ“stules nosÅ«tÄ«Å¡anas'; +$labels['defaultabook'] = 'NoklusÄ“tÄ adreÅ¡u grÄmata'; +$labels['autocompletesingle'] = 'AutomÄtiski aizpildot, nerÄdÄ«t alternatÄ«vÄs e-pasta adreses'; +$labels['listnamedisplay'] = 'RÄdÄ«t kontaktus kÄ'; +$labels['spellcheckbeforesend'] = 'Pirms vÄ“stules nosÅ«tÄ«Å¡anas pÄrbaudÄ«t pareizrakstÄ«bu'; $labels['spellcheckoptions'] = 'PareizrakstÄ«bas iestatÄ«jumi'; $labels['spellcheckignoresyms'] = 'IgnorÄ“t vÄrdus, kuri satur simbolus'; $labels['spellcheckignorenums'] = 'IgnorÄ“t vÄrdus, kuri satur skaitļus'; $labels['spellcheckignorecaps'] = 'IgnorÄ“t vÄrdus, kuri rakstÄ«ti ar lielajiem burtiem'; $labels['addtodict'] = 'Pievienot vÄrdnÄ«cai'; -$labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; -$labels['forwardmode'] = 'Messages forwarding'; -$labels['inline'] = 'inline'; -$labels['asattachment'] = 'as attachment'; +$labels['mailtoprotohandler'] = 'Atverot mailto: saites, lietot Å¡o e-pasta programmu'; +$labels['standardwindows'] = 'IzlÄ“coÅ¡ie logi kÄ parasti logi'; +$labels['forwardmode'] = 'VÄ“stuļu pÄrsÅ«tÄ«Å¡ana'; +$labels['inline'] = 'iekļaujot'; +$labels['asattachment'] = 'kÄ pielikumu'; $labels['folder'] = 'Mapi'; $labels['folders'] = 'Mapes'; @@ -491,8 +496,8 @@ $labels['parentfolder'] = 'Virsmape'; $labels['location'] = 'AtraÅ¡anÄs vieta'; $labels['info'] = 'InformÄcija'; $labels['getfoldersize'] = 'UzklikÅ¡Ä·iniet, lai uzzinÄtu mapes izmÄ“ru'; -$labels['changesubscription'] = 'UzklikÅ¡Ä·iniet, lai mainÄ«tu abonÄ“Å¡anu'; -$labels['foldertype'] = 'Mapes veids'; +$labels['changesubscription'] = 'UzklikÅ¡Ä·iniet, lai mainÄ«tu abonÄ“Å¡anas iestatÄ«jumus'; +$labels['foldertype'] = 'Mapes tips'; $labels['personalfolder'] = 'PrivÄta mape'; $labels['otherfolder'] = 'Cita lietotÄja mape'; $labels['sharedfolder'] = 'Publiska mape'; @@ -502,7 +507,7 @@ $labels['sortasc'] = 'KÄrtot augoÅ¡Ä secÄ«bÄ'; $labels['sortdesc'] = 'KÄrtot dilstoÅ¡Ä secÄ«bÄ'; $labels['undo'] = 'Atsaukt'; -$labels['installedplugins'] = 'Installed plugins'; +$labels['installedplugins'] = 'UzstÄdÄ«tie spraudņi'; $labels['plugin'] = 'Spraudnis'; $labels['version'] = 'Versija'; $labels['source'] = 'OriÄ£inÄls'; @@ -516,7 +521,7 @@ $labels['MB'] = 'MB'; $labels['GB'] = 'GB'; // character sets -$labels['unicode'] = 'Unikoda'; +$labels['unicode'] = 'Unikods'; $labels['english'] = 'Angļu'; $labels['westerneuropean'] = 'Rietumeiropas'; $labels['easterneuropean'] = 'Austrumeiropas'; diff --git a/program/localization/lv_LV/messages.inc b/program/localization/lv_LV/messages.inc index b69a73e2b..37ceb0463 100644 --- a/program/localization/lv_LV/messages.inc +++ b/program/localization/lv_LV/messages.inc @@ -28,7 +28,7 @@ $messages['dberror'] = 'DatubÄzes kļūda!'; $messages['requesttimedout'] = 'PieprasÄ«jumam iestÄjÄs noilgums'; $messages['errorreadonly'] = 'NeizdevÄs veikt darbÄ«bu: mape ir tikai lasÄma (read only)'; $messages['errornoperm'] = 'NeizdevÄs veikt darbÄ«bu: piekļuve liegta'; -$messages['erroroverquota'] = 'OperÄciju nav iespÄ“jams veikt. Uz diska nav brÄ«vas veitas.'; +$messages['erroroverquota'] = 'OperÄciju veikt nav iespÄ“jams. Uz diska nav brÄ«vas veitas.'; $messages['erroroverquotadelete'] = 'Uz diska nav brÄ«vas vietas. Lai dzÄ“stu vÄ“stuli, lietojiet SHIFT+DEL.'; $messages['invalidrequest'] = 'NederÄ«gs pieprasÄ«jums! Dati netika saglabÄti ...'; $messages['invalidhost'] = 'NederÄ«gs servera nosaukums'; @@ -45,7 +45,7 @@ $messages['sendingmessage'] = 'Tiek sÅ«tÄ«ta vÄ“stule ...'; $messages['messagesent'] = 'VÄ“stule nosÅ«tÄ«ta veiksmÄ«gi'; $messages['savingmessage'] = 'VÄ“stule tiek saglabÄta ...'; $messages['messagesaved'] = 'VÄ“stule saglabÄta Uzmetumos'; -$messages['successfullysaved'] = 'VÄ“stule veiksmÄ«gi saglabÄta'; +$messages['successfullysaved'] = 'VeiksmÄ«gi saglabÄts.'; $messages['addedsuccessfully'] = 'Kontakts veiksmÄ«gi pievienots adreÅ¡u grÄmatai'; $messages['contactexists'] = 'Kontakts ar Å¡Ädu e-pasta adresi jau eksistÄ“'; $messages['contactnameexists'] = 'Kontakts ar Å¡Ädu vÄrdu jau eksistÄ“.'; @@ -100,72 +100,74 @@ $messages['deletedsuccessfully'] = 'VeiksmÄ«gi izdzÄ“sts'; $messages['converting'] = 'Tiek noņemts vÄ“stules formatÄ“jums...'; $messages['messageopenerror'] = 'NevarÄ“ja ielÄdÄ“t vÄ“stuli no servera'; $messages['fileuploaderror'] = 'Faila augÅ¡upielÄde neveiksmÄ«ga'; -$messages['filesizeerror'] = 'IelÄdÄ“tais fails pÄrsniedz pieļaujamo $size apjomu'; -$messages['copysuccess'] = 'VeiksmÄ«gi nokopÄ“tas $nr vÄ“stules'; -$messages['copyerror'] = 'NevarÄ“ja nokopÄ“t nevienu adresi'; +$messages['filesizeerror'] = 'AugÅ¡upielÄdÄ“tais fails pÄrsniedz pieļaujamo $size izmÄ“ru.'; +$messages['copysuccess'] = 'VeiksmÄ«gi nokopÄ“tas $nr adreses.'; +$messages['copyerror'] = 'NevarÄ“ja nokopÄ“t nevienu adresi.'; $messages['sourceisreadonly'] = 'Adreses avots ir lasÄ«Å¡anas režīmÄ tikai'; -$messages['errorsavingcontact'] = 'NevarÄ“ja saglabÄt kontakta adreses'; -$messages['movingmessage'] = 'PÄrvietoju vÄ“stules...'; +$messages['errorsavingcontact'] = 'Kontakta adresi nevarÄ“ja saglabÄt.'; +$messages['movingmessage'] = 'PÄrvieto vÄ“stules...'; $messages['copyingmessage'] = 'KopÄ“ vÄ“stules...'; $messages['copyingcontact'] = 'KopÄ“ kontaktus...'; $messages['deletingmessage'] = 'DzÄ“Å¡ vÄ“stules...'; $messages['markingmessage'] = 'AtzÄ«mÄ“ vÄ“stules...'; -$messages['addingmember'] = 'Pievieno kontaktu(s) grupai...'; -$messages['removingmember'] = 'Atvieno kontaktu(s) no grupas...'; -$messages['receiptsent'] = 'SaņemÅ¡anas apstiprinÄjums nosÅ«tÄ«ts'; -$messages['errorsendingreceipt'] = 'NeizdevÄs nosÅ«tÄ«t apstiprinÄjumu'; -$messages['deleteidentityconfirm'] = 'Vai tieÅ¡Äm vÄ“laties dzÄ“st Å¡o identitÄti?'; -$messages['nodeletelastidentity'] = 'Å o identitÄti nevar izdzÄ“st, tÄ ir pati pÄ“dÄ“jÄ.'; -$messages['forbiddencharacter'] = 'Mapes nosaukums satur aizliegtus simbolus'; -$messages['selectimportfile'] = 'LÅ«dzu izvÄ“lieties failu, ko vÄ“laties augÅ¡upielÄdÄ“t'; -$messages['addresswriterror'] = 'IzvÄ“lÄ“tÄs adreÅ¡u grÄmatas datus nevar labot'; +$messages['addingmember'] = 'Kontaktus pievieno grupai...'; +$messages['removingmember'] = 'Kontaktus atvieno no grupas...'; +$messages['receiptsent'] = 'SaņemÅ¡anas apstiprinÄjums nosÅ«tÄ«ts veiksmÄ«gi.'; +$messages['errorsendingreceipt'] = 'NeizdevÄs nosÅ«tÄ«t saņemÅ¡anas apstiprinÄjumu.'; +$messages['deleteidentityconfirm'] = 'Vai JÅ«s tieÅ¡Äm vÄ“laties dzÄ“st Å¡o identitÄti?'; +$messages['nodeletelastidentity'] = 'Å o identitÄti nav iespÄ“jams izdzÄ“st, jo tÄ ir pati pÄ“dÄ“jÄ.'; +$messages['forbiddencharacter'] = 'Mapes nosaukums satur aizliegtus simbolus.'; +$messages['selectimportfile'] = 'LÅ«dzu norÄdiet failu, kuru vÄ“laties augÅ¡upielÄdÄ“t.'; +$messages['addresswriterror'] = 'IzvÄ“lÄ“tÄs adreÅ¡u grÄmatas datus nav iespÄ“jams rediģēt.'; $messages['contactaddedtogroup'] = 'Kontakti tika veiksmÄ«gi pievienoti Å¡ai grupai.'; $messages['contactremovedfromgroup'] = 'Kontakti tika veiksmÄ«gi atvienoti no Å¡Ä«s grupas.'; $messages['nogroupassignmentschanged'] = 'GrupÄ nekas netika mainÄ«ts.'; $messages['importwait'] = 'ImportÄ“ju, lÅ«dzu uzgaidiet...'; $messages['importformaterror'] = 'Imports neizdevÄs! AugÅ¡upielÄdÄ“tais fails nav derÄ«gs importam.'; -$messages['importconfirm'] = '<b>VeiksmÄ«gi ieimportÄ“ti $inserted kontakti, netika importÄ“ti $skipped esoÅ¡i ieraksti</b>:<p><em>$names</em></p>'; +$messages['importconfirm'] = '<b>VeiksmÄ«gi ieimportÄ“ti $inserted kontakti</b>'; $messages['importconfirmskipped'] = '<b>Izlaida $skipped jau eksistÄ“joÅ¡us ierakstus</b>'; +$messages['importmessagesuccess'] = 'VeiksmÄ«gi ieimportÄ“tas $nr vÄ“stules'; +$messages['importmessageerror'] = 'ImportÄ“Å¡anas kļūda! AugÅ¡upielÄdÄ“tÄ datne satur nekorektus datus'; $messages['opnotpermitted'] = 'DarbÄ«ba nav atļauta!'; -$messages['nofromaddress'] = 'IzvÄ“lÄ“tajai identitÄtei nav norÄdÄ«ta e-pasta adrese'; -$messages['editorwarning'] = 'PÄrslÄ“dzoties uz vienkÄrÅ¡otu teksta redaktoru, tiks pazaudÄ“ts esoÅ¡ais teksta formatÄ“jums. Vai vÄ“laties turpinÄt?'; -$messages['httpreceivedencrypterror'] = 'Kļūme. LÅ«dzu sazinieties ar administratoru. <b>Nav iespÄ“jams nosÅ«tÄ«t vÄ“stuli.</b>'; +$messages['nofromaddress'] = 'IzvÄ“lÄ“tajai identitÄtei nav norÄdÄ«ta e-pasta adrese.'; +$messages['editorwarning'] = 'PÄrslÄ“dzoties uz vienkÄrÅ¡otu teksta redaktoru, tiks pazaudÄ“ts esoÅ¡ais teksta formatÄ“jums. Vai tieÅ¡Äm vÄ“laties turpinÄt?'; +$messages['httpreceivedencrypterror'] = 'Notika kritiska kļūme. LÅ«dzu nekavÄ“joties sazinieties ar JÅ«su administratoru. <b>JÅ«su vÄ“stuli nosÅ«tÄ«t nav iespÄ“jams.</b>'; $messages['smtpconnerror'] = 'SMTP kļūme ($code): NeizdevÄs pieslÄ“gties serverim'; -$messages['smtpautherror'] = 'SMTP kļūme ($code): NeizdevÄs autentificÄ“ties'; -$messages['smtpfromerror'] = 'SMTP kļūme ($code): NeizdevÄs iestatÄ«t sÅ«tÄ«tÄju "$from" ($msg)'; -$messages['smtptoerror'] = 'SMTP kļūme ($code): NeizdevÄs pievienot saņēmÄ“ju "$to" ($msg)'; -$messages['smtprecipientserror'] = 'SMTP kļūme: Nav iespÄ“jams parsÄ“t saņēmÄ“ju sarakstu'; -$messages['smtperror'] = 'SMTP kļūme: $msg'; +$messages['smtpautherror'] = 'SMTP kļūda ($code): NeizdevÄs autorizÄ“ties.'; +$messages['smtpfromerror'] = 'SMTP kļūda ($code): NeizdevÄs iestatÄ«t sÅ«tÄ«tÄju "$from" ($msg).'; +$messages['smtptoerror'] = 'SMTP kļūda ($code): NeizdevÄs pievienot saņēmÄ“ju "$to" ($msg).'; +$messages['smtprecipientserror'] = 'SMTP kļūda: Nav iespÄ“jams aptrÄdÄt saņēmÄ“ju sarakstu.'; +$messages['smtperror'] = 'SMTP kļūda: $msg'; $messages['emailformaterror'] = 'Nepareiza e-pasta adrese: $email'; $messages['toomanyrecipients'] = 'PÄrÄk daudz saņēmÄ“ju. Samaziniet skaitu lÄ«dz $max.'; $messages['maxgroupmembersreached'] = 'Grupas dalÄ«bnieku skaits pÄrsniedz limitu $max.'; -$messages['internalerror'] = 'Servera iekÅ¡Ä“jÄ kļūda. LÅ«dzu mÄ“Ä£iniet vÄ“lreiz.'; -$messages['contactdelerror'] = 'NeizdevÄs izdzÄ“st kontaktu(s).'; -$messages['contactdeleted'] = 'Kontakti veiksmÄ«gi izdzÄ“sti.'; -$messages['contactrestoreerror'] = 'NeizdevÄs atjaunot izdzÄ“stos kontaktus.'; -$messages['contactrestored'] = 'Kontakti veiksmÄ«gi atjaunoti.'; -$messages['groupdeleted'] = 'Grupa veiksmÄ«gi izdzÄ“sta.'; -$messages['grouprenamed'] = 'Grupa veiksmÄ«gi pÄrdÄ“vÄ“ta.'; -$messages['groupcreated'] = 'Grupa veiksmÄ«gi izveidota.'; -$messages['savedsearchdeleted'] = 'SaglabÄtais meklÄ“Å¡anas pieprasÄ«jums veiksmÄ«gi dzÄ“sts.'; -$messages['savedsearchdeleteerror'] = 'NeizdevÄs nodzÄ“st saglabÄto meklÄ“Å¡anas pieprasÄ«jumu.'; -$messages['savedsearchcreated'] = 'SaglabÄtais meklÄ“Å¡anas pieprasÄ«jums veiksmÄ«gi saglabÄts.'; -$messages['savedsearchcreateerror'] = 'NeizdevÄs saglabÄt meklÄ“Å¡anas pieprasÄ«jumu.'; +$messages['internalerror'] = 'Notika servera iekÅ¡Ä“jÄ kļūda. LÅ«dzu mÄ“Ä£iniet vÄ“lreiz.'; +$messages['contactdelerror'] = 'Kontaktus izdzÄ“st neizdevÄs.'; +$messages['contactdeleted'] = 'Kontakti izdzÄ“sti veiksmÄ«gi.'; +$messages['contactrestoreerror'] = 'IzdzÄ“stos kontaktus atjaunot neizdevÄs.'; +$messages['contactrestored'] = 'Kontakti atjaunoti veiksmÄ«gi.'; +$messages['groupdeleted'] = 'Grupa izdzÄ“sta veiksmÄ«gi.'; +$messages['grouprenamed'] = 'Grupa pÄrdÄ“vÄ“ta veiksmÄ«gi.'; +$messages['groupcreated'] = 'Grupa izveidota veiksmÄ«gi.'; +$messages['savedsearchdeleted'] = 'SaglabÄtais meklÄ“Å¡anas pieprasÄ«jums izdzÄ“sts veiksmÄ«gi.'; +$messages['savedsearchdeleteerror'] = 'SaglabÄto meklÄ“Å¡anas pieprasÄ«jumu izdzÄ“st neizdevÄs.'; +$messages['savedsearchcreated'] = 'SaglabÄtais meklÄ“Å¡anas pieprasÄ«jums saglabÄts veiksmÄ«gi.'; +$messages['savedsearchcreateerror'] = 'MeklÄ“Å¡anas pieprasÄ«jumu izveidot neizdevÄs.'; $messages['messagedeleted'] = 'VÄ“stule(s) veiksmÄ«gi izdzÄ“sta(s).'; $messages['messagemoved'] = 'VÄ“stule(s) veiksmÄ«gi pÄrvietota(s).'; $messages['messagecopied'] = 'VÄ“stule(s) veiksmÄ«gi pÄrkopÄ“ta(s).'; -$messages['messagemarked'] = 'VÄ“stule(s) veiksmÄ«gi iezÄ«mÄ“ta(s).'; -$messages['autocompletechars'] = 'Ievadiet vismaz $min burtus, lai meklÄ“tu automÄtiski.'; -$messages['autocompletemore'] = 'Atrasti vairÄki ieraksti. Papildiniet meklÄ“Å¡anas kritÄ“riju.'; +$messages['messagemarked'] = 'VÄ“stule(s) veiksmÄ«gi atzÄ«mÄ“ta(s).'; +$messages['autocompletechars'] = 'Lai automÄtiski meklÄ“tu, ievadiet vismaz $min burtus.'; +$messages['autocompletemore'] = 'Atrasti vairÄki ieraksti. Papildiniet meklÄ“Å¡anas kritÄ“riju ar vairÄk burtiem.'; $messages['namecannotbeempty'] = 'LÅ«dzu ievadiet vÄrdu.'; -$messages['nametoolong'] = 'VÄrds ir par garu.'; +$messages['nametoolong'] = 'VÄrds ir pÄrÄk garÅ¡.'; $messages['folderupdated'] = 'Mape vieksmÄ«gi atjaunota.'; $messages['foldercreated'] = 'Mape veiksmÄ«gi izveidota.'; $messages['invalidimageformat'] = 'NederÄ«gs attÄ“la formÄts.'; $messages['mispellingsfound'] = 'VÄ“stulÄ“ atrastas pareizrakstÄ«bas kļūdas.'; -$messages['parentnotwritable'] = 'NeizdevÄs izveidot/pÄrvietot mapi uz atzÄ«mÄ“to virsmapi. Nav piekļuves tiesÄ«bu.'; -$messages['messagetoobig'] = 'VÄ“stule ir pÄrÄk liela, lai to varÄ“tu apstrÄdÄt.'; +$messages['parentnotwritable'] = 'NeizdevÄs izveidot/pÄrvietot mapi atzÄ«mÄ“tajÄ virsmapÄ“. Nav piekļuves tiesÄ«bu.'; +$messages['messagetoobig'] = 'VÄ“stule daļa ir pÄrÄk liela, lai to varÄ“tu apstrÄdÄt.'; $messages['attachmentvalidationerror'] = 'BRĪDINÄ€JUMS! Å is pielikums ir aizdomÄ«gs, jo tÄ tips neatbilst tipam, kurÅ¡ ir uzrÄdÄ«ts e-pasta ziņojumÄ. Ja jÅ«s neuzticaties sÅ«tÄ«tÄjam, Å¡o failu Jums vaÄ¼Ä vÄ“rt nevajadzÄ“tu, jo tas var saturÄ“t ļaunprÄtÄ«gu saturu. <br/><br/><em>BÅ«tu jÄbÅ«t: $expected; Bet ir: $detected</em>'; -$messages['noscriptwarning'] = 'UzmanÄ«bu: lai lasÄ«tu e-pastus, JÅ«su tÄ«mekļa pÄrlÅ«kÄ jÄbÅ«t iespÄ“jotiem JavaScript.'; +$messages['noscriptwarning'] = 'UzmanÄ«bu: lai lasÄ«tu e-pastus, JÅ«su pÄrlÅ«kprogrammÄ jÄbÅ«t ieslÄ“gtiem JavaScript.'; ?> diff --git a/program/localization/mk_MK/labels.inc b/program/localization/mk_MK/labels.inc index bb9606e6a..519df5823 100755 --- a/program/localization/mk_MK/labels.inc +++ b/program/localization/mk_MK/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Ðепратени'; $labels['sent'] = 'Пратени'; $labels['trash'] = 'Корпа'; $labels['junk'] = 'Ѓубре'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'ÐаÑлов'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'Компактно'; $labels['empty'] = 'ИÑпразни'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'ИÑкориÑтен проÑтор'; $labels['unknown'] = 'непознато'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Ðово пребарување'; $labels['searchmod'] = 'Модификатори на пребарувањето'; $labels['msgtext'] = 'Цело пиÑмо'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Отвори во нов прозорец'; $labels['emlsave'] = 'Преземи (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Прикажи ја поÑледната Ñтран $labels['group'] = 'Group'; $labels['groups'] = 'Групи'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Лични адреÑи'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/ml_IN/labels.inc b/program/localization/ml_IN/labels.inc index ed0e7402a..7d3fdc501 100644 --- a/program/localization/ml_IN/labels.inc +++ b/program/localization/ml_IN/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'പൂരàµâ€à´¤àµà´¤à´¿à´¯à´¾à´•à´¾à´¤àµà´¤à´µ'; $labels['sent'] = 'അയചàµà´šà´µ'; $labels['trash'] = 'ചവറàµà´±àµà´•àµà´Ÿàµà´Ÿ'; $labels['junk'] = 'ആവശàµà´¯à´®à´¿à´²àµà´²à´¾à´¤àµà´¤à´µ'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'വിഷയം'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'à´šàµà´°àµà´•àµà´•àµ'; $labels['empty'] = 'ശൂനàµà´¯à´‚'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'à´¡à´¿à´¸àµà´•àµà´•àµ ഉപയോഗം'; $labels['unknown'] = 'അറിയാതàµà´¤'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Reset search'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'à´®àµà´´àµà´µà´¨àµâ€ സനàµà´¦àµ‡à´¶à´µàµà´‚'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'à´ªàµà´¤à´¿à´¯ വിനàµâ€à´¡àµ‹à´¯à´¿à´²àµâ€ à´¤àµà´±à´•àµà´•àµà´•'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Show last page'; $labels['group'] = 'കൂടàµà´Ÿà´‚'; $labels['groups'] = 'കൂടàµà´Ÿà´™àµà´™à´³àµâ€'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'à´¸àµà´µà´•à´¾à´°àµà´¯ വിലാസങàµà´™à´³àµâ€'; $labels['searchsave'] = 'തിരയലàµâ€ സൂകàµà´·à´¿à´•àµà´•àµà´•'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'à´…à´•àµà´•à´™àµà´™à´³àµâ€ ഉളàµà´³ à $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'നിഘണàµà´Ÿàµà´µà´¿à´²àµâ€ ചേരàµâ€à´•àµà´•àµà´•'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/mr_IN/labels.inc b/program/localization/mr_IN/labels.inc index 02b129e0b..d26583d4d 100755 --- a/program/localization/mr_IN/labels.inc +++ b/program/localization/mr_IN/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'मसà¥à¤¦à¤¾'; $labels['sent'] = 'पाठवलेले'; $labels['trash'] = 'कचरा पेटी'; $labels['junk'] = 'नको असलेले कचरा संदेश'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'विषय'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'यादी दरà¥à¤¶à¤• पधà¥â€à¤¦à¤¤'; $labels['folderactions'] = 'फोलà¥à¤¡à¤° कृती..'; $labels['compact'] = 'छोटा'; $labels['empty'] = 'रिकामा'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'डिसà¥à¤•à¤šà¤¾ वापर'; $labels['unknown'] = 'माहित नसलेला'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'परत शोध'; $labels['searchmod'] = 'बदलकरà¥à¤¤à¥â€à¤¯à¤¾à¤‚ना शोधा'; $labels['msgtext'] = 'संपूरà¥à¤£ संदेश'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'नवीन खिडकी उघडा'; $labels['emlsave'] = 'इà¤à¤®à¤à¤² सà¥â€à¤µà¤°à¥‚पात उतरवून घà¥à¤¯à¤¾'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'शेवटचा संच दाखवा'; $labels['group'] = 'गट'; $labels['groups'] = 'अनेक गट'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'वैयकà¥à¤¤à¤¿à¤• पतà¥à¤¤à¥‡'; $labels['searchsave'] = 'शोध जतन करा'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/ms_MY/labels.inc b/program/localization/ms_MY/labels.inc index 318af05ad..a6bdfbfa0 100644 --- a/program/localization/ms_MY/labels.inc +++ b/program/localization/ms_MY/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Draf'; $labels['sent'] = 'Hantar'; $labels['trash'] = 'Tong Sampah'; $labels['junk'] = 'Junk'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Subjek'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Mod senarai paparan'; $labels['folderactions'] = 'Aksi folder'; $labels['compact'] = 'Kompak'; $labels['empty'] = 'Kosong'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Penggunaan cakera'; $labels['unknown'] = 'tidak diketahui'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Set semula carian'; $labels['searchmod'] = 'Pengubah carian'; $labels['msgtext'] = 'Keseluruhan mesej'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Buka dalam tetingkap baru'; $labels['emlsave'] = 'Muat-turun (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Papar set akhir'; $labels['group'] = 'Group'; $labels['groups'] = 'Kumpulan'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Alamat-alamat Peribadi'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/nb_NO/labels.inc b/program/localization/nb_NO/labels.inc index cba58dc9c..b5c8ce4c6 100644 --- a/program/localization/nb_NO/labels.inc +++ b/program/localization/nb_NO/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Kladd'; $labels['sent'] = 'Sendt'; $labels['trash'] = 'Slettet'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Emne'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Listevisningsmodus'; $labels['folderactions'] = 'Mappehandlinger...'; $labels['compact'] = 'Rydd opp'; $labels['empty'] = 'Tøm'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Plassforbruk'; $labels['unknown'] = 'ukjent'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Nullstill søk'; $labels['searchmod'] = 'Søke felt'; $labels['msgtext'] = 'Hele meldingen'; $labels['body'] = 'Meldingstekst'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Ã…pne i nytt vindu'; $labels['emlsave'] = 'Last ned (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Vis siste sett'; $labels['group'] = 'Gruppe'; $labels['groups'] = 'Grupper'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Egne adresser'; $labels['searchsave'] = 'Lagre søk'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorer ord med tall'; $labels['spellcheckignorecaps'] = 'Ignorer ord med kun store bokstaver'; $labels['addtodict'] = 'Legg til i ordbok'; $labels['mailtoprotohandler'] = 'Registrer protokollhÃ¥ndtering for mailto-lenker'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Meldinger videresendes'; $labels['inline'] = 'i teksten'; $labels['asattachment'] = 'som vedlegg'; diff --git a/program/localization/ne_NP/labels.inc b/program/localization/ne_NP/labels.inc index 29d43ef9c..5f69e1916 100644 --- a/program/localization/ne_NP/labels.inc +++ b/program/localization/ne_NP/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'डà¥à¤°à¤¾à¤«à¥à¤Ÿà¤¹à¤°à¥‚'; $labels['sent'] = 'पठईà¤à¤•à¤¾ मेलहरà¥'; $labels['trash'] = 'रदà¥à¤¦à¥€ टोकरी'; $labels['junk'] = 'सà¥à¤ªà¤¾à¤®'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'विषय'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'छोटो गरà¥à¤¨à¥à¤¹à¥‹à¤¸'; $labels['empty'] = 'खाली गरà¥à¤¨à¥‡'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'डिसà¥à¤•à¤•à¥‹ उपà¤à¥‹à¤—'; $labels['unknown'] = 'अजà¥à¤žà¤¾à¤¤'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'पन: खोज'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Open in new window'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'अनà¥à¤¤à¤¿à¤® सेट देखाउनà¥à $labels['group'] = 'Group'; $labels['groups'] = 'समूहहरà¥'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'वà¥à¤¯à¤•à¥à¤¤à¤¿à¤—त ठेगानाहरà¥'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/nl_BE/labels.inc b/program/localization/nl_BE/labels.inc index eb44eefc0..1e6bb2d2f 100644 --- a/program/localization/nl_BE/labels.inc +++ b/program/localization/nl_BE/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Concepten'; $labels['sent'] = 'Verzonden berichten'; $labels['trash'] = 'Prullenbak'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Onderwerp'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Lijstweergave mode'; $labels['folderactions'] = 'Acties voor map...'; $labels['compact'] = 'Comprimeren'; $labels['empty'] = 'Legen'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Gebruikte schijfruimte'; $labels['unknown'] = 'onbekend'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Zoek opnieuw'; $labels['searchmod'] = 'Zoekopties'; $labels['msgtext'] = 'Volledig bericht'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Openen in een nieuw venster'; $labels['emlsave'] = 'Opslaan (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Toon laatste'; $labels['group'] = 'Groep'; $labels['groups'] = 'Groepen'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Personlijke adressen'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/nl_NL/labels.inc b/program/localization/nl_NL/labels.inc index 7bd48bd4a..8a6f994fa 100644 --- a/program/localization/nl_NL/labels.inc +++ b/program/localization/nl_NL/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Concepten'; $labels['sent'] = 'Verzonden'; $labels['trash'] = 'Prullenbak'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Toon echte namen voor speciale mappen'; // message listing $labels['subject'] = 'Onderwerp'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Lijstweergave'; $labels['folderactions'] = 'Mapacties...'; $labels['compact'] = 'Opschonen'; $labels['empty'] = 'Legen'; +$labels['importmessages'] = 'Berichten importeren'; $labels['quota'] = 'Opslagverbruik'; $labels['unknown'] = 'onbekend'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Wis zoekopdracht'; $labels['searchmod'] = 'Zoekopties'; $labels['msgtext'] = 'Gehele bericht'; $labels['body'] = 'Inhoud'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Openen in een nieuw venster'; $labels['emlsave'] = 'Opslaan (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Laatste pagina'; $labels['group'] = 'Groep'; $labels['groups'] = 'Groepen'; +$labels['listgroup'] = 'Toon groepsleden'; $labels['personaladrbook'] = 'Persoonlijk adresboek'; $labels['searchsave'] = 'Zoekopdracht opslaan'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Negeer woorden met cijfers'; $labels['spellcheckignorecaps'] = 'Negeer woorden welke volledig uit hoofdletters bestaan'; $labels['addtodict'] = 'Voeg toe aan woordenboek'; $labels['mailtoprotohandler'] = 'Registreer protocolhandler voor mailto: links'; +$labels['standardwindows'] = 'Behandel pop-ups als normale vensters'; $labels['forwardmode'] = 'Berichten doorsturen'; $labels['inline'] = 'invoegen'; $labels['asattachment'] = 'als bijlage'; diff --git a/program/localization/nn_NO/labels.inc b/program/localization/nn_NO/labels.inc index d1a1c5700..5934a01d9 100644 --- a/program/localization/nn_NO/labels.inc +++ b/program/localization/nn_NO/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Kladd'; $labels['sent'] = 'Sendt'; $labels['trash'] = 'Sletta'; $labels['junk'] = 'Søppel'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Emne'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Listevisningmodus'; $labels['folderactions'] = 'Mappehandlingar'; $labels['compact'] = 'Kompakt'; $labels['empty'] = 'Tom'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Plassbruk'; $labels['unknown'] = 'ukjend'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Tilbakestill søk'; $labels['searchmod'] = 'Søkeutsagn'; $labels['msgtext'] = 'Heile eposten'; $labels['body'] = 'Meldingstekst'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Opna i nytt vindauga'; $labels['emlsave'] = 'Last ned (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Siste side'; $labels['group'] = 'Gruppe'; $labels['groups'] = 'Gruppar'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Personlege adresser'; $labels['searchsave'] = 'Lagre søk'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorer ord med tal'; $labels['spellcheckignorecaps'] = 'Ignorer ord med berre store bokstavar'; $labels['addtodict'] = 'Legg til i ordliste'; $labels['mailtoprotohandler'] = 'Registrer protokollhandsaming for mailto-lenkjer'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Meldingar vidaresendast'; $labels['inline'] = 'i teksten'; $labels['asattachment'] = 'som vedlegg'; diff --git a/program/localization/pl_PL/labels.inc b/program/localization/pl_PL/labels.inc index 426ac381e..d7b9cd2d4 100644 --- a/program/localization/pl_PL/labels.inc +++ b/program/localization/pl_PL/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Kopie robocze'; $labels['sent'] = 'WysÅ‚ane'; $labels['trash'] = 'Kosz'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Pokaż prawdziwe nazwy dla folderów specjalnych'; // message listing $labels['subject'] = 'Temat'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Typ listy'; $labels['folderactions'] = 'DziaÅ‚ania na folderach...'; $labels['compact'] = 'PorzÄ…dkuj'; $labels['empty'] = 'Opróżnij'; +$labels['importmessages'] = 'Import wiadomoÅ›ci'; $labels['quota'] = 'Użyte miejsce'; $labels['unknown'] = 'nieznane'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Wyczyść filtr'; $labels['searchmod'] = 'Parametry wyszukiwania'; $labels['msgtext'] = 'CaÅ‚a wiadomość'; $labels['body'] = 'Treść'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Otwórz w nowym oknie'; $labels['emlsave'] = 'Pobierz (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Ostatnia strona'; $labels['group'] = 'Grupa'; $labels['groups'] = 'Grupy'; +$labels['listgroup'] = 'CzÅ‚onkowie grupy'; $labels['personaladrbook'] = 'Kontakty osobiste'; $labels['searchsave'] = 'Zapisz wyszukiwanie'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignoruj sÅ‚owa zawierajÄ…ce cyfry'; $labels['spellcheckignorecaps'] = 'Ignoruj sÅ‚owa pisane wielkimi literami'; $labels['addtodict'] = 'Dodaj do sÅ‚ownika'; $labels['mailtoprotohandler'] = 'Zainstaluj obsÅ‚ugÄ™ linków mailto:'; +$labels['standardwindows'] = 'Traktuj okna wyskakujÄ…ce jako standardowe okna'; $labels['forwardmode'] = 'Przekazywanie wiadomoÅ›ci'; $labels['inline'] = 'w treÅ›ci'; $labels['asattachment'] = 'jako zaÅ‚Ä…cznik'; diff --git a/program/localization/pl_PL/messages.inc b/program/localization/pl_PL/messages.inc index fb7ad6c97..3cac0c426 100644 --- a/program/localization/pl_PL/messages.inc +++ b/program/localization/pl_PL/messages.inc @@ -126,6 +126,8 @@ $messages['importwait'] = 'Importowanie, proszÄ™ czekać...'; $messages['importformaterror'] = 'Import nieudany! Użyty plik nie jest poprawnym plikiem importu danych.'; $messages['importconfirm'] = '<b>PomyÅ›lnie dodano $inserted kontaktów, pominiÄ™to $skipped istniejÄ…cych wpisów</b>:<p><em>$names</em></p>.'; $messages['importconfirmskipped'] = '<b>PominiÄ™to $skipped istniejÄ…cych wpisów.</b>'; +$messages['importmessagesuccess'] = 'PomyÅ›lnie zaimportowano nastÄ™pujÄ…cÄ… liczbÄ™ wiadomoÅ›ci: $nr'; +$messages['importmessageerror'] = 'Import nieudany! Wgrywany plik nie jest poprawnÄ… wiadomoÅ›ciÄ… lub plikiem skrzynki pocztowej'; $messages['opnotpermitted'] = 'Niedozwolona operacja!'; $messages['nofromaddress'] = 'Brak adresu e-mail w wybranej tożsamoÅ›ci.'; $messages['editorwarning'] = 'Zmiana edytora spowoduje utratÄ™ formatowania tekstu. Czy jesteÅ› pewien, że chcesz to zrobić?'; diff --git a/program/localization/ps/labels.inc b/program/localization/ps/labels.inc index 262e3d490..d5e513419 100755 --- a/program/localization/ps/labels.inc +++ b/program/localization/ps/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'بارليک'; $labels['sent'] = 'Ù„ÛÚ–Ù„ شوي ليکونه'; $labels['trash'] = 'کثاÙت دانÛ'; $labels['junk'] = 'جنک'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'مضمون'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'Ú©ÛÚšÚ©Ù„ÛŒ'; $labels['empty'] = 'تش'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'ټيکلي لارښود'; $labels['unknown'] = 'نامعلوم'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'د Ù¾Ù„Ù¼Ù†Û Ø¨ÙŠØ§Ø³Ù…ÙˆÙ†'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'په نوي Ú©Ú“Ú©Û Ú©Û Ù¾Ø±Ø§Ù†ÙŠØ²Ù‡'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'پای غونډ وښيه'; $labels['group'] = 'Group'; $labels['groups'] = 'Ú‰Ù„Û'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Úاني پتÛ'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/pt_BR/labels.inc b/program/localization/pt_BR/labels.inc index 9a1946eee..e70ae35b9 100644 --- a/program/localization/pt_BR/labels.inc +++ b/program/localization/pt_BR/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Rascunhos'; $labels['sent'] = 'Enviados'; $labels['trash'] = 'Lixeira'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Exibir o nome real das pastas de sistema'; // message listing $labels['subject'] = 'Assunto'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Visualização em lista'; $labels['folderactions'] = 'Ações para as pastas...'; $labels['compact'] = 'Compactar'; $labels['empty'] = 'Esvaziar'; +$labels['importmessages'] = 'Importar mensagens'; $labels['quota'] = 'Uso de disco'; $labels['unknown'] = 'desconhecido'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Limpar pesquisa'; $labels['searchmod'] = 'Opções da pesquisa'; $labels['msgtext'] = 'Mensagem inteira'; $labels['body'] = 'Conteúdo'; +$labels['type'] = 'Tipo'; $labels['openinextwin'] = 'Abrir em nova janela'; $labels['emlsave'] = 'Baixar (formato .eml)'; @@ -267,7 +270,7 @@ $labels['yourmessage'] = 'Esta é uma confirmação de leitura da sua mensagem'; $labels['receiptnote'] = 'Nota: Esta confirmação de leitura somente informa que a mensagem foi aberta no computador do destinatário. Não há garantia que o destinatário tenha lido ou compreendido o conteúdo da mensagem.'; // address boook -$labels['name'] = 'Nome de exibição'; +$labels['name'] = 'Nome'; $labels['firstname'] = 'Primeiro Nome'; $labels['surname'] = 'Sobrenome'; $labels['middlename'] = 'Segundo Nome'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Última Página'; $labels['group'] = 'Grupo'; $labels['groups'] = 'Grupos'; +$labels['listgroup'] = 'Listar membros do grupo'; $labels['personaladrbook'] = 'Endereços pessoais'; $labels['searchsave'] = 'Salvar pesquisa'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorar palavras com números'; $labels['spellcheckignorecaps'] = 'Ignorar palavras com todas letras maiúsculas'; $labels['addtodict'] = 'Adicionar ao dicionário'; $labels['mailtoprotohandler'] = 'Associar links de e-mail (mailto:) para envio de mensagem através do webmail'; +$labels['standardwindows'] = 'Usar popups como janelas do navegador'; $labels['forwardmode'] = 'Encaminhamento de mensagens'; $labels['inline'] = 'Em linha (no corpo da mensagem)'; $labels['asattachment'] = 'como anexo'; @@ -484,7 +489,7 @@ $labels['messagecount'] = 'Mensagens'; $labels['create'] = 'Criar'; $labels['createfolder'] = 'Criar nova pasta'; $labels['managefolders'] = 'Gerenciar pastas'; -$labels['specialfolders'] = 'Pastas especiais'; +$labels['specialfolders'] = 'Pastas de sistema'; $labels['properties'] = 'Propriedades'; $labels['folderproperties'] = 'Propriedades da pasta'; $labels['parentfolder'] = 'Pasta pai'; diff --git a/program/localization/pt_PT/labels.inc b/program/localization/pt_PT/labels.inc index 316255e5e..cc4c534e0 100644 --- a/program/localization/pt_PT/labels.inc +++ b/program/localization/pt_PT/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Rascunhos'; $labels['sent'] = 'Itens Enviados'; $labels['trash'] = 'Reciclagem'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Mostrar nomes reais para as pastas especiais'; // message listing $labels['subject'] = 'Assunto'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Modo de visualização'; $labels['folderactions'] = 'Acções para pastas...'; $labels['compact'] = 'Compactar'; $labels['empty'] = 'Esvaziar'; +$labels['importmessages'] = 'Importar mensagens'; $labels['quota'] = 'Espaço utilizado'; $labels['unknown'] = 'desconhecido'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Limpar pesquisa'; $labels['searchmod'] = 'Pesquisar em'; $labels['msgtext'] = 'Mensagem completa'; $labels['body'] = 'Corpo'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Abrir numa nova janela'; $labels['emlsave'] = 'Guardar como (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Última página'; $labels['group'] = 'Grupo'; $labels['groups'] = 'Grupos'; +$labels['listgroup'] = 'Lista de membros do grupo'; $labels['personaladrbook'] = 'Endereços pessoais'; $labels['searchsave'] = 'Guardar pesquisa'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorar palavras com números'; $labels['spellcheckignorecaps'] = 'Ignorar palavras em maiúsculas'; $labels['addtodict'] = 'Adicionar ao dicionário'; $labels['mailtoprotohandler'] = 'Registar manipulador de protocolo para mailto: links'; +$labels['standardwindows'] = 'Lidar com popups como janelas padrão'; $labels['forwardmode'] = 'Reencaminhamento de mensagens'; $labels['inline'] = 'em linha'; $labels['asattachment'] = 'como anexo'; diff --git a/program/localization/ro_RO/labels.inc b/program/localization/ro_RO/labels.inc index 6b59da313..4f6ddb1fa 100644 --- a/program/localization/ro_RO/labels.inc +++ b/program/localization/ro_RO/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Ciorne'; $labels['sent'] = 'Trimise'; $labels['trash'] = 'Gunoi'; $labels['junk'] = 'Spam'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Subiect'; @@ -46,25 +47,25 @@ $labels['to'] = 'Destinatar'; $labels['cc'] = 'Copie (CC)'; $labels['bcc'] = 'Copie oarbă (BCC)'; $labels['replyto'] = 'Răspunde la'; -$labels['followupto'] = 'Followup-To'; +$labels['followupto'] = 'Followup La'; $labels['date'] = 'Data'; $labels['size'] = 'Mărime'; $labels['priority'] = 'Prioritate'; $labels['organization'] = 'OrganizaÅ£ie'; -$labels['readstatus'] = 'Starea de citit'; +$labels['readstatus'] = 'Citit/Necitit'; $labels['listoptions'] = 'Listează opÅ£iunile...'; $labels['mailboxlist'] = 'Dosare'; $labels['messagesfromto'] = 'Mesaje de la $from până la $to din $count'; $labels['threadsfromto'] = 'Grupuri de la $from până la $to din $count'; -$labels['messagenrof'] = '$nr mesaje din $count'; +$labels['messagenrof'] = 'Mesajul $nr din $count'; $labels['fromtoshort'] = '$from - $to din $count'; $labels['copy'] = 'Copiază'; $labels['move'] = 'Mută'; $labels['moveto'] = 'Mută in...'; $labels['download'] = 'Descarcă'; -$labels['open'] = 'Open'; +$labels['open'] = 'Deschide'; $labels['showattachment'] = 'Arată'; $labels['showanyway'] = 'Arată oricum'; @@ -127,22 +128,22 @@ $labels['checkmail'] = 'Verifică mesaje noi'; $labels['compose'] = 'Scrie un mesaj'; $labels['writenewmessage'] = 'Scrie mesaj nou'; $labels['reply'] = 'Răspunde'; -$labels['replytomessage'] = 'Răspunde la mesaj'; +$labels['replytomessage'] = 'Răspunde expeditorului'; $labels['replytoallmessage'] = 'Răspunde la toÅ£i'; $labels['replyall'] = 'Răspunde la toÅ£i'; -$labels['replylist'] = 'Lista de răspuns'; +$labels['replylist'] = 'Răspunde listei'; $labels['forward'] = 'ÃŽnaintează'; $labels['forwardinline'] = 'ÃŽnaintează ca citat'; $labels['forwardattachment'] = 'ÃŽnaintează ca ataÅŸament'; $labels['forwardmessage'] = 'Trimite mesajul mai departe'; -$labels['deletemessage'] = 'Trimite mesajul la gunoi'; +$labels['deletemessage'] = 'Șterge mesajul'; $labels['movemessagetotrash'] = 'Mută mesajul la gunoi'; $labels['printmessage'] = 'Listează mesajul'; $labels['previousmessage'] = 'AfiÅŸează mesajul anterior'; $labels['firstmessage'] = 'AfiÅŸează primul mesaj'; $labels['nextmessage'] = 'AfiÅŸează următorul mesaj'; $labels['lastmessage'] = 'AfiÅŸează ultimul mesaj'; -$labels['backtolist'] = 'ÃŽnapoi la lista cu mesaje'; +$labels['backtolist'] = 'ÃŽnapoi la mesaje'; $labels['viewsource'] = 'AfiÅŸează sursa'; $labels['mark'] = 'Marchează'; $labels['markmessages'] = 'Marchează mesajele'; @@ -157,12 +158,12 @@ $labels['options'] = 'OpÅ£iuni'; $labels['select'] = 'Selectează'; $labels['all'] = 'Toate'; -$labels['none'] = 'Fără sortare'; +$labels['none'] = 'Niciunul'; $labels['currpage'] = 'Pagina curentă'; $labels['unread'] = 'Necitite'; $labels['flagged'] = 'Marcat'; $labels['unanswered'] = 'Fără răspuns'; -$labels['withattachment'] = 'With attachment'; +$labels['withattachment'] = 'Cu ataÈ™ament'; $labels['deleted'] = 'Åžterse'; $labels['undeleted'] = 'Nu a fost È™ters'; $labels['invert'] = 'Inversează'; @@ -190,9 +191,10 @@ $labels['listsorting'] = 'Sortează după'; $labels['listorder'] = 'Ordinea de sortare'; $labels['listmode'] = 'Mod de vizualizare'; -$labels['folderactions'] = 'Actiuni asupra folder-ului...'; +$labels['folderactions'] = 'AcÈ›iuni dosar...'; $labels['compact'] = 'Compactează'; $labels['empty'] = 'GoleÅŸte'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'SpaÅ£iu folosit'; $labels['unknown'] = 'necunoscut'; @@ -203,17 +205,18 @@ $labels['resetsearch'] = 'Anulează căutarea'; $labels['searchmod'] = 'Parametrii de căutare'; $labels['msgtext'] = 'Tot mesajul'; $labels['body'] = 'Corp'; +$labels['type'] = 'Type'; -$labels['openinextwin'] = 'Deschide într-o fereastră nouă'; +$labels['openinextwin'] = 'Deschide în fereastră nouă'; $labels['emlsave'] = 'Salvează în format .eml'; -$labels['changeformattext'] = 'Display in plain text format'; -$labels['changeformathtml'] = 'Display in HTML format'; +$labels['changeformattext'] = 'AfiÈ™ează în format text'; +$labels['changeformathtml'] = 'AfiÈ™ează în format HTML'; // message compose $labels['editasnew'] = 'Editează ca nou'; $labels['send'] = 'Trimite'; $labels['sendmessage'] = 'Trimite mesaj'; -$labels['savemessage'] = 'Salvează această ciornă'; +$labels['savemessage'] = 'Salvează ciornă'; $labels['addattachment'] = 'AtaÅŸează fiÅŸier'; $labels['charset'] = 'Set de caractere'; $labels['editortype'] = 'Tip de editor'; @@ -244,21 +247,21 @@ $labels['highest'] = 'Cea mai mare'; $labels['nosubject'] = '(fără subiect)'; $labels['showimages'] = 'AfiÅŸează imagini'; $labels['alwaysshow'] = 'AfiÅŸează întotdeauna imaginile de la $sender'; -$labels['isdraft'] = 'Acesta este un mesaj schiţă.'; +$labels['isdraft'] = 'Acest mesaj este o ciornă.'; $labels['andnmore'] = '$nr mai multe...'; $labels['togglemoreheaders'] = 'Arată mai mult din antet'; $labels['togglefullheaders'] = 'Arată mai puÈ›in din antet'; $labels['htmltoggle'] = 'HTML'; $labels['plaintoggle'] = 'Text simplu'; -$labels['savesentmessagein'] = 'Salvează mesajele în'; +$labels['savesentmessagein'] = 'Salvează mesajele trimise în'; $labels['dontsave'] = 'Nu salva'; -$labels['maxuploadsize'] = 'Mărimea maximă admisă a fiÅŸierului este $size'; +$labels['maxuploadsize'] = 'Mărimea maxim admisă a fiÅŸierului este $size'; -$labels['addcc'] = 'Adaugă Cc'; -$labels['addbcc'] = 'Adaugă Bcc'; +$labels['addcc'] = 'Adaugă CC'; +$labels['addbcc'] = 'Adaugă BCC'; $labels['addreplyto'] = 'Adaugă Raspunde-La'; -$labels['addfollowupto'] = 'Adaugă Followup-To'; +$labels['addfollowupto'] = 'Adaugă Followup-La'; // mdn $labels['mdnrequest'] = 'Expeditorul acestui mesaj a solicitat să fie notificat la cititrea mesajului. DoriÅ£i să notificaÅ£i expeditorul?'; @@ -267,7 +270,7 @@ $labels['yourmessage'] = 'Aceasta este o confirmare de primire a mesajului dumne $labels['receiptnote'] = 'Notă: Această confirmare doar vă informează că mesajul a fost afiÅŸat pe calculatorul destinatarului. Nu există nici o garanÅ£ie că destinatarul a citit sau a inÅ£eles conÅ£inutul mesajului.'; // address boook -$labels['name'] = 'Numele Contactului'; +$labels['name'] = 'Numele Contact'; $labels['firstname'] = 'Nume'; $labels['surname'] = 'Prenume'; $labels['middlename'] = 'IniÅ£iala tatălui'; @@ -281,11 +284,11 @@ $labels['maidenname'] = 'Nume de fată'; $labels['email'] = 'E-Mail'; $labels['phone'] = 'Telefon'; $labels['address'] = 'Adresă'; -$labels['street'] = 'Stradă'; +$labels['street'] = 'Strada'; $labels['locality'] = 'OraÈ™'; $labels['zipcode'] = 'Cod poÅŸtal'; $labels['region'] = 'Stat/JudeÅ£'; -$labels['country'] = 'Èšară'; +$labels['country'] = 'Èšara'; $labels['birthday'] = 'Ziua de naÅŸtere:'; $labels['anniversary'] = 'Aniversare'; $labels['website'] = 'Pagină web'; @@ -302,8 +305,8 @@ $labels['advsearch'] = 'Căutare avansată'; $labels['advanced'] = 'Avansat'; $labels['other'] = 'Altele'; -$labels['typehome'] = 'Pagina Principală'; -$labels['typework'] = 'Servici'; +$labels['typehome'] = 'Acasă'; +$labels['typework'] = 'Serviciu'; $labels['typeother'] = 'Altele'; $labels['typemobile'] = 'Mobil'; $labels['typemain'] = 'Principal'; @@ -318,7 +321,7 @@ $labels['typeblog'] = 'Blog'; $labels['typeprofile'] = 'Profil'; $labels['addfield'] = 'Adaugă câmp...'; -$labels['addcontact'] = 'Adaugă contactul selectat în agendă'; +$labels['addcontact'] = 'Adaugă contact nou'; $labels['editcontact'] = 'Modifică contact'; $labels['contacts'] = 'Contacte'; $labels['contactproperties'] = 'Proprietăţile contactului...'; @@ -331,7 +334,7 @@ $labels['delete'] = 'Åžterge'; $labels['rename'] = 'RedenumeÅŸte'; $labels['addphoto'] = 'Adaugă'; $labels['replacephoto'] = 'ÃŽnlocuieÈ™te'; -$labels['uploadphoto'] = 'ÃŽncarcă poya'; +$labels['uploadphoto'] = 'ÃŽncarcă imagine'; $labels['newcontact'] = 'Creează contact nou'; $labels['deletecontact'] = 'Åžterge contactul selectat'; @@ -348,12 +351,13 @@ $labels['groupdelete'] = 'Șterge grupul'; $labels['groupremoveselected'] = 'Șterge contactele selectate din grup'; $labels['previouspage'] = 'Pagina anterioară'; -$labels['firstpage'] = 'Arată primul set'; +$labels['firstpage'] = 'Prima pagină'; $labels['nextpage'] = 'Pagina următoare'; -$labels['lastpage'] = 'Arată ultimul set'; +$labels['lastpage'] = 'Ultima pagină'; $labels['group'] = 'Grup'; $labels['groups'] = 'Grupuri'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Adrese personale'; $labels['searchsave'] = 'Salvează căutarea'; @@ -364,7 +368,7 @@ $labels['importcontacts'] = 'Importă contacte'; $labels['importfromfile'] = 'Importă din fiÅŸier:'; $labels['importtarget'] = 'Adaugă contactele noi în agenda:'; $labels['importreplace'] = 'ÃŽnlocuieÅŸte întreaga agendă'; -$labels['importdesc'] = 'PuteÈ›i încărcat contacte dintr-o agendă existentă.<br/>Momentan este suportat importul în formatul <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> sau în formatul CSV (comma-separated).'; +$labels['importdesc'] = 'PuteÈ›i încărca contacte dintr-o agendă existentă.<br/>Momentan este suportat importul în formatul <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> sau în formatul CSV (comma-separated).'; $labels['done'] = 'Finalizat'; // settings @@ -395,14 +399,14 @@ $labels['language'] = 'Limba'; $labels['timezone'] = 'Fus orar'; $labels['pagesize'] = 'Rânduri pe pagină'; $labels['signature'] = 'Semnătură'; -$labels['dstactive'] = 'Reglare automată oră de vară'; +$labels['dstactive'] = 'Reglare ora de vară'; $labels['showinextwin'] = 'Deschide mesajul în fereastră nouă'; $labels['composeextwin'] = 'Compune mesajul în fereastră nouă'; $labels['htmleditor'] = 'Scrie mesaje HTML'; $labels['htmlonreply'] = 'la răspunsul doar către un mesaj HTML'; $labels['htmlonreplyandforward'] = 'la trimitere mai departe sau la răspuns la mesaj HTML'; $labels['htmlsignature'] = 'Semnatură HTML'; -$labels['showemail'] = 'Show email address with display name'; +$labels['showemail'] = 'Arată adresa email alături de nume afiÈ™at'; $labels['previewpane'] = 'Previzualizare mail'; $labels['skin'] = 'Temă interfaţă'; $labels['logoutclear'] = 'GoleÅŸte CoÅŸul de Gunoi la deconectare'; @@ -411,15 +415,15 @@ $labels['uisettings'] = 'Interfaţă utilizator'; $labels['serversettings'] = 'ConfiguraÅ£ii server'; $labels['mailboxview'] = 'AfiÅŸare căsuţă poÅŸtală'; $labels['mdnrequests'] = 'Notificări expeditor'; -$labels['askuser'] = 'întreabă utilizatorul'; +$labels['askuser'] = 'întreabă-mă'; $labels['autosend'] = 'trimite automat'; $labels['autosendknown'] = 'trimite confirmarea de primire către contactele mele, în rest întreabă-mă'; $labels['autosendknownignore'] = 'trimite confirmarea de primire către contactele mele, în rest ignoră'; $labels['ignore'] = 'ignoră'; -$labels['readwhendeleted'] = 'Marchează mesajul ca ÅŸi citit la ÅŸtergere'; +$labels['readwhendeleted'] = 'Marchează mesajul ca citit la ÅŸtergere'; $labels['flagfordeletion'] = 'Marchează mesajul pentru ÅŸtergere în loc de a-l ÅŸterge direct'; $labels['skipdeleted'] = 'Nu arăta mesajele ÅŸterse'; -$labels['deletealways'] = 'Dacă mutarea mesajelor în coÅŸ eÅŸuează, se vor ÅŸterge'; +$labels['deletealways'] = 'Dacă mutarea mesajelor în CoÅŸ eÅŸuează, È™terge-le'; $labels['deletejunk'] = 'Șterge direct mesajele în Junk'; $labels['showremoteimages'] = 'Arată imaginile care nu fac parte din e-mail'; $labels['fromknownsenders'] = 'de la expeditori cunoscuÅ£i'; @@ -443,7 +447,7 @@ $labels['checkallfolders'] = 'Verifică toate dosarele pentru mesaje noi'; $labels['displaynext'] = 'După ÅŸtergerea sau mutarea unui mesaj afiÅŸează-l pe următorul din listă'; $labels['defaultfont'] = 'Font-ul implicit al mesajului HTML'; $labels['mainoptions'] = 'OpÅ£iuni principale'; -$labels['browseroptions'] = 'Optiuni browser'; +$labels['browseroptions'] = 'OpÈ›iuni browser'; $labels['section'] = 'SecÅ£iune'; $labels['maintenance'] = 'Mentenanţă'; $labels['newmessage'] = 'Mesaj nou'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignoră cuvintele cu numere'; $labels['spellcheckignorecaps'] = 'Ignoră cuvintele din litere mari'; $labels['addtodict'] = 'Adaugă la dicÅ£ionar'; $labels['mailtoprotohandler'] = 'ÃŽregistrează handler protocol pentru mailto: link-uri'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Trimitere mai departe mesaj'; $labels['inline'] = 'într-e linii'; $labels['asattachment'] = 'ca ataÈ™ament'; diff --git a/program/localization/ru_RU/labels.inc b/program/localization/ru_RU/labels.inc index 8a136aa77..d2b8e75c4 100644 --- a/program/localization/ru_RU/labels.inc +++ b/program/localization/ru_RU/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Черновики'; $labels['sent'] = 'Отправленные'; $labels['trash'] = 'Корзина'; $labels['junk'] = 'СПÐÐœ'; +$labels['show_real_foldernames'] = 'Показывать наÑтоÑщие Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ñпециальных папок'; // message listing $labels['subject'] = 'Тема'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Режим проÑмотра'; $labels['folderactions'] = 'Операции над папкой...'; $labels['compact'] = 'Сжать'; $labels['empty'] = 'ОпуÑтошить'; +$labels['importmessages'] = 'Импорт Ñообщений'; $labels['quota'] = 'Квота'; $labels['unknown'] = 'неизвеÑтно'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'СброÑ'; $labels['searchmod'] = 'Варианты поиÑка'; $labels['msgtext'] = 'Ð’ÑÑ‘ Ñообщение'; $labels['body'] = 'Тело пиÑьма'; +$labels['type'] = 'Тип'; $labels['openinextwin'] = 'Открыть в новом окне'; $labels['emlsave'] = 'Сохранить (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Показать поÑледнюю ÑÑ‚Ñ€Ð°Ð½Ð¸Ñ†Ñ $labels['group'] = 'Группа'; $labels['groups'] = 'Группы'; +$labels['listgroup'] = 'СпиÑок членов группы'; $labels['personaladrbook'] = 'ПерÑональные адреÑа'; $labels['searchsave'] = 'Сохранить запроÑ'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'ПропуÑкать Ñлова Ñ Ñ†Ð¸Ñ„Ñ€Ð° $labels['spellcheckignorecaps'] = 'ПропуÑкать Ñлова из пропиÑных букв'; $labels['addtodict'] = 'Добавить в Ñловарь'; $labels['mailtoprotohandler'] = 'ЗарегиÑтрировать обработчик Ð´Ð»Ñ ÑÑылок mailto:'; +$labels['standardwindows'] = 'Обрабатывать вÑплывающие окна как обычные'; $labels['forwardmode'] = 'ПереÑылка Ñообщений'; $labels['inline'] = 'в текÑте'; $labels['asattachment'] = 'как вложение'; diff --git a/program/localization/si_LK/labels.inc b/program/localization/si_LK/labels.inc index d8cd71662..92d33d3b7 100644 --- a/program/localization/si_LK/labels.inc +++ b/program/localization/si_LK/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'කටු සටහන්'; $labels['sent'] = 'යà·à·€à·–'; $labels['trash'] = 'ඉවà¶à¶½à¶± බඳුන'; $labels['junk'] = 'සුන්බුන්'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'මà·à¶à·˜à¶šà·à·€'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'බහà·à¶½à·”ම් ක්â€à¶»à·’යà·...'; $labels['compact'] = 'සංයුක්à¶'; $labels['empty'] = 'හිස්'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Disk usage'; $labels['unknown'] = 'නොදනී'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'සෙවුම යලි පිහිටවීම'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'සම්පූර්ණ පණිවිඩය'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'නව කවුළුවක විවෘචකරන්න'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'අවසà·à¶± පිටුව පෙන්වනà $labels['group'] = 'කණ්ඩà·à¶ºà¶¸'; $labels['groups'] = 'කණ්ඩà·à¶ºà¶¸à·Š'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'පුද්ගලික ලිපිනය'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'අංක සහිචවචන නොසල $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'à·à¶¶à·Šà¶¯ කà·à·‚යට එක් කරන්න'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/sk_SK/labels.inc b/program/localization/sk_SK/labels.inc index 10673382a..465252409 100644 --- a/program/localization/sk_SK/labels.inc +++ b/program/localization/sk_SK/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'RozpÃsané'; $labels['sent'] = 'Odoslané'; $labels['trash'] = 'Kôš'; $labels['junk'] = 'Nevyžiadaná poÅ¡ta'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Predmet'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Režim zobrazenia zoznamu'; $labels['folderactions'] = 'Akcie so zložkou...'; $labels['compact'] = 'ZhustiÅ¥ prieÄinok'; $labels['empty'] = 'VyprázdniÅ¥'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Zaplnenie schránky'; $labels['unknown'] = 'neznáme'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'VyÄistiÅ¥ vyhľadávanie'; $labels['searchmod'] = 'Parametre hľadanie'; $labels['msgtext'] = 'Celá správa'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'OtvoriÅ¥ v novom okne'; $labels['emlsave'] = 'StiahnuÅ¥'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Posledná stránka'; $labels['group'] = 'Skupina'; $labels['groups'] = 'Skupiny'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Osobné adresy'; $labels['searchsave'] = 'UložiÅ¥ vyhľadávanie'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'IgnorovaÅ¥ slová s ÄÃslami'; $labels['spellcheckignorecaps'] = 'IgnorovaÅ¥ slová pÃsané veľkými pÃsmenami'; $labels['addtodict'] = 'PridaÅ¥ do slovnÃka'; $labels['mailtoprotohandler'] = 'ZaregistrovaÅ¥ handler pre odkazy „mailto:“'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Preposielanie správ'; $labels['inline'] = 'v tele spávy'; $labels['asattachment'] = 'ako prÃloha'; diff --git a/program/localization/sl_SI/labels.inc b/program/localization/sl_SI/labels.inc index 6b9ba2d41..c33ea479c 100644 --- a/program/localization/sl_SI/labels.inc +++ b/program/localization/sl_SI/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Osnutki'; $labels['sent'] = 'Poslano'; $labels['trash'] = 'Smeti'; $labels['junk'] = 'Nezaželena sporoÄila'; +$labels['show_real_foldernames'] = 'Prikaži prava imena za posebne mape'; // message listing $labels['subject'] = 'Zadeva'; @@ -162,7 +163,7 @@ $labels['currpage'] = 'Trenutna stran'; $labels['unread'] = 'Neprebrano'; $labels['flagged'] = 'OznaÄeno'; $labels['unanswered'] = 'NeoznaÄeno'; -$labels['withattachment'] = 'With attachment'; +$labels['withattachment'] = 'S priponko'; $labels['deleted'] = 'Izbrisano'; $labels['undeleted'] = 'Ni izbrisano'; $labels['invert'] = 'Zamenjaj'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'NaÄin prikaza seznama'; $labels['folderactions'] = 'Upravljanje map...'; $labels['compact'] = 'Stisni'; $labels['empty'] = 'Izprazni'; +$labels['importmessages'] = 'Uvozi sporoÄila'; $labels['quota'] = 'Poraba prostora'; $labels['unknown'] = 'neznana'; @@ -203,11 +205,12 @@ $labels['resetsearch'] = 'PrekliÄi iskanje'; $labels['searchmod'] = 'Spremembe iskanja'; $labels['msgtext'] = 'Celotno sporoÄilo'; $labels['body'] = 'Vsebina sporoÄila'; +$labels['type'] = 'Tip'; $labels['openinextwin'] = 'Odpri v novem oknu'; $labels['emlsave'] = 'Prenos datoteke (.eml)'; -$labels['changeformattext'] = 'Display in plain text format'; -$labels['changeformathtml'] = 'Display in HTML format'; +$labels['changeformattext'] = 'Prikaži kot golo besedilo'; +$labels['changeformathtml'] = 'Prikaži v formatu HTML'; // message compose $labels['editasnew'] = 'Uredi kot novo'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Zadnja stran'; $labels['group'] = 'Skupina'; $labels['groups'] = 'Skupine'; +$labels['listgroup'] = 'IzpiÅ¡i seznam Älanov skupine'; $labels['personaladrbook'] = 'Stiki'; $labels['searchsave'] = 'Shrani iskanje'; @@ -402,7 +406,7 @@ $labels['htmleditor'] = 'Sestavi sporoÄila z obogatenim besedilom'; $labels['htmlonreply'] = 'le pri odgovoru na sporoÄila z obogatenim besedilom'; $labels['htmlonreplyandforward'] = 'le pri posredovanju ali odgovoru na sporoÄila z obogatenim besedilom'; $labels['htmlsignature'] = 'Podpis z obogatenim besedilom'; -$labels['showemail'] = 'Show email address with display name'; +$labels['showemail'] = 'Prikaži e-naslove poleg imen'; $labels['previewpane'] = 'Prikaži predogled'; $labels['skin'] = 'Tema uporabniÅ¡kega vmesnika'; $labels['logoutclear'] = 'Izprazni mapo Smeti ob odjavi'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ne upoÅ¡tevaj besed, ki vsebujejo Å¡tevilke'; $labels['spellcheckignorecaps'] = 'Ne upoÅ¡tevaj besed, ki vsebujejo samo velike Ärke'; $labels['addtodict'] = 'Dodaj v slovar'; $labels['mailtoprotohandler'] = 'Registriraj upravljavca protokola za e-naslov: povezave'; +$labels['standardwindows'] = 'Prikaži pojavna okna kot obiÄajna'; $labels['forwardmode'] = 'Posredovanje sporoÄil'; $labels['inline'] = 'medvrstiÄno'; $labels['asattachment'] = 'Kot priponka'; diff --git a/program/localization/sl_SI/messages.inc b/program/localization/sl_SI/messages.inc index 081d912c1..dc731d01b 100644 --- a/program/localization/sl_SI/messages.inc +++ b/program/localization/sl_SI/messages.inc @@ -126,6 +126,8 @@ $messages['importwait'] = 'Uvažanje poteka...'; $messages['importformaterror'] = 'Uvoz ni uspel! Uvožena datoteka ni pravega formata.'; $messages['importconfirm'] = '<b>UspeÅ¡no uvoženi $inserted stiki, $skipped stikov že obstaja v imeniku</b>:<p><em>$names</em></p>'; $messages['importconfirmskipped'] = '<b>PreskoÄeni že obstojeÄi vnosi $skipped </b>'; +$messages['importmessagesuccess'] = 'UpeÅ¡no ste uvozili $nr sporoÄil.'; +$messages['importmessageerror'] = 'Uvoz je spodletel. Naložena datoteka ni veljavno sporoÄilo ali poÅ¡tna datoteka'; $messages['opnotpermitted'] = 'Operacija ni dovoljena.'; $messages['nofromaddress'] = 'V izbrani identiteti manjka elektronski naslov.'; $messages['editorwarning'] = 'Preklop v sploÅ¡en urejevalnik onemogoÄa uporabo izbranih nastavitev oblikovanja. Želite nadaljevati?'; diff --git a/program/localization/sq_AL/labels.inc b/program/localization/sq_AL/labels.inc index ba9b559d8..e2cb6791b 100644 --- a/program/localization/sq_AL/labels.inc +++ b/program/localization/sq_AL/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Drafte'; $labels['sent'] = 'Dërguar'; $labels['trash'] = 'Fshirë'; $labels['junk'] = 'Reklama'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Tema'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'Zvogëlo'; $labels['empty'] = 'Boshatis'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Përdorimi i diskut'; $labels['unknown'] = 'i panjohur'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Pastro kërkimin'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Open in new window'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Shfaq grupin e fundit'; $labels['group'] = 'Group'; $labels['groups'] = 'Grupet'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Adresat Personale'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/sr_CS/labels.inc b/program/localization/sr_CS/labels.inc index 130d3a7a6..4bdf25020 100644 --- a/program/localization/sr_CS/labels.inc +++ b/program/localization/sr_CS/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'U pripremi'; $labels['sent'] = 'ПоÑлате'; $labels['trash'] = 'Канта'; $labels['junk'] = 'Смеће'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'ÐаÑлов'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'ЛиÑÑ‚ режим приказивања'; $labels['folderactions'] = 'ПоÑтавке фаÑцикле'; $labels['compact'] = 'Компакција'; $labels['empty'] = 'ИÑпразни'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Квота'; $labels['unknown'] = 'непозната'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Прикажи Ñве поруке'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Цела порука'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Отвори у новом прозору'; $labels['emlsave'] = 'Довнлоад (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Прикажи поÑледњи Ñкуп'; $labels['group'] = 'Група'; $labels['groups'] = 'Групе'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Личне адреÑе'; $labels['searchsave'] = 'Сачувај претрагу'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'игнориши речи Ñа бројевР$labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Додај у речник'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/sv_SE/labels.inc b/program/localization/sv_SE/labels.inc index f61433527..7169aeba8 100644 --- a/program/localization/sv_SE/labels.inc +++ b/program/localization/sv_SE/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Utkast'; $labels['sent'] = 'Skickat'; $labels['trash'] = 'Papperskorg'; $labels['junk'] = 'Skräp'; +$labels['show_real_foldernames'] = 'Visa verkliga namn pÃ¥ särskilda kataloger'; // message listing $labels['subject'] = 'Ämne'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Visningsläge'; $labels['folderactions'] = 'Hantera kataloger'; $labels['compact'] = 'Packa'; $labels['empty'] = 'Töm'; +$labels['importmessages'] = 'Importera meddelanden'; $labels['quota'] = 'Diskutrymme'; $labels['unknown'] = 'okänt'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Ã…terställ sökning'; $labels['searchmod'] = 'Sökalternativ'; $labels['msgtext'] = 'Hela meddelandet'; $labels['body'] = 'InnehÃ¥ll'; +$labels['type'] = 'Typ'; $labels['openinextwin'] = 'Öppna i nytt fönster'; $labels['emlsave'] = 'Spara (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Visa sista sidan'; $labels['group'] = 'Grupp'; $labels['groups'] = 'Kontaktgrupper'; +$labels['listgroup'] = 'Visa gruppmedlemmar'; $labels['personaladrbook'] = 'Personliga adresser'; $labels['searchsave'] = 'Lägg till sökning'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignorera ord med siffror'; $labels['spellcheckignorecaps'] = 'Ignorera ord med enbart stora bokstäver'; $labels['addtodict'] = 'Lägg till i ordlista'; $labels['mailtoprotohandler'] = 'Ange program för hantering av mailto-länkar'; +$labels['standardwindows'] = 'Hantera popup-rutor som standardfönster'; $labels['forwardmode'] = 'Vidarebefordra meddelande'; $labels['inline'] = 'Infogat'; $labels['asattachment'] = 'Bilaga'; diff --git a/program/localization/ta_IN/labels.inc b/program/localization/ta_IN/labels.inc index bc1db7d00..197e80606 100644 --- a/program/localization/ta_IN/labels.inc +++ b/program/localization/ta_IN/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'வரைவà¯à®•à®³à¯'; $labels['sent'] = 'அனà¯à®ªà¯à®ªà®¿à®¯ அஞà¯à®šà®²à¯'; $labels['trash'] = 'கà¯à®ªà¯à®ªà¯ˆ'; $labels['junk'] = 'எரிதமà¯'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'தலைபà¯à®ªà¯'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'கà¯à®±à¯à®•à®¿à®¯'; $labels['empty'] = 'காலி'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'பயனà¯à®ªà®¾à®Ÿà¯à®Ÿà¯ அளவà¯'; $labels['unknown'] = 'தெரியாத'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'தேடலை மறà¯à®…மை'; $labels['searchmod'] = 'மாறà¯à®±à®¿à®•à®³à¯ˆ தேடà¯'; $labels['msgtext'] = 'à®®à¯à®´à¯ செயà¯à®¤à®¿'; $labels['body'] = 'Body'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'பà¯à®¤à¯ சாளரதà¯à®¤à®¿à®²à¯ திற'; $labels['emlsave'] = 'பதிவிறகà¯à®•à¯ (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'கடைசி கà¯à®´à¯à®µà¯ˆ காடà¯à®Ÿà $labels['group'] = 'Group'; $labels['groups'] = 'கà¯à®´à¯à®•à¯à®•à®³à¯'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'சà¯à®¯ à®®à¯à®•à®µà®°à®¿'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; diff --git a/program/localization/th_TH/labels.inc b/program/localization/th_TH/labels.inc index 03b4161fb..85b091e5b 100644 --- a/program/localization/th_TH/labels.inc +++ b/program/localization/th_TH/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'à¸à¸¥à¹ˆà¸à¸‡à¸ˆà¸”หมายร่าง'; $labels['sent'] = 'à¸à¸¥à¹ˆà¸à¸‡à¸‚าà¸à¸à¸'; $labels['trash'] = 'ถังขยะ'; $labels['junk'] = 'à¸à¸¥à¹ˆà¸à¸‡à¸ˆà¸”หมายขยะ'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'หัวจดหมาย'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'List view mode'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'à¹à¸šà¸šà¸¢à¹ˆà¸'; $labels['empty'] = 'ว่างเปล่า'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'พื้นที่ใช้งาน'; $labels['unknown'] = 'ไม่ทราบ'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ล้างà¸à¸²à¸£à¸„้นหา'; $labels['searchmod'] = 'Search modifiers'; $labels['msgtext'] = 'Entire message'; $labels['body'] = 'เนื้à¸à¸«à¸²'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Open in new window'; $labels['emlsave'] = 'Download (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Show last page'; $labels['group'] = 'Group'; $labels['groups'] = 'Groups'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Personal Addresses'; $labels['searchsave'] = 'Save search'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ignore words with numbers'; $labels['spellcheckignorecaps'] = 'Ignore words with all letters capitalized'; $labels['addtodict'] = 'Add to dictionary'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'เป็นไฟล์à¹à¸™à¸š'; diff --git a/program/localization/tr_TR/labels.inc b/program/localization/tr_TR/labels.inc index 9e78ea3fa..c62c5c079 100644 --- a/program/localization/tr_TR/labels.inc +++ b/program/localization/tr_TR/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Taslaklar'; $labels['sent'] = 'Giden'; $labels['trash'] = 'Çöp'; $labels['junk'] = 'Ä°stenmeyen'; +$labels['show_real_foldernames'] = 'Özel klasörler için gerçek isimleri göster'; // message listing $labels['subject'] = 'Konu'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Liste görünümü'; $labels['folderactions'] = 'Klasör eylemleri...'; $labels['compact'] = 'SıklaÅŸtır'; $labels['empty'] = 'BoÅŸalt'; +$labels['importmessages'] = 'Mesajları içe aktar'; $labels['quota'] = 'Disk kullanımı'; $labels['unknown'] = 'bilinmeyen'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Aramayı bitir'; $labels['searchmod'] = 'Arama detayları'; $labels['msgtext'] = 'Tüm posta gövdesi'; $labels['body'] = 'Gövde'; +$labels['type'] = 'Tip'; $labels['openinextwin'] = 'Yeni pencerede aç'; $labels['emlsave'] = 'Ä°ndir (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Sonuncuyu göster'; $labels['group'] = 'Grup'; $labels['groups'] = 'Gruplar'; +$labels['listgroup'] = 'Grup üyelerini listele'; $labels['personaladrbook'] = 'Adresler'; $labels['searchsave'] = 'Aramayı kaydet'; @@ -402,7 +406,7 @@ $labels['htmleditor'] = 'HTML postaları oluÅŸtur'; $labels['htmlonreply'] = 'sadece HTML postaları yanıtlarken'; $labels['htmlonreplyandforward'] = 'HTML biçimindeki posta yanıtlandığında veye iletildiÄŸinde'; $labels['htmlsignature'] = 'HTML imza'; -$labels['showemail'] = 'Show email address with display name'; +$labels['showemail'] = 'Eposta adresini görünüm ismi ile görüntüle'; $labels['previewpane'] = 'Önizleme panelini göster'; $labels['skin'] = 'Arayüz görünümü'; $labels['logoutclear'] = 'Oturumu kapatınca Çöpü temizle'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'İçinde rakam geçen kelimleri göz ardı et $labels['spellcheckignorecaps'] = 'Tümü büyük harf olan kelimleri göz ardı et'; $labels['addtodict'] = 'Sözlüğe Ekle'; $labels['mailtoprotohandler'] = 'mailto: baÄŸlantıları için protokol iÅŸleyici kayıt et'; +$labels['standardwindows'] = 'Popup pencerelerini standart pencere olarak yönet'; $labels['forwardmode'] = 'Posta yönlendirme'; $labels['inline'] = 'postanın içinde'; $labels['asattachment'] = 'ek olarak'; diff --git a/program/localization/tr_TR/messages.inc b/program/localization/tr_TR/messages.inc index 3b451d556..3f728b523 100644 --- a/program/localization/tr_TR/messages.inc +++ b/program/localization/tr_TR/messages.inc @@ -126,6 +126,8 @@ $messages['importwait'] = 'Aktarılıyor, lütfen bekleyin...'; $messages['importformaterror'] = 'İçe aktarım baÅŸarısız. Yüklenen dosya geçerli bir içe aktarım dosyası deÄŸil.'; $messages['importconfirm'] = '<b>$inserted kiÅŸi baÅŸarıyla aktarıldı</b>'; $messages['importconfirmskipped'] = '<b>Var olan $skipped girdi atlandı</b>'; +$messages['importmessagesuccess'] = '$nr adet mesaj baÅŸarıyla içe aktarıldı'; +$messages['importmessageerror'] = 'İçe aktarım baÅŸarısız. Yüklenen dosya geçerli bir içe aktarım dosyası deÄŸil.'; $messages['opnotpermitted'] = 'Bu iÅŸleme izin verilmedi!'; $messages['nofromaddress'] = 'Seçili kimlikte e-posta adresi yok'; $messages['editorwarning'] = 'Düz metin düzenleyiciye geçmek, metin üzerindeki bütün biçimlendirmeleri kaldıracak. Devam etmek istiyor musunuz?'; diff --git a/program/localization/uk_UA/labels.inc b/program/localization/uk_UA/labels.inc index 4605bb98d..6ff37ee21 100644 --- a/program/localization/uk_UA/labels.inc +++ b/program/localization/uk_UA/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'Чернетки'; $labels['sent'] = 'ÐадіÑлані'; $labels['trash'] = 'Кошик'; $labels['junk'] = 'Спам'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Тема'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Режим переглÑду'; $labels['folderactions'] = 'Операції з папкою...'; $labels['compact'] = 'СтиÑнути'; $labels['empty'] = 'Спорожнити'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'ВикориÑтано'; $labels['unknown'] = 'невідомо'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'ОчиÑтити пошук'; $labels['searchmod'] = 'Де шукати'; $labels['msgtext'] = 'Ð’ уÑьому лиÑÑ‚Ñ–'; $labels['body'] = 'Тіло повідомленнÑ'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Відкрити в новому вікні'; $labels['emlsave'] = 'Зберегти (.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'ОÑÑ‚Ð°Ð½Ð½Ñ Ñторінка'; $labels['group'] = 'Група'; $labels['groups'] = 'Групи'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'ПерÑональні адреÑи'; $labels['searchsave'] = 'Зберегти пошук'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Ігнорувати Ñлова із чиÑл $labels['spellcheckignorecaps'] = 'Ігнорувати Ñлова із великими буквами'; $labels['addtodict'] = 'Додати до Ñловника'; $labels['mailtoprotohandler'] = 'ЗареєÑтрувати обробник Ð´Ð»Ñ Ð¿Ð¾Ñилань mailto'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'ПереÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ'; $labels['inline'] = 'у текÑÑ‚Ñ–'; $labels['asattachment'] = 'Ñк вкладеннÑ'; diff --git a/program/localization/vi_VN/labels.inc b/program/localization/vi_VN/labels.inc index f1cf95149..aad0dafe6 100644 --- a/program/localization/vi_VN/labels.inc +++ b/program/localization/vi_VN/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'ThÆ° nháp'; $labels['sent'] = 'Äã gá»i'; $labels['trash'] = 'Sá»t rác'; $labels['junk'] = 'ThÆ° rác'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = 'Tiêu Ä‘á»'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'Xem dạng danh sách'; $labels['folderactions'] = 'Thao tác vá»›i thÆ° mục'; $labels['compact'] = 'Nén'; $labels['empty'] = 'Trống'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'Lượng Ä‘Ä©a sá» dụng'; $labels['unknown'] = 'Không rõ'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'Thiết láºp lại tìm kiếm'; $labels['searchmod'] = 'Tìm kiếm vá»›i từ khóa và ký tá»± đặc biệt [() : " - ]'; $labels['msgtext'] = 'Toà n bá»™ thÆ°'; $labels['body'] = 'Ná»™i dung thÆ°'; +$labels['type'] = 'Type'; $labels['openinextwin'] = 'Mở trong khung cá»a má»›i'; $labels['emlsave'] = 'Tải vá» theo định dạng .eml'; @@ -354,6 +357,7 @@ $labels['lastpage'] = 'Hiển thị trang cuối'; $labels['group'] = 'Nhóm'; $labels['groups'] = 'Các nhóm'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = 'Các địa chỉ cá nhân'; $labels['searchsave'] = 'LÆ°u tìm kiếm'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = 'Bá» qua các từ kèm số'; $labels['spellcheckignorecaps'] = 'Bá» qua các từ được viết hoa'; $labels['addtodict'] = 'Thêm và o từ Ä‘iển'; $labels['mailtoprotohandler'] = 'Xác định cách xá» lý giao thức mailto: liên kết'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Chuyển tiếp thÆ°'; $labels['inline'] = 'ná»™i tuyến'; $labels['asattachment'] = 'dạng gá»i kèm'; diff --git a/program/localization/zh_CN/labels.inc b/program/localization/zh_CN/labels.inc index 23a42b96d..b568a7008 100644 --- a/program/localization/zh_CN/labels.inc +++ b/program/localization/zh_CN/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'è‰ç¨¿ç®±'; $labels['sent'] = 'å·²å‘é€é‚®ä»¶'; $labels['trash'] = 'å·²åˆ é™¤é‚®ä»¶'; $labels['junk'] = '垃圾邮件'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = '主题'; @@ -193,6 +194,7 @@ $labels['listmode'] = 'åˆ—è¡¨è§†å›¾æ ·å¼'; $labels['folderactions'] = '文件夹æ“作...'; $labels['compact'] = '压缩'; $labels['empty'] = '清空'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = '邮箱容é‡'; $labels['unknown'] = '未知'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = '清空'; $labels['searchmod'] = '修改æœç´¢'; $labels['msgtext'] = 'æ•´å°é‚®ä»¶'; $labels['body'] = 'æ£æ–‡'; +$labels['type'] = 'Type'; $labels['openinextwin'] = '在新窗å£ä¸æ‰“å¼€'; $labels['emlsave'] = '下载(.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = '最åŽä¸€é¡µ'; $labels['group'] = '分组'; $labels['groups'] = '分组'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = '个人通讯录'; $labels['searchsave'] = 'ä¿å˜æœç´¢'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = '忽略带数å—çš„å•è¯'; $labels['spellcheckignorecaps'] = '忽略所有大写å—æ¯çš„å•è¯'; $labels['addtodict'] = 'æ·»åŠ åˆ°å—å…¸ä¸'; $labels['mailtoprotohandler'] = 'Register protocol handler for mailto: links'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = '邮件转å‘æ–¹å¼'; $labels['inline'] = '内嵌'; $labels['asattachment'] = '作为附件'; diff --git a/program/localization/zh_TW/labels.inc b/program/localization/zh_TW/labels.inc index a545f2f81..7726da5dd 100644 --- a/program/localization/zh_TW/labels.inc +++ b/program/localization/zh_TW/labels.inc @@ -37,6 +37,7 @@ $labels['drafts'] = 'è‰ç¨¿åŒ£'; $labels['sent'] = '寄件備份'; $labels['trash'] = '垃圾桶'; $labels['junk'] = '垃圾郵件'; +$labels['show_real_foldernames'] = 'Show real names for special folders'; // message listing $labels['subject'] = '主旨'; @@ -193,6 +194,7 @@ $labels['listmode'] = '清單檢視模å¼'; $labels['folderactions'] = '資料夾動作...'; $labels['compact'] = '壓縮'; $labels['empty'] = '清空'; +$labels['importmessages'] = 'Import messages'; $labels['quota'] = 'ç£ç¢Ÿä½¿ç”¨é‡'; $labels['unknown'] = '未知'; @@ -203,6 +205,7 @@ $labels['resetsearch'] = 'é‡è¨æœå°‹'; $labels['searchmod'] = '修改æœå°‹'; $labels['msgtext'] = 'æ•´å°éƒµä»¶'; $labels['body'] = '內文'; +$labels['type'] = 'Type'; $labels['openinextwin'] = '在新視窗開啟'; $labels['emlsave'] = '下載(.eml)'; @@ -354,6 +357,7 @@ $labels['lastpage'] = '顯示最後一é '; $labels['group'] = '群組'; $labels['groups'] = '群組'; +$labels['listgroup'] = 'List group members'; $labels['personaladrbook'] = '個人通訊錄'; $labels['searchsave'] = '儲å˜æœå°‹çµæžœ'; @@ -472,6 +476,7 @@ $labels['spellcheckignorenums'] = '忽略數å—'; $labels['spellcheckignorecaps'] = '忽略大寫å—æ¯'; $labels['addtodict'] = 'åŠ å…¥è©žå…¸'; $labels['mailtoprotohandler'] = '註冊mailto:å”定處ç†ç¨‹å¼'; +$labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = '郵件轉寄方å¼'; $labels['inline'] = '放入內文'; $labels['asattachment'] = '當æˆé™„件'; diff --git a/program/steps/addressbook/copy.inc b/program/steps/addressbook/copy.inc index 480a9b52e..d4387194a 100644 --- a/program/steps/addressbook/copy.inc +++ b/program/steps/addressbook/copy.inc @@ -57,10 +57,16 @@ foreach ($cids as $source => $cid) foreach ($cid as $cid) { $a_record = $CONTACTS->get_record($cid, true); + // avoid copying groups + if ($a_record['_type'] == 'group') + continue; + // Check if contact exists, if so, we'll need it's ID // Note: Some addressbooks allows empty email address field - if (!empty($a_record['email'])) - $result = $TARGET->search('email', $a_record['email'], 1, true, true); + // @TODO: should we check all email addresses? + $email = $CONTACTS->get_col_values('email', $a_record, true); + if (!empty($email)) + $result = $TARGET->search('email', $email[0], 1, true, true); else if (!empty($a_record['name'])) $result = $TARGET->search('name', $a_record['name'], 1, true, true); else @@ -114,7 +120,7 @@ foreach ($cids as $source => $cid) } } -if ($success == 0) +if (!$success) $OUTPUT->show_message($errormsg, 'error'); else $OUTPUT->show_message('copysuccess', 'notice', array('nr' => $success)); diff --git a/program/steps/addressbook/delete.inc b/program/steps/addressbook/delete.inc index 56118583c..3bb2ef500 100644 --- a/program/steps/addressbook/delete.inc +++ b/program/steps/addressbook/delete.inc @@ -68,48 +68,14 @@ foreach ($cids as $source => $cid) $page = isset($_SESSION['page']) ? $_SESSION['page'] : 1; // update saved search after data changed -if (($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request])) { - $sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); - $afields = $RCMAIL->config->get('contactlist_fields'); - $search = (array)$_SESSION['search'][$search_request]; - $records = array(); - - // Get records from all sources (refresh search) - foreach ($search as $s => $set) { - $source = $RCMAIL->get_address_book($s); - - // reset page - $source->set_page(1); - $source->set_pagesize(9999); - $source->set_search_set($set); - - // get records - $result = $source->list_records($afields); - - if (!$result->count) { - unset($search[$s]); - continue; - } - - while ($row = $result->next()) { - $row['sourceid'] = $s; - $key = rcube_addressbook::compose_contact_key($row, $sort_col); - $records[$key] = $row; - } - unset($result); - - $search[$s] = $source->get_search_set(); - } - - $_SESSION['search'][$search_request] = $search; - +if (($records = rcmail_search_update(true)) !== false) { // create resultset object $count = count($records); $first = ($page-1) * $PAGE_SIZE; $result = new rcube_result_set($count, $first); + $pages = ceil((count($records) + $delcnt) / $PAGE_SIZE); // get records from the next page to add to the list - $pages = ceil((count($records) + $delcnt) / $PAGE_SIZE); if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) { // sort the records ksort($records, SORT_LOCALE_STRING); diff --git a/program/steps/addressbook/func.inc b/program/steps/addressbook/func.inc index d416cc14f..8ec581f9a 100644 --- a/program/steps/addressbook/func.inc +++ b/program/steps/addressbook/func.inc @@ -307,7 +307,7 @@ function rcmail_contacts_list($attrib) global $CONTACTS, $OUTPUT; // define list of cols to be displayed - $a_show_cols = array('name'); + $a_show_cols = array('name','action'); // add id to message list table if not specified if (!strlen($attrib['id'])) @@ -322,7 +322,7 @@ function rcmail_contacts_list($attrib) $OUTPUT->include_script('list.js'); // add some labels to client - $OUTPUT->add_label('deletecontactconfirm', 'copyingcontact', 'contactdeleting'); + $OUTPUT->add_label('deletecontactconfirm', 'copyingcontact', 'movingcontact', 'contactdeleting'); return $out; } @@ -336,31 +336,73 @@ function rcmail_js_contacts_list($result, $prefix='') return; // define list of cols to be displayed - $a_show_cols = array('name'); + $a_show_cols = array('name','action'); while ($row = $result->next()) { + $row['CID'] = $row['ID']; + $row['email'] = reset(rcube_addressbook::get_col_values('email', $row, true)); + + $source_id = $OUTPUT->get_env('source'); $a_row_cols = array(); - $classes = array('person'); // org records will follow some day + $classes = array($row['_type'] ? $row['_type'] : 'person'); // build contact ID with source ID if (isset($row['sourceid'])) { $row['ID'] = $row['ID'].'-'.$row['sourceid']; + $source_id = $row['sourceid']; } // format each col foreach ($a_show_cols as $col) { - $val = $col == 'name' ? rcube_addressbook::compose_list_name($row) : $row[$col]; - $a_row_cols[$col] = Q($val); + $val = ''; + switch ($col) { + case 'name': + $val = Q(rcube_addressbook::compose_list_name($row)); + break; + + case 'action': + if ($row['_type'] == 'group') { + $val = html::a(array( + 'href' => '#list', + 'rel' => $row['ID'], + 'title' => rcube_label('listgroup'), + 'onclick' => sprintf("return %s.command('pushgroup',{'source':'%s','id':'%s'},this,event)", JS_OBJECT_NAME, $source_id, $row['CID']), + ), '»'); + } + else + $val = ' '; + break; + + default: + $val = Q($row[$col]); + break; + } + + $a_row_cols[$col] = $val; } if ($row['readonly']) $classes[] = 'readonly'; - $OUTPUT->command($prefix.'add_contact_row', $row['ID'], $a_row_cols, join(' ', $classes)); + $OUTPUT->command($prefix.'add_contact_row', $row['ID'], $a_row_cols, join(' ', $classes), array_intersect_key($row, array('ID'=>1,'readonly'=>1,'_type'=>1,'email'=>1,'name'=>1))); } } +function rcmail_contacts_list_title($attrib) +{ + global $OUTPUT; + + $attrib += array('label' => 'contacts', 'id' => 'rcmabooklisttitle', 'tag' => 'span'); + unset($attrib['name']); + + $OUTPUT->add_gui_object('addresslist_title', $attrib['id']); + $OUTPUT->add_label('contacts'); + + return html::tag($attrib['tag'], $attrib, rcube_label($attrib['label']), html::$common_attrib); +} + + // similar function as /steps/settings/identities.inc::rcmail_identity_frame() function rcmail_contact_frame($attrib) { @@ -429,7 +471,7 @@ function rcmail_get_type_label($type) function rcmail_contact_form($form, $record, $attrib = null) { - global $RCMAIL, $CONFIG; + global $RCMAIL; // Allow plugins to modify contact form content $plugin = $RCMAIL->plugins->exec_hook('contact_form', array( @@ -438,7 +480,7 @@ function rcmail_contact_form($form, $record, $attrib = null) $form = $plugin['form']; $record = $plugin['record']; $edit_mode = $RCMAIL->action != 'show'; - $del_button = $attrib['deleteicon'] ? html::img(array('src' => $CONFIG['skin_path'] . $attrib['deleteicon'], 'alt' => rcube_label('delete'))) : rcube_label('delete'); + $del_button = $attrib['deleteicon'] ? html::img(array('src' => $RCMAIL->output->get_skin_file($attrib['deleteicon']), 'alt' => rcube_label('delete'))) : rcube_label('delete'); unset($attrib['deleteicon']); $out = ''; @@ -551,22 +593,13 @@ function rcmail_contact_form($form, $record, $attrib = null) // iterate over possible subtypes and collect values with their subtype if (is_array($colprop['subtypes'])) { $values = $subtypes = array(); - foreach ($colprop['subtypes'] as $i => $st) { - $newval = false; - if ($record[$field.':'.$st]) { - $subtypes[count($values)] = $st; - $newval = $record[$field.':'.$st]; - } - else if ($i == 0 && $record[$field]) { - $subtypes[count($values)] = $st; - $newval = $record[$field]; - } - if ($newval !== false) { - if (is_array($newval) && isset($newval[0])) - $values = array_merge($values, $newval); - else - $values[] = $newval; + foreach (rcube_addressbook::get_col_values($field, $record) as $st => $vals) { + foreach((array)$vals as $value) { + $i = count($values); + $subtypes[$i] = $st; + $values[$i] = $value; } + // TODO: add $st to $select_subtype if missing ? } } else { @@ -704,12 +737,15 @@ function rcmail_contact_form($form, $record, $attrib = null) function rcmail_contact_photo($attrib) { - global $SOURCE_ID, $CONTACTS, $CONTACT_COLTYPES, $RCMAIL, $CONFIG; + global $SOURCE_ID, $CONTACTS, $CONTACT_COLTYPES, $RCMAIL; if ($result = $CONTACTS->get_result()) $record = $result->first(); - $photo_img = $attrib['placeholder'] ? $CONFIG['skin_path'] . $attrib['placeholder'] : 'program/resources/blank.gif'; + $photo_img = $attrib['placeholder'] ? $RCMAIL->output->get_skin_file($attrib['placeholder']) : 'program/resources/blank.gif'; + if ($record['_type'] == 'group' && $attrib['placeholdergroup']) + $photo_img = $RCMAIL->output->get_skin_file($attrib['placeholdergroup']); + $RCMAIL->output->set_env('photo_placeholder', $photo_img); unset($attrib['placeholder']); @@ -743,6 +779,54 @@ function rcmail_format_date_col($val) return format_date($val, $RCMAIL->config->get('date_format', 'Y-m-d'), false); } +/** + * Updates saved search after data changed + */ +function rcmail_search_update($return = false) +{ + global $RCMAIL; + + if (($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request])) { + $search = (array)$_SESSION['search'][$search_request]; + $sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); + $afields = $return ? $RCMAIL->config->get('contactlist_fields') : array('name', 'email'); + $records = array(); + + foreach ($search as $s => $set) { + $source = $RCMAIL->get_address_book($s); + + // reset page + $source->set_page(1); + $source->set_pagesize(9999); + $source->set_search_set($set); + + // get records + $result = $source->list_records($afields); + + if (!$result->count) { + unset($search[$s]); + continue; + } + + if ($return) { + while ($row = $result->next()) { + $row['sourceid'] = $s; + $key = rcube_addressbook::compose_contact_key($row, $sort_col); + $records[$key] = $row; + } + unset($result); + } + + $search[$s] = $source->get_search_set(); + } + + $_SESSION['search'][$search_request] = $search; + + return $records; + } + + return false; +} /** * Returns contact ID(s) and source(s) from GET/POST data @@ -800,6 +884,7 @@ $OUTPUT->add_handlers(array( 'directorylist' => 'rcmail_directory_list', // 'groupslist' => 'rcmail_contact_groups', 'addresslist' => 'rcmail_contacts_list', + 'addresslisttitle' => 'rcmail_contacts_list_title', 'addressframe' => 'rcmail_contact_frame', 'recordscountdisplay' => 'rcmail_rowcount_display', 'searchform' => array($OUTPUT, 'search_form') diff --git a/program/steps/addressbook/list.inc b/program/steps/addressbook/list.inc index 1bb28658b..aca58d279 100644 --- a/program/steps/addressbook/list.inc +++ b/program/steps/addressbook/list.inc @@ -19,47 +19,20 @@ +-----------------------------------------------------------------------+ */ -$afields = $RCMAIL->config->get('contactlist_fields'); +if (!empty($_GET['_page'])) + $page = intval($_GET['_page']); +else + $page = !empty($_SESSION['page']) ? $_SESSION['page'] : 1; -// Use search result -if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) -{ - $search = (array)$_SESSION['search'][$_REQUEST['_search']]; - $records = array(); - - if (!empty($_GET['_page'])) - $page = intval($_GET['_page']); - else - $page = isset($_SESSION['page']) ? $_SESSION['page'] : 1; - - $_SESSION['page'] = $page; - $sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); - - // Get records from all sources - foreach ($search as $s => $set) { - $source = $RCMAIL->get_address_book($s); - - // reset page - $source->set_page(1); - $source->set_pagesize(9999); - $source->set_search_set($set); - - // get records - $result = $source->list_records($afields); - - while ($row = $result->next()) { - $row['sourceid'] = $s; - $key = rcube_addressbook::compose_contact_key($row, $sort_col); - $records[$key] = $row; - } - unset($result); - } +$_SESSION['page'] = $page; +// Use search result +if (($records = rcmail_search_update(true)) !== false) { // sort the records ksort($records, SORT_LOCALE_STRING); // create resultset object - $count = count($records); + $count = count($records); $first = ($page-1) * $PAGE_SIZE; $result = new rcube_result_set($count, $first); @@ -72,6 +45,7 @@ if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search } // List selected directory else { + $afields = $RCMAIL->config->get('contactlist_fields'); $CONTACTS = rcmail_contact_source(null, true); // get contacts for this user @@ -81,6 +55,11 @@ else { $OUTPUT->show_message('contactsearchonly', 'notice'); $OUTPUT->command('command', 'advanced-search'); } + + if ($CONTACTS->group_id) { + $OUTPUT->command('set_group_prop', array('ID' => $CONTACTS->group_id) + + array_intersect_key((array)$CONTACTS->get_group($CONTACTS->group_id), array('name'=>1,'email'=>1))); + } } // update message count display diff --git a/program/steps/addressbook/move.inc b/program/steps/addressbook/move.inc new file mode 100644 index 000000000..f8204e9ee --- /dev/null +++ b/program/steps/addressbook/move.inc @@ -0,0 +1,208 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/steps/addressbook/move.inc | + | | + | This file is part of the Roundcube Webmail client | + | Copyright (C) 2007-2013, The Roundcube Dev Team | + | | + | Licensed under the GNU General Public License version 3 or | + | any later version with exceptions for skins & plugins. | + | See the README file for a full license statement. | + | | + | PURPOSE: | + | Move a contact record from one direcotry to another | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + | Author: Aleksander Machniak <alec@alec.pl> | + +-----------------------------------------------------------------------+ +*/ + +// only process ajax requests +if (!$OUTPUT->ajax_call) { + return; +} + +$cids = rcmail_get_cids(); +$target = get_input_value('_to', RCUBE_INPUT_POST); +$target_group = get_input_value('_togid', RCUBE_INPUT_POST); + +$all = 0; +$deleted = 0; +$success = 0; +$errormsg = 'moveerror'; +$maxnum = $RCMAIL->config->get('max_group_members', 0); +$page = !empty($_SESSION['page']) ? $_SESSION['page'] : 1; + +foreach ($cids as $source => $source_cids) { + // Something wrong, target not specified + if (!strlen($target)) { + break; + } + + // It maight happen when moving records from search result + // Do nothing, go to next source + if ((string)$target === (string)$source) { + continue; + } + + $CONTACTS = $RCMAIL->get_address_book($source); + $TARGET = $RCMAIL->get_address_book($target); + + if (!$TARGET || !$TARGET->ready || $TARGET->readonly) { + break; + } + + if (!$CONTACTS || !$CONTACTS->ready || $CONTACTS->readonly) { + continue; + } + + $ids = array(); + + foreach ($source_cids as $idx => $cid) { + $a_record = $CONTACTS->get_record($cid, true); + + // avoid moving groups + if ($a_record['_type'] == 'group') { + unset($source_cids[$idx]); + continue; + } + + // Check if contact exists, if so, we'll need it's ID + // Note: Some addressbooks allows empty email address field + // @TODO: should we check all email addresses? + $email = $CONTACTS->get_col_values('email', $a_record, true); + if (!empty($email)) + $result = $TARGET->search('email', $email[0], 1, true, true); + else if (!empty($a_record['name'])) + $result = $TARGET->search('name', $a_record['name'], 1, true, true); + else + $result = new rcube_result_set(); + + // insert contact record + if (!$result->count) { + $plugin = $RCMAIL->plugins->exec_hook('contact_create', array( + 'record' => $a_record, 'source' => $target, 'group' => $target_group)); + + if (!$plugin['abort']) { + if ($insert_id = $TARGET->insert($plugin['record'], false)) { + $ids[] = $insert_id; + $success++; + } + } + else if ($plugin['result']) { + $ids = array_merge($ids, $plugin['result']); + $success++; + } + } + else { + $record = $result->first(); + $ids[] = $record['ID']; + $errormsg = empty($a_record['email']) ? 'contactnameexists' : 'contactexists'; + } + } + + // remove source contacts + if ($success && !empty($source_cids)) { + $all += count($source_cids); + $plugin = $RCMAIL->plugins->exec_hook('contact_delete', array( + 'id' => $source_cids, 'source' => $source)); + + $del_status = !$plugin['abort'] ? $CONTACTS->delete($source_cids) : $plugin['result']; + + if ($del_status) { + $deleted += $del_status; + } + } + + // assign to group + if ($target_group && $TARGET->groups && !empty($ids)) { + $plugin = $RCMAIL->plugins->exec_hook('group_addmembers', array( + 'group_id' => $target_group, 'ids' => $ids, 'source' => $target)); + + if (!$plugin['abort']) { + $TARGET->reset(); + $TARGET->set_group($target_group); + + if ($maxnum && ($TARGET->count()->count + count($plugin['ids']) > $maxnum)) { + $OUTPUT->show_message('maxgroupmembersreached', 'warning', array('max' => $maxnum)); + $OUTPUT->send(); + } + + if (($cnt = $TARGET->add_to_group($target_group, $plugin['ids'])) && $cnt > $success) + $success = $cnt; + } + else if ($plugin['result']) { + $success = $plugin['result']; + } + + $errormsg = $plugin['message'] ? $plugin['message'] : 'moveerror'; + } +} + +if (!$deleted || $deleted != $all) { + // update saved search after data changed + if ($deleted) { + rcmail_search_update(); + } + $OUTPUT->command('list_contacts'); +} +else { + // update saved search after data changed + if (($records = rcmail_search_update(true)) !== false) { + // create resultset object + $count = count($records); + $first = ($page-1) * $PAGE_SIZE; + $result = new rcube_result_set($count, $first); + $pages = ceil((count($records) + $delcnt) / $PAGE_SIZE); + + // get records from the next page to add to the list + if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) { + // sort the records + ksort($records, SORT_LOCALE_STRING); + + $first += $PAGE_SIZE; + // create resultset object + $res = new rcube_result_set($count, $first - $deleted); + + if ($PAGE_SIZE < $count) { + $records = array_slice($records, $first - $deleted, $deleted); + } + + $res->records = array_values($records); + $records = $res; + } + else { + unset($records); + } + } + else { + // count contacts for this user + $result = $CONTACTS->count(); + // get records from the next page to add to the list + $pages = ceil(($result->count + $deleted) / $PAGE_SIZE); + + if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) { + $CONTACTS->set_page($page); + $records = $CONTACTS->list_records(null, -$deleted); + } + } + + // update message count display + $OUTPUT->set_env('pagecount', ceil($result->count / $PAGE_SIZE)); + $OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result)); + + // add new rows from next page (if any) + if (!empty($records)) { + rcmail_js_contacts_list($records); + } +} + +if (!$success) + $OUTPUT->show_message($errormsg, 'error'); +else + $OUTPUT->show_message('movesuccess', 'notice', array('nr' => $success)); + +// send response +$OUTPUT->send(); diff --git a/program/steps/addressbook/save.inc b/program/steps/addressbook/save.inc index 25bfbd48b..e7e5efc63 100644 --- a/program/steps/addressbook/save.inc +++ b/program/steps/addressbook/save.inc @@ -134,11 +134,11 @@ if (!empty($cid)) $record['email'] = reset($CONTACTS->get_col_values('email', $record, true)); $record['name'] = rcube_addressbook::compose_list_name($record); - foreach (array('name', 'email') as $col) + foreach (array('name') as $col) $a_js_cols[] = Q((string)$record[$col]); // update the changed col in list - $OUTPUT->command('parent.update_contact_row', $cid, $a_js_cols, $newcid, $source); + $OUTPUT->command('parent.update_contact_row', $cid, $a_js_cols, $newcid, $source, $record); // show confirmation $OUTPUT->show_message('successfullysaved', 'confirmation', null, false); diff --git a/program/steps/addressbook/show.inc b/program/steps/addressbook/show.inc index 1a97c65b1..950764bb1 100644 --- a/program/steps/addressbook/show.inc +++ b/program/steps/addressbook/show.inc @@ -207,9 +207,8 @@ function rcmail_contact_record_groups($contact_id) return ''; } - $table = new html_table(array('cols' => 2, 'cellspacing' => 0, 'border' => 0)); - - $members = $CONTACTS->get_record_groups($contact_id); + $members = $CONTACTS->get_record_groups($contact_id); + $table = new html_table(array('cols' => 2, 'cellspacing' => 0, 'border' => 0)); $checkbox = new html_checkbox(array('name' => '_gid[]', 'class' => 'groupmember', 'disabled' => $CONTACTS->readonly)); diff --git a/program/steps/addressbook/undo.inc b/program/steps/addressbook/undo.inc index 9c171143c..c23bd1cb6 100644 --- a/program/steps/addressbook/undo.inc +++ b/program/steps/addressbook/undo.inc @@ -46,30 +46,7 @@ foreach ((array)$undo['data'] as $source => $cid) } // update saved search after data changed -if ($delcnt && ($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request])) { - $search = (array)$_SESSION['search'][$search_request]; - - foreach ($search as $s => $set) { - $source = $RCMAIL->get_address_book($s); - - // reset page - $source->set_page(1); - $source->set_pagesize(9999); - $source->set_search_set($set); - - // get records - $result = $source->list_records(array('name', 'email')); - - if (!$result->count) { - unset($search[$s]); - continue; - } - - $search[$s] = $source->get_search_set(); - } - - $_SESSION['search'][$search_request] = $search; -} +rcmail_search_update(); $RCMAIL->session->remove('contact_undo'); diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc index 3649d148c..8c0b1ffc0 100644 --- a/program/steps/mail/check_recent.inc +++ b/program/steps/mail/check_recent.inc @@ -81,9 +81,10 @@ foreach ($a_mailboxes as $mbox_name) { if (empty($_GET['_list'])) continue; - // get overall message count; allow caching because rcube_storage::folder_status() did a refresh + // get overall message count; allow caching because rcube_storage::folder_status() + // did a refresh but only in list mode $list_mode = $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL'; - $all_count = $RCMAIL->storage->count($mbox_name, $list_mode, false, false); + $all_count = $RCMAIL->storage->count($mbox_name, $list_mode, $list_mode == 'THREADS', false); $page = $RCMAIL->storage->get_page(); $page_size = $RCMAIL->storage->get_pagesize(); diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index 9ee57d31e..9ffde8a57 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -170,6 +170,9 @@ $OUTPUT->set_env('compose_mode', $compose_mode); $config_show_sig = $RCMAIL->config->get('show_sig', 1); if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) { // don't add signature in draft/edit mode, we'll also not remove the old-one + // but only on page display, later we should be able to change identity/sig (#1489229) + if ($config_show_sig == 1 || $config_show_sig == 2) + $OUTPUT->set_env('show_sig_later', true); } else if ($config_show_sig == 1) $OUTPUT->set_env('show_sig', true); @@ -219,8 +222,8 @@ if (!empty($msg_uid) && empty($COMPOSE['as_attachment'])) $COMPOSE['param']['sent_mbox'] = $sent_folder; } } - else if ($compose_mode == RCUBE_COMPOSE_DRAFT) { - if ($draft_info = $MESSAGE->headers->get('x-draft-info')) { + else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) { + if ($compose_mode == RCUBE_COMPOSE_DRAFT && ($draft_info = $MESSAGE->headers->get('x-draft-info'))) { // get reply_uid/forward_uid to flag the original message when sending $info = rcmail_draftinfo_decode($draft_info); @@ -242,7 +245,7 @@ if (!empty($msg_uid) && empty($COMPOSE['as_attachment'])) if ($in_reply_to = $MESSAGE->headers->get('in-reply-to')) $COMPOSE['reply_msgid'] = '<' . $in_reply_to . '>'; - $COMPOSE['references'] = $MESSAGE->headers->references; + $COMPOSE['references'] = $MESSAGE->headers->references; } } else { @@ -327,7 +330,8 @@ foreach ($parts as $header) { $fvalue .= $v; if ($v = $MESSAGE->headers->cc) $fvalue .= (!empty($fvalue) ? $separator : '') . $v; - if ($v = $MESSAGE->headers->get('Sender', false)) + // Use Sender header (#1489011) + if (($v = $MESSAGE->headers->get('Sender', false)) && strpos($v, '-bounces@') === false) $fvalue .= (!empty($fvalue) ? $separator : '') . $v; // When To: and Reply-To: are the same we add From: address to the list (#1489037) @@ -474,6 +478,7 @@ function rcmail_compose_header_from($attrib) if (count($MESSAGE->identities)) { $a_signatures = array(); + $identities = array(); $separator = intval($RCMAIL->config->get('reply_mode')) > 0 && ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD) ? '---' : '-- '; @@ -511,12 +516,21 @@ function rcmail_compose_header_from($attrib) $a_signatures[$identity_id]['text'] = $text; $a_signatures[$identity_id]['html'] = $html; } + + // add bcc and reply-to + if (!empty($sql_arr['reply-to'])) { + $identities[$identity_id]['replyto'] = $sql_arr['reply-to']; + } + if (!empty($sql_arr['bcc'])) { + $identities[$identity_id]['bcc'] = $sql_arr['bcc']; + } } - $out = $select_from->show($MESSAGE->compose['from']); + $out = $select_from->show((int)$MESSAGE->compose['from']); // add signatures to client $OUTPUT->set_env('signatures', $a_signatures); + $OUTPUT->set_env('identities', $identities); } // no identities, display text input field else { @@ -585,15 +599,32 @@ function rcmail_prepare_message_body() } // reply/edit/draft/forward else if ($compose_mode && ($compose_mode != RCUBE_COMPOSE_REPLY || intval($RCMAIL->config->get('reply_mode')) != -1)) { - $isHtml = rcmail_compose_editor_mode(); + $isHtml = rcmail_compose_editor_mode(); + $messages = array(); if (!empty($MESSAGE->parts)) { + // collect IDs of message/rfc822 parts + if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) { + foreach ($MESSAGE->attachments as $part) { + if ($part->mimetype == 'message/rfc822') { + $messages[] = $part->mime_id; + } + } + } + foreach ($MESSAGE->parts as $part) { // skip no-content and attachment parts (#1488557) if ($part->type != 'content' || !$part->size || $MESSAGE->is_attachment($part)) { continue; } + // skip all content parts inside the message/rfc822 part in DRAFT/EDIT mode + foreach ($messages as $mimeid) { + if (strpos($part->mime_id, $mimeid . '.') === 0) { + continue 2; + } + } + if ($part_body = rcmail_compose_part_body($part, $isHtml)) { $body .= ($body ? ($isHtml ? '<br/>' : "\n") : '') . $part_body; } @@ -1010,7 +1041,9 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml) $loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment; } - $cid_map = $messages = array(); + $cid_map = array(); + $messages = array(); + foreach ((array)$message->mime_parts as $pid => $part) { if ($part->disposition == 'attachment' || ($part->disposition == 'inline' && $bodyIsHtml) || $part->filename) { @@ -1022,25 +1055,32 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml) if ($part->ctype_primary == 'message' && $compose_mode == RCUBE_COMPOSE_REPLY) { continue; } - // skip inline images when forwarding in plain text - if ($part->content_id && !$bodyIsHtml && $compose_mode == RCUBE_COMPOSE_FORWARD) { + // skip inline images when forwarding in text mode + if ($part->content_id && $part->disposition == 'inline' && !$bodyIsHtml && $compose_mode == RCUBE_COMPOSE_FORWARD) { continue; } - $skip = false; + // skip message/rfc822 attachments on forwards (#1489214) + // Thunderbird when forwarding in inline mode displays such attachments + // and skips any attachments from inside of such part, this however + // skipped e.g. images used in HTML body or other attachments. So, + // better to skip .eml attachments but not their content (included files). if ($part->mimetype == 'message/rfc822') { + if ($compose_mode == RCUBE_COMPOSE_FORWARD) { + continue; + } $messages[] = $part->mime_id; - } else if ($messages) { + } + else if ($compose_mode != RCUBE_COMPOSE_FORWARD) { // skip attachments included in message/rfc822 attachment (#1486487) foreach ($messages as $mimeid) - if (strpos($part->mime_id, $mimeid.'.') === 0) { - $skip = true; - break; + if (strpos($part->mime_id, $mimeid . '.') === 0) { + continue 2; } } - if (!$skip && (($attachment = $loaded_attachments[rcmail_attachment_name($part) . $part->mimetype]) - || ($attachment = rcmail_save_attachment($message, $pid)))) { + if (($attachment = $loaded_attachments[rcmail_attachment_name($part) . $part->mimetype]) + || ($attachment = rcmail_save_attachment($message, $pid))) { $COMPOSE['attachments'][$attachment['id']] = $attachment; if ($bodyIsHtml && ($part->content_id || $part->content_location)) { $url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s', diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index ab4b41155..454650628 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -120,7 +120,7 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') { if (!$OUTPUT->ajax_call) $OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash', 'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage', - 'copy', 'move', 'quota', 'replyall', 'replylist'); + 'copy', 'move', 'quota', 'replyall', 'replylist', 'importwait'); $pagetitle = $RCMAIL->localize_foldername($RCMAIL->storage->mod_folder($mbox_name), true); $pagetitle = str_replace($delimiter, " \xC2\xBB ", $pagetitle); @@ -128,6 +128,40 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') { $OUTPUT->set_pagetitle($pagetitle); } +// register UI objects +$OUTPUT->add_handlers(array( + 'mailboxlist' => 'rcmail_mailbox_list', + 'messages' => 'rcmail_message_list', + 'messagecountdisplay' => 'rcmail_messagecount_display', + 'quotadisplay' => 'rcmail_quota_display', + 'mailboxname' => 'rcmail_mailbox_name_display', + 'messageheaders' => 'rcmail_message_headers', + 'messagefullheaders' => 'rcmail_message_full_headers', + 'messagebody' => 'rcmail_message_body', + 'messagecontentframe' => 'rcmail_messagecontent_frame', + 'messageimportform' => 'rcmail_message_import_form', + 'searchfilter' => 'rcmail_search_filter', + 'searchform' => array($OUTPUT, 'search_form'), +)); + +// register action aliases +$RCMAIL->register_action_map(array( + 'refresh' => 'check_recent.inc', + 'preview' => 'show.inc', + 'print' => 'show.inc', + 'move' => 'move_del.inc', + 'delete' => 'move_del.inc', + 'send' => 'sendmail.inc', + 'expunge' => 'folders.inc', + 'purge' => 'folders.inc', + 'remove-attachment' => 'attachments.inc', + 'display-attachment' => 'attachments.inc', + 'upload' => 'attachments.inc', + 'group-expand' => 'autocomplete.inc', +)); + + + /** * Returns 'to' if current folder is configured Sent or Drafts * or their subfolders, otherwise returns 'from'. @@ -900,7 +934,7 @@ function rcmail_message_headers($attrib, $headers=null) $value = $headers[$hkey]; else if ($headers['others'][$hkey]) $value = $headers['others'][$hkey]; - else + else if (!$attrib['valueof']) continue; if (in_array($hkey, $exclude_headers)) @@ -1579,45 +1613,6 @@ function rcmail_draftinfo_decode($str) } -function rcmail_message_part_controls($attrib) -{ - global $MESSAGE, $RCMAIL; - - $part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC)); - if (!is_object($MESSAGE) || !is_array($MESSAGE->parts) || !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE->mime_parts[$part]) - return ''; - - $part = $MESSAGE->mime_parts[$part]; - $table = new html_table(array('cols' => 3)); - - $filename = rcmail_attachment_name($part); - - if (!empty($filename)) { - $table->add('title', Q(rcube_label('filename'))); - $table->add('header', Q($filename)); - $table->add('download-link', html::a(array('href' => './?'.str_replace('_frame=', '_download=', $_SERVER['QUERY_STRING'])), Q(rcube_label('download')))); - } - - $table->add('title', Q(rcube_label('filesize'))); - $table->add('header', Q($RCMAIL->message_part_size($part))); - - return $table->show($attrib); -} - - -function rcmail_message_part_frame($attrib) -{ - global $MESSAGE; - - $part = $MESSAGE->mime_parts[asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))]; - $ctype_primary = strtolower($part->ctype_primary); - - $attrib['src'] = './?' . str_replace('_frame=', ($ctype_primary=='text' ? '_embed=' : '_preload='), $_SERVER['QUERY_STRING']); - - return html::iframe($attrib); -} - - /** * clear message composing settings */ @@ -1786,9 +1781,12 @@ function rcmail_identity_select($MESSAGE, $identities = null, $compose_mode = 'r // Try Return-Path if ($from_idx === null && ($return_path = $MESSAGE->headers->others['return-path'])) { foreach ($identities as $idx => $ident) { - if (strpos($return_path, str_replace('@', '=', $ident['email_ascii']).'@') !== false) { - $from_idx = $idx; - break; + $ident = str_replace('@', '=', $ident['email_ascii']) . '@'; + foreach ((array)$return_path as $path) { + if (strpos($path, $ident) !== false) { + $from_idx = $idx; + break 2; + } } } } @@ -1919,35 +1917,37 @@ function rcmail_message_error($uid=null) $RCMAIL->output->send('messageerror'); } -// register UI objects -$OUTPUT->add_handlers(array( - 'mailboxlist' => 'rcmail_mailbox_list', - 'messages' => 'rcmail_message_list', - 'messagecountdisplay' => 'rcmail_messagecount_display', - 'quotadisplay' => 'rcmail_quota_display', - 'mailboxname' => 'rcmail_mailbox_name_display', - 'messageheaders' => 'rcmail_message_headers', - 'messagefullheaders' => 'rcmail_message_full_headers', - 'messagebody' => 'rcmail_message_body', - 'messagecontentframe' => 'rcmail_messagecontent_frame', - 'messagepartframe' => 'rcmail_message_part_frame', - 'messagepartcontrols' => 'rcmail_message_part_controls', - 'searchfilter' => 'rcmail_search_filter', - 'searchform' => array($OUTPUT, 'search_form'), -)); +function rcmail_message_import_form($attrib = array()) +{ + global $OUTPUT; -// register action aliases -$RCMAIL->register_action_map(array( - 'refresh' => 'check_recent.inc', - 'preview' => 'show.inc', - 'print' => 'show.inc', - 'moveto' => 'move_del.inc', - 'delete' => 'move_del.inc', - 'send' => 'sendmail.inc', - 'expunge' => 'folders.inc', - 'purge' => 'folders.inc', - 'remove-attachment' => 'attachments.inc', - 'display-attachment' => 'attachments.inc', - 'upload' => 'attachments.inc', - 'group-expand' => 'autocomplete.inc', -)); + // set defaults + $attrib += array('id' => 'rcmImportform', 'buttons' => 'yes'); + + // Get filesize, enable upload progress bar + $max_filesize = rcube_upload_init(); + + $button = new html_inputfield(array('type' => 'button')); + $fileinput = new html_inputfield(array( + 'type' => 'file', + 'name' => '_file[]', + 'size' => $attrib['attachmentfieldsize'], + 'multiple' => 'multiple', + 'accept' => ".eml, .mbox, message/rfc822, text/*", + )); + + $out = html::div($attrib, + $OUTPUT->form_tag(array('id' => $attrib['id'].'Frm', 'method' => 'post', 'enctype' => 'multipart/form-data'), + html::tag('input', array('type' => 'hidden', 'name' => '_unlock', 'value' => '')) . + html::div(null, $fileinput->show()) . + html::div('hint', rcube_label(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))) . + (get_boolean($attrib['buttons']) ? html::div('buttons', + $button->show(rcube_label('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) . ' ' . + $button->show(rcube_label('upload'), array('class' => 'button mainaction', 'onclick' => JS_OBJECT_NAME . ".command('import-messages', this.form)")) + ) : '') + ) + ); + + $OUTPUT->add_gui_object('importform', $attrib['id'].'Frm'); + return $out; +} diff --git a/program/steps/mail/get.inc b/program/steps/mail/get.inc index 372757720..a27e788a3 100644 --- a/program/steps/mail/get.inc +++ b/program/steps/mail/get.inc @@ -38,19 +38,34 @@ ob_end_clean(); // similar code as in program/steps/mail/show.inc if (!empty($_GET['_uid'])) { + $uid = get_input_value('_uid', RCUBE_INPUT_GET); $RCMAIL->config->set('prefer_html', true); - $MESSAGE = new rcube_message(get_input_value('_uid', RCUBE_INPUT_GET)); + $MESSAGE = new rcube_message($uid); } // check connection status check_storage_status(); +$part_id = get_input_value('_part', RCUBE_INPUT_GPC); + // show part page if (!empty($_GET['_frame'])) { - if (($part_id = get_input_value('_part', RCUBE_INPUT_GPC)) && ($part = $MESSAGE->mime_parts[$part_id])) { - $OUTPUT->set_pagetitle(rcmail_attachment_name($part)); + if ($part_id && ($part = $MESSAGE->mime_parts[$part_id])) { + $filename = rcmail_attachment_name($part); + $OUTPUT->set_pagetitle($filename); } + // register UI objects + $OUTPUT->add_handlers(array( + 'messagepartframe' => 'rcmail_message_part_frame', + 'messagepartcontrols' => 'rcmail_message_part_controls', + )); + + $OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder()); + $OUTPUT->set_env('uid', $uid); + $OUTPUT->set_env('part', $part_id); + $OUTPUT->set_env('filename', $filename); + $OUTPUT->send('messagepart'); exit; } @@ -92,9 +107,8 @@ else if ($_GET['_thumb']) { exit; } -else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) { - - if ($part = $MESSAGE->mime_parts[$pid]) { +else if (strlen($part_id)) { + if ($part = $MESSAGE->mime_parts[$part_id]) { $mimetype = rcmail_fix_mimetype($part->mimetype); // allow post-processing of the message body @@ -378,7 +392,9 @@ else { header('HTTP/1.1 404 Not Found'); exit; - +/** + * Handles nicely storage connection errors + */ function check_storage_status() { $error = rcmail::get_instance()->storage->get_error_code(); @@ -410,3 +426,49 @@ function check_storage_status() exit; } } + +/** + * Attachment properties table + */ +function rcmail_message_part_controls($attrib) +{ + global $MESSAGE, $RCMAIL; + + $part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC)); + if (!is_object($MESSAGE) || !is_array($MESSAGE->parts) + || !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE->mime_parts[$part] + ) { + return ''; + } + + $part = $MESSAGE->mime_parts[$part]; + $table = new html_table(array('cols' => 2)); + + $table->add('title', Q(rcube_label('namex')).':'); + $table->add('header', Q(rcmail_attachment_name($part))); + + $table->add('title', Q(rcube_label('type')).':'); + $table->add('header', Q($part->mimetype)); + + $table->add('title', Q(rcube_label('size')).':'); + $table->add('header', Q($RCMAIL->message_part_size($part))); + + return $table->show($attrib); +} + +/** + * Attachment preview frame + */ +function rcmail_message_part_frame($attrib) +{ + global $MESSAGE, $RCMAIL; + + $part = $MESSAGE->mime_parts[asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))]; + $ctype_primary = strtolower($part->ctype_primary); + + $attrib['src'] = './?' . str_replace('_frame=', ($ctype_primary=='text' ? '_embed=' : '_preload='), $_SERVER['QUERY_STRING']); + + $RCMAIL->output->add_gui_object('messagepartframe', $attrib['id']); + + return html::iframe($attrib); +} diff --git a/program/steps/mail/import.inc b/program/steps/mail/import.inc new file mode 100644 index 000000000..f7e7a3eb8 --- /dev/null +++ b/program/steps/mail/import.inc @@ -0,0 +1,105 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/steps/mail/import.inc | + | | + | This file is part of the Roundcube Webmail client | + | Copyright (C) 2005-2013, The Roundcube Dev Team | + | | + | Licensed under the GNU General Public License version 3 or | + | any later version with exceptions for skins & plugins. | + | See the README file for a full license statement. | + | | + | PURPOSE: | + | Save the uploaded file(s) as messages to the current IMAP folder | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ +*/ + +// clear all stored output properties (like scripts and env vars) +$OUTPUT->reset(); + +if (is_array($_FILES['_file'])) { + $imported = 0; + + foreach ((array)$_FILES['_file']['tmp_name'] as $i => $filepath) { + // Process uploaded file if there is no error + $err = $_FILES['_file']['error'][$i]; + + if (!$err) { + // check file content type first + list($mtype_primary,) = explode('/', rc_mime_content_type($filepath, $_FILES['_file']['name'][$i], $_FILES['_file']['type'][$i])); + if (!in_array($mtype_primary, array('text','message'))) { + $OUTPUT->show_message('importmessageerror', 'error'); + continue; + } + + // read the first few lines to detect header-like structure + $fp = fopen($filepath, 'r'); + do { $line = fgets($fp); } + while ($line !== false && trim($line) == ''); + + if (!preg_match('/^From\s+-/', $line) && !preg_match('/^[a-z-_]+:\s+.+/i', $line)) { + $OUTPUT->show_message('importmessageerror', 'error'); + continue; + } + + $message = $lastline = ''; + fseek($fp, 0); + while (($line = fgets($fp)) !== false) { + // importing mbox file, split by From - lines + if (preg_match('/^From\s+-/', $line) && $lastline == '') { + if (!empty($message)) { + if ($RCMAIL->storage->save_message(null, rtrim($message))) { + $imported++; + } + else { + rcube::raise_error("Failed to import message to " . $RCMAIL->storage->get_folder(), false, true); + } + $message = ''; + } + continue; + } + + $message .= $line; + $lastline = rtrim($line); + } + + if (!empty($message) && $RCMAIL->storage->save_message(null, rtrim($message))) { + $imported++; + } + } + + if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) { + $msg = rcube_label(array('name' => 'filesizeerror', 'vars' => array('size' => show_bytes(parse_bytes(ini_get('upload_max_filesize')))))); + } + else if ($err) { + $OUTPUT->show_message('fileuploaderror', 'error'); + } + } // end foreach + + if ($imported) { + $OUTPUT->show_message(rcube_label(array('name' => 'importmessagesuccess', 'nr' => $imported, 'vars' => array('nr' => $imported))), 'confirmation'); + $OUTPUT->command('command', 'list'); + } + else { + $OUTPUT->show_message('importmessageerror', 'error'); + } +} +else if ($_SERVER['REQUEST_METHOD'] == 'POST') { + // if filesize exceeds post_max_size then $_FILES array is empty, + // show filesizeerror instead of fileuploaderror + if ($maxsize = ini_get('post_max_size')) + $msg = rcube_label(array('name' => 'filesizeerror', 'vars' => array('size' => show_bytes(parse_bytes($maxsize))))); + else + $msg = rcube_label('fileuploaderror'); + + $OUTPUT->command('display_message', $msg, 'error'); +} + +// send html page with JS calls as response +$OUTPUT->send('iframe'); + diff --git a/program/steps/mail/list_contacts.inc b/program/steps/mail/list_contacts.inc index 7e3b349cd..dab146431 100644 --- a/program/steps/mail/list_contacts.inc +++ b/program/steps/mail/list_contacts.inc @@ -19,10 +19,10 @@ +-----------------------------------------------------------------------+ */ -$afields = $RCMAIL->config->get('contactlist_fields'); -$sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); -$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50)); -$page = max(1, intval($_GET['_page'])); +$afields = $RCMAIL->config->get('contactlist_fields'); +$addr_sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); +$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50)); +$list_page = max(1, intval($_GET['_page'])); // Use search result if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) { @@ -42,7 +42,7 @@ if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search while ($row = $result->next()) { $row['sourceid'] = $s; - $key = rcube_addressbook::compose_contact_key($row, $sort_col); + $key = rcube_addressbook::compose_contact_key($row, $addr_sort_col); $records[$key] = $row; } unset($result); @@ -53,7 +53,7 @@ if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search // create resultset object $count = count($records); - $first = ($page-1) * $page_size; + $first = ($list_page-1) * $page_size; $result = new rcube_result_set($count, $first); // we need only records for current page @@ -71,10 +71,13 @@ else { if ($CONTACTS && $CONTACTS->ready) { // set list properties $CONTACTS->set_pagesize($page_size); - $CONTACTS->set_page($page); + $CONTACTS->set_page($list_page); + if ($group_id = get_input_value('_gid', RCUBE_INPUT_GPC)) { + $CONTACTS->set_group($group_id); + } // list groups of this source (on page one) - if ($CONTACTS->groups && $CONTACTS->list_page == 1) { + else if ($CONTACTS->groups && $CONTACTS->list_page == 1) { foreach ($CONTACTS->list_groups() as $group) { $CONTACTS->reset(); $CONTACTS->set_group($group['ID']); @@ -89,6 +92,19 @@ else { 'contactgroup' => html::span(array('title' => $email), Q($group['name']))), 'group'); } } + // make virtual groups clickable to list their members + else if ($group_prop['virtual']) { + $row_id = 'G'.$group['ID']; + $OUTPUT->command('add_contact_row', $row_id, array( + 'contactgroup' => html::a(array( + 'href' => '#list', + 'rel' => $row['ID'], + 'title' => rcube_label('listgroup'), + 'onclick' => sprintf("return %s.command('pushgroup',{'source':'%s','id':'%s'},this,event)", JS_OBJECT_NAME, $source, $group['ID']), + ), Q($group['name']) . ' ' . html::span('action', '»'))), + 'group', + array('ID' => $group['ID'], 'name' => $group['name'], 'virtual' => true)); + } // show group with count else if (($result = $CONTACTS->count()) && $result->count) { $row_id = 'E'.$group['ID']; @@ -97,10 +113,12 @@ else { 'contactgroup' => Q($group['name'] . ' (' . intval($result->count) . ')')), 'group'); } } + + $CONTACTS->reset(); + $CONTACTS->set_group(0); } // get contacts for this user - $CONTACTS->set_group(0); $result = $CONTACTS->list_records($afields); } } @@ -118,10 +136,13 @@ else if (!empty($result) && $result->count > 0) { foreach ($emails as $i => $email) { $row_id = $row['ID'].$i; $jsresult[$row_id] = format_email_recipient($email, $name); + $classname = $row['_type'] == 'group' ? 'group' : 'person'; + $keyname = $row['_type'] == 'group' ? 'contactgroup' : 'contact'; + $OUTPUT->command('add_contact_row', $row_id, array( - 'contact' => html::span(array('title' => $email), Q($name ? $name : $email) . + $keyname => html::span(array('title' => $email), Q($name ? $name : $email) . ($name && count($emails) > 1 ? ' ' . html::span('email', Q($email)) : '') - )), 'person'); + )), $classname); } } } diff --git a/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc index e21ba2c6b..f15cd2460 100644 --- a/program/steps/mail/move_del.inc +++ b/program/steps/mail/move_del.inc @@ -29,7 +29,7 @@ $old_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL'); $old_pages = ceil($old_count / $RCMAIL->storage->get_pagesize()); // move messages -if ($RCMAIL->action == 'moveto' && !empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) { +if ($RCMAIL->action == 'move' && !empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) { $count = sizeof(explode(',', ($uids = get_input_value('_uid', RCUBE_INPUT_POST)))); $target = get_input_value('_target_mbox', RCUBE_INPUT_POST, true); $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true); @@ -126,7 +126,7 @@ else rcmail_set_unseen_count($mbox, $unseen_count); } - if ($RCMAIL->action == 'moveto' && strlen($target)) { + if ($RCMAIL->action == 'move' && strlen($target)) { rcmail_send_unread_count($target, true); } diff --git a/program/steps/mail/search_contacts.inc b/program/steps/mail/search_contacts.inc index 2e6bb12f8..6a30ad1f5 100644 --- a/program/steps/mail/search_contacts.inc +++ b/program/steps/mail/search_contacts.inc @@ -19,16 +19,15 @@ +-----------------------------------------------------------------------+ */ -$search = get_input_value('_q', RCUBE_INPUT_GPC, true); -$sources = $RCMAIL->get_address_sources(); -$search_mode = (int) $RCMAIL->config->get('addressbook_search_mode'); -$sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); -$afields = $RCMAIL->config->get('contactlist_fields'); +$search = get_input_value('_q', RCUBE_INPUT_GPC, true); +$sources = $RCMAIL->get_address_sources(); +$search_mode = (int) $RCMAIL->config->get('addressbook_search_mode'); +$addr_sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); +$afields = $RCMAIL->config->get('contactlist_fields'); +$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50)); +$records = array(); +$search_set = array(); -$page = 1; -$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50)); - -$records = $search_set = array(); foreach ($sources as $s) { $source = $RCMAIL->get_address_book($s['id']); $source->set_page(1); @@ -46,7 +45,7 @@ foreach ($sources as $s) { while ($row = $result->next()) { $row['sourceid'] = $s['id']; - $key = rcube_addressbook::compose_contact_key($row, $sort_col); + $key = rcube_addressbook::compose_contact_key($row, $addr_sort_col); $records[$key] = $row; } diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index cb3a40524..cf22a2af9 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -391,10 +391,6 @@ if (!empty($mailcc)) { if (!empty($mailbcc)) { $headers['Bcc'] = $mailbcc; } -if (!empty($identity_arr['bcc']) && stripos($headers['Bcc'], $identity_arr['bcc']) === false) { - $headers['Bcc'] = ($headers['Bcc'] ? $headers['Bcc'].', ' : '') . $identity_arr['bcc']; - $RECIPIENT_COUNT ++; -} if (($max_recipients = (int) $RCMAIL->config->get('max_recipients')) > 0) { if ($RECIPIENT_COUNT > $max_recipients) { @@ -412,9 +408,6 @@ 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'] = rcmail_email_input_format($identity_arr['reply-to'], false, true); -} if (!empty($headers['Reply-To'])) { $headers['Mail-Reply-To'] = $headers['Reply-To']; } diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc index d8d4372f9..59f4d55e1 100644 --- a/program/steps/mail/show.inc +++ b/program/steps/mail/show.inc @@ -275,9 +275,13 @@ function rcmail_contact_exists($email) if ($email) { // @TODO: search in all address books? $CONTACTS = $RCMAIL->get_address_book(-1, true); - $existing = $CONTACTS->search('email', $email, true, false); - if ($existing->count) - return true; + + if (is_object($CONTACTS)) { + $existing = $CONTACTS->search('email', $email, true, false); + if ($existing->count) { + return true; + } + } } return false; diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc index 34a72dd95..6d116e7d2 100644 --- a/program/steps/settings/folders.inc +++ b/program/steps/settings/folders.inc @@ -232,16 +232,16 @@ function rcube_subscription_form($attrib) // add any necessary "virtual" parent folders if ($parent_folder && !isset($seen[$parent_folder])) { for ($i=1; $i<=$level; $i++) { - $ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i)); - if ($ancestor_folder && !$seen[$ancestor_folder]++) { - $ancestor_name = rcube_charset_convert($foldersplit[$i-1], 'UTF7-IMAP'); - $list_folders[] = array( + $ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i)); + if ($ancestor_folder && !$seen[$ancestor_folder]++) { + $ancestor_name = rcube_charset_convert($foldersplit[$i-1], 'UTF7-IMAP'); + $list_folders[] = array( 'id' => $ancestor_folder, 'name' => $ancestor_name, 'level' => $i-1, 'virtual' => true, ); - } + } } } @@ -291,7 +291,8 @@ function rcube_subscription_form($attrib) $classes[] = 'virtual'; } - if (!$protected) { + // Check \Noselect flag (of existing folder) + if (!$protected && in_array($folder['id'], $a_unsubscribed)) { $attrs = $STORAGE->folder_attributes($folder['id']); $noselect = in_array('\\Noselect', $attrs); } diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc index ce86b1cd6..dbc9b3ce2 100644 --- a/program/steps/settings/func.inc +++ b/program/steps/settings/func.inc @@ -19,926 +19,1175 @@ +-----------------------------------------------------------------------+ */ -if (!$OUTPUT->ajax_call) - $OUTPUT->set_pagetitle(rcube_label('preferences')); - +if (!$OUTPUT->ajax_call) { + $OUTPUT->set_pagetitle(rcube_label('preferences')); +} // similar function as /steps/settings/identities.inc::rcmail_identity_frame() function rcmail_preferences_frame($attrib) { - global $OUTPUT; + global $OUTPUT; - if (!$attrib['id']) - $attrib['id'] = 'rcmprefsframe'; + if (!$attrib['id']) { + $attrib['id'] = 'rcmprefsframe'; + } - return $OUTPUT->frame($attrib, true); + return $OUTPUT->frame($attrib, true); } function rcmail_sections_list($attrib) { - global $RCMAIL; + global $RCMAIL; - // add id to message list table if not specified - if (!strlen($attrib['id'])) - $attrib['id'] = 'rcmsectionslist'; + // add id to message list table if not specified + if (!strlen($attrib['id'])) { + $attrib['id'] = 'rcmsectionslist'; + } - list($list, $cols) = rcmail_user_prefs(); + list($list, $cols) = rcmail_user_prefs(); - // create XHTML table - $out = rcube_table_output($attrib, $list, $cols, 'id'); + // create XHTML table + $out = rcube_table_output($attrib, $list, $cols, 'id'); - // set client env - $RCMAIL->output->add_gui_object('sectionslist', $attrib['id']); - $RCMAIL->output->include_script('list.js'); + // set client env + $RCMAIL->output->add_gui_object('sectionslist', $attrib['id']); + $RCMAIL->output->include_script('list.js'); - return $out; + return $out; } function rcmail_identities_list($attrib) { - global $OUTPUT, $RCMAIL; + global $OUTPUT, $RCMAIL; - // add id to message list table if not specified - if (!strlen($attrib['id'])) - $attrib['id'] = 'rcmIdentitiesList'; + // add id to message list table if not specified + if (!strlen($attrib['id'])) { + $attrib['id'] = 'rcmIdentitiesList'; + } - // get identities list and define 'mail' column - $list = $RCMAIL->user->list_identities(); - foreach ($list as $idx => $row) - $list[$idx]['mail'] = trim($row['name'] . ' <' . rcube_idn_to_utf8($row['email']) .'>'); + // get identities list and define 'mail' column + $list = $RCMAIL->user->list_identities(); + foreach ($list as $idx => $row) { + $list[$idx]['mail'] = trim($row['name'] . ' <' . rcube_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( - 'list' => $list, - 'cols' => array('mail'))); + // get all identites from DB and define list of cols to be displayed + $plugin = $RCMAIL->plugins->exec_hook('identities_list', array( + 'list' => $list, + 'cols' => array('mail') + )); - // @TODO: use <UL> instead of <TABLE> for identities list - // create XHTML table - $out = rcube_table_output($attrib, $plugin['list'], $plugin['cols'], 'identity_id'); + // @TODO: use <UL> instead of <TABLE> for identities list + // create XHTML table + $out = rcube_table_output($attrib, $plugin['list'], $plugin['cols'], 'identity_id'); - // set client env - $OUTPUT->add_gui_object('identitieslist', $attrib['id']); + // set client env + $OUTPUT->add_gui_object('identitieslist', $attrib['id']); - return $out; + return $out; } // similar function as in /steps/addressbook/edit.inc function get_form_tags($attrib, $action, $id = null, $hidden = null) { - global $EDIT_FORM, $RCMAIL; - - $form_start = $form_end = ''; - - if (empty($EDIT_FORM)) { - $request_key = $action . (isset($id) ? '.'.$id : ''); - $form_start = $RCMAIL->output->request_form(array( - 'name' => 'form', - 'method' => 'post', - 'task' => $RCMAIL->task, - 'action' => $action, - 'request' => $request_key, - 'noclose' => true - ) + $attrib); - - if (is_array($hidden)) { - $hiddenfields = new html_hiddenfield($hidden); - $form_start .= $hiddenfields->show(); - } + global $EDIT_FORM, $RCMAIL; + + $form_start = $form_end = ''; + + if (empty($EDIT_FORM)) { + $request_key = $action . (isset($id) ? '.'.$id : ''); + $form_start = $RCMAIL->output->request_form(array( + 'name' => 'form', + 'method' => 'post', + 'task' => $RCMAIL->task, + 'action' => $action, + 'request' => $request_key, + 'noclose' => true + ) + $attrib); + + if (is_array($hidden)) { + $hiddenfields = new html_hiddenfield($hidden); + $form_start .= $hiddenfields->show(); + } - $form_end = !strlen($attrib['form']) ? '</form>' : ''; + $form_end = !strlen($attrib['form']) ? '</form>' : ''; - $EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form'; - $RCMAIL->output->add_gui_object('editform', $EDIT_FORM); - } + $EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form'; + $RCMAIL->output->add_gui_object('editform', $EDIT_FORM); + } - return array($form_start, $form_end); + return array($form_start, $form_end); } -function rcmail_user_prefs($current=null) +function rcmail_user_prefs($current = null) { - global $RCMAIL; - - $sections['general'] = array('id' => 'general', 'section' => rcube_label('uisettings')); - $sections['mailbox'] = array('id' => 'mailbox', 'section' => rcube_label('mailboxview')); - $sections['mailview'] = array('id' => 'mailview','section' => rcube_label('messagesdisplaying')); - $sections['compose'] = array('id' => 'compose', 'section' => rcube_label('messagescomposition')); - $sections['addressbook'] = array('id' => 'addressbook','section' => rcube_label('addressbook')); - $sections['folders'] = array('id' => 'folders', 'section' => rcube_label('specialfolders')); - $sections['server'] = array('id' => 'server', 'section' => rcube_label('serversettings')); - - // hook + define list cols - $plugin = $RCMAIL->plugins->exec_hook('preferences_sections_list', - array('list' => $sections, 'cols' => array('section'))); - - $sections = $plugin['list']; - - $config = $RCMAIL->config->all(); - $no_override = array_flip($RCMAIL->config->get('dont_override', array())); - - foreach ($sections as $idx => $sect) { - - if ($current && $sect['id'] != $current) - continue; - - $blocks = array(); - - switch ($sect['id']) { - // general - case 'general': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - ); - - // language selection - if (!isset($no_override['language'])) { - $a_lang = $RCMAIL->list_languages(); - asort($a_lang); - - $field_id = 'rcmfd_lang'; - $select_lang = new html_select(array('name' => '_language', 'id' => $field_id)); - $select_lang->add(array_values($a_lang), array_keys($a_lang)); - - $blocks['main']['options']['language'] = array( - 'title' => html::label($field_id, Q(rcube_label('language'))), - 'content' => $select_lang->show($RCMAIL->user->language), - ); - } - - // timezone selection - if (!isset($no_override['timezone'])) { - $field_id = 'rcmfd_timezone'; - $select_timezone = new html_select(array('name' => '_timezone', 'id' => $field_id)); - $select_timezone->add(rcube_label('autodetect'), 'auto'); - - $zones = array(); - foreach (DateTimeZone::listIdentifiers() as $i => $tzs) { - try { - $tz = new DateTimeZone($tzs); - $date = new DateTime('2012-12-21', $tz); - $offset = $date->format('Z') + 45000; - $sortkey = sprintf('%06d.%s', $offset, $tzs); - $zones[$sortkey] = array($tzs, $date->format('P')); - } - catch (Exception $e) {} - } - - ksort($zones); - foreach ($zones as $zone) { - list($tzs, $offset) = $zone; - $select_timezone->add('(GMT ' . $offset . ') ' . strtr($tzs, '_', ' '), $tzs); - } - - $blocks['main']['options']['timezone'] = array( - 'title' => html::label($field_id, Q(rcube_label('timezone'))), - 'content' => $select_timezone->show((string)$config['timezone']), - ); - } - - // date/time formatting - if (!isset($no_override['time_format'])) { - $reftime = mktime(7,30,0); - $field_id = 'rcmfd_time_format'; - $select_time = new html_select(array('name' => '_time_format', 'id' => $field_id)); - foreach ((array)$RCMAIL->config->get('time_formats', array('G:i', 'H:i', 'g:i a', 'h:i A')) as $choice) - $select_time->add(date($choice, $reftime), $choice); - - $blocks['main']['options']['time_format'] = array( - 'title' => html::label($field_id, Q(rcube_label('timeformat'))), - 'content' => $select_time->show($RCMAIL->config->get('time_format')), - ); - } - - if (!isset($no_override['date_format'])) { - $refdate = mktime(12,30,0,7,24); - $field_id = 'rcmfd_date_format'; - $select_date = new html_select(array('name' => '_date_format', 'id' => $field_id)); - foreach ((array)$RCMAIL->config->get('date_formats', array('Y-m-d','d-m-Y','Y/m/d','m/d/Y','d/m/Y','d.m.Y','j.n.Y')) as $choice) - $select_date->add(date($choice, $refdate), $choice); - - $blocks['main']['options']['date_format'] = array( - 'title' => html::label($field_id, Q(rcube_label('dateformat'))), - 'content' => $select_date->show($config['date_format']), - ); - } + global $RCMAIL; - // MM: Show checkbox for toggling 'pretty dates' - if (!isset($no_override['prettydate'])) { - $field_id = 'rcmfd_prettydate'; - $input_prettydate = new html_checkbox(array('name' => '_pretty_date', 'id' => $field_id, 'value' => 1)); + $sections['general'] = array('id' => 'general', 'section' => rcube_label('uisettings')); + $sections['mailbox'] = array('id' => 'mailbox', 'section' => rcube_label('mailboxview')); + $sections['mailview'] = array('id' => 'mailview','section' => rcube_label('messagesdisplaying')); + $sections['compose'] = array('id' => 'compose', 'section' => rcube_label('messagescomposition')); + $sections['addressbook'] = array('id' => 'addressbook','section' => rcube_label('addressbook')); + $sections['folders'] = array('id' => 'folders', 'section' => rcube_label('specialfolders')); + $sections['server'] = array('id' => 'server', 'section' => rcube_label('serversettings')); - $blocks['main']['options']['prettydate'] = array( - 'title' => html::label($field_id, Q(rcube_label('prettydate'))), - 'content' => $input_prettydate->show($config['prettydate']?1:0), - ); - } + // hook + define list cols + $plugin = $RCMAIL->plugins->exec_hook('preferences_sections_list', + array('list' => $sections, 'cols' => array('section'))); - if (!isset($no_override['refresh_interval'])) { - $field_id = 'rcmfd_refresh_interval'; - $select_refresh_interval = new html_select(array('name' => '_refresh_interval', 'id' => $field_id)); + $sections = $plugin['list']; + $config = $RCMAIL->config->all(); + $no_override = array_flip((array)$RCMAIL->config->get('dont_override')); - $select_refresh_interval->add(rcube_label('never'), 0); - foreach (array(1, 3, 5, 10, 15, 30, 60) as $min) { - if (!$config['min_refresh_interval'] || $config['min_refresh_interval'] <= $min * 60) { - $label = rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min))); - $select_refresh_interval->add($label, $min); + foreach ($sections as $idx => $sect) { + if ($current && $sect['id'] != $current) { + continue; } - } - $blocks['main']['options']['refresh_interval'] = array( - 'title' => html::label($field_id, Q(rcube_label('refreshinterval'))), - 'content' => $select_refresh_interval->show($config['refresh_interval']/60), - ); - } - - // show drop-down for available skins - if (!isset($no_override['skin'])) { - $skins = rcmail_get_skins(); - - if (count($skins) > 1) { - $field_id = 'rcmfd_skin'; - $input_skin = new html_radiobutton(array('name'=>'_skin')); - - $blocks['skin'] = array('name' => Q(rcube_label('skin')),); - - foreach($skins as $skin) { - $thumbnail = "./skins/$skin/thumbnail.png"; - if (!is_file($thumbnail)) - $thumbnail = './program/resources/blank.gif'; - - $skinname = ucfirst($skin); - $author_link = $license_link = ''; - $meta = @json_decode(@file_get_contents("./skins/$skin/meta.json"), true); - if (is_array($meta) && $meta['name']) { - $skinname = $meta['name']; - $author_link = $meta['url'] ? html::a(array('href' => $meta['url'], 'target' => '_blank'), Q($meta['author'])) : Q($meta['author']); - $license_link = $meta['license-url'] ? html::a(array('href' => $meta['license-url'], 'target' => '_blank'), Q($meta['license'])) : Q($meta['license']); - } - - $blocks['skin']['options'][$skin]['content'] = html::label(array('class' => 'skinselection'), - html::span('skinitem', $input_skin->show($config['skin'], array('value' => $skin, 'id' => $field_id.$skin))) . - html::span('skinitem', html::img(array('src' => $thumbnail, 'class' => 'skinthumbnail', 'alt' => $skin, 'width' => 64, 'height' => 64))) . - html::span('skinitem', html::span('skinname', Q($skinname)) . html::br() . - html::span('skinauthor', $author_link ? 'by ' . $author_link : '') . html::br() . - html::span('skinlicense', $license_link ? rcube_label('license').': ' . $license_link : '')) - ); + $blocks = array(); + + switch ($sect['id']) { + + // general + case 'general': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + 'skin' => array('name' => Q(rcube_label('skin'))), + 'browser' => array('name' => Q(rcube_label('browseroptions'))), + ); + + // language selection + if (!isset($no_override['language'])) { + if (!$current) { + continue 2; + } + + $a_lang = $RCMAIL->list_languages(); + asort($a_lang); + + $field_id = 'rcmfd_lang'; + $select = new html_select(array('name' => '_language', 'id' => $field_id)); + $select->add(array_values($a_lang), array_keys($a_lang)); + + $blocks['main']['options']['language'] = array( + 'title' => html::label($field_id, Q(rcube_label('language'))), + 'content' => $select->show($RCMAIL->user->language), + ); + } + + // timezone selection + if (!isset($no_override['timezone'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_timezone'; + $select = new html_select(array('name' => '_timezone', 'id' => $field_id)); + $select->add(rcube_label('autodetect'), 'auto'); + + $zones = array(); + foreach (DateTimeZone::listIdentifiers() as $i => $tzs) { + try { + $tz = new DateTimeZone($tzs); + $date = new DateTime('2012-12-21', $tz); + $offset = $date->format('Z') + 45000; + $sortkey = sprintf('%06d.%s', $offset, $tzs); + $zones[$sortkey] = array($tzs, $date->format('P')); + } + catch (Exception $e) {} + } + + ksort($zones); + + foreach ($zones as $zone) { + list($tzs, $offset) = $zone; + $select->add('(GMT ' . $offset . ') ' . strtr($tzs, '_', ' '), $tzs); + } + + $blocks['main']['options']['timezone'] = array( + 'title' => html::label($field_id, Q(rcube_label('timezone'))), + 'content' => $select->show((string)$config['timezone']), + ); + } + + // date/time formatting + if (!isset($no_override['time_format'])) { + if (!$current) { + continue 2; + } + + $reftime = mktime(7,30,0); + $defaults = array('G:i', 'H:i', 'g:i a', 'h:i A'); + $formats = (array)$RCMAIL->config->get('time_formats', $defaults); + $field_id = 'rcmfd_time_format'; + $select = new html_select(array('name' => '_time_format', 'id' => $field_id)); + + foreach ($formats as $choice) { + $select->add(date($choice, $reftime), $choice); + } + + $blocks['main']['options']['time_format'] = array( + 'title' => html::label($field_id, Q(rcube_label('timeformat'))), + 'content' => $select->show($RCMAIL->config->get('time_format')), + ); + } + + if (!isset($no_override['date_format'])) { + if (!$current) { + continue 2; + } + + $refdate = mktime(12,30,0,7,24); + $defaults = array('Y-m-d','d-m-Y','Y/m/d','m/d/Y','d/m/Y','d.m.Y','j.n.Y'); + $formats = (array)$RCMAIL->config->get('date_formats', $defaults); + $field_id = 'rcmfd_date_format'; + $select = new html_select(array('name' => '_date_format', 'id' => $field_id)); + + foreach ($formats as $choice) { + $select->add(date($choice, $refdate), $choice); + } + + $blocks['main']['options']['date_format'] = array( + 'title' => html::label($field_id, Q(rcube_label('dateformat'))), + 'content' => $select->show($config['date_format']), + ); + } + + // Show checkbox for toggling 'pretty dates' + if (!isset($no_override['prettydate'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_prettydate'; + $input = new html_checkbox(array('name' => '_pretty_date', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['prettydate'] = array( + 'title' => html::label($field_id, Q(rcube_label('prettydate'))), + 'content' => $input->show($config['prettydate']?1:0), + ); + } + + if (!isset($no_override['refresh_interval'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_refresh_interval'; + $select = new html_select(array('name' => '_refresh_interval', 'id' => $field_id)); + + $select->add(rcube_label('never'), 0); + foreach (array(1, 3, 5, 10, 15, 30, 60) as $min) { + if (!$config['min_refresh_interval'] || $config['min_refresh_interval'] <= $min * 60) { + $label = rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min))); + $select->add($label, $min); + } + } + + $blocks['main']['options']['refresh_interval'] = array( + 'title' => html::label($field_id, Q(rcube_label('refreshinterval'))), + 'content' => $select->show($config['refresh_interval']/60), + ); + } + + // show drop-down for available skins + if (!isset($no_override['skin'])) { + if (!$current) { + continue 2; + } + + $skins = rcmail_get_skins(); + + if (count($skins) > 1) { + $field_id = 'rcmfd_skin'; + $input = new html_radiobutton(array('name'=>'_skin')); + + foreach ($skins as $skin) { + $thumbnail = "./skins/$skin/thumbnail.png"; + if (!is_file($thumbnail)) + $thumbnail = './program/resources/blank.gif'; + + $skinname = ucfirst($skin); + $author_link = $license_link = ''; + $meta = @json_decode(@file_get_contents("./skins/$skin/meta.json"), true); + + if (is_array($meta) && $meta['name']) { + $skinname = $meta['name']; + $author_link = $meta['url'] ? html::a(array('href' => $meta['url'], 'target' => '_blank'), Q($meta['author'])) : Q($meta['author']); + $license_link = $meta['license-url'] ? html::a(array('href' => $meta['license-url'], 'target' => '_blank'), Q($meta['license'])) : Q($meta['license']); + } + + $blocks['skin']['options'][$skin]['content'] = html::label(array('class' => 'skinselection'), + html::span('skinitem', $input->show($config['skin'], array('value' => $skin, 'id' => $field_id.$skin))) . + html::span('skinitem', html::img(array('src' => $thumbnail, 'class' => 'skinthumbnail', 'alt' => $skin, 'width' => 64, 'height' => 64))) . + html::span('skinitem', html::span('skinname', Q($skinname)) . html::br() . + html::span('skinauthor', $author_link ? 'by ' . $author_link : '') . html::br() . + html::span('skinlicense', $license_link ? rcube_label('license').': ' . $license_link : '')) + ); + } + } + } + + // standard_windows option decides if new windows should be + // opened as popups or standard windows (which can be handled by browsers as tabs) + if (!isset($no_override['standard_windows'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_standard_windows'; + $checkbox = new html_checkbox(array('name' => '_standard_windows', 'id' => $field_id, 'value' => 1)); + + $blocks['browser']['options']['standard_windows'] = array( + 'title' => html::label($field_id, Q(rcube_label('standardwindows'))), + 'content' => $checkbox->show($config['standard_windows']?1:0), + ); + } + + if ($current) { + $product_name = $RCMAIL->config->get('product_name', 'Roundcube Webmail'); + $RCMAIL->output->add_script(sprintf("%s.check_protocol_handler('%s', '#mailtoprotohandler');", + JS_OBJECT_NAME, JQ($product_name)), 'foot'); + } + + $blocks['browser']['options']['mailtoprotohandler'] = array( + 'content' => html::a(array( + 'href' => '#', + 'id' => 'mailtoprotohandler'), Q(rcube_label('mailtoprotohandler'))), + ); + + break; + + // Mailbox view (mail screen) + case 'mailbox': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + 'new_message' => array('name' => Q(rcube_label('newmessage'))), + ); + + // show config parameter for preview pane + if (!isset($no_override['preview_pane'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_preview'; + $input = new html_checkbox(array('name' => '_preview_pane', 'id' => $field_id, 'value' => 1, + 'onchange' => "$('#rcmfd_preview_pane_mark_read').prop('disabled', !this.checked)")); + + $blocks['main']['options']['preview_pane'] = array( + 'title' => html::label($field_id, Q(rcube_label('previewpane'))), + 'content' => $input->show($config['preview_pane']?1:0), + ); + } + + // show config parameter for preview pane auto mark as read delay + if (!isset($no_override['preview_pane_mark_read'])) { + if (!$current) { + continue 2; + } + + // apply default if config option is not set at all + $config['preview_pane_mark_read'] = $RCMAIL->config->get('preview_pane_mark_read', 0); + + $field_id = 'rcmfd_preview_pane_mark_read'; + $select = new html_select(array('name' => '_preview_pane_mark_read', 'id' => $field_id, + 'disabled' => $config['preview_pane']?0:1)); + + $select->add(rcube_label('never'), '-1'); + $select->add(rcube_label('immediately'), 0); + + foreach (array(5, 10, 20, 30) as $sec) { + $label = rcube_label(array('name' => 'afternseconds', 'vars' => array('n' => $sec))); + $select->add($label, $sec); + } + + $blocks['main']['options']['preview_pane_mark_read'] = array( + 'title' => html::label($field_id, Q(rcube_label('previewpanemarkread'))), + 'content' => $select->show(intval($config['preview_pane_mark_read'])), + ); + } + + if (!isset($no_override['mdn_requests'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_mdn_requests'; + $select = new html_select(array('name' => '_mdn_requests', 'id' => $field_id)); + $select->add(rcube_label('askuser'), 0); + $select->add(rcube_label('autosend'), 1); + $select->add(rcube_label('autosendknown'), 3); + $select->add(rcube_label('autosendknownignore'), 4); + $select->add(rcube_label('ignore'), 2); + + $blocks['main']['options']['mdn_requests'] = array( + 'title' => html::label($field_id, Q(rcube_label('mdnrequests'))), + 'content' => $select->show($config['mdn_requests']), + ); + } + + if (!isset($no_override['autoexpand_threads'])) { + if (!$current) { + continue 2; + } + + $storage = $RCMAIL->get_storage(); + $supported = $storage->get_capability('THREAD'); + + if ($supported) { + $field_id = 'rcmfd_autoexpand_threads'; + $select = new html_select(array('name' => '_autoexpand_threads', 'id' => $field_id)); + $select->add(rcube_label('never'), 0); + $select->add(rcube_label('do_expand'), 1); + $select->add(rcube_label('expand_only_unread'), 2); + + $blocks['main']['options']['autoexpand_threads'] = array( + 'title' => html::label($field_id, Q(rcube_label('autoexpand_threads'))), + 'content' => $select->show($config['autoexpand_threads']), + ); + } + } + + // show page size selection + if (!isset($no_override['mail_pagesize'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_mail_pagesize'; + $input = new html_inputfield(array('name' => '_mail_pagesize', 'id' => $field_id, 'size' => 5)); + $size = intval($config['mail_pagesize'] ? $config['mail_pagesize'] : $config['pagesize']); + + $blocks['main']['options']['pagesize'] = array( + 'title' => html::label($field_id, Q(rcube_label('pagesize'))), + 'content' => $input->show($size ? $size : 50), + ); + } + + if (!isset($no_override['check_all_folders'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_check_all_folders'; + $input = new html_checkbox(array('name' => '_check_all_folders', 'id' => $field_id, 'value' => 1)); + + $blocks['new_message']['options']['check_all_folders'] = array( + 'title' => html::label($field_id, Q(rcube_label('checkallfolders'))), + 'content' => $input->show($config['check_all_folders']?1:0), + ); + } + break; + + // Message viewing + case 'mailview': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + ); + + // show checkbox to open message view in new window + if (!isset($no_override['message_extwin'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_message_extwin'; + $input = new html_checkbox(array('name' => '_message_extwin', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['message_extwin'] = array( + 'title' => html::label($field_id, Q(rcube_label('showinextwin'))), + 'content' => $input->show($config['message_extwin']?1:0), + ); + } + + // show checkbox to show email instead of name + if (!isset($no_override['message_show_email'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_message_show_email'; + $input = new html_checkbox(array('name' => '_message_show_email', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['message_show_email'] = array( + 'title' => html::label($field_id, Q(rcube_label('showemail'))), + 'content' => $input->show($config['message_show_email']?1:0), + ); + } + + // show checkbox for HTML/plaintext messages + if (!isset($no_override['prefer_html'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_htmlmsg'; + $input = new html_checkbox(array('name' => '_prefer_html', 'id' => $field_id, 'value' => 1, + 'onchange' => "$('#rcmfd_show_images').prop('disabled', !this.checked).val(0)")); + + $blocks['main']['options']['prefer_html'] = array( + 'title' => html::label($field_id, Q(rcube_label('preferhtml'))), + 'content' => $input->show($config['prefer_html']?1:0), + ); + } + + if (!isset($no_override['default_charset'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_default_charset'; + + $blocks['main']['options']['default_charset'] = array( + 'title' => html::label($field_id, Q(rcube_label('defaultcharset'))), + 'content' => $RCMAIL->output->charset_selector(array( + 'name' => '_default_charset', 'selected' => $config['default_charset'] + ))); + } + + if (!isset($no_override['show_images'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_show_images'; + $input = new html_select(array('name' => '_show_images', 'id' => $field_id, + 'disabled' => !$config['prefer_html'])); + + $input->add(rcube_label('never'), 0); + $input->add(rcube_label('fromknownsenders'), 1); + $input->add(rcube_label('always'), 2); + + $blocks['main']['options']['show_images'] = array( + 'title' => html::label($field_id, Q(rcube_label('showremoteimages'))), + 'content' => $input->show($config['prefer_html'] ? $config['show_images'] : 0), + ); + } + + if (!isset($no_override['inline_images'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_inline_images'; + $input = new html_checkbox(array('name' => '_inline_images', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['inline_images'] = array( + 'title' => html::label($field_id, Q(rcube_label('showinlineimages'))), + 'content' => $input->show($config['inline_images']?1:0), + ); + } + + // "display after delete" checkbox + if (!isset($no_override['display_next'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_displaynext'; + $input = new html_checkbox(array('name' => '_display_next', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['display_next'] = array( + 'title' => html::label($field_id, Q(rcube_label('displaynext'))), + 'content' => $input->show($config['display_next']?1:0), + ); + } + break; + + // Mail composition + case 'compose': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + 'sig' => array('name' => Q(rcube_label('signatureoptions'))), + 'spellcheck' => array('name' => Q(rcube_label('spellcheckoptions'))), + ); + + // show checkbox to compose messages in a new window + if (!isset($no_override['compose_extwin'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfdcompose_extwin'; + $input = new html_checkbox(array('name' => '_compose_extwin', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['compose_extwin'] = array( + 'title' => html::label($field_id, Q(rcube_label('composeextwin'))), + 'content' => $input->show($config['compose_extwin']?1:0), + ); + } + + if (!isset($no_override['htmleditor'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_htmleditor'; + $select = new html_select(array('name' => '_htmleditor', 'id' => $field_id)); + + $select->add(rcube_label('never'), 0); + $select->add(rcube_label('always'), 1); + $select->add(rcube_label('htmlonreply'), 2); + $select->add(rcube_label('htmlonreplyandforward'), 3); + + $blocks['main']['options']['htmleditor'] = array( + 'title' => html::label($field_id, Q(rcube_label('htmleditor'))), + 'content' => $select->show(intval($config['htmleditor'])), + ); + } + + if (!isset($no_override['draft_autosave'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_autosave'; + $select = new html_select(array('name' => '_draft_autosave', 'id' => $field_id, 'disabled' => empty($config['drafts_mbox']))); + + $select->add(rcube_label('never'), 0); + foreach (array(1, 3, 5, 10) as $i => $min) { + $label = rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min))); + $select->add($label, $min*60); + } + + $blocks['main']['options']['draft_autosave'] = array( + 'title' => html::label($field_id, Q(rcube_label('autosavedraft'))), + 'content' => $select->show($config['draft_autosave']), + ); + } + + if (!isset($no_override['mime_param_folding'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_param_folding'; + $select = new html_select(array('name' => '_mime_param_folding', 'id' => $field_id)); + + $select->add(rcube_label('2231folding'), 0); + $select->add(rcube_label('miscfolding'), 1); + $select->add(rcube_label('2047folding'), 2); + + $blocks['main']['options']['mime_param_folding'] = array( + 'advanced' => true, + 'title' => html::label($field_id, Q(rcube_label('mimeparamfolding'))), + 'content' => $select->show($config['mime_param_folding']), + ); + } + + if (!isset($no_override['force_7bit'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_force_7bit'; + $input = new html_checkbox(array('name' => '_force_7bit', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['force_7bit'] = array( + 'advanced' => true, + 'title' => html::label($field_id, Q(rcube_label('force7bit'))), + 'content' => $input->show($config['force_7bit']?1:0), + ); + } + + if (!isset($no_override['mdn_default'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_mdn_default'; + $input = new html_checkbox(array('name' => '_mdn_default', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['mdn_default'] = array( + 'title' => html::label($field_id, Q(rcube_label('reqmdn'))), + 'content' => $input->show($config['mdn_default']?1:0), + ); + } + + if (!isset($no_override['dsn_default'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_dsn_default'; + $input = new html_checkbox(array('name' => '_dsn_default', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['dsn_default'] = array( + 'title' => html::label($field_id, Q(rcube_label('reqdsn'))), + 'content' => $input->show($config['dsn_default']?1:0), + ); + } + + if (!isset($no_override['reply_same_folder'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_reply_same_folder'; + $input = new html_checkbox(array('name' => '_reply_same_folder', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['reply_same_folder'] = array( + 'title' => html::label($field_id, Q(rcube_label('replysamefolder'))), + 'content' => $input->show($config['reply_same_folder']?1:0), + ); + } + + if (!isset($no_override['reply_mode'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_reply_mode'; + $select = new html_select(array('name' => '_reply_mode', 'id' => $field_id)); + + $select->add(rcube_label('replyempty'), -1); + $select->add(rcube_label('replybottomposting'), 0); + $select->add(rcube_label('replytopposting'), 1); + + $blocks['main']['options']['reply_mode'] = array( + 'title' => html::label($field_id, Q(rcube_label('whenreplying'))), + 'content' => $select->show(intval($config['reply_mode'])), + ); + } + + if (!isset($no_override['spellcheck_before_send']) && $config['enable_spellcheck']) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_spellcheck_before_send'; + $input = new html_checkbox(array('name' => '_spellcheck_before_send', 'id' => $field_id, 'value' => 1)); + + $blocks['spellcheck']['options']['spellcheck_before_send'] = array( + 'title' => html::label($field_id, Q(rcube_label('spellcheckbeforesend'))), + 'content' => $input->show($config['spellcheck_before_send']?1:0), + ); + } + + if ($config['enable_spellcheck']) { + if (!$current) { + continue 2; + } + + foreach (array('syms', 'nums', 'caps') as $key) { + $key = 'spellcheck_ignore_'.$key; + if (!isset($no_override[$key])) { + $input = new html_checkbox(array('name' => '_'.$key, 'id' => 'rcmfd_'.$key, 'value' => 1)); + + $blocks['spellcheck']['options'][$key] = array( + 'title' => html::label($field_id, Q(rcube_label(str_replace('_', '', $key)))), + 'content' => $input->show($config[$key]?1:0), + ); + } + } + } + + if (!isset($no_override['show_sig'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_show_sig'; + $select = new html_select(array('name' => '_show_sig', 'id' => $field_id)); + + $select->add(rcube_label('never'), 0); + $select->add(rcube_label('always'), 1); + $select->add(rcube_label('newmessageonly'), 2); + $select->add(rcube_label('replyandforwardonly'), 3); + + $blocks['sig']['options']['show_sig'] = array( + 'title' => html::label($field_id, Q(rcube_label('autoaddsignature'))), + 'content' => $select->show($RCMAIL->config->get('show_sig', 1)), + ); + } + + if (!isset($no_override['strip_existing_sig'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_strip_existing_sig'; + $input = new html_checkbox(array('name' => '_strip_existing_sig', 'id' => $field_id, 'value' => 1)); + + $blocks['sig']['options']['strip_existing_sig'] = array( + 'title' => html::label($field_id, Q(rcube_label('replyremovesignature'))), + 'content' => $input->show($config['strip_existing_sig']?1:0), + ); + } + + if (!isset($no_override['forward_attachment'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_forward_attachment'; + $select = new html_select(array('name' => '_forward_attachment', 'id' => $field_id)); + + $select->add(rcube_label('inline'), 0); + $select->add(rcube_label('asattachment'), 1); + + $blocks['main']['options']['forward_attachment'] = array( + 'title' => html::label($field_id, Q(rcube_label('forwardmode'))), + 'content' => $select->show(intval($config['forward_attachment'])), + ); + } + + if (!isset($no_override['default_font'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_default_font'; + $fonts = rcube_fontdefs(); + $selected = $config['default_font']; + + $select = '<select name="_default_font" id="'.$field_id.'">'; + $select .= '<option value=""' . (!$selected ? ' selected="selected"' : '') . '>---</option>'; + foreach ($fonts as $fname => $font) { + $select .= '<option value="'.$fname.'"' + . ($fname == $selected ? ' selected="selected"' : '') + . ' style=\'font-family: ' . $font . '\'>' + . Q($fname) . '</option>'; + } + $select .= '</select>'; + + $blocks['main']['options']['default_font'] = array( + 'title' => html::label($field_id, Q(rcube_label('defaultfont'))), + 'content' => $select + ); + } + break; + + // Addressbook config + case 'addressbook': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + ); + + if (!isset($no_override['default_addressbook']) + && (!$current || ($books = $RCMAIL->get_address_sources(true, true))) + ) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_default_addressbook'; + $select = new html_select(array('name' => '_default_addressbook', 'id' => $field_id)); + + foreach ($books as $book) { + $select->add(html_entity_decode($book['name'], ENT_COMPAT, 'UTF-8'), $book['id']); + } + + $blocks['main']['options']['default_addressbook'] = array( + 'title' => html::label($field_id, Q(rcube_label('defaultabook'))), + 'content' => $select->show($config['default_addressbook']), + ); + } + + // show addressbook listing mode selection + if (!isset($no_override['addressbook_name_listing'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_addressbook_name_listing'; + $select = new html_select(array('name' => '_addressbook_name_listing', 'id' => $field_id)); + + $select->add(rcube_label('name'), 0); + $select->add(rcube_label('firstname') . ' ' . rcube_label('surname'), 1); + $select->add(rcube_label('surname') . ' ' . rcube_label('firstname'), 2); + $select->add(rcube_label('surname') . ', ' . rcube_label('firstname'), 3); + + $blocks['main']['options']['list_name_listing'] = array( + 'title' => html::label($field_id, Q(rcube_label('listnamedisplay'))), + 'content' => $select->show($config['addressbook_name_listing']), + ); + } + + // show addressbook sort column + if (!isset($no_override['addressbook_sort_col'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_addressbook_sort_col'; + $select = new html_select(array('name' => '_addressbook_sort_col', 'id' => $field_id)); + + $select->add(rcube_label('name'), 'name'); + $select->add(rcube_label('firstname'), 'firstname'); + $select->add(rcube_label('surname'), 'surname'); + + $blocks['main']['options']['sort_col'] = array( + 'title' => html::label($field_id, Q(rcube_label('listsorting'))), + 'content' => $select->show($config['addressbook_sort_col']), + ); + } + + // show addressbook page size selection + if (!isset($no_override['addressbook_pagesize'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_addressbook_pagesize'; + $input = new html_inputfield(array('name' => '_addressbook_pagesize', 'id' => $field_id, 'size' => 5)); + $size = intval($config['addressbook_pagesize'] ? $config['addressbook_pagesize'] : $config['pagesize']); + + $blocks['main']['options']['pagesize'] = array( + 'title' => html::label($field_id, Q(rcube_label('pagesize'))), + 'content' => $input->show($size ? $size : 50), + ); + } + + if (!isset($no_override['autocomplete_single'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_autocomplete_single'; + $checkbox = new html_checkbox(array('name' => '_autocomplete_single', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['autocomplete_single'] = array( + 'title' => html::label($field_id, Q(rcube_label('autocompletesingle'))), + 'content' => $checkbox->show($config['autocomplete_single']?1:0), + ); + } + break; + + // Special IMAP folders + case 'folders': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + ); + + if (!isset($no_override['show_real_foldernames'])) { + if (!$current) { + continue 2; + } + + $field_id = 'show_real_foldernames'; + $input = new html_checkbox(array('name' => '_show_real_foldernames', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['show_real_foldernames'] = array( + 'title' => html::label($field_id, Q(rcube_label('show_real_foldernames'))), + 'content' => $input->show($config['show_real_foldernames']?1:0), + ); + } + + // Configure special folders + if (!isset($no_override['default_folders']) && $current) { + $select = rcmail_mailbox_select(array( + 'noselection' => '---', + 'realnames' => true, + 'maxlength' => 30, + 'folder_filter' => 'mail', + 'folder_rights' => 'w', + // #1486114, #1488279 + 'onchange' => "if ($(this).val() == 'INBOX') $(this).val('')", + )); + } + + if (!isset($no_override['drafts_mbox'])) { + if (!$current) { + continue 2; + } + + $blocks['main']['options']['drafts_mbox'] = array( + 'title' => Q(rcube_label('drafts')), + 'content' => $select->show($config['drafts_mbox'], array('name' => "_drafts_mbox")), + ); + } + + if (!isset($no_override['sent_mbox'])) { + if (!$current) { + continue 2; + } + + $blocks['main']['options']['sent_mbox'] = array( + 'title' => Q(rcube_label('sent')), + 'content' => $select->show($config['sent_mbox'], array('name' => "_sent_mbox")), + ); + } + + if (!isset($no_override['junk_mbox'])) { + if (!$current) { + continue 2; + } + + $blocks['main']['options']['junk_mbox'] = array( + 'title' => Q(rcube_label('junk')), + 'content' => $select->show($config['junk_mbox'], array('name' => "_junk_mbox")), + ); + } + + if (!isset($no_override['trash_mbox'])) { + if (!$current) { + continue 2; + } + + $blocks['main']['options']['trash_mbox'] = array( + 'title' => Q(rcube_label('trash')), + 'content' => $select->show($config['trash_mbox'], array('name' => "_trash_mbox")), + ); + } + break; + + // Server settings + case 'server': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + 'maintenance' => array('name' => Q(rcube_label('maintenance'))), + ); + + if (!isset($no_override['read_when_deleted'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_read_deleted'; + $input = new html_checkbox(array('name' => '_read_when_deleted', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['read_when_deleted'] = array( + 'title' => html::label($field_id, Q(rcube_label('readwhendeleted'))), + 'content' => $input->show($config['read_when_deleted']?1:0), + ); + } + + if (!isset($no_override['flag_for_deletion'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_flag_for_deletion'; + $input = new html_checkbox(array('name' => '_flag_for_deletion', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['flag_for_deletion'] = array( + 'title' => html::label($field_id, Q(rcube_label('flagfordeletion'))), + 'content' => $input->show($config['flag_for_deletion']?1:0), + ); + } + + // don't show deleted messages + if (!isset($no_override['skip_deleted'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_skip_deleted'; + $input = new html_checkbox(array('name' => '_skip_deleted', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['skip_deleted'] = array( + 'title' => html::label($field_id, Q(rcube_label('skipdeleted'))), + 'content' => $input->show($config['skip_deleted']?1:0), + ); + } + + if (!isset($no_override['delete_always'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_delete_always'; + $input = new html_checkbox(array('name' => '_delete_always', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['delete_always'] = array( + 'title' => html::label($field_id, Q(rcube_label('deletealways'))), + 'content' => $input->show($config['delete_always']?1:0), + ); + } + + if (!isset($no_override['delete_junk'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_delete_junk'; + $input = new html_checkbox(array('name' => '_delete_junk', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['delete_junk'] = array( + 'title' => html::label($field_id, Q(rcube_label('deletejunk'))), + 'content' => $input->show($config['delete_junk']?1:0), + ); + } + + // Trash purging on logout + if (!isset($no_override['logout_purge'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_logout_purge'; + $input = new html_checkbox(array('name' => '_logout_purge', 'id' => $field_id, 'value' => 1)); + + $blocks['maintenance']['options']['logout_purge'] = array( + 'title' => html::label($field_id, Q(rcube_label('logoutclear'))), + 'content' => $input->show($config['logout_purge']?1:0), + ); + } + + // INBOX compacting on logout + if (!isset($no_override['logout_expunge'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_logout_expunge'; + $input = new html_checkbox(array('name' => '_logout_expunge', 'id' => $field_id, 'value' => 1)); + + $blocks['maintenance']['options']['logout_expunge'] = array( + 'title' => html::label($field_id, Q(rcube_label('logoutcompact'))), + 'content' => $input->show($config['logout_expunge']?1:0), + ); + } } - } - } - - $product_name = $RCMAIL->config->get('product_name', 'Roundcube Webmail'); - $RCMAIL->output->add_script(sprintf("%s.check_protocol_handler('%s', '#mailtoprotohandler');", - JS_OBJECT_NAME, JQ($product_name)), 'foot'); - - $blocks['browser'] = array( - 'name' => Q(rcube_label('browseroptions')), - 'options' => array('mailtoprotohandler' => array( - 'content' => html::a(array( - 'href' => '#', - 'id' => 'mailtoprotohandler'), Q(rcube_label('mailtoprotohandler'))), - )), - ); - - break; - - // Mailbox view (mail screen) - case 'mailbox': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - 'new_message' => array('name' => Q(rcube_label('newmessage'))), - ); - - // show config parameter for preview pane - if (!isset($no_override['preview_pane'])) { - $field_id = 'rcmfd_preview'; - $input_preview = new html_checkbox(array('name' => '_preview_pane', 'id' => $field_id, 'value' => 1, - 'onchange' => "$('#rcmfd_preview_pane_mark_read').prop('disabled', !this.checked)")); - - $blocks['main']['options']['preview_pane'] = array( - 'title' => html::label($field_id, Q(rcube_label('previewpane'))), - 'content' => $input_preview->show($config['preview_pane']?1:0), - ); - } - - // show config parameter for preview pane auto mark as read delay - if (!isset($no_override['preview_pane_mark_read'])) { - // apply default if config option is not set at all - $config['preview_pane_mark_read'] = $RCMAIL->config->get('preview_pane_mark_read', 0); - - $field_id = 'rcmfd_preview_pane_mark_read'; - $select_delay = new html_select(array('name' => '_preview_pane_mark_read', 'id' => $field_id, - 'disabled' => $config['preview_pane']?0:1)); - - $select_delay->add(rcube_label('never'), '-1'); - $select_delay->add(rcube_label('immediately'), 0); - foreach(array(5, 10, 20, 30) as $sec) - $select_delay->add(rcube_label(array('name' => 'afternseconds', 'vars' => array('n' => $sec))), $sec); - - $blocks['main']['options']['preview_pane_mark_read'] = array( - 'title' => html::label($field_id, Q(rcube_label('previewpanemarkread'))), - 'content' => $select_delay->show(intval($config['preview_pane_mark_read'])), - ); - } - - if (!isset($no_override['mdn_requests'])) { - $field_id = 'rcmfd_mdn_requests'; - $select_mdn_requests = new html_select(array('name' => '_mdn_requests', 'id' => $field_id)); - $select_mdn_requests->add(rcube_label('askuser'), 0); - $select_mdn_requests->add(rcube_label('autosend'), 1); - $select_mdn_requests->add(rcube_label('autosendknown'), 3); - $select_mdn_requests->add(rcube_label('autosendknownignore'), 4); - $select_mdn_requests->add(rcube_label('ignore'), 2); - - $blocks['main']['options']['mdn_requests'] = array( - 'title' => html::label($field_id, Q(rcube_label('mdnrequests'))), - 'content' => $select_mdn_requests->show($config['mdn_requests']), - ); - } - - $storage = $RCMAIL->get_storage(); - $threading_supported = $storage->get_capability('THREAD'); - - if (!isset($no_override['autoexpand_threads']) && $threading_supported) { - $field_id = 'rcmfd_autoexpand_threads'; - $select_autoexpand_threads = new html_select(array('name' => '_autoexpand_threads', 'id' => $field_id)); - $select_autoexpand_threads->add(rcube_label('never'), 0); - $select_autoexpand_threads->add(rcube_label('do_expand'), 1); - $select_autoexpand_threads->add(rcube_label('expand_only_unread'), 2); - - $blocks['main']['options']['autoexpand_threads'] = array( - 'title' => html::label($field_id, Q(rcube_label('autoexpand_threads'))), - 'content' => $select_autoexpand_threads->show($config['autoexpand_threads']), - ); - } - - // show page size selection - if (!isset($no_override['mail_pagesize'])) { - $field_id = 'rcmfd_mail_pagesize'; - $input_pagesize = new html_inputfield(array('name' => '_mail_pagesize', 'id' => $field_id, 'size' => 5)); - - $size = intval($config['mail_pagesize'] ? $config['mail_pagesize'] : $config['pagesize']); - - $blocks['main']['options']['pagesize'] = array( - 'title' => html::label($field_id, Q(rcube_label('pagesize'))), - 'content' => $input_pagesize->show($size ? $size : 50), - ); - } - if (!isset($no_override['check_all_folders'])) { - $field_id = 'rcmfd_check_all_folders'; - $input_check_all = new html_checkbox(array('name' => '_check_all_folders', 'id' => $field_id, 'value' => 1)); - - $blocks['new_message']['options']['check_all_folders'] = array( - 'title' => html::label($field_id, Q(rcube_label('checkallfolders'))), - 'content' => $input_check_all->show($config['check_all_folders']?1:0), - ); - } - - break; - - // Message viewing - case 'mailview': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - ); - - // show checkbox to open message view in new window - if (!isset($no_override['message_extwin'])) { - $field_id = 'rcmfd_message_extwin'; - $input_msgextwin = new html_checkbox(array('name' => '_message_extwin', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['message_extwin'] = array( - 'title' => html::label($field_id, Q(rcube_label('showinextwin'))), - 'content' => $input_msgextwin->show($config['message_extwin']?1:0), - ); - } - - // show checkbox to show email instead of name - if (!isset($no_override['message_show_email'])) { - $field_id = 'rcmfd_message_show_email'; - $input_msgshowemail = new html_checkbox(array('name' => '_message_show_email', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['message_show_email'] = array( - 'title' => html::label($field_id, Q(rcube_label('showemail'))), - 'content' => $input_msgshowemail->show($config['message_show_email']?1:0), - ); - } - - // show checkbox for HTML/plaintext messages - if (!isset($no_override['prefer_html'])) { - $field_id = 'rcmfd_htmlmsg'; - $input_preferhtml = new html_checkbox(array('name' => '_prefer_html', 'id' => $field_id, 'value' => 1, - 'onchange' => "$('#rcmfd_show_images').prop('disabled', !this.checked).val(0)")); - - $blocks['main']['options']['prefer_html'] = array( - 'title' => html::label($field_id, Q(rcube_label('preferhtml'))), - 'content' => $input_preferhtml->show($config['prefer_html']?1:0), - ); - } - - if (!isset($no_override['default_charset'])) { - $field_id = 'rcmfd_default_charset'; - - $blocks['main']['options']['default_charset'] = array( - 'title' => html::label($field_id, Q(rcube_label('defaultcharset'))), - 'content' => $RCMAIL->output->charset_selector(array( - 'name' => '_default_charset', 'selected' => $config['default_charset'] - )) - ); - } - - if (!isset($no_override['show_images'])) { - $field_id = 'rcmfd_show_images'; - $input_show_images = new html_select(array('name' => '_show_images', 'id' => $field_id, - 'disabled' => !$config['prefer_html'])); - $input_show_images->add(rcube_label('never'), 0); - $input_show_images->add(rcube_label('fromknownsenders'), 1); - $input_show_images->add(rcube_label('always'), 2); - - $blocks['main']['options']['show_images'] = array( - 'title' => html::label($field_id, Q(rcube_label('showremoteimages'))), - 'content' => $input_show_images->show($config['prefer_html'] ? $config['show_images'] : 0), - ); - } - - if (!isset($no_override['inline_images'])) { - $field_id = 'rcmfd_inline_images'; - $input_inline_images = new html_checkbox(array('name' => '_inline_images', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['inline_images'] = array( - 'title' => html::label($field_id, Q(rcube_label('showinlineimages'))), - 'content' => $input_inline_images->show($config['inline_images']?1:0), - ); - } - - // "display after delete" checkbox - if (!isset($no_override['display_next'])) { - $field_id = 'rcmfd_displaynext'; - $input_displaynext = new html_checkbox(array('name' => '_display_next', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['display_next'] = array( - 'title' => html::label($field_id, Q(rcube_label('displaynext'))), - 'content' => $input_displaynext->show($config['display_next']?1:0), - ); - } - - break; - - // Mail composition - case 'compose': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - 'sig' => array('name' => Q(rcube_label('signatureoptions'))), - 'spellcheck' => array('name' => Q(rcube_label('spellcheckoptions'))), - ); - - // show checkbox to compose messages in a new window - if (!isset($no_override['compose_extwin'])) { - $field_id = 'rcmfdcompose_extwin'; - $input_compextwin = new html_checkbox(array('name' => '_compose_extwin', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['compose_extwin'] = array( - 'title' => html::label($field_id, Q(rcube_label('composeextwin'))), - 'content' => $input_compextwin->show($config['compose_extwin']?1:0), - ); - } - - if (!isset($no_override['htmleditor'])) { - $field_id = 'rcmfd_htmleditor'; - $select_htmleditor = new html_select(array('name' => '_htmleditor', 'id' => $field_id)); - $select_htmleditor->add(rcube_label('never'), 0); - $select_htmleditor->add(rcube_label('always'), 1); - $select_htmleditor->add(rcube_label('htmlonreply'), 2); - $select_htmleditor->add(rcube_label('htmlonreplyandforward'), 3); - - $blocks['main']['options']['htmleditor'] = array( - 'title' => html::label($field_id, Q(rcube_label('htmleditor'))), - 'content' => $select_htmleditor->show(intval($config['htmleditor'])), - ); - } - - if (!isset($no_override['draft_autosave'])) { - $field_id = 'rcmfd_autosave'; - $select_autosave = new html_select(array('name' => '_draft_autosave', 'id' => $field_id, 'disabled' => empty($config['drafts_mbox']))); - $select_autosave->add(rcube_label('never'), 0); - foreach (array(1, 3, 5, 10) as $i => $min) - $select_autosave->add(rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min))), $min*60); - - $blocks['main']['options']['draft_autosave'] = array( - 'title' => html::label($field_id, Q(rcube_label('autosavedraft'))), - 'content' => $select_autosave->show($config['draft_autosave']), - ); - } - - if (!isset($no_override['mime_param_folding'])) { - $field_id = 'rcmfd_param_folding'; - $select_param_folding = new html_select(array('name' => '_mime_param_folding', 'id' => $field_id)); - $select_param_folding->add(rcube_label('2231folding'), 0); - $select_param_folding->add(rcube_label('miscfolding'), 1); - $select_param_folding->add(rcube_label('2047folding'), 2); - - $blocks['main']['options']['mime_param_folding'] = array( - 'advanced' => true, - 'title' => html::label($field_id, Q(rcube_label('mimeparamfolding'))), - 'content' => $select_param_folding->show($config['mime_param_folding']), - ); - } - - if (!isset($no_override['force_7bit'])) { - $field_id = 'rcmfd_force_7bit'; - $input_7bit = new html_checkbox(array('name' => '_force_7bit', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['force_7bit'] = array( - 'title' => html::label($field_id, Q(rcube_label('force7bit'))), - 'content' => $input_7bit->show($config['force_7bit']?1:0), - ); - } - - if (!isset($no_override['mdn_default'])) { - $field_id = 'rcmfd_mdn_default'; - $input_mdn = new html_checkbox(array('name' => '_mdn_default', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['mdn_default'] = array( - 'title' => html::label($field_id, Q(rcube_label('reqmdn'))), - 'content' => $input_mdn->show($config['mdn_default']?1:0), - ); - } - - if (!isset($no_override['dsn_default'])) { - $field_id = 'rcmfd_dsn_default'; - $input_dsn = new html_checkbox(array('name' => '_dsn_default', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['dsn_default'] = array( - 'title' => html::label($field_id, Q(rcube_label('reqdsn'))), - 'content' => $input_dsn->show($config['dsn_default']?1:0), - ); - } - - if (!isset($no_override['reply_same_folder'])) { - $field_id = 'rcmfd_reply_same_folder'; - $input_reply_same_folder = new html_checkbox(array('name' => '_reply_same_folder', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['reply_same_folder'] = array( - 'title' => html::label($field_id, Q(rcube_label('replysamefolder'))), - 'content' => $input_reply_same_folder->show($config['reply_same_folder']?1:0), - ); - } - - if (!isset($no_override['reply_mode'])) { - $field_id = 'rcmfd_reply_mode'; - $select_replymode = new html_select(array('name' => '_reply_mode', 'id' => $field_id)); - $select_replymode->add(rcube_label('replyempty'), -1); - $select_replymode->add(rcube_label('replybottomposting'), 0); - $select_replymode->add(rcube_label('replytopposting'), 1); - - $blocks['main']['options']['reply_mode'] = array( - 'title' => html::label($field_id, Q(rcube_label('whenreplying'))), - 'content' => $select_replymode->show(intval($config['reply_mode'])), - ); - } - if (!isset($no_override['spellcheck_before_send']) && $config['enable_spellcheck']) { - $field_id = 'rcmfd_spellcheck_before_send'; - $input_spellcheck = new html_checkbox(array('name' => '_spellcheck_before_send', 'id' => $field_id, 'value' => 1)); + $found = false; + $data = $RCMAIL->plugins->exec_hook('preferences_list', + array('section' => $sect['id'], 'blocks' => $blocks, 'current' => $current)); - $blocks['spellcheck']['options']['spellcheck_before_send'] = array( - 'title' => html::label($field_id, Q(rcube_label('spellcheckbeforesend'))), - 'content' => $input_spellcheck->show($config['spellcheck_before_send']?1:0), - ); - } - - if ($config['enable_spellcheck']) { - foreach (array('syms', 'nums', 'caps') as $key) { - $key = 'spellcheck_ignore_'.$key; - if (!isset($no_override[$key])) { - $input_spellcheck = new html_checkbox(array('name' => '_'.$key, 'id' => 'rcmfd_'.$key, 'value' => 1)); - - $blocks['spellcheck']['options'][$key] = array( - 'title' => html::label($field_id, Q(rcube_label(str_replace('_', '', $key)))), - 'content' => $input_spellcheck->show($config[$key]?1:0), - ); + // create output + foreach ($data['blocks'] as $block) { + if (!empty($block['content']) || !empty($block['options'])) { + $found = true; + break; + } } - } - } - if (!isset($no_override['show_sig'])) { - $field_id = 'rcmfd_show_sig'; - $select_show_sig = new html_select(array('name' => '_show_sig', 'id' => $field_id)); - $select_show_sig->add(rcube_label('never'), 0); - $select_show_sig->add(rcube_label('always'), 1); - $select_show_sig->add(rcube_label('newmessageonly'), 2); - $select_show_sig->add(rcube_label('replyandforwardonly'), 3); - - $blocks['sig']['options']['show_sig'] = array( - 'title' => html::label($field_id, Q(rcube_label('autoaddsignature'))), - 'content' => $select_show_sig->show($RCMAIL->config->get('show_sig', 1)), - ); + if (!$found) + unset($sections[$idx]); + else + $sections[$idx]['blocks'] = $data['blocks']; } - if (!isset($no_override['strip_existing_sig'])) { - $field_id = 'rcmfd_strip_existing_sig'; - $input_stripexistingsig = new html_checkbox(array('name' => '_strip_existing_sig', 'id' => $field_id, 'value' => 1)); - - $blocks['sig']['options']['strip_existing_sig'] = array( - 'title' => html::label($field_id, Q(rcube_label('replyremovesignature'))), - 'content' => $input_stripexistingsig->show($config['strip_existing_sig']?1:0), - ); - } - - if (!isset($no_override['forward_attachment'])) { - $field_id = 'rcmfd_forward_attachment'; - $select = new html_select(array('name' => '_forward_attachment', 'id' => $field_id)); - $select->add(rcube_label('inline'), 0); - $select->add(rcube_label('asattachment'), 1); - - $blocks['main']['options']['forward_attachment'] = array( - 'title' => html::label($field_id, Q(rcube_label('forwardmode'))), - 'content' => $select->show(intval($config['forward_attachment'])), - ); - } - - if (!isset($no_override['default_font'])) { - $field_id = 'rcmfd_default_font'; - $fonts = rcube_fontdefs(); - $selected = $config['default_font']; - - $select = '<select name="_default_font" id="'.$field_id.'">'; - $select .= '<option value=""' . (!$selected ? ' selected="selected"' : '') . '>---</option>'; - foreach ($fonts as $fname => $font) - $select .= '<option value="'.$fname.'"' - . ($fname == $selected ? ' selected="selected"' : '') - . ' style=\'font-family: ' . $font . '\'>' - . Q($fname) . '</option>'; - $select .= '</select>'; - - $blocks['main']['options']['default_font'] = array( - 'title' => html::label($field_id, Q(rcube_label('defaultfont'))), - 'content' => $select - ); - } - - break; - - - // Addressbook config - case 'addressbook': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - ); - - if (!isset($no_override['default_addressbook']) - && ($books = $RCMAIL->get_address_sources(true, true)) - ) { - $field_id = 'rcmfd_default_addressbook'; - $select_abook = new html_select(array('name' => '_default_addressbook', 'id' => $field_id)); - - foreach ($books as $book) { - $select_abook->add(html_entity_decode($book['name'], ENT_COMPAT, 'UTF-8'), $book['id']); - } - - $blocks['main']['options']['default_addressbook'] = array( - 'title' => html::label($field_id, Q(rcube_label('defaultabook'))), - 'content' => $select_abook->show($config['default_addressbook']), - ); - } - - // show addressbook listing mode selection - if (!isset($no_override['addressbook_name_listing'])) { - $field_id = 'rcmfd_addressbook_name_listing'; - $select_listing = new html_select(array('name' => '_addressbook_name_listing', 'id' => $field_id)); - $select_listing->add(rcube_label('name'), 0); - $select_listing->add(rcube_label('firstname') . ' ' . rcube_label('surname'), 1); - $select_listing->add(rcube_label('surname') . ' ' . rcube_label('firstname'), 2); - $select_listing->add(rcube_label('surname') . ', ' . rcube_label('firstname'), 3); - - $blocks['main']['options']['list_name_listing'] = array( - 'title' => html::label($field_id, Q(rcube_label('listnamedisplay'))), - 'content' => $select_listing->show($config['addressbook_name_listing']), - ); - } - - // show addressbook sort column - if (!isset($no_override['addressbook_sort_col'])) { - $field_id = 'rcmfd_addressbook_sort_col'; - $select_sort = new html_select(array('name' => '_addressbook_sort_col', 'id' => $field_id)); - $select_sort->add(rcube_label('name'), 'name'); - $select_sort->add(rcube_label('firstname'), 'firstname'); - $select_sort->add(rcube_label('surname'), 'surname'); - - $blocks['main']['options']['sort_col'] = array( - 'title' => html::label($field_id, Q(rcube_label('listsorting'))), - 'content' => $select_sort->show($config['addressbook_sort_col']), - ); - } - - // show addressbook page size selection - if (!isset($no_override['addressbook_pagesize'])) { - $field_id = 'rcmfd_addressbook_pagesize'; - $input_pagesize = new html_inputfield(array('name' => '_addressbook_pagesize', 'id' => $field_id, 'size' => 5)); - - $size = intval($config['addressbook_pagesize'] ? $config['addressbook_pagesize'] : $config['pagesize']); - - $blocks['main']['options']['pagesize'] = array( - 'title' => html::label($field_id, Q(rcube_label('pagesize'))), - 'content' => $input_pagesize->show($size ? $size : 50), - ); - } - - if (!isset($no_override['autocomplete_single'])) { - $field_id = 'rcmfd_autocomplete_single'; - $checkbox = new html_checkbox(array('name' => '_autocomplete_single', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['autocomplete_single'] = array( - 'title' => html::label($field_id, Q(rcube_label('autocompletesingle'))), - 'content' => $checkbox->show($config['autocomplete_single']?1:0), - ); - } - - break; - - // Special IMAP folders - case 'folders': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - ); - - // Configure special folders - if (!isset($no_override['default_folders'])) { - // load folders list only when needed - if ($current) { - $select = rcmail_mailbox_select(array( - 'noselection' => '---', - 'realnames' => true, - 'maxlength' => 30, - 'folder_filter' => 'mail', - 'folder_rights' => 'w', - // #1486114, #1488279 - 'onchange' => "if ($(this).val() == 'INBOX') $(this).val('')", - )); - } - else // dummy select - $select = new html_select(); - - if (!isset($no_override['drafts_mbox'])) - $blocks['main']['options']['drafts_mbox'] = array( - 'title' => Q(rcube_label('drafts')), - 'content' => $select->show($config['drafts_mbox'], array('name' => "_drafts_mbox")), - ); - - if (!isset($no_override['sent_mbox'])) - $blocks['main']['options']['sent_mbox'] = array( - 'title' => Q(rcube_label('sent')), - 'content' => $select->show($config['sent_mbox'], array('name' => "_sent_mbox")), - ); - - if (!isset($no_override['junk_mbox'])) - $blocks['main']['options']['junk_mbox'] = array( - 'title' => Q(rcube_label('junk')), - 'content' => $select->show($config['junk_mbox'], array('name' => "_junk_mbox")), - ); - - if (!isset($no_override['trash_mbox'])) - $blocks['main']['options']['trash_mbox'] = array( - 'title' => Q(rcube_label('trash')), - 'content' => $select->show($config['trash_mbox'], array('name' => "_trash_mbox")), - ); - } - - break; - - // Server settings - case 'server': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - 'maintenance' => array('name' => Q(rcube_label('maintenance'))), - ); - - if (!isset($no_override['read_when_deleted'])) { - $field_id = 'rcmfd_read_deleted'; - $input_readdeleted = new html_checkbox(array('name' => '_read_when_deleted', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['read_when_deleted'] = array( - 'title' => html::label($field_id, Q(rcube_label('readwhendeleted'))), - 'content' => $input_readdeleted->show($config['read_when_deleted']?1:0), - ); - } - - if (!isset($no_override['flag_for_deletion'])) { - $field_id = 'rcmfd_flag_for_deletion'; - $input_flagfordeletion = new html_checkbox(array('name' => '_flag_for_deletion', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['flag_for_deletion'] = array( - 'title' => html::label($field_id, Q(rcube_label('flagfordeletion'))), - 'content' => $input_flagfordeletion->show($config['flag_for_deletion']?1:0), - ); - } - - // don't show deleted messages - if (!isset($no_override['skip_deleted'])) { - $field_id = 'rcmfd_skip_deleted'; - $input_purge = new html_checkbox(array('name' => '_skip_deleted', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['skip_deleted'] = array( - 'title' => html::label($field_id, Q(rcube_label('skipdeleted'))), - 'content' => $input_purge->show($config['skip_deleted']?1:0), - ); - } - - if (!isset($no_override['delete_always'])) { - $field_id = 'rcmfd_delete_always'; - $input_delete_always = new html_checkbox(array('name' => '_delete_always', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['delete_always'] = array( - 'title' => html::label($field_id, Q(rcube_label('deletealways'))), - 'content' => $input_delete_always->show($config['delete_always']?1:0), - ); - } - - if (!isset($no_override['delete_junk'])) { - $field_id = 'rcmfd_delete_junk'; - $input_delete_junk = new html_checkbox(array('name' => '_delete_junk', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['delete_junk'] = array( - 'title' => html::label($field_id, Q(rcube_label('deletejunk'))), - 'content' => $input_delete_junk->show($config['delete_junk']?1:0), - ); - } - - // Trash purging on logout - if (!isset($no_override['logout_purge'])) { - $field_id = 'rcmfd_logout_purge'; - $input_purge = new html_checkbox(array('name' => '_logout_purge', 'id' => $field_id, 'value' => 1)); - - $blocks['maintenance']['options']['logout_purge'] = array( - 'title' => html::label($field_id, Q(rcube_label('logoutclear'))), - 'content' => $input_purge->show($config['logout_purge']?1:0), - ); - } - - // INBOX compacting on logout - if (!isset($no_override['logout_expunge'])) { - $field_id = 'rcmfd_logout_expunge'; - $input_expunge = new html_checkbox(array('name' => '_logout_expunge', 'id' => $field_id, 'value' => 1)); - - $blocks['maintenance']['options']['logout_expunge'] = array( - 'title' => html::label($field_id, Q(rcube_label('logoutcompact'))), - 'content' => $input_expunge->show($config['logout_expunge']?1:0), - ); - } - - break; - } - - $data = $RCMAIL->plugins->exec_hook('preferences_list', array('section' => $sect['id'], 'blocks' => $blocks)); - $found = false; - - // create output - foreach ($data['blocks'] as $block) { - if (!empty($block['content']) || !empty($block['options'])) { - $found = true; - break; - } - } - - if (!$found) - unset($sections[$idx]); - else - $sections[$idx]['blocks'] = $data['blocks']; - } - - return array($sections, $plugin['cols']); + return array($sections, $plugin['cols']); } function rcmail_get_skins() { - $path = 'skins'; - $skins = array(); - - $dir = opendir($path); + $path = RCUBE_INSTALL_PATH . 'skins'; + $skins = array(); + $dir = opendir($path); - if (!$dir) - return false; + if (!$dir) { + return false; + } - while (($file = readdir($dir)) !== false) - { - $filename = $path.'/'.$file; - if (!preg_match('/^\./', $file) && is_dir($filename) && is_readable($filename)) - $skins[] = $file; - } + while (($file = readdir($dir)) !== false) { + $filename = $path.'/'.$file; + if (!preg_match('/^\./', $file) && is_dir($filename) && is_readable($filename)) { + $skins[] = $file; + } + } - closedir($dir); + closedir($dir); - return $skins; + return $skins; } @@ -988,9 +1237,9 @@ function rcmail_update_folder_row($name, $oldname=null, $subscribe=false, $class // register UI objects $OUTPUT->add_handlers(array( - 'prefsframe' => 'rcmail_preferences_frame', - 'sectionslist' => 'rcmail_sections_list', - 'identitieslist' => 'rcmail_identities_list', + 'prefsframe' => 'rcmail_preferences_frame', + 'sectionslist' => 'rcmail_sections_list', + 'identitieslist' => 'rcmail_identities_list', )); // register action aliases diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc index 3bb82aa38..19edb41d4 100644 --- a/program/steps/settings/save_prefs.inc +++ b/program/steps/settings/save_prefs.inc @@ -34,6 +34,7 @@ switch ($CURR_SECTION) 'time_format' => isset($_POST['_time_format']) ? get_input_value('_time_format', RCUBE_INPUT_POST) : ($CONFIG['time_format'] ? $CONFIG['time_format'] : 'H:i'), 'prettydate' => isset($_POST['_pretty_date']) ? TRUE : FALSE, 'refresh_interval' => isset($_POST['_refresh_interval']) ? intval($_POST['_refresh_interval'])*60 : $CONFIG['refresh_interval'], + 'standard_windows' => isset($_POST['_standard_windows']) ? TRUE : FALSE, 'skin' => isset($_POST['_skin']) ? get_input_value('_skin', RCUBE_INPUT_POST) : $CONFIG['skin'], ); @@ -119,6 +120,8 @@ switch ($CURR_SECTION) case 'folders': $a_user_prefs = array( + 'show_real_foldernames' => + isset($_POST['_show_real_foldernames']) ? TRUE : FALSE, 'drafts_mbox' => get_input_value('_drafts_mbox', RCUBE_INPUT_POST, true), 'sent_mbox' => get_input_value('_sent_mbox', RCUBE_INPUT_POST, true), 'junk_mbox' => get_input_value('_junk_mbox', RCUBE_INPUT_POST, true), |