diff options
Diffstat (limited to 'program')
78 files changed, 1473 insertions, 316 deletions
diff --git a/program/include/rcmail.php b/program/include/rcmail.php index 0483f0e18..4b3f13760 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -346,6 +346,44 @@ class rcmail extends rcube return $list; } + /** + * Getter for compose responses. + * These are stored in local config and user preferences. + * + * @param boolean True to sort the list alphabetically + * @param boolean True if only this user's responses shall be listed + * @return array List of the current user's stored responses + */ + public function get_compose_responses($sorted = false, $user_only = false) + { + $responses = array(); + + if (!$user_only) { + foreach ($this->config->get('compose_responses_static', array()) as $response) { + if (empty($response['key'])) + $response['key'] = substr(md5($response['name']), 0, 16); + $response['static'] = true; + $response['class'] = 'readonly'; + $k = $sorted ? '0000-' . strtolower($response['name']) : $response['key']; + $responses[$k] = $response; + } + } + + foreach ($this->config->get('compose_responses', array()) as $response) { + if (empty($response['key'])) + $response['key'] = substr(md5($response['name']), 0, 16); + $k = $sorted ? strtolower($response['name']) : $response['key']; + $responses[$k] = $response; + } + + // sort list by name + if ($sorted) { + ksort($responses, SORT_LOCALE_STRING); + } + + return array_values($responses); + } + /** * Init output object for GUI and add common scripts. diff --git a/program/include/rcmail_output_html.php b/program/include/rcmail_output_html.php index 7cab3725e..8a960673d 100644 --- a/program/include/rcmail_output_html.php +++ b/program/include/rcmail_output_html.php @@ -1165,7 +1165,7 @@ class rcmail_output_html extends rcmail_output } else if ($attrib['type'] == 'link') { $btn_content = isset($attrib['content']) ? $attrib['content'] : ($attrib['label'] ? $attrib['label'] : $attrib['command']); - $link_attrib = array('href', 'onclick', 'title', 'id', 'class', 'style', 'tabindex', 'target'); + $link_attrib = array_merge(html::$common_attrib, array('href', 'onclick', 'tabindex', 'target')); if ($attrib['innerclass']) $btn_content = html::span($attrib['innerclass'], $btn_content); } @@ -1280,7 +1280,12 @@ class rcmail_output_html extends rcmail_output */ public function _write($templ = '', $base_path = '') { - $output = empty($templ) ? $this->default_template : trim($templ); + $output = trim($templ); + + if (empty($output)) { + $output = $this->default_template; + $is_empty = true; + } // set default page title if (empty($this->pagetitle)) { @@ -1371,8 +1376,8 @@ class rcmail_output_html extends rcmail_output } // add css files in head, before scripts, for speed up with parallel downloads - if (!empty($this->css_files) && - (($pos = stripos($output, '<script ')) || ($pos = stripos($output, '</head>'))) + if (!empty($this->css_files) && !$is_empty + && (($pos = stripos($output, '<script ')) || ($pos = stripos($output, '</head>'))) ) { $css = ''; foreach ($this->css_files as $file) { diff --git a/program/js/app.js b/program/js/app.js index 7fbab8003..1f75e219c 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -256,12 +256,14 @@ function rcube_webmail() } else if (this.env.action == 'compose') { this.env.address_group_stack = []; - this.env.compose_commands = ['send-attachment', 'remove-attachment', 'send', 'cancel', 'toggle-editor', 'list-adresses', 'pushgroup', 'search', 'reset-search', 'extwin']; + this.env.compose_commands = ['send-attachment', 'remove-attachment', 'send', 'cancel', + 'toggle-editor', 'list-adresses', 'pushgroup', 'search', 'reset-search', 'extwin', + 'insert-response', 'save-response']; if (this.env.drafts_mailbox) this.env.compose_commands.push('savedraft') - this.enable_command(this.env.compose_commands, 'identities', true); + this.enable_command(this.env.compose_commands, 'identities', 'responses', true); // add more commands (not enabled) $.merge(this.env.compose_commands, ['add-recipient', 'firstpage', 'previouspage', 'nextpage', 'lastpage']); @@ -272,6 +274,23 @@ function rcube_webmail() this.enable_command('spellcheck', true); } + // init canned response functions + if (this.gui_objects.responseslist) { + $('a.insertresponse', this.gui_objects.responseslist) + .attr('unselectable', 'on') + .mousedown(function(e){ return rcube_event.cancel(e); }) + .mouseup(function(e){ + ref.command('insert-response', $(this).attr('rel')); + $(document.body).trigger('mouseup'); // hides the menu + return rcube_event.cancel(e); + }); + + // avoid textarea loosing focus when hitting the save-response button/link + for (var i=0; this.buttons['save-response'] && i < this.buttons['save-response'].length; i++) { + $('#'+this.buttons['save-response'][i].id).mousedown(function(e){ return rcube_event.cancel(e); }) + } + } + document.onmouseup = function(e){ return p.doc_mouse_up(e); }; // init message compose form @@ -381,7 +400,7 @@ function rcube_webmail() break; case 'settings': - this.enable_command('preferences', 'identities', 'save', 'folders', true); + this.enable_command('preferences', 'identities', 'responses', 'save', 'folders', true); if (this.env.action == 'identities') { this.enable_command('add', this.env.identities_level < 2); @@ -402,6 +421,9 @@ function rcube_webmail() parent.rcmail.enable_command('purge', this.env.messagecount); $("input[type='text']").first().select(); } + else if (this.env.action == 'responses') { + this.enable_command('add', true); + } if (this.gui_objects.identitieslist) { this.identity_list = new rcube_list_widget(this.gui_objects.identitieslist, {multiselect:false, draggable:false, keyboard:false}); @@ -418,8 +440,22 @@ function rcube_webmail() this.sections_list.init(); this.sections_list.focus(); } - else if (this.gui_objects.subscriptionlist) + else if (this.gui_objects.subscriptionlist) { this.init_subscription_list(); + } + else if (this.gui_objects.responseslist) { + this.responses_list = new rcube_list_widget(this.gui_objects.responseslist, {multiselect:false, draggable:false, keyboard:false}); + this.responses_list.addEventListener('select', function(list){ + var win, id = list.get_single_selection(); + p.enable_command('delete', !!id && $.inArray(id, p.env.readonly_responses) < 0); + if (id && (win = p.get_frame_window(p.env.contentframe))) { + p.set_busy(true); + p.location_href({ _action:'edit-response', _key:id, _framed:1 }, win); + } + }); + this.responses_list.init(); + this.responses_list.focus(); + } break; @@ -463,6 +499,7 @@ function rcube_webmail() // flag object as complete this.loaded = true; + this.env.lastrefresh = new Date(); // show message if (this.pending_message) @@ -725,6 +762,13 @@ function rcube_webmail() case 'add': if (this.task == 'addressbook') this.load_contact(0, 'add'); + else if (this.task == 'settings' && this.env.action == 'responses') { + var frame; + if ((frame = this.get_frame_window(this.env.contentframe))) { + this.set_busy(true); + this.location_href({ _action:'add-response', _framed:1 }, frame); + } + } else if (this.task == 'settings') { this.identity_list.clear_selection(); this.load_identity(0, 'add-identity'); @@ -788,7 +832,10 @@ function rcube_webmail() // addressbook task else if (this.task == 'addressbook') this.delete_contacts(); - // user settings task + // settings: canned response + else if (this.task == 'settings' && this.env.action == 'responses') + this.delete_response(); + // settings: user identities else if (this.task == 'settings') this.delete_identity(); break; @@ -815,37 +862,24 @@ function rcube_webmail() break; case 'toggle_status': - if (props && !props._row) - break; - - flag = 'read'; - - if (props._row.uid) { - uid = props._row.uid; + case 'toggle_flag': + flag = command == 'toggle_flag' ? 'flagged' : 'read'; + if (uid = props) { + // toggle flagged/unflagged + if (flag == 'flagged') { + if (this.message_list.rows[uid].flagged) + flag = 'unflagged'; + } // toggle read/unread - if (this.message_list.rows[uid].deleted) + else if (this.message_list.rows[uid].deleted) flag = 'undelete'; else if (!this.message_list.rows[uid].unread) flag = 'unread'; - } - this.mark_message(flag, uid); - break; - - case 'toggle_flag': - if (props && !props._row) - break; - - flag = 'flagged'; - - if (props._row.uid) { - uid = props._row.uid; - // toggle flagged/unflagged - if (this.message_list.rows[uid].flagged) - flag = 'unflagged'; + this.mark_message(flag, uid); } - this.mark_message(flag, uid); + break; case 'always-load': @@ -1031,7 +1065,7 @@ function rcube_webmail() url = {_reply_uid: uid, _mbox: this.env.mailbox}; if (command == 'reply-all') // do reply-list, when list is detected and popup menu wasn't used - url._all = (!props && this.commands['reply-list'] ? 'list' : 'all'); + url._all = (!props && this.env.reply_all_mode == 1 && this.commands['reply-list'] ? 'list' : 'all'); else if (command == 'reply-list') url._all = 'list'; @@ -1173,6 +1207,7 @@ function rcube_webmail() // user settings commands case 'preferences': case 'identities': + case 'responses': case 'folders': this.goto_url('settings/' + command); break; @@ -1439,7 +1474,7 @@ function rcube_webmail() // select the folder if one of its childs is currently selected // don't select if it's virtual (#1488346) - if (this.env.mailbox && this.env.mailbox.indexOf(name + this.env.delimiter) == 0 && !node.virtual) + if (this.env.mailbox && this.env.mailbox.startsWith(name + this.env.delimiter) && !node.virtual) this.command('list', name); } else { @@ -1620,8 +1655,8 @@ function rcube_webmail() this.env.coltypes = []; for (i=0; i<cols.length; i++) - if (cols[i].id && cols[i].id.match(/^rcm/)) { - name = cols[i].id.replace(/^rcm/, ''); + if (cols[i].id && cols[i].id.startsWith('rcm')) { + name = cols[i].id.slice(3); this.env.coltypes.push(name); } @@ -1704,7 +1739,7 @@ function rcube_webmail() this.init_message_row = function(row) { - var expando, self = this, uid = row.uid, + var i, fn = {}, self = this, uid = row.uid, status_icon = (this.env.status_col != null ? 'status' : 'msg') + 'icn' + row.uid; if (uid && this.env.messages[uid]) @@ -1712,8 +1747,7 @@ function rcube_webmail() // set eventhandler to status icon if (row.icon = document.getElementById(status_icon)) { - row.icon._row = row.obj; - row.icon.onclick = function(e) { self.command('toggle_status', this); return rcube_event.cancel(e); }; + fn.icon = function(e) { self.command('toggle_status', uid); }; } // save message icon position too @@ -1722,24 +1756,28 @@ function rcube_webmail() else row.msgicon = row.icon; - // set eventhandler to flag icon, if icon found + // set eventhandler to flag icon if (this.env.flagged_col != null && (row.flagicon = document.getElementById('flagicn'+row.uid))) { - row.flagicon._row = row.obj; - row.flagicon.onclick = function(e) { self.command('toggle_flag', this); return rcube_event.cancel(e); }; + fn.flagicon = function(e) { self.command('toggle_flag', uid); }; } - if (!row.depth && row.has_children && (expando = document.getElementById('rcmexpando'+row.uid))) { - row.expando = expando; - expando.onclick = function(e) { return self.expand_message_row(e, uid); }; + // set event handler to thread expand/collapse icon + if (!row.depth && row.has_children && (row.expando = document.getElementById('rcmexpando'+row.uid))) { + fn.expando = function(e) { self.expand_message_row(e, uid); }; + } + + // attach events + $.each(fn, function(i, f) { + row[i].onclick = function(e) { f(e); return rcube_event.cancel(e); }; if (bw.touch) { - expando.addEventListener('touchend', function(e) { + row[i].addEventListener('touchend', function(e) { if (e.changedTouches.length == 1) { - self.expand_message_row(e, uid); + f(e); return rcube_event.cancel(e); } }, false); } - } + }); this.triggerEvent('insertrow', { uid:uid, row:row }); }; @@ -2024,12 +2062,14 @@ function rcube_webmail() if (name && (frame = this.get_frame_element(name))) { if (!show && (win = this.get_frame_window(name))) { - if (win.stop) - win.stop(); - else // IE - win.document.execCommand('Stop'); + if (win.location.href.indexOf(this.env.blankpage) < 0) { + if (win.stop) + win.stop(); + else // IE + win.document.execCommand('Stop'); - win.location.href = this.env.blankpage; + win.location.href = this.env.blankpage; + } } else if (!bw.safari && !bw.konq) $(frame)[show ? 'show' : 'hide'](); @@ -2704,9 +2744,6 @@ function rcube_webmail() } } - if (this.env.display_next && this.env.next_uid) - post_data._next_uid = this.env.next_uid; - if (count < 0) post_data._count = (count*-1); // remove threads from the end of the list @@ -2742,6 +2779,9 @@ function rcube_webmail() if (this.env.search_request) data._search = this.env.search_request; + if (this.env.display_next && this.env.next_uid) + data._next_uid = this.env.next_uid; + return data; }; @@ -2992,9 +3032,12 @@ function rcube_webmail() // test if purge command is allowed this.purge_mailbox_test = function() { - return (this.env.exists && (this.env.mailbox == this.env.trash_mailbox || this.env.mailbox == this.env.junk_mailbox - || this.env.mailbox.match('^' + RegExp.escape(this.env.trash_mailbox) + RegExp.escape(this.env.delimiter)) - || this.env.mailbox.match('^' + RegExp.escape(this.env.junk_mailbox) + RegExp.escape(this.env.delimiter)))); + return (this.env.exists && ( + this.env.mailbox == this.env.trash_mailbox + || this.env.mailbox == this.env.junk_mailbox + || this.env.mailbox.startsWith(this.env.trash_mailbox + this.env.delimiter) + || this.env.mailbox.startsWith(this.env.junk_mailbox + this.env.delimiter) + )); }; @@ -3285,6 +3328,154 @@ function rcube_webmail() return true; }; + this.insert_response = function(key) + { + var insert = this.env.textresponses[key] ? this.env.textresponses[key].text : null; + if (!insert) + return false; + + // insert into tinyMCE editor + if ($("input[name='_is_html']").val() == '1') { + var editor = tinyMCE.get(this.env.composebody); + editor.getWin().focus(); // correct focus in IE & Chrome + editor.selection.setContent(insert, { format:'text' }); + } + // replace selection in compose textarea + else { + var textarea = rcube_find_object(this.env.composebody), + selection = $(textarea).is(':focus') ? this.get_input_selection(textarea) : { start:0, end:0 }, + inp_value = textarea.value; + pre = inp_value.substring(0, selection.start), + end = inp_value.substring(selection.end, inp_value.length); + + // insert response text + textarea.value = pre + insert + end; + + // set caret after inserted text + this.set_caret_pos(textarea, selection.start + insert.length); + textarea.focus(); + } + }; + + /** + * Open the dialog to save a new canned response + */ + this.save_response = function() + { + var sigstart, text = '', strip = false; + + // get selected text from tinyMCE editor + if ($("input[name='_is_html']").val() == '1') { + var editor = tinyMCE.get(this.env.composebody); + editor.getWin().focus(); // correct focus in IE & Chrome + text = editor.selection.getContent({ format:'text' }); + + if (!text) { + text = editor.getContent({ format:'text' }); + strip = true; + } + } + // get selected text from compose textarea + else { + var textarea = rcube_find_object(this.env.composebody), sigstart; + if (textarea && $(textarea).is(':focus')) { + text = this.get_input_selection(textarea).text; + } + + if (!text && textarea) { + text = textarea.value; + strip = true; + } + } + + // strip off signature + if (strip) { + sigstart = text.indexOf('-- \n'); + if (sigstart > 0) { + text = text.substring(0, sigstart); + } + } + + // show dialog to enter a name and to modify the text to be saved + var buttons = {}, + html = '<form class="propform">' + + '<div class="prop block"><label>' + this.get_label('responsename') + '</label>' + + '<input type="text" name="name" id="ffresponsename" size="40" /></div>' + + '<div class="prop block"><label>' + this.get_label('responsetext') + '</label>' + + '<textarea name="text" id="ffresponsetext" cols="40" rows="8"></textarea></div>' + + '</form>'; + + buttons[this.gettext('save')] = function(e) { + var name = $('#ffresponsename').val(), + text = $('#ffresponsetext').val(); + + if (!text) { + $('#ffresponsetext').select(); + return false; + } + if (!name) + name = text.substring(0,40); + + var lock = ref.display_message(ref.get_label('savingresponse'), 'loading'); + ref.http_post('settings/responses', { _insert:1, _name:name, _text:text }, lock); + $(this).dialog('close'); + }; + + buttons[this.gettext('cancel')] = function() { + $(this).dialog('close'); + }; + + this.show_popup_dialog(html, this.gettext('savenewresponse'), buttons); + + $('#ffresponsetext').val(text); + $('#ffresponsename').select(); + }; + + this.add_response_item = function(response) + { + var key = response.key; + this.env.textresponses[key] = response; + + // append to responses list + if (this.gui_objects.responseslist) { + var li = $('<li>').appendTo(this.gui_objects.responseslist); + $('<a>').addClass('insertresponse active') + .attr('href', '#') + .attr('rel', key) + .html(this.quote_html(response.name)) + .appendTo(li) + .mousedown(function(e){ + return rcube_event.cancel(e); + }) + .mouseup(function(e){ + ref.command('insert-response', key); + $(document.body).trigger('mouseup'); // hides the menu + return rcube_event.cancel(e); + }); + } + }; + + this.edit_responses = function() + { + // TODO: implement inline editing of responses + }; + + this.delete_response = function(key) + { + if (!key && this.responses_list) { + var selection = this.responses_list.get_selection(); + key = selection[0]; + } + + // submit delete request + if (key && confirm(this.get_label('deleteresponseconfirm'))) { + this.http_post('settings/delete-response', { _key: key }, false); + return true; + } + + return false; + }; + this.stop_spellchecking = function() { var ed; @@ -3559,6 +3750,7 @@ function rcube_webmail() } this.env.identity = id; + this.triggerEvent('change_identity'); return true; }; @@ -3990,7 +4182,7 @@ function rcube_webmail() return; // ...new search value contains old one and previous search was not finished or its result was empty - if (old_value && old_value.length && q.indexOf(old_value) == 0 && (!ac || ac.num <= 0) && this.env.contacts && !this.env.contacts.length) + if (old_value && old_value.length && q.startsWith(old_value) && (!ac || ac.num <= 0) && this.env.contacts && !this.env.contacts.length) return; var i, lock, source, xhr, reqid = new Date().getTime(), @@ -5210,6 +5402,35 @@ function rcube_webmail() } }; + this.update_response_row = function(response, oldkey) + { + var list = this.responses_list; + + if (list && oldkey) { + list.update_row(oldkey, [ response.name ], response.key, true); + } + else if (list) { + list.insert_row({ id:'rcmrow'+response.key, cols:[ { className:'name', innerHTML:response.name } ] }); + list.select(response.key); + } + }; + + this.remove_response = function(key) + { + var frame; + + if (this.env.textresponses) { + delete this.env.textresponses[key]; + } + + if (this.responses_list) { + this.responses_list.remove_row(key); + if (this.env.contentframe && (frame = this.get_frame_window(this.env.contentframe))) { + frame.location.href = this.env.blankpage; + } + } + }; + /*********************************************************/ /********* folder manager methods *********/ @@ -5246,7 +5467,7 @@ function rcube_webmail() if (this.check_droptarget(folder) && !this.env.subscriptionrows[this.get_folder_row_id(this.env.mailbox)][2] && (folder != this.env.mailbox.replace(reg, '')) && - (!folder.match(new RegExp('^'+RegExp.escape(this.env.mailbox+this.env.delimiter)))) + (!folder.startsWith(this.env.mailbox + this.env.delimiter)) ) { this.env.dstfolder = folder; $(row).addClass('droptarget'); @@ -5372,7 +5593,7 @@ function rcube_webmail() tmp = tmp_name; } // protected folder's child - else if (tmp && folders[n][0].indexOf(tmp) == 0) + else if (tmp && folders[n][0].startsWith(tmp)) slist.push(folders[n][0]); // other else { @@ -5383,7 +5604,7 @@ function rcube_webmail() // check if subfolder of a protected folder for (n=0; n<slist.length; n++) { - if (name.indexOf(slist[n]+this.env.delimiter) == 0) + if (name.startsWith(slist[n] + this.env.delimiter)) rowid = this.get_folder_row_id(slist[n]); } @@ -5495,13 +5716,13 @@ function rcube_webmail() this.get_subfolders = function(folder) { var name, list = [], - regex = new RegExp('^'+RegExp.escape(folder)+RegExp.escape(this.env.delimiter)), + prefix = folder + this.env.delimiter, row = $('#'+this.get_folder_row_id(folder)).get(0); while (row = row.nextSibling) { if (row.id) { name = this.env.subscriptionrows[row.id][0]; - if (regex.test(name)) { + if (name && name.startsWith(prefix)) { list.push(row.id); } else @@ -5898,24 +6119,23 @@ function rcube_webmail() }; // open a jquery UI dialog with the given content - this.show_popup_dialog = function(html, title, buttons) + this.show_popup_dialog = function(html, title, buttons, options) { // forward call to parent window if (this.is_framed()) { - parent.rcmail.show_popup_dialog(html, title, buttons); - return; + return parent.rcmail.show_popup_dialog(html, title, buttons); } var popup = $('<div class="popup">') .html(html) - .dialog({ + .dialog($.extend({ title: title, buttons: buttons, modal: true, resizable: true, width: 500, close: function(event, ui) { $(this).remove() } - }); + }, options || {})); // resize and center popup var win = $(window), w = win.width(), h = win.height(), @@ -5925,6 +6145,8 @@ function rcube_webmail() height: Math.min(h - 40, height + 75 + (buttons ? 50 : 0)), width: Math.min(w - 20, width + 20) }); + + return popup; }; // enable/disable buttons for page shifting @@ -6103,7 +6325,7 @@ function rcube_webmail() div.className.match(/collapsed/)) { // add children's counters for (var k in this.env.unread_counts) - if (k.indexOf(mbox + this.env.delimiter) == 0) + if (k.startsWith(mbox + this.env.delimiter)) childcount += this.env.unread_counts[k]; } @@ -6297,7 +6519,7 @@ function rcube_webmail() if (result === false) return false; else - query = result; + url = this.url(action, result); } url += '&_remote=1'; @@ -6534,7 +6756,7 @@ function rcube_webmail() // post the given form to a hidden iframe this.async_upload_form = function(form, action, onload) { - var ts = new Date().getTime(), + var frame, ts = new Date().getTime(), frame_name = 'rcmupload'+ts; // upload progress support @@ -6553,21 +6775,19 @@ function rcube_webmail() // have to do it this way for IE // otherwise the form will be posted to a new window if (document.all) { - var html = '<iframe name="'+frame_name+'" src="program/resources/blank.gif" style="width:0;height:0;visibility:hidden;"></iframe>'; - document.body.insertAdjacentHTML('BeforeEnd', html); + document.body.insertAdjacentHTML('BeforeEnd', '<iframe name="'+frame_name+'"' + + ' src="program/resources/blank.gif" style="width:0;height:0;visibility:hidden;"></iframe>'); + frame = $('iframe[name="'+frame_name+'"]'); } - else { // for standards-compilant browsers - var frame = document.createElement('iframe'); - frame.name = frame_name; - frame.style.border = 'none'; - frame.style.width = 0; - frame.style.height = 0; - frame.style.visibility = 'hidden'; - document.body.appendChild(frame); + // for standards-compliant browsers + else { + frame = $('<iframe>').attr('name', frame_name) + .css({border: 'none', width: 0, height: 0, visibility: 'hidden'}) + .appendTo(document.body); } // handle upload errors, parsing iframe content in onload - $(frame_name).bind('load', {ts:ts}, onload); + frame.bind('load', {ts:ts}, onload); $(form).attr({ target: frame_name, @@ -6744,6 +6964,9 @@ function rcube_webmail() if (this.task == 'mail' && this.gui_objects.mailboxlist) params = this.check_recent_params(); + params._last = Math.floor(this.env.lastrefresh.getTime() / 1000); + this.env.lastrefresh = new Date(); + // plugins should bind to 'requestrefresh' event to add own params this.http_request('refresh', params, lock); }; @@ -6770,6 +6993,14 @@ function rcube_webmail() /********* helper methods *********/ /********************************************************/ + /** + * Quote html entities + */ + this.quote_html = function(str) + { + return String(str).replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); + }; + // get window.opener.rcmail if available this.opener = function() { @@ -6834,6 +7065,57 @@ function rcube_webmail() } }; + // get selected text from an input field + // http://stackoverflow.com/questions/7186586/how-to-get-the-selected-text-in-textarea-using-jquery-in-internet-explorer-7 + this.get_input_selection = function(obj) + { + var start = 0, end = 0, + normalizedValue, range, + textInputRange, len, endRange; + + if (typeof obj.selectionStart == "number" && typeof obj.selectionEnd == "number") { + normalizedValue = obj.value; + start = obj.selectionStart; + end = obj.selectionEnd; + } + else { + range = document.selection.createRange(); + + if (range && range.parentElement() == obj) { + len = obj.value.length; + normalizedValue = obj.value; //.replace(/\r\n/g, "\n"); + + // create a working TextRange that lives only in the input + textInputRange = obj.createTextRange(); + textInputRange.moveToBookmark(range.getBookmark()); + + // Check if the start and end of the selection are at the very end + // of the input, since moveStart/moveEnd doesn't return what we want + // in those cases + endRange = obj.createTextRange(); + endRange.collapse(false); + + if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { + start = end = len; + } + else { + start = -textInputRange.moveStart("character", -len); + start += normalizedValue.slice(0, start).split("\n").length - 1; + + if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) { + end = len; + } + else { + end = -textInputRange.moveEnd("character", -len); + end += normalizedValue.slice(0, end).split("\n").length - 1; + } + } + } + } + + return { start:start, end:end, text:normalizedValue.substr(start, end-start) }; + }; + // disable/enable all fields of a form this.lock_form = function(form, lock) { diff --git a/program/js/common.js b/program/js/common.js index afaf91639..02934f734 100644 --- a/program/js/common.js +++ b/program/js/common.js @@ -592,6 +592,14 @@ Date.prototype.getStdTimezoneOffset = function() return tzo; } +// define String's startsWith() method for old browsers +if (!String.prototype.startsWith) { + String.prototype.startsWith = function(search, position) { + position = position || 0; + return this.slice(position, search.length) === search; + }; +} + // Make getElementById() case-sensitive on IE if (bw.ie) { document._getElementById = document.getElementById; diff --git a/program/js/editor.js b/program/js/editor.js index 6d7b9538a..020971d6e 100644 --- a/program/js/editor.js +++ b/program/js/editor.js @@ -161,8 +161,8 @@ function rcmail_editor_images() for (i in files) { att = files[i]; - if (att.complete && att.mimetype.indexOf('image/') == 0) { - list.push([att.name, rcmail.env.comm_path+'&_action=display-attachment&_file='+i+'&_id='+rcmail.env.compose_id]); + if (att.complete && att.mimetype.startsWith('image/')) { + list.push([att.name, rcmail.env.comm_path+'&_id='+rcmail.env.compose_id+'&_action=display-attachment&_file='+i]); } } diff --git a/program/js/list.js b/program/js/list.js index cb69bc462..e1d57745c 100644 --- a/program/js/list.js +++ b/program/js/list.js @@ -31,6 +31,7 @@ function rcube_list_widget(list, p) this.list = list ? list : null; this.tagname = this.list ? this.list.nodeName.toLowerCase() : 'table'; + this.id_regexp = /^rcmrow([a-z0-9\-_=\+\/]+)/i; this.thead; this.tbody; this.fixed_header; @@ -55,7 +56,6 @@ function rcube_list_widget(list, p) this.column_fixed = null; this.last_selected = 0; this.shift_start = 0; - this.in_selection_before = false; this.focused = false; this.drag_mouse_start = null; this.dblclick_time = 500; // default value on MS Windows is 500 @@ -111,7 +111,7 @@ init: function() init_row: function(row) { // make references in internal array and set event handlers - if (row && String(row.id).match(/^rcmrow([a-z0-9\-_=\+\/]+)/i)) { + if (row && String(row.id).match(this.id_regexp)) { var self = this, uid = RegExp.$1; row.uid = uid; @@ -405,10 +405,7 @@ drag_column: function(e, col) drag_row: function(e, id) { // don't do anything (another action processed before) - var evtarget = rcube_event.get_target(e), - tagname = evtarget.tagName.toLowerCase(); - - if (evtarget && (tagname == 'input' || tagname == 'img' || (tagname != 'a' && evtarget.onclick))) + if (!this.is_event_target(e)) return true; // accept right-clicks @@ -420,12 +417,13 @@ drag_row: function(e, id) // selects currently unselected row if (!this.in_selection_before) { var mod_key = rcube_event.get_modifier(e); - this.select_row(id, mod_key, false); + this.select_row(id, mod_key, true); } if (this.draggable && this.selection.length && this.in_selection(id)) { this.drag_start = true; this.drag_mouse_start = rcube_event.get_mouse_pos(e); + rcube_event.add_listener({event:'mousemove', object:this, method:'drag_mouse_move'}); rcube_event.add_listener({event:'mouseup', object:this, method:'drag_mouse_up'}); if (bw.touch) { @@ -446,19 +444,16 @@ drag_row: function(e, id) */ click_row: function(e, id) { - var now = new Date().getTime(), - mod_key = rcube_event.get_modifier(e), - evtarget = rcube_event.get_target(e), - tagname = evtarget.tagName.toLowerCase(); - - if ((evtarget && (tagname == 'input' || tagname == 'img'))) + // don't do anything (another action processed before) + if (!this.is_event_target(e)) return true; - var dblclicked = now - this.rows[id].clicked < this.dblclick_time; + var now = new Date().getTime(), + dblclicked = now - this.rows[id].clicked < this.dblclick_time; // unselects currently selected row - if (!this.drag_active && this.in_selection_before == id && !dblclicked) - this.select_row(id, mod_key, false); + if (!this.drag_active && !dblclicked && this.in_selection_before == id) + this.select_row(id, rcube_event.get_modifier(e), true); this.drag_start = false; this.in_selection_before = false; @@ -482,6 +477,18 @@ click_row: function(e, id) }, +/** + * Check target of the current event + */ +is_event_target: function(e) +{ + var target = rcube_event.get_target(e), + tagname = target.tagName.toLowerCase(); + + return !(target && (tagname == 'input' || tagname == 'img' || (tagname != 'a' && target.onclick))); +}, + + /* * Returns thread root ID for specified row ID */ @@ -726,7 +733,7 @@ get_first_row: function() var i, len, rows = this.tbody.childNodes; for (i=0, len=rows.length-1; i<len; i++) - if (rows[i].id && String(rows[i].id).match(/^rcmrow([a-z0-9\-_=\+\/]+)/i) && this.rows[RegExp.$1] != null) + if (rows[i].id && String(rows[i].id).match(this.id_regexp) && this.rows[RegExp.$1] != null) return RegExp.$1; } @@ -739,7 +746,7 @@ get_last_row: function() var i, rows = this.tbody.childNodes; for (i=rows.length-1; i>=0; i--) - if (rows[i].id && String(rows[i].id).match(/^rcmrow([a-z0-9\-_=\+\/]+)/i) && this.rows[RegExp.$1] != null) + if (rows[i].id && String(rows[i].id).match(this.id_regexp) && this.rows[RegExp.$1] != null) return RegExp.$1; } @@ -769,6 +776,7 @@ get_cell: function(row, index) select_row: function(id, mod_key, with_mouse) { var select_before = this.selection.join(','); + if (!this.multiselect) mod_key = 0; @@ -787,7 +795,7 @@ select_row: function(id, mod_key, with_mouse) break; case CONTROL_KEY: - if (!with_mouse) + if (with_mouse) this.highlight_row(id, true); break; @@ -799,6 +807,7 @@ select_row: function(id, mod_key, with_mouse) this.highlight_row(id, false); break; } + this.multi_selecting = true; } @@ -856,14 +865,8 @@ select_first: function(mod_key) { var row = this.get_first_row(); if (row) { - if (mod_key) { - this.shift_select(row, mod_key); - this.triggerEvent('select'); - this.scrollto(row); - } - else { - this.select(row); - } + this.select_row(row, mod_key, false); + this.scrollto(row); } }, @@ -875,14 +878,8 @@ select_last: function(mod_key) { var row = this.get_last_row(); if (row) { - if (mod_key) { - this.shift_select(row, mod_key); - this.triggerEvent('select'); - this.scrollto(row); - } - else { - this.select(row); - } + this.select_row(row, mod_key, false); + this.scrollto(row); } }, @@ -912,7 +909,8 @@ shift_select: function(id, control) from_rowIndex = this._rowIndex(this.rows[this.shift_start].obj), to_rowIndex = this._rowIndex(to_row.obj); - if (!to_row.expanded && to_row.has_children) + // if we're going down the list, and we hit a thread, and it's closed, select the whole thread + if (from_rowIndex < to_rowIndex && !to_row.expanded && to_row.has_children) if (to_row = this.rows[(this.row_children(id)).pop()]) to_rowIndex = this._rowIndex(to_row.obj); @@ -934,6 +932,7 @@ shift_select: function(id, control) } }, + /** * Helper method to emulate the rowIndex property of non-tr elements */ @@ -1134,10 +1133,13 @@ key_press: function(e) // Stop propagation so that the browser doesn't scroll rcube_event.cancel(e); return this.use_arrow_key(keyCode, mod_key); - case 61: - case 107: // Plus sign on a numeric keypad (fc11 + firefox 3.5.2) - case 109: case 32: + rcube_event.cancel(e); + return this.select_row(this.last_selected, mod_key, true); + case 37: // Left arrow key + case 39: // Right arrow key + case 107: // Plus sign on a numeric keypad + case 109: // Minus sign on a numeric keypad // Stop propagation rcube_event.cancel(e); var ret = this.use_plusminus_key(keyCode, mod_key); @@ -1202,21 +1204,30 @@ use_arrow_key: function(keyCode, mod_key) use_plusminus_key: function(keyCode, mod_key) { var selected_row = this.rows[this.last_selected]; - if (!selected_row) + + if (!selected_row || !selected_row.has_children) return; - if (keyCode == 32) - keyCode = selected_row.expanded ? 109 : 61; - if (keyCode == 61 || keyCode == 107) + // expand + if (keyCode == 39 || keyCode == 107) { + if (selected_row.expanded) + return; + if (mod_key == CONTROL_KEY || this.multiexpand) this.expand_all(selected_row); else - this.expand(selected_row); - else + this.expand(selected_row); + } + // collapse + else { + if (!selected_row.expanded) + return; + if (mod_key == CONTROL_KEY || this.multiexpand) this.collapse_all(selected_row); else this.collapse(selected_row); + } this.update_expando(selected_row.uid, selected_row.expanded); @@ -1231,7 +1242,8 @@ scrollto: function(id) { var row = this.rows[id].obj; if (row && this.frame) { - var scroll_to = Number(row.offsetTop); + var scroll_to = Number(row.offsetTop), + head_offset = 0; // expand thread if target row is hidden (collapsed) if (!scroll_to && this.rows[id].parent_uid) { @@ -1240,8 +1252,14 @@ scrollto: function(id) scroll_to = Number(row.offsetTop); } - if (scroll_to < Number(this.frame.scrollTop)) - this.frame.scrollTop = scroll_to; + if (this.fixed_header) + head_offset = Number(this.thead.offsetHeight); + + // if row is above the frame (or behind header) + if (scroll_to < Number(this.frame.scrollTop) + head_offset) { + // scroll window so that row isn't behind header + this.frame.scrollTop = scroll_to - head_offset; + } else if (scroll_to + Number(row.offsetHeight) > Number(this.frame.scrollTop) + Number(this.frame.offsetHeight)) this.frame.scrollTop = (scroll_to + Number(row.offsetHeight)) - Number(this.frame.offsetHeight); } diff --git a/program/lib/Roundcube/html.php b/program/lib/Roundcube/html.php index 5911c04d7..f6f744cb2 100644 --- a/program/lib/Roundcube/html.php +++ b/program/lib/Roundcube/html.php @@ -3,7 +3,7 @@ /* +-----------------------------------------------------------------------+ | This file is part of the Roundcube Webmail client | - | Copyright (C) 2005-2011, The Roundcube Dev Team | + | 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. | @@ -32,8 +32,8 @@ class html public static $doctype = 'xhtml'; public static $lc_tags = true; - public static $common_attrib = array('id','class','style','title','align'); - public static $containers = array('iframe','div','span','p','h1','h2','h3','form','textarea','table','thead','tbody','tr','th','td','style','script'); + public static $common_attrib = array('id','class','style','title','align','unselectable'); + public static $containers = array('iframe','div','span','p','h1','h2','h3','ul','form','textarea','table','thead','tbody','tr','th','td','style','script'); /** @@ -645,7 +645,7 @@ class html_select extends html $option_content = self::quote($option_content); } - $this->content .= self::tag('option', $attr + $option, $option_content, array('class','style','title','disabled')); + $this->content .= self::tag('option', $attr + $option, $option_content, array('value','label','class','style','title','disabled','selected')); } return parent::show(); diff --git a/program/lib/Roundcube/rcube_addressbook.php b/program/lib/Roundcube/rcube_addressbook.php index 6e2b439d8..886f65cb9 100644 --- a/program/lib/Roundcube/rcube_addressbook.php +++ b/program/lib/Roundcube/rcube_addressbook.php @@ -209,6 +209,7 @@ abstract class rcube_addressbook public function validate(&$save_data, $autofix = false) { $rcube = rcube::get_instance(); + $valid = true; // check validity of email addresses foreach ($this->get_col_values('email', $save_data, true) as $email) { @@ -216,12 +217,28 @@ abstract class rcube_addressbook if (!rcube_utils::check_email(rcube_utils::idn_to_ascii($email))) { $error = $rcube->gettext(array('name' => 'emailformaterror', 'vars' => array('email' => $email))); $this->set_error(self::ERROR_VALIDATE, $error); - return false; + $valid = false; + break; } } } - return true; + // allow plugins to do contact validation and auto-fixing + $plugin = $rcube->plugins->exec_hook('contact_validate', array( + 'record' => $save_data, + 'autofix' => $autofix, + 'valid' => $valid, + )); + + if ($valid && !$plugin['valid']) { + $this->set_error(self::ERROR_VALIDATE, $plugin['error']); + } + + if (is_array($plugin['record'])) { + $save_data = $plugin['record']; + } + + return $plugin['valid']; } /** @@ -515,8 +532,12 @@ abstract class rcube_addressbook $fn = join(' ', array($contact['surname'], $contact['firstname'], $contact['middlename'])); else if ($compose_mode == 1) $fn = join(' ', array($contact['firstname'], $contact['middlename'], $contact['surname'])); - else + else if ($compose_mode == 0) $fn = !empty($contact['name']) ? $contact['name'] : join(' ', array($contact['prefix'], $contact['firstname'], $contact['middlename'], $contact['surname'], $contact['suffix'])); + else { + $plugin = rcube::get_instance()->plugins->exec_hook('contact_listname', array('contact' => $contact)); + $fn = $plugin['fn']; + } $fn = trim($fn, ', '); diff --git a/program/lib/Roundcube/rcube_contacts.php b/program/lib/Roundcube/rcube_contacts.php index 6d01368a1..5c9e5ab39 100644 --- a/program/lib/Roundcube/rcube_contacts.php +++ b/program/lib/Roundcube/rcube_contacts.php @@ -592,8 +592,8 @@ class rcube_contacts extends rcube_addressbook // validate e-mail addresses $valid = parent::validate($save_data, $autofix); - // require at least one e-mail address (syntax check is already done) - if ($valid && !array_filter($this->get_col_values('email', $save_data, true))) { + // require at least one email address or a name + if ($valid && !strlen($save_data['firstname'].$save_data['surname'].$save_data['name']) && !array_filter($this->get_col_values('email', $save_data, true))) { $this->set_error(self::ERROR_VALIDATE, 'noemailwarning'); $valid = false; } diff --git a/program/lib/Roundcube/rcube_html2text.php b/program/lib/Roundcube/rcube_html2text.php index 6f79e2f8e..01362e6fb 100644 --- a/program/lib/Roundcube/rcube_html2text.php +++ b/program/lib/Roundcube/rcube_html2text.php @@ -608,7 +608,7 @@ class rcube_html2text $this->width = $p_width; // Add citation markers and create <pre> block - $body = preg_replace_callback('/((?:^|\n)>*)([^\n]*)/', array($this, 'blockquote_citation_ballback'), trim($body)); + $body = preg_replace_callback('/((?:^|\n)>*)([^\n]*)/', array($this, 'blockquote_citation_callback'), trim($body)); $body = '<pre>' . htmlspecialchars($body) . '</pre>'; $text = substr_replace($text, $body . "\n", $start, $end + 13 - $start); @@ -624,7 +624,7 @@ class rcube_html2text /** * Callback function to correctly add citation markers for blockquote contents */ - public function blockquote_citation_ballback($m) + public function blockquote_citation_callback($m) { $line = ltrim($m[2]); $space = $line[0] == '>' ? '' : ' '; diff --git a/program/lib/Roundcube/rcube_ldap.php b/program/lib/Roundcube/rcube_ldap.php index 64288f973..b733e2465 100644 --- a/program/lib/Roundcube/rcube_ldap.php +++ b/program/lib/Roundcube/rcube_ldap.php @@ -52,7 +52,7 @@ class rcube_ldap extends rcube_addressbook * * @var array */ - private static $group_types = array( + private $group_types = array( 'group' => 'member', 'groupofnames' => 'member', 'kolabgroupofnames' => 'member', @@ -94,6 +94,9 @@ class rcube_ldap extends rcube_addressbook $this->prop['groups']['name_attr'] = 'cn'; if (empty($this->prop['groups']['scope'])) $this->prop['groups']['scope'] = 'sub'; + // extend group objectclass => member attribute mapping + if (!empty($this->prop['groups']['class_member_attr'])) + $this->group_types = array_merge($this->group_types, $this->prop['groups']['class_member_attr']); // add group name attrib to the list of attributes to be fetched $fetch_attributes[] = $this->prop['groups']['name_attr']; @@ -292,6 +295,14 @@ class rcube_ldap extends rcube_addressbook if ($this->prop['search_base_dn'] && $this->prop['search_filter'] && (strstr($bind_dn, '%dn') || strstr($this->base_dn, '%dn') || strstr($this->groups_base_dn, '%dn')) ) { + $search_attribs = array('uid'); + if ($search_bind_attrib = (array)$this->prop['search_bind_attrib']) { + foreach ($search_bind_attrib as $r => $attr) { + $search_attribs[] = $attr; + $replaces[$r] = ''; + } + } + $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); @@ -321,10 +332,18 @@ class rcube_ldap extends rcube_addressbook } } - $res = $ldap->search($search_base_dn, $search_filter, 'sub', array('uid')); + $res = $ldap->search($search_base_dn, $search_filter, 'sub', $search_attribs); if ($res) { $res->rewind(); $replaces['%dn'] = $res->get_dn(); + + // add more replacements from 'search_bind_attrib' config + if ($search_bind_attrib) { + $res = $res->current(); + foreach ($search_bind_attrib as $r => $attr) { + $replaces[$r] = $res[$attr][0]; + } + } } if ($ldap != $this->ldap) { @@ -355,6 +374,23 @@ class rcube_ldap extends rcube_addressbook $this->base_dn = strtr($this->base_dn, $replaces); $this->groups_base_dn = strtr($this->groups_base_dn, $replaces); + // replace placeholders in filter settings + if (!empty($this->prop['filter'])) + $this->prop['filter'] = strtr($this->prop['filter'], $replaces); + if (!empty($this->prop['groups']['filter'])) + $this->prop['groups']['filter'] = strtr($this->prop['groups']['filter'], $replaces); + if (!empty($this->prop['groups']['member_filter'])) + $this->prop['groups']['member_filter'] = strtr($this->prop['groups']['member_filter'], $replaces); + + if (!empty($this->prop['group_filters'])) { + foreach ($this->prop['group_filters'] as $i => $gf) { + if (!empty($gf['base_dn'])) + $this->prop['group_filters'][$i]['base_dn'] = strtr($gf['base_dn'], $replaces); + if (!empty($gf['filter'])) + $this->prop['group_filters'][$i]['filter'] = strtr($gf['filter'], $replaces); + } + } + if (empty($bind_user)) { $bind_user = $u; } @@ -559,9 +595,10 @@ class rcube_ldap extends rcube_addressbook /** * Get all members of the given group * - * @param string Group DN - * @param array Group entries (if called recursively) - * @return array Accumulated group members + * @param string Group DN + * @param boolean Count only + * @param array Group entries (if called recursively) + * @return array Accumulated group members */ function list_group_members($dn, $count = false, $entries = null) { @@ -569,7 +606,7 @@ class rcube_ldap extends rcube_addressbook // fetch group object if (empty($entries)) { - $attribs = array('dn','objectClass','member','uniqueMember','memberURL'); + $attribs = array_merge(array('dn','objectClass','memberURL'), array_values($this->group_types)); $entries = $this->ldap->read_entries($dn, '(objectClass=*)', $attribs); if ($entries === false) { return $group_members; @@ -581,17 +618,17 @@ class rcube_ldap extends rcube_addressbook $attrs = array(); 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), '')) + 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; } + else if (!empty($entry['memberurl'])) { + $members = $this->_list_group_memberurl($dn, $entry, $count); + $group_members = array_merge($group_members, $members); + } if ($this->prop['sizelimit'] && count($group_members) > $this->prop['sizelimit']) { break 2; @@ -608,6 +645,7 @@ class rcube_ldap extends rcube_addressbook * @param string Group DN * @param array Group entry * @param string Member attribute to use + * @param boolean Count only * @return array Accumulated group members */ private function _list_group_members($dn, $entry, $attr, $count) @@ -621,8 +659,7 @@ class rcube_ldap extends rcube_addressbook // read these attributes for all members $attrib = $count ? array('dn','objectClass') : $this->prop['list_attributes']; - $attrib[] = 'member'; - $attrib[] = 'uniqueMember'; + $attrib = array_merge($attrib, array_values($this->group_types)); $attrib[] = 'memberURL'; $filter = $this->prop['groups']['member_filter'] ? $this->prop['groups']['member_filter'] : '(objectclass=*)'; @@ -669,7 +706,7 @@ class rcube_ldap extends rcube_addressbook 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))) + if ($this->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]; @@ -1354,7 +1391,7 @@ class rcube_ldap extends rcube_addressbook $out[$this->primary_key] = self::dn_encode($rec['dn']); // determine record type - if (self::is_group_entry($rec)) { + if ($this->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']; @@ -1479,11 +1516,11 @@ class rcube_ldap extends rcube_addressbook /** * Determines whether the given LDAP entry is a group record */ - private static function is_group_entry($entry) + private function is_group_entry($entry) { $classes = array_map('strtolower', (array)$entry['objectclass']); - return count(array_intersect(array_keys(self::$group_types), $classes)) > 0; + return count(array_intersect(array_keys($this->group_types), $classes)) > 0; } /** @@ -1914,7 +1951,7 @@ class rcube_ldap extends rcube_addressbook if (!empty($object_classes)) { foreach ((array)$object_classes as $oc) { - if ($attr = self::$group_types[strtolower($oc)]) { + if ($attr = $this->group_types[strtolower($oc)]) { return $attr; } } diff --git a/program/lib/Roundcube/rcube_mime.php b/program/lib/Roundcube/rcube_mime.php index 9c2220328..a931c27c1 100644 --- a/program/lib/Roundcube/rcube_mime.php +++ b/program/lib/Roundcube/rcube_mime.php @@ -810,7 +810,7 @@ class rcube_mime } $mime_types = $mime_extensions = array(); - $regex = "/([\w\+\-\.\/]+)\t+([\w\s]+)/i"; + $regex = "/([\w\+\-\.\/]+)\s+([\w\s]+)/i"; foreach((array)$lines as $line) { // skip comments or mime types w/o any extensions if ($line[0] == '#' || !preg_match($regex, $line, $matches)) diff --git a/program/lib/Roundcube/rcube_plugin_api.php b/program/lib/Roundcube/rcube_plugin_api.php index 5a25ada02..2258f1486 100644 --- a/program/lib/Roundcube/rcube_plugin_api.php +++ b/program/lib/Roundcube/rcube_plugin_api.php @@ -35,8 +35,9 @@ class rcube_plugin_api public $url = 'plugins/'; public $task = ''; public $output; - public $handlers = array(); - public $allowed_prefs = array(); + public $handlers = array(); + public $allowed_prefs = array(); + public $allowed_session_prefs = array(); protected $plugins = array(); protected $tasks = array(); diff --git a/program/lib/Roundcube/rcube_spellcheck_atd.php b/program/lib/Roundcube/rcube_spellcheck_atd.php index 68e8b7cb8..9f073f56f 100644 --- a/program/lib/Roundcube/rcube_spellcheck_atd.php +++ b/program/lib/Roundcube/rcube_spellcheck_atd.php @@ -39,6 +39,18 @@ class rcube_spellcheck_atd extends rcube_spellcheck_engine ); /** + * Return a list of languages supported by this backend + * + * @see rcube_spellcheck_engine::languages() + */ + function languages() + { + $langs = array_values($this->langhosts); + $langs[] = 'en'; + return $langs; + } + + /** * Set content and check spelling * * @see rcube_spellcheck_engine::check() diff --git a/program/lib/Roundcube/rcube_spellcheck_enchant.php b/program/lib/Roundcube/rcube_spellcheck_enchant.php index a22251e00..14d6fff46 100644 --- a/program/lib/Roundcube/rcube_spellcheck_enchant.php +++ b/program/lib/Roundcube/rcube_spellcheck_enchant.php @@ -31,6 +31,24 @@ class rcube_spellcheck_enchant extends rcube_spellcheck_engine private $matches = array(); /** + * Return a list of languages supported by this backend + * + * @see rcube_spellcheck_engine::languages() + */ + function languages() + { + $this->init(); + + $langs = array(); + $dicts = enchant_broker_list_dicts($this->enchant_broker); + foreach ($dicts as $dict) { + $langs[] = preg_replace('/-.*$/', '', $dict['lang_tag']); + } + + return array_unique($langs); + } + + /** * Initializes Enchant dictionary */ private function init() diff --git a/program/lib/Roundcube/rcube_spellcheck_engine.php b/program/lib/Roundcube/rcube_spellcheck_engine.php index 88e10ac05..3cb4ca3de 100644 --- a/program/lib/Roundcube/rcube_spellcheck_engine.php +++ b/program/lib/Roundcube/rcube_spellcheck_engine.php @@ -43,6 +43,13 @@ abstract class rcube_spellcheck_engine } /** + * Return a list of languages supported by this backend + * + * @return array Indexed list of language codes + */ + abstract function languages(); + + /** * Set content and check spelling * * @param string $text Text content for spellchecking diff --git a/program/lib/Roundcube/rcube_spellcheck_googie.php b/program/lib/Roundcube/rcube_spellcheck_googie.php index 70507dc23..3777942a6 100644 --- a/program/lib/Roundcube/rcube_spellcheck_googie.php +++ b/program/lib/Roundcube/rcube_spellcheck_googie.php @@ -26,13 +26,28 @@ */ class rcube_spellcheck_googie extends rcube_spellcheck_engine { - const GOOGLE_HOST = 'ssl://www.google.com'; - const GOOGLE_PORT = 443; + const GOOGIE_HOST = 'ssl://spell.roundcube.net'; + const GOOGIE_PORT = 443; private $matches = array(); private $content; /** + * Return a list of languages supported by this backend + * + * @see rcube_spellcheck_engine::languages() + */ + function languages() + { + return array('am','ar','ar','bg','br','ca','cs','cy','da', + 'de_CH','de_DE','el','en_GB','en_US', + 'eo','es','et','eu','fa','fi','fr_FR','ga','gl','gl', + 'he','hr','hu','hy','is','it','ku','lt','lv','nl', + 'pl','pt_BR','pt_PT','ro','ru', + 'sk','sl','sv','uk'); + } + + /** * Set content and check spelling * * @see rcube_spellcheck_engine::check() @@ -52,25 +67,25 @@ class rcube_spellcheck_googie extends rcube_spellcheck_engine $path = $a_uri['path'] . ($a_uri['query'] ? '?'.$a_uri['query'] : '') . $this->lang; } else { - $host = self::GOOGLE_HOST; - $port = self::GOOGLE_PORT; + $host = self::GOOGIE_HOST; + $port = self::GOOGIE_PORT; $path = '/tbproxy/spell?lang=' . $this->lang; } - // Google has some problem with spaces, use \n instead - $gtext = str_replace(' ', "\n", $text); + $path .= sprintf('&key=%06d', $_SESSION['user_id']); $gtext = '<?xml version="1.0" encoding="utf-8" ?>' .'<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1">' - .'<text>' . $gtext . '</text>' + .'<text>' . htmlspecialchars($text, ENT_QUOTES, RCUBE_CHARSET) . '</text>' .'</spellrequest>'; $store = ''; if ($fp = fsockopen($host, $port, $errno, $errstr, 30)) { $out = "POST $path HTTP/1.0\r\n"; $out .= "Host: " . str_replace('ssl://', '', $host) . "\r\n"; + $out .= "User-Agent: Roundcube Webmail/" . RCMAIL_VERSION . " (Googiespell Wrapper)\r\n"; $out .= "Content-Length: " . strlen($gtext) . "\r\n"; - $out .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $out .= "Content-Type: text/xml\r\n"; $out .= "Connection: Close\r\n\r\n"; $out .= $gtext; fwrite($fp, $out); @@ -83,8 +98,10 @@ class rcube_spellcheck_googie extends rcube_spellcheck_engine // parse HTTP response if (preg_match('!^HTTP/1.\d (\d+)(.+)!', $store, $m)) { $http_status = $m[1]; - if ($http_status != '200') + if ($http_status != '200') { $this->error = 'HTTP ' . $m[1] . $m[2]; + $this->error .= "\n" . $store; + } } if (!$store) { @@ -92,6 +109,7 @@ class rcube_spellcheck_googie extends rcube_spellcheck_engine } else if (preg_match('/<spellresult error="([^"]+)"/', $store, $m) && $m[1]) { $this->error = "Error code $m[1] returned"; + $this->error .= preg_match('/<errortext>([^<]+)/', $store, $m) ? ": " . html_entity_decode($m[1]) : ''; } preg_match_all('/<c o="([^"]*)" l="([^"]*)" s="([^"]*)">([^<]*)<\/c>/', $store, $matches, PREG_SET_ORDER); diff --git a/program/lib/Roundcube/rcube_spellcheck_pspell.php b/program/lib/Roundcube/rcube_spellcheck_pspell.php index ce089ed8f..b12684e43 100644 --- a/program/lib/Roundcube/rcube_spellcheck_pspell.php +++ b/program/lib/Roundcube/rcube_spellcheck_pspell.php @@ -30,6 +30,35 @@ class rcube_spellcheck_pspell extends rcube_spellcheck_engine private $matches = array(); /** + * Return a list of languages supported by this backend + * + * @see rcube_spellcheck_engine::languages() + */ + function languages() + { + $defaults = array('en'); + $langs = array(); + + // get aspell dictionaries + exec('aspell dump dicts', $dicts); + if (!empty($dicts)) { + $seen = array(); + foreach ($dicts as $lang) { + $lang = preg_replace('/-.*$/', '', $lang); + $langc = strlen($lang) == 2 ? $lang.'_'.strtoupper($lang) : $lang; + if (!$seen[$langc]++) + $langs[] = $lang; + } + $langs = array_unique($langs); + } + else { + $langs = $defaults; + } + + return $langs; + } + + /** * Initializes PSpell dictionary */ private function init() diff --git a/program/lib/Roundcube/rcube_spellchecker.php b/program/lib/Roundcube/rcube_spellchecker.php index 31835dbb5..3182ff378 100644 --- a/program/lib/Roundcube/rcube_spellchecker.php +++ b/program/lib/Roundcube/rcube_spellchecker.php @@ -65,6 +65,52 @@ class rcube_spellchecker } } + /** + * Return a list of supported languages + */ + function languages() + { + // trust configuration + $configured = $this->rc->config->get('spellcheck_languages'); + if (!empty($configured) && is_array($configured) && !$configured[0]) { + return $configured; + } + else if (!empty($configured)) { + $langs = (array)$configured; + } + else if ($this->backend) { + $langs = $this->backend->languages(); + } + + // load index + @include(RCUBE_LOCALIZATION_DIR . 'index.inc'); + + // add correct labels + $languages = array(); + foreach ($langs as $lang) { + $langc = strtolower(substr($lang, 0, 2)); + $alias = $rcube_language_aliases[$langc]; + if (!$alias) { + $alias = $langc.'_'.strtoupper($langc); + } + if ($rcube_languages[$lang]) { + $languages[$lang] = $rcube_languages[$lang]; + } + else if ($rcube_languages[$alias]) { + $languages[$lang] = $rcube_languages[$alias]; + } + else { + $languages[$lang] = ucfirst($lang); + } + } + + // remove possible duplicates (#1489395) + $languages = array_unique($languages); + + asort($languages); + + return $languages; + } /** * Set content and check spelling @@ -152,7 +198,7 @@ class rcube_spellchecker // send output $out = '<?xml version="1.0" encoding="'.RCUBE_CHARSET.'"?><spellresult charschecked="'.mb_strlen($this->content).'">'; - foreach ($this->matches as $item) { + foreach ((array)$this->matches as $item) { $out .= '<c o="'.$item[1].'" l="'.$item[2].'">'; $out .= is_array($item[4]) ? implode("\t", $item[4]) : $item[4]; $out .= '</c>'; @@ -173,7 +219,7 @@ class rcube_spellchecker { $result = array(); - foreach ($this->matches as $item) { + foreach ((array)$this->matches as $item) { if ($this->engine == 'pspell') { $word = $item[0]; } diff --git a/program/lib/Roundcube/rcube_user.php b/program/lib/Roundcube/rcube_user.php index 5e9c9af80..57f63361d 100644 --- a/program/lib/Roundcube/rcube_user.php +++ b/program/lib/Roundcube/rcube_user.php @@ -163,8 +163,16 @@ class rcube_user if (!$this->ID) return false; - $config = $this->rc->config; - $old_prefs = (array)$this->get_prefs(); + $plugin = $this->rc->plugins->exec_hook('preferences_update', array( + 'userid' => $this->ID, 'prefs' => $a_user_prefs, 'old' => (array)$this->get_prefs())); + + if (!empty($plugin['abort'])) { + return; + } + + $a_user_prefs = $plugin['prefs']; + $old_prefs = $plugin['old']; + $config = $this->rc->config; // merge (partial) prefs array with existing settings $save_prefs = $a_user_prefs + $old_prefs; diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php index b73bc0812..27a618d83 100644 --- a/program/lib/Roundcube/rcube_utils.php +++ b/program/lib/Roundcube/rcube_utils.php @@ -454,6 +454,9 @@ class rcube_utils // cut out all contents between { and } while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos))) { + $nested = strpos($source, '{', $pos+1); + if ($nested && $nested < $pos2) // when dealing with nested blocks (e.g. @media), take the inner one + $pos = $nested; $length = $pos2 - $pos - 1; $styles = substr($source, $pos+1, $length); @@ -744,40 +747,13 @@ class rcube_utils */ public static function strtotime($date) { - $date = trim($date); - - // check for MS Outlook vCard date format YYYYMMDD - if (preg_match('/^([12][90]\d\d)([01]\d)([0123]\d)$/', $date, $m)) { - return mktime(0,0,0, intval($m[2]), intval($m[3]), intval($m[1])); - } - - // common little-endian formats, e.g. dd/mm/yyyy (not all are supported by strtotime) - if (preg_match('/^(\d{1,2})[.\/-](\d{1,2})[.\/-](\d{4})$/', $date, $m) - && $m[1] > 0 && $m[1] <= 31 && $m[2] > 0 && $m[2] <= 12 && $m[3] >= 1970 - ) { - return mktime(0,0,0, intval($m[2]), intval($m[1]), intval($m[3])); - } + $date = self::clean_datestr($date); // unix timestamp if (is_numeric($date)) { return (int) $date; } - // Clean malformed data - $date = preg_replace( - array( - '/GMT\s*([+-][0-9]+)/', // support non-standard "GMTXXXX" literal - '/[^a-z0-9\x20\x09:+-]/i', // remove any invalid characters - '/\s*(Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*/i', // remove weekday names - ), - array( - '\\1', - '', - '', - ), $date); - - $date = trim($date); - // if date parsing fails, we have a date in non-rfc format. // remove token from the end and try again while ((($ts = @strtotime($date)) === false) || ($ts < 0)) { @@ -805,8 +781,8 @@ class rcube_utils return $date; } - $dt = false; - $date = trim($date); + $dt = false; + $date = self::clean_datestr($date); // try to parse string with DateTime first if (!empty($date)) { @@ -831,6 +807,52 @@ class rcube_utils return $dt; } + /** + * Clean up date string for strtotime() input + * + * @param string $date Date string + * + * @return string Date string + */ + public static function clean_datestr($date) + { + $date = trim($date); + + // check for MS Outlook vCard date format YYYYMMDD + if (preg_match('/^([12][90]\d\d)([01]\d)([0123]\d)$/', $date, $m)) { + return sprintf('%04d-%02d-%02d 00:00:00', intval($m[1]), intval($m[2]), intval($m[3])); + } + + // Clean malformed data + $date = preg_replace( + array( + '/GMT\s*([+-][0-9]+)/', // support non-standard "GMTXXXX" literal + '/[^a-z0-9\x20\x09:+-\/]/i', // remove any invalid characters + '/\s*(Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*/i', // remove weekday names + ), + array( + '\\1', + '', + '', + ), $date); + + $date = trim($date); + + // try to fix dd/mm vs. mm/dd discrepancy, we can't do more here + if (preg_match('/^(\d{1,2})[.\/-](\d{1,2})[.\/-](\d{4})$/', $date, $m)) { + $mdy = $m[2] > 12 && $m[1] <= 12; + $day = $mdy ? $m[2] : $m[1]; + $month = $mdy ? $m[1] : $m[2]; + $date = sprintf('%04d-%02d-%02d 00:00:00', intval($m[3]), $month, $day); + } + // I've found that YYYY.MM.DD is recognized wrong, so here's a fix + else if (preg_match('/^(\d{4})\.(\d{1,2})\.(\d{1,2})$/', $date)) { + $date = str_replace('.', '-', $date) . ' 00:00:00'; + } + + return $date; + } + /* * Idn_to_ascii wrapper. * Intl/Idn modules version of this function doesn't work with e-mail address diff --git a/program/lib/Roundcube/rcube_vcard.php b/program/lib/Roundcube/rcube_vcard.php index d54dc56ad..5f74ccbd4 100644 --- a/program/lib/Roundcube/rcube_vcard.php +++ b/program/lib/Roundcube/rcube_vcard.php @@ -518,20 +518,28 @@ class rcube_vcard */ public static function cleanup($vcard) { - // Convert special types (like Skype) to normal type='skype' classes with this simple regex ;) - $vcard = preg_replace( - '/item(\d+)\.(TEL|EMAIL|URL)([^:]*?):(.*?)item\1.X-ABLabel:(?:_\$!<)?([\w-() ]*)(?:>!\$_)?./s', - '\2;type=\5\3:\4', - $vcard); - // convert Apple X-ABRELATEDNAMES into X-* fields for better compatibility $vcard = preg_replace_callback( '/item(\d+)\.(X-ABRELATEDNAMES)([^:]*?):(.*?)item\1.X-ABLabel:(?:_\$!<)?([\w-() ]*)(?:>!\$_)?./s', array('self', 'x_abrelatednames_callback'), $vcard); - // Remove cruft like item1.X-AB*, item1.ADR instead of ADR, and empty lines - $vcard = preg_replace(array('/^item\d*\.X-AB.*$/m', '/^item\d*\./m', "/\n+/"), array('', '', "\n"), $vcard); + // Cleanup + $vcard = preg_replace(array( + // convert special types (like Skype) to normal type='skype' classes with this simple regex ;) + '/item(\d+)\.(TEL|EMAIL|URL)([^:]*?):(.*?)item\1.X-ABLabel:(?:_\$!<)?([\w-() ]*)(?:>!\$_)?./s', + '/^item\d*\.X-AB.*$/m', // remove cruft like item1.X-AB* + '/^item\d*\./m', // remove item1.ADR instead of ADR + '/\n+/', // remove empty lines + '/^(N:[^;\R]*)$/m', // if N doesn't have any semicolons, add some + ), + array( + '\2;type=\5\3:\4', + '', + '', + "\n", + '\1;;;;', + ), $vcard); // convert X-WAB-GENDER to X-GENDER if (preg_match('/X-WAB-GENDER:(\d)/', $vcard, $matches)) { @@ -539,9 +547,6 @@ class rcube_vcard $vcard = preg_replace('/X-WAB-GENDER:\d/', 'X-GENDER:' . $value, $vcard); } - // if N doesn't have any semicolons, add some - $vcard = preg_replace('/^(N:[^;\R]*)$/m', '\1;;;;', $vcard); - return $vcard; } @@ -612,8 +617,8 @@ class rcube_vcard $enc = null; foreach($regs2[1] as $attrid => $attr) { + $attr = preg_replace('/[\s\t\n\r\0\x0B]/', '', $attr); if ((list($key, $value) = explode('=', $attr)) && $value) { - $value = trim($value); if ($key == 'ENCODING') { $value = strtoupper($value); // add next line(s) to value string if QP line end detected @@ -792,7 +797,7 @@ class rcube_vcard return $result; } - $s = strtr($s, $rep2); + $s = trim(strtr($s, $rep2)); } // some implementations (GMail) use non-standard backslash before colon (#1489085) diff --git a/program/localization/be_BE/labels.inc b/program/localization/be_BE/labels.inc index b5a3ed6d8..549c315a6 100644 --- a/program/localization/be_BE/labels.inc +++ b/program/localization/be_BE/labels.inc @@ -29,7 +29,7 @@ $labels['drafts'] = 'Чарнавікі'; $labels['sent'] = 'Дасланыя'; $labels['trash'] = 'Сметніца'; $labels['junk'] = 'Спам'; -$labels['show_real_foldernames'] = 'Паказваць сапраўдныя імёны для адмысловых папак'; +$labels['show_real_foldernames'] = 'Паказваць сапраўдныя назвы для адмысловых папак'; $labels['subject'] = 'Тэма'; $labels['from'] = 'Ад каго'; $labels['sender'] = 'Адпраўнік'; @@ -44,7 +44,7 @@ $labels['priority'] = 'Прыярытэт'; $labels['organization'] = 'Установа'; $labels['readstatus'] = 'Не прачытанае'; $labels['listoptions'] = 'Параметры спісу...'; -$labels['mailboxlist'] = 'Тэчкі'; +$labels['mailboxlist'] = 'Папкі'; $labels['messagesfromto'] = 'Паведамленні $from—$to з $count'; $labels['threadsfromto'] = 'Абмеркаванні $from—$to з $count'; $labels['messagenrof'] = 'Паведамленне $nr з $count'; @@ -52,11 +52,11 @@ $labels['fromtoshort'] = '$from—$to з $count'; $labels['copy'] = 'Капіраваць'; $labels['move'] = 'Перамясціць'; $labels['moveto'] = 'Перамясціць у...'; -$labels['download'] = 'Спампаваць'; -$labels['open'] = 'Адчыніць'; +$labels['download'] = 'Сцягнуць'; +$labels['open'] = 'Адкрыць'; $labels['showattachment'] = 'Паказаць'; $labels['showanyway'] = 'Усё адно паказваць'; -$labels['filename'] = 'Імя файла'; +$labels['filename'] = 'Назва файла'; $labels['filesize'] = 'Памер файла'; $labels['addtoaddressbook'] = 'Дадаць у адрасную кнігу'; $labels['sun'] = 'нд'; @@ -177,8 +177,8 @@ $labels['msgtext'] = 'Усё паведамленне'; $labels['body'] = 'Цела'; $labels['type'] = 'Тып'; $labels['namex'] = 'Імя'; -$labels['openinextwin'] = 'Адчыніць у новым акне'; -$labels['emlsave'] = 'Спампаваць (.eml)'; +$labels['openinextwin'] = 'Адкрыць у новым акне'; +$labels['emlsave'] = 'Сцягнуць (.eml)'; $labels['changeformattext'] = 'Паказаць як просты тэкст'; $labels['changeformathtml'] = 'Паказаць як HTML'; $labels['editasnew'] = 'Адрэдагаваць як новае'; @@ -197,11 +197,19 @@ $labels['spellcheck'] = 'Правапіс'; $labels['checkspelling'] = 'Праверыць правапіс'; $labels['resumeediting'] = 'Працягнуць рэдагаванне'; $labels['revertto'] = 'Адкаціцца на'; +$labels['responses'] = 'Адказы'; +$labels['insertresponse'] = 'Уставіць адказ'; +$labels['manageresponses'] = 'Кіраваць адказамі'; +$labels['savenewresponse'] = 'Захаваць новы адказ'; +$labels['editresponses'] = 'Рэдагаваць адказы'; +$labels['editresponse'] = 'Рэдагаваць адказ'; +$labels['responsename'] = 'Назва'; +$labels['responsetext'] = 'Тэкст адказу'; $labels['attach'] = 'Далучыць'; $labels['attachments'] = 'Далучэнні'; -$labels['upload'] = 'Запампаваць'; +$labels['upload'] = 'Апублікаваць'; $labels['uploadprogress'] = '$percent ($current з $total)'; -$labels['close'] = 'Зачыніць'; +$labels['close'] = 'Закрыць'; $labels['messageoptions'] = 'Параметры паведамлення...'; $labels['low'] = 'Нізкі'; $labels['lowest'] = 'Найнізшы'; @@ -228,7 +236,7 @@ $labels['mdnrequest'] = 'Адпраўнік пажадаў даведацца а $labels['receiptread'] = 'Пацверджанне атрымання (прачытання)'; $labels['yourmessage'] = 'Гэта пацверджанне аб атрыманні вашага паведамлення'; $labels['receiptnote'] = 'Заўвага: Гэтае пацверджанне значыць адно, што паведамленне было адлюстравана на экране кампутара адрасата. Няма гарантыі, што атрымальнік прачытаў альбо зразумеў змест паведамлення.'; -$labels['name'] = 'Экраннае імя'; +$labels['name'] = 'Экранная назва'; $labels['firstname'] = 'Імя'; $labels['surname'] = 'Прозвішча'; $labels['middlename'] = 'Другое імя'; @@ -286,10 +294,10 @@ $labels['edit'] = 'Рэдагаваць'; $labels['cancel'] = 'Скасаваць'; $labels['save'] = 'Захаваць'; $labels['delete'] = 'Выдаліць'; -$labels['rename'] = 'Перайменаваць'; +$labels['rename'] = 'Пераназваць'; $labels['addphoto'] = 'Дадаць'; $labels['replacephoto'] = 'Замяніць'; -$labels['uploadphoto'] = 'Запампаваць фота'; +$labels['uploadphoto'] = 'Апублікаваць фота'; $labels['newcontact'] = 'Стварыць новую картку кантакта'; $labels['deletecontact'] = 'Выдаліць абраных кантактаў'; $labels['composeto'] = 'Скласці ліст да'; @@ -300,7 +308,7 @@ $labels['exportall'] = 'Экспартаваць усё'; $labels['exportsel'] = 'Экспартаваць абранае'; $labels['exportvcards'] = 'Экспартаваць кантакты ў фармаце vCard'; $labels['newcontactgroup'] = 'Стварыць новую групу кантактаў'; -$labels['grouprename'] = 'Перайменаваць групу'; +$labels['grouprename'] = 'Пераназваць групу'; $labels['groupdelete'] = 'Выдаліць групу'; $labels['groupremoveselected'] = 'Выдаліць абраных кантакаў з групы'; $labels['previouspage'] = 'Папярэдняя старонка'; @@ -321,7 +329,7 @@ $labels['importreplace'] = 'Замяніць адрасную кнігу цал $labels['importgroups'] = 'Імпартаваць прызначэнні групы'; $labels['importgroupsall'] = 'Усе (стварыць групы пры неабходнасці)'; $labels['importgroupsexisting'] = 'Толькі для існуючых груп'; -$labels['importdesc'] = 'Кантакты можна запампаваць з існуючай адраснай кнігі.<br/>На дадзены момант падтрымліваюцца адрасы ў фарматах <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> і CSV (значэнні цераз коску).'; +$labels['importdesc'] = 'Кантакты можна загрузіць з існуючай адраснай кнігі.<br/>На дадзены момант падтрымліваюцца адрасы ў фарматах <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> і CSV (значэнні праз коску).'; $labels['done'] = 'Гатова'; $labels['settingsfor'] = 'Настаўленні для'; $labels['about'] = 'Апісанне'; @@ -348,13 +356,13 @@ $labels['timezone'] = 'Часавая зона'; $labels['pagesize'] = 'Радкоў на старонку'; $labels['signature'] = 'Подпіс'; $labels['dstactive'] = 'Летні/зімовы час'; -$labels['showinextwin'] = 'Адчыняць паведамленне ў новым акне'; +$labels['showinextwin'] = 'Адкрываць паведамленні ў новым акне'; $labels['composeextwin'] = 'Складаць у новым акне'; $labels['htmleditor'] = 'Складаць паведамленні ў HTML'; $labels['htmlonreply'] = 'у адказ на паведамленні ў HTML'; $labels['htmlonreplyandforward'] = 'пры перасылцы альбо ў адказ на паведамленні ў HTML'; $labels['htmlsignature'] = 'Подпіс у HTML'; -$labels['showemail'] = 'Паказваць адрас электроннай пошты разам з экранным імем'; +$labels['showemail'] = 'Паказваць адрас электроннай пошты разам з экраннай назвай'; $labels['previewpane'] = 'Панэль прагляду'; $labels['skin'] = 'Тэма інтэрфейсу'; $labels['logoutclear'] = 'Ачышчаць Сметніцу па выхадзе'; @@ -384,7 +392,7 @@ $labels['never'] = 'ніколі'; $labels['immediately'] = 'імгненна'; $labels['messagesdisplaying'] = 'Адлюстраванне паведамленняў'; $labels['messagescomposition'] = 'Складанне паведамленняў'; -$labels['mimeparamfolding'] = 'Імёны далучэнняў'; +$labels['mimeparamfolding'] = 'Назвы далучэнняў'; $labels['2231folding'] = 'Поўны RFC 2231 (Thunderbird)'; $labels['miscfolding'] = 'RFC 2047/2231 (MS Outlook)'; $labels['2047folding'] = 'Поўны RFC 2047 (інш.)'; @@ -429,7 +437,7 @@ $labels['forwardmode'] = 'Перасылка паведамленняў'; $labels['inline'] = 'у тэксце'; $labels['asattachment'] = 'як далучэнне'; $labels['folder'] = 'Папка'; -$labels['folders'] = 'Тэчкі'; +$labels['folders'] = 'Папкі'; $labels['foldername'] = 'Назва папкі'; $labels['subscribed'] = 'Падпісаная'; $labels['messagecount'] = 'Паведамленні'; diff --git a/program/localization/be_BE/messages.inc b/program/localization/be_BE/messages.inc index 4b2f07a2f..5833fd8a4 100644 --- a/program/localization/be_BE/messages.inc +++ b/program/localization/be_BE/messages.inc @@ -35,8 +35,8 @@ $messages['loggedout'] = 'Сесія скасавана. Да пабачэння $messages['mailboxempty'] = 'У скрынцы пуста.'; $messages['refreshing'] = 'Абнаўляецца...'; $messages['loading'] = 'Загружаецца...'; -$messages['uploading'] = 'Файл запампоўваюцца...'; -$messages['uploadingmany'] = 'Файлы запампоўваюцца...'; +$messages['uploading'] = 'Файл зацягваецца...'; +$messages['uploadingmany'] = 'Файлы зацягваюцца...'; $messages['loadingdata'] = 'Загружаюцца даныя...'; $messages['checkingmail'] = 'Праверка новых паведамленняў...'; $messages['sendingmessage'] = 'Паведамленне адпраўляецца...'; @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Паведамленні адпраўлены.'; $messages['savingmessage'] = 'Паведамленне захоўваецца...'; $messages['messagesaved'] = 'Паведамленне захавана ў Чарнавікі.'; $messages['successfullysaved'] = 'Захавана.'; +$messages['savingresponse'] = 'Тэкст адказу захоўваецца...'; +$messages['deleteresponseconfirm'] = 'Напраўду выдаліць тэкст адказу?'; $messages['addedsuccessfully'] = 'Кантакт дададзены ў адрасную кнігу.'; $messages['contactexists'] = 'Кантакт з такім самым адрасам эл. пошты ўжо існуе.'; $messages['contactnameexists'] = 'Кантакт з такім самым імем ужо існуе.'; @@ -82,7 +84,7 @@ $messages['nobodywarning'] = 'Адправіць гэта паведамленн $messages['notsentwarning'] = 'Паведамленне не адпраўлена. Жадаеце скасаваць сваё паведамленне?'; $messages['noldapserver'] = 'Задайце ldap-сервер для пошуку.'; $messages['nosearchname'] = 'Задайце імя кантакта альбо адрас электроннай пошты.'; -$messages['notuploadedwarning'] = 'Не ўсе далучэнні пакуль яшчэ запампаваныя. Пачакайце альбо скасуйце аперацыю.'; +$messages['notuploadedwarning'] = 'Не ўсе далучэнні пакуль яшчэ зацягнутыя. Пачакайце альбо скасуйце аперацыю.'; $messages['searchsuccessful'] = 'Знойдзена $nr паведамленняў.'; $messages['contactsearchsuccessful'] = 'Знойдзена $nr кантактаў.'; $messages['searchnomatch'] = 'Пошук не даў выніку.'; @@ -97,8 +99,8 @@ $messages['folderexpunged'] = 'Папка сціснута. '; $messages['deletedsuccessfully'] = 'Выдалена.'; $messages['converting'] = 'Фарматаванне выдаляецца...'; $messages['messageopenerror'] = 'Не ўдалося загрузіць паведамленне з сервера.'; -$messages['fileuploaderror'] = 'Не ўдалося запампаваць файл.'; -$messages['filesizeerror'] = 'Запампаваны файл перавышае максімальна дазволены памер $size.'; +$messages['fileuploaderror'] = 'Не ўдалося зацягнуць файл.'; +$messages['filesizeerror'] = 'Зацягнуты файл перавышае максімальна дазволены памер $size.'; $messages['copysuccess'] = '$nr кантактаў скапіявана.'; $messages['movesuccess'] = '$nr кантактаў перамешчана.'; $messages['copyerror'] = 'Не ўдалося скапіяваць ніводнага кантакта.'; @@ -118,17 +120,17 @@ $messages['errorsendingreceipt'] = 'Не ўдалося адправіць па $messages['deleteidentityconfirm'] = 'Напраўду выдаліць гэтую тоеснасць?'; $messages['nodeletelastidentity'] = 'Гэтую тоеснасць выдаліць няможна, бо апошняя.'; $messages['forbiddencharacter'] = 'Назва папкі змяшчае забаронены знак.'; -$messages['selectimportfile'] = 'Абярыце файл на запампоўку.'; +$messages['selectimportfile'] = 'Абярыце файл да зацягвання.'; $messages['addresswriterror'] = 'Абраная адрасная кніга ёсць толькі-для-чытання.'; $messages['contactaddedtogroup'] = 'Кантакты дададзены ў групу.'; $messages['contactremovedfromgroup'] = 'Кантакты выдаленыя з групы.'; $messages['nogroupassignmentschanged'] = 'Усе прызначэнні групы засталіся без зменаў.'; $messages['importwait'] = 'Ідзе імпартаванне. Чакайце...'; -$messages['importformaterror'] = 'Імпартаванне не ўдалося! Запампаваны файл не ўтрымоўвае слушных даных на імпарт.'; +$messages['importformaterror'] = 'Імпартаванне не ўдалося! Загружаны файл не ўтрымоўвае слушных даных на імпарт.'; $messages['importconfirm'] = '<b>$inserted кантактаў імпартаваныя</b>'; $messages['importconfirmskipped'] = '<b>Прапушчана $skipped існуючых запісаў</b>'; $messages['importmessagesuccess'] = '$nr паведамленняў імпартавана'; -$messages['importmessageerror'] = 'Не ўдалося імпартаваць! Запампаваны файл не ёсць слушным паведамленнем альбо файлам паштовай скрынкі'; +$messages['importmessageerror'] = 'Не ўдалося імпартаваць! Загружаны файл не ёсць слушным паведамленнем альбо файлам паштовай скрынкі'; $messages['opnotpermitted'] = 'Аперацыя не дазволеная!'; $messages['nofromaddress'] = 'У абранай тоеснасці не стае адрасу эл. пошты.'; $messages['editorwarning'] = 'Змена рэдактара прывядзе да страты фарматавання. Працягнуць?'; diff --git a/program/localization/bg_BG/labels.inc b/program/localization/bg_BG/labels.inc index 29c99e8f4..0394f19b9 100644 --- a/program/localization/bg_BG/labels.inc +++ b/program/localization/bg_BG/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Правопис'; $labels['checkspelling'] = 'Проверка на правописа'; $labels['resumeediting'] = 'Продължи черновата'; $labels['revertto'] = 'Върни се към'; +$labels['responses'] = 'Отговори'; +$labels['insertresponse'] = 'Вмъкване на отговори'; +$labels['manageresponses'] = 'Настройка на отговори'; +$labels['savenewresponse'] = 'Запис на нов отговор'; +$labels['editresponses'] = 'Редакция на отговори'; +$labels['editresponse'] = 'Редакция на отговор'; +$labels['responsename'] = 'Име'; +$labels['responsetext'] = 'Текст на отговор'; $labels['attach'] = 'Прикачи'; $labels['attachments'] = 'Прикачени файлове'; $labels['upload'] = 'Качи'; diff --git a/program/localization/bg_BG/messages.inc b/program/localization/bg_BG/messages.inc index 210eda1b1..48e1fbcc0 100644 --- a/program/localization/bg_BG/messages.inc +++ b/program/localization/bg_BG/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Писмото е изпратено успешно. $messages['savingmessage'] = 'Записване на писмо...'; $messages['messagesaved'] = 'Писмото е записано в Чернови.'; $messages['successfullysaved'] = 'Успешен запис.'; +$messages['savingresponse'] = 'Записване текст на отговор...'; +$messages['deleteresponseconfirm'] = 'Желаете ли да изтриете текст за отговор?'; $messages['addedsuccessfully'] = 'Контактът е добавен в адресната книга.'; $messages['contactexists'] = 'Вече съществува контакт с този e-mail адрес.'; $messages['contactnameexists'] = 'Вече съществува контакт с това име.'; @@ -54,6 +56,8 @@ $messages['contactnotfound'] = 'Търсеният контакт не е нам $messages['contactsearchonly'] = 'Използвайте полето за да търсите контакти'; $messages['sendingfailed'] = 'Неуспешно изпращане на писмо.'; $messages['senttooquickly'] = 'Моля изчакайте $sec секунди преди да изпратите писмото.'; +$messages['errorsavingsent'] = 'Възникна грешка при записване на изпратеното писмо.'; +$messages['errorsaving'] = 'Възникна грешка при записването.'; $messages['errormoving'] = 'Писмото не може да бъде преместено.'; $messages['errorcopying'] = 'Писмото не може да бъде копирано.'; $messages['errordeleting'] = 'Писмото не може да бъде изтрито.'; @@ -140,6 +144,7 @@ $messages['smtperror'] = 'SMTP грешка: $msg'; $messages['emailformaterror'] = 'Невалиден e-mail адрес: $email'; $messages['toomanyrecipients'] = 'Прекалено много адреси за изпращане (максимум: $max).'; $messages['maxgroupmembersreached'] = 'Броят на членовете на групата е повече от максималния: $max.'; +$messages['internalerror'] = 'Възникна вътрешна грешка. Моля опитайте отново.'; $messages['contactdelerror'] = 'Невъзможно изтриване на контакти.'; $messages['contactdeleted'] = 'Контактът беше изтрит успешно.'; $messages['contactrestoreerror'] = 'Неуспешно възстановяване на изтрите контакти.'; diff --git a/program/localization/bs_BA/messages.inc b/program/localization/bs_BA/messages.inc index 3424013c5..9e0f083ff 100644 --- a/program/localization/bs_BA/messages.inc +++ b/program/localization/bs_BA/messages.inc @@ -54,6 +54,8 @@ $messages['contactnotfound'] = 'Traženi kontakt nije pronađen.'; $messages['contactsearchonly'] = 'Unesite neki pojam za pretragu'; $messages['sendingfailed'] = 'Greška pri slanju poruke.'; $messages['senttooquickly'] = 'Molimo sačekajte $sec sekundi prije slanja ove poruke.'; +$messages['errorsavingsent'] = 'Desila se greška pri snimanju poslane poruke.'; +$messages['errorsaving'] = 'Desila se greška pri snimanju.'; $messages['errormoving'] = 'Nije moguće premjestiti poruke.'; $messages['errorcopying'] = 'Nije moguće kopirati poruke.'; $messages['errordeleting'] = 'Nije moguće obrisati poruke.'; @@ -140,6 +142,7 @@ $messages['smtperror'] = 'SMTP greška: $msg'; $messages['emailformaterror'] = 'Netačna email adresa: $email'; $messages['toomanyrecipients'] = 'Previše primaoca. Smanjite broj primaoca na $max.'; $messages['maxgroupmembersreached'] = 'Broj članova grupe prelazi maksimum od $max.'; +$messages['internalerror'] = 'Dogodila se interna greška. Molimo vas da pokušate ponovo.'; $messages['contactdelerror'] = 'Kontakti ne mogu biti obrisani.'; $messages['contactdeleted'] = 'Kontakti su uspješno obrisani.'; $messages['contactrestoreerror'] = 'Nije moguće vratiti obrisane kontakte.'; diff --git a/program/localization/ca_ES/labels.inc b/program/localization/ca_ES/labels.inc index 065431fbc..a93b18434 100644 --- a/program/localization/ca_ES/labels.inc +++ b/program/localization/ca_ES/labels.inc @@ -175,14 +175,14 @@ $labels['resetsearch'] = 'Neteja cerca'; $labels['searchmod'] = 'Cerca modificadors'; $labels['msgtext'] = 'Missatge sencer'; $labels['body'] = 'Cos'; -$labels['type'] = 'tipus:'; +$labels['type'] = 'Tipus'; $labels['namex'] = 'Nom'; $labels['openinextwin'] = 'Obre a una nova finestra'; $labels['emlsave'] = 'Descarrega (.eml)'; $labels['changeformattext'] = 'Mostra en format de text net'; $labels['changeformathtml'] = 'Mostra en format HTML'; $labels['editasnew'] = 'Edita com a nou'; -$labels['send'] = 'Enviar'; +$labels['send'] = 'Envia'; $labels['sendmessage'] = 'Envia el missatge'; $labels['savemessage'] = 'Desa aquest esborrany'; $labels['addattachment'] = 'Adjunta un fitxer'; @@ -316,7 +316,11 @@ $labels['searchdelete'] = 'Suprimeix la cerca'; $labels['import'] = 'Importa'; $labels['importcontacts'] = 'Importa contactes'; $labels['importfromfile'] = 'Importa des d\'un fitxer:'; +$labels['importtarget'] = 'Afegeix contactes a'; $labels['importreplace'] = 'Reemplaça la llibreta d\'adreçes sencera'; +$labels['importgroups'] = 'Importa assignacions de grup'; +$labels['importgroupsall'] = 'Tot (crea grups si és necessari)'; +$labels['importgroupsexisting'] = 'Només per a grups existents'; $labels['importdesc'] = 'Podeu carregar contactes des d\'una llibreta de direccions.<br/>Actualment donem suport a la importació d\'adreces des de fitxers de tipus <a href="http://ca.wikipedia.org/wiki/VCard">vCard</a> o CSV (valors separats per comes).'; $labels['done'] = 'Fet'; $labels['settingsfor'] = 'Configuració per a'; @@ -344,8 +348,8 @@ $labels['timezone'] = 'Fus horari'; $labels['pagesize'] = 'Files per pàgina'; $labels['signature'] = 'Signatura'; $labels['dstactive'] = 'Horari d\'estiu'; -$labels['showinextwin'] = 'Obrir el missatge en una nova finestra'; -$labels['composeextwin'] = 'Redactar en una nova finestra'; +$labels['showinextwin'] = 'Obre el missatge en una nova finestra'; +$labels['composeextwin'] = 'Redacta en una nova finestra'; $labels['htmleditor'] = 'Escriu missatges en HTML'; $labels['htmlonreply'] = 'només en resposta a missatges en HTML'; $labels['htmlonreplyandforward'] = 'en reenviament o resposta a missatge HTML'; diff --git a/program/localization/ca_ES/messages.inc b/program/localization/ca_ES/messages.inc index 06a72cb50..5f5854de8 100644 --- a/program/localization/ca_ES/messages.inc +++ b/program/localization/ca_ES/messages.inc @@ -54,6 +54,8 @@ $messages['contactnotfound'] = 'No s\'ha trobat el contacte sol·licitat.'; $messages['contactsearchonly'] = 'Introduïu termes de cerca per trobar contactes'; $messages['sendingfailed'] = 'Error enviant el missatge.'; $messages['senttooquickly'] = 'Si us plau, espereu $sec segon(s) abans d\'enviar aquest missatge.'; +$messages['errorsavingsent'] = 'S\'ha produït un error mentre es desava el missatge enviat.'; +$messages['errorsaving'] = 'S\'ha produït un error mentre es desava.'; $messages['errormoving'] = 'No s\'ha pogut moure el(s) missatge(s).'; $messages['errorcopying'] = 'No s\'ha pogut copiar el(s) missatge(s).'; $messages['errordeleting'] = 'No s\'ha pogut suprimir el(s) missatge(s).'; @@ -140,6 +142,7 @@ $messages['smtperror'] = 'Error SMTP: $msg'; $messages['emailformaterror'] = 'Adreça de correu no vàlida: $email'; $messages['toomanyrecipients'] = 'Massa destinataris. Reduïu el nombre de destinataris a $max.'; $messages['maxgroupmembersreached'] = 'El nombre de membres del grup excedeix el màxim de $max.'; +$messages['internalerror'] = 'S\'ha produït un error intern. Si us plau torneu-ho a provar.'; $messages['contactdelerror'] = 'No s\'han pogut suprimir el(s) contacte(s).'; $messages['contactdeleted'] = 'Contacte(s) suprimit(s) correctament.'; $messages['contactrestoreerror'] = 'No s\'ha pogut restaurar el(s) contacte(s) suprimit(s).'; diff --git a/program/localization/cs_CZ/labels.inc b/program/localization/cs_CZ/labels.inc index d887d8d0a..aac514ec5 100644 --- a/program/localization/cs_CZ/labels.inc +++ b/program/localization/cs_CZ/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Pravopis'; $labels['checkspelling'] = 'Zkontrolovat pravopis'; $labels['resumeediting'] = 'Pokračovat v úpravách'; $labels['revertto'] = 'Přejít na'; +$labels['responses'] = 'Odpovědi'; +$labels['insertresponse'] = 'Vložit odpověd'; +$labels['manageresponses'] = 'Spravovat odpovědí'; +$labels['savenewresponse'] = 'Uložit novou odpověď'; +$labels['editresponses'] = 'Upravit odpovědi'; +$labels['editresponse'] = 'Upravit odpověď'; +$labels['responsename'] = 'Název'; +$labels['responsetext'] = 'Text odpovědi'; $labels['attach'] = 'Přiložit'; $labels['attachments'] = 'Přílohy'; $labels['upload'] = 'Nahrát'; diff --git a/program/localization/cs_CZ/messages.inc b/program/localization/cs_CZ/messages.inc index 0bd6b0e82..2e3a75c52 100644 --- a/program/localization/cs_CZ/messages.inc +++ b/program/localization/cs_CZ/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Zpráva byla odeslána'; $messages['savingmessage'] = 'Ukládám zprávu...'; $messages['messagesaved'] = 'Zpráva uložena do Rozepsané'; $messages['successfullysaved'] = 'Uloženo'; +$messages['savingresponse'] = 'Ukládám text odpovědi...'; +$messages['deleteresponseconfirm'] = 'Opravdu chcete odstranit tento text odpovědi?'; $messages['addedsuccessfully'] = 'Kontakt byl úspěšně přidán do adresáře'; $messages['contactexists'] = 'Kontakt se zadanou e-mailovou adresou již existuje'; $messages['contactnameexists'] = 'Kontakt se stejným jménem již existuje'; diff --git a/program/localization/cy_GB/messages.inc b/program/localization/cy_GB/messages.inc index 5dd8230c7..be6c4dac6 100644 --- a/program/localization/cy_GB/messages.inc +++ b/program/localization/cy_GB/messages.inc @@ -54,6 +54,8 @@ $messages['contactnotfound'] = 'Ni gafwyd hyd i\'r cysylltiad gofynnwyd amdano'; $messages['contactsearchonly'] = 'Rhowch dermau chwilio i ganfod cysylltiadau'; $messages['sendingfailed'] = 'Methwyd danfon y neges'; $messages['senttooquickly'] = 'Arhoswch $sec eiliad cyn danfon y neges'; +$messages['errorsavingsent'] = 'Fe gafwyd gwall wrth gadw\'r neges ddanfonwyd.'; +$messages['errorsaving'] = 'Fe gafwyd gwall wrth gadw'; $messages['errormoving'] = 'Methwyd symud y neges'; $messages['errorcopying'] = 'Methwyd copïo\'r neges(euon)'; $messages['errordeleting'] = 'Methwyd dileu y neges'; @@ -140,6 +142,7 @@ $messages['smtperror'] = 'Gwall SMTP: $msg'; $messages['emailformaterror'] = 'Cyfeiriad e-bost anghywir: $email'; $messages['toomanyrecipients'] = 'Gormod o dderbynnwyr. Lleihewch y nifer i $max'; $messages['maxgroupmembersreached'] = 'Mae nifer o aelodau\'r grŵp yn fwy na\'r uchafswm o $max'; +$messages['internalerror'] = 'Fe gafwyd gwall mewnol. Rhowch gynnig arni eto.'; $messages['contactdelerror'] = 'Methwyd dileu cyswllt'; $messages['contactdeleted'] = 'Cyswllt wedi ei ddileu yn llwyddiannus'; $messages['contactrestoreerror'] = 'Methwyd adfer y cyswllt/cysylltiadau a ddilëwyd'; diff --git a/program/localization/da_DK/labels.inc b/program/localization/da_DK/labels.inc index 52de86d92..53d32090c 100644 --- a/program/localization/da_DK/labels.inc +++ b/program/localization/da_DK/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Stav'; $labels['checkspelling'] = 'Stavekontrol'; $labels['resumeediting'] = 'Genoptag redigering'; $labels['revertto'] = 'Vend tilbage til'; +$labels['responses'] = 'Svar'; +$labels['insertresponse'] = 'Indsæt et svar'; +$labels['manageresponses'] = 'Administrer svar'; +$labels['savenewresponse'] = 'Gem et nyt svar'; +$labels['editresponses'] = 'Rediger svar'; +$labels['editresponse'] = 'Rediger svar'; +$labels['responsename'] = 'Navn'; +$labels['responsetext'] = 'Svartekst'; $labels['attach'] = 'Vedhæft'; $labels['attachments'] = 'Vedhæftninger'; $labels['upload'] = 'Overfør'; @@ -316,7 +324,11 @@ $labels['searchdelete'] = 'Slet søgning'; $labels['import'] = 'Importér'; $labels['importcontacts'] = 'Importér kontakter'; $labels['importfromfile'] = 'Importér fra fil:'; +$labels['importtarget'] = 'Tilføj kontakter til'; $labels['importreplace'] = 'Overskriv hele adressebogen'; +$labels['importgroups'] = 'Importer gruppetildelinger'; +$labels['importgroupsall'] = 'Alle (opret grupper hvis nødvendigt)'; +$labels['importgroupsexisting'] = 'Kun for eksisterende grupper'; $labels['importdesc'] = 'Du kan uploade kontakter fra en eksisterende adressebog. <br/>I øjeblikket supportere vi import af adresser fra <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> og CSV (komma-separeret) data format.'; $labels['done'] = 'Færdig'; $labels['settingsfor'] = 'Indstillinger for'; diff --git a/program/localization/da_DK/messages.inc b/program/localization/da_DK/messages.inc index c12236eef..1e4635b8d 100644 --- a/program/localization/da_DK/messages.inc +++ b/program/localization/da_DK/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Beskeden blev afsendt succesfuldt.'; $messages['savingmessage'] = 'Gemmer besked...'; $messages['messagesaved'] = 'Beskeden er gemt i kladdemappen.'; $messages['successfullysaved'] = 'Gemt succesfuldt'; +$messages['savingresponse'] = 'Gemmer svartekst...'; +$messages['deleteresponseconfirm'] = 'Er du sikker på, at du ønsker at slette svarteksten?'; $messages['addedsuccessfully'] = 'Kontakten blev tilføjet adressebogen.'; $messages['contactexists'] = 'Der er allerede en kontakt med denne e-mailadresse.'; $messages['contactnameexists'] = 'En kontakt med samme navn eksisterer allerede.'; @@ -54,6 +56,8 @@ $messages['contactnotfound'] = 'Den søgte kontakt blev ikke fundet.'; $messages['contactsearchonly'] = 'Indtast søgeord for at finde kontakter.'; $messages['sendingfailed'] = 'Beskeden kunne ikke sendes.'; $messages['senttooquickly'] = 'Vent venligst $sec sekunder før du sender denne besked.'; +$messages['errorsavingsent'] = 'Der opstod en fejl ved at gemme den sendte besked.'; +$messages['errorsaving'] = 'Der opstod en fejl ved at gemme.'; $messages['errormoving'] = 'Beskeden kunne ikke flyttes.'; $messages['errorcopying'] = 'Beskeden kunne ikke kopieres.'; $messages['errordeleting'] = 'Beskeden kunne ikke slettes.'; @@ -140,6 +144,7 @@ $messages['smtperror'] = 'SMTP fejl: $msg'; $messages['emailformaterror'] = 'Ugyldig e-mailadresse: $email'; $messages['toomanyrecipients'] = 'For mange modtagere. Reducer antallet af modtagere til $max.'; $messages['maxgroupmembersreached'] = 'Antallet af gruppemedlemmer overstiger maksimum på $max.'; +$messages['internalerror'] = 'En intern fejl opstod. Prøv venligst igen.'; $messages['contactdelerror'] = 'Kunne ikke slette kontakt(er).'; $messages['contactdeleted'] = 'Kontakt(er) slettet.'; $messages['contactrestoreerror'] = 'Kunne ikke gendanne slettede kontakt(er).'; diff --git a/program/localization/de_CH/labels.inc b/program/localization/de_CH/labels.inc index e5fe1ec66..b416d0b98 100644 --- a/program/localization/de_CH/labels.inc +++ b/program/localization/de_CH/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Rechtschreibung'; $labels['checkspelling'] = 'Rechtschreibung prüfen'; $labels['resumeediting'] = 'Bearbeitung fortsetzen'; $labels['revertto'] = 'Zurück zu'; +$labels['responses'] = 'Antworten'; +$labels['insertresponse'] = 'Antwort einfügen'; +$labels['manageresponses'] = 'Antworten verwalten'; +$labels['savenewresponse'] = 'Neue Antwort speichern'; +$labels['editresponses'] = 'Antworten bearbeiten'; +$labels['editresponse'] = 'Antwort bearbeiten'; +$labels['responsename'] = 'Name'; +$labels['responsetext'] = 'Antworttext'; $labels['attach'] = 'Anhängen'; $labels['attachments'] = 'Anhänge'; $labels['upload'] = 'Hochladen'; diff --git a/program/localization/de_CH/messages.inc b/program/localization/de_CH/messages.inc index 4e5ccaa46..2f3257703 100644 --- a/program/localization/de_CH/messages.inc +++ b/program/localization/de_CH/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Nachricht erfolgreich gesendet'; $messages['savingmessage'] = 'Nachricht wird gespeichert...'; $messages['messagesaved'] = 'Nachricht als Entwurf gespeichert'; $messages['successfullysaved'] = 'Erfolgreich gespeichert'; +$messages['savingresponse'] = 'Antwort wird gespeichert...'; +$messages['deleteresponseconfirm'] = 'Wollen Sie diese Antwort wirklich löschen?'; $messages['addedsuccessfully'] = 'Kontakt zum Adressbuch hinzugefügt'; $messages['contactexists'] = 'Es existiert bereits ein Kontakt mit dieser E-Mail-Adresse.'; $messages['contactnameexists'] = 'Es existiert bereits ein Kontakt mit diesem Namen'; @@ -54,6 +56,8 @@ $messages['contactnotfound'] = 'Die gewählte Adresse wurde nicht gefunden'; $messages['contactsearchonly'] = 'Geben Sie einen Suchbegriff ein, um Kontakte zu finden'; $messages['sendingfailed'] = 'Versand der Nachricht fehlgeschlagen'; $messages['senttooquickly'] = 'Bitte warten Sie $sec Sekunde(n) vor dem Senden dieser Nachricht'; +$messages['errorsavingsent'] = 'Beim Speichern der gesendeten Nachricht ist ein Fehler aufgetreten.'; +$messages['errorsaving'] = 'Beim Speichern ist ein Fehler aufgetreten.'; $messages['errormoving'] = 'Nachricht(en) konnte(n) nicht verschoben werden.'; $messages['errorcopying'] = 'Nachticht(en) konnte(n) nicht kopiert werden.'; $messages['errordeleting'] = 'Nachricht(en) konnte(n) nicht gelöscht werden.'; @@ -140,6 +144,7 @@ $messages['smtperror'] = 'SMTP Fehler: $msg'; $messages['emailformaterror'] = 'Ungültige E-Mail-Adresse: $email'; $messages['toomanyrecipients'] = 'Zuviele Empfänger angegeben. Reduzieren Sie die Empfängeradressen auf $max.'; $messages['maxgroupmembersreached'] = 'Die Anzahl Adressen in dieser Gruppe überschreitet das Maximum von $max.'; +$messages['internalerror'] = 'Ein interner Fehler ist aufgetreten. Bitte versuchen Sie den Vorgang erneut.'; $messages['contactdelerror'] = 'Fehler beim Löschen.'; $messages['contactdeleted'] = 'Kontakt(e) erfolgreich gelöscht.'; $messages['contactrestoreerror'] = 'Die gelöschten Kontakte konnten nicht wiederhergestellt werden.'; diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc index 840c9358c..8f221a3a9 100644 --- a/program/localization/en_US/labels.inc +++ b/program/localization/en_US/labels.inc @@ -232,6 +232,15 @@ $labels['checkspelling'] = 'Check spelling'; $labels['resumeediting'] = 'Resume editing'; $labels['revertto'] = 'Revert to'; +$labels['responses'] = 'Responses'; +$labels['insertresponse'] = 'Insert a response'; +$labels['manageresponses'] = 'Manage responses'; +$labels['savenewresponse'] = 'Save new response'; +$labels['editresponses'] = 'Edit responses'; +$labels['editresponse'] = 'Edit response'; +$labels['responsename'] = 'Name'; +$labels['responsetext'] = 'Response Text'; + $labels['attach'] = 'Attach'; $labels['attachments'] = 'Attachments'; $labels['upload'] = 'Upload'; @@ -484,6 +493,9 @@ $labels['standardwindows'] = 'Handle popups as standard windows'; $labels['forwardmode'] = 'Messages forwarding'; $labels['inline'] = 'inline'; $labels['asattachment'] = 'as attachment'; +$labels['replyallmode'] = 'Default action of [Reply all] button'; +$labels['replyalldefault'] = 'reply to all'; +$labels['replyalllist'] = 'reply to mailing list only (if found)'; $labels['folder'] = 'Folder'; $labels['folders'] = 'Folders'; diff --git a/program/localization/en_US/messages.inc b/program/localization/en_US/messages.inc index 9733109ad..033c820d1 100644 --- a/program/localization/en_US/messages.inc +++ b/program/localization/en_US/messages.inc @@ -46,6 +46,8 @@ $messages['messagesent'] = 'Message sent successfully.'; $messages['savingmessage'] = 'Saving message...'; $messages['messagesaved'] = 'Message saved to Drafts.'; $messages['successfullysaved'] = 'Successfully saved.'; +$messages['savingresponse'] = 'Saving response text...'; +$messages['deleteresponseconfirm'] = 'Do you really want to delete this response text?'; $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.'; diff --git a/program/localization/es_ES/messages.inc b/program/localization/es_ES/messages.inc index 3a8b5ab31..694544cca 100644 --- a/program/localization/es_ES/messages.inc +++ b/program/localization/es_ES/messages.inc @@ -54,6 +54,8 @@ $messages['contactnotfound'] = 'El contacto solicitado no existe.'; $messages['contactsearchonly'] = 'Ingrese algún criterio para buscar contactos'; $messages['sendingfailed'] = 'Error al enviar mensaje.'; $messages['senttooquickly'] = 'Por favor, espere $sec segundo(s) antes de mandar este mensaje.'; +$messages['errorsavingsent'] = 'Ha ocurrido un error al guardar el mensaje enviado.'; +$messages['errorsaving'] = 'Ha ocurrido un error al guardar.'; $messages['errormoving'] = 'No se ha podido mover el/los mensaje(s).'; $messages['errorcopying'] = 'No se ha podido copiar el/los mensaje(s).'; $messages['errordeleting'] = 'No se ha podido eliminar el/los mensaje(s).'; @@ -140,6 +142,7 @@ $messages['smtperror'] = 'Error SMTP: $msg'; $messages['emailformaterror'] = 'Dirección e-mail incorrecta: $email'; $messages['toomanyrecipients'] = 'Hay demasiados destinatarios. Reduzca el número de destinatarios a $max.'; $messages['maxgroupmembersreached'] = 'El número de miembros del grupo excede el máximo de $max.'; +$messages['internalerror'] = 'Ha ocurrido un error interno. Por favor, inténtelo de nuevo.'; $messages['contactdelerror'] = 'No se ha podido eliminar el/los contacto(s).'; $messages['contactdeleted'] = 'Contacto(s) eliminado(s) correctamente.'; $messages['contactrestoreerror'] = 'No se han podido restaurar los contactos borrados.'; diff --git a/program/localization/fa_IR/labels.inc b/program/localization/fa_IR/labels.inc index de23577a0..14f6f8621 100644 --- a/program/localization/fa_IR/labels.inc +++ b/program/localization/fa_IR/labels.inc @@ -18,16 +18,16 @@ $labels['welcome'] = 'به $product خوش آمدید'; $labels['username'] = 'نام کاربری'; $labels['password'] = 'گذرواژه'; -$labels['server'] = 'سرویسدهنده'; +$labels['server'] = 'سرور'; $labels['login'] = 'ورود'; -$labels['logout'] = 'برونرفت'; -$labels['mail'] = 'پست'; +$labels['logout'] = 'خروج'; +$labels['mail'] = 'نامه'; $labels['settings'] = 'تنظیمات'; $labels['addressbook'] = 'دفتر نشانی'; $labels['inbox'] = 'صندوق ورودی'; $labels['drafts'] = 'پیشنویسها'; $labels['sent'] = 'فرستاده شده'; -$labels['trash'] = 'حذف شدهها'; +$labels['trash'] = 'زبالهدان'; $labels['junk'] = 'بنجل'; $labels['show_real_foldernames'] = 'نمایش نام واقعی برای پوشههای ویژه'; $labels['subject'] = 'موضوع'; @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'املاء'; $labels['checkspelling'] = 'بررسی املایی'; $labels['resumeediting'] = 'ادامهی ویرایش'; $labels['revertto'] = 'برگرداندن به'; +$labels['responses'] = 'پاسخها'; +$labels['insertresponse'] = 'درج پاسخ'; +$labels['manageresponses'] = 'مدیریت پاسخها'; +$labels['savenewresponse'] = 'ذخیره پاسخ جدید'; +$labels['editresponses'] = 'ویرایش پاسخها'; +$labels['editresponse'] = 'ویرایش پاسخ'; +$labels['responsename'] = 'نام'; +$labels['responsetext'] = 'متن پاسخ'; $labels['attach'] = 'پیوست کردن'; $labels['attachments'] = 'پیوستها'; $labels['upload'] = 'بارگذاری'; diff --git a/program/localization/fa_IR/messages.inc b/program/localization/fa_IR/messages.inc index 43f5a6c2a..502b0445a 100644 --- a/program/localization/fa_IR/messages.inc +++ b/program/localization/fa_IR/messages.inc @@ -54,6 +54,8 @@ $messages['contactnotfound'] = 'مخاطب درخواست شده پیدا نشد $messages['contactsearchonly'] = 'برای یافتن مخاطب عبارتی را جستجو کنید'; $messages['sendingfailed'] = 'ارسال پیغام ناموفق بود.'; $messages['senttooquickly'] = 'لطفا قبل از ارسال این پیغام $sec ثانیه صبر کنید.'; +$messages['errorsavingsent'] = 'خطایی رخ داده است پیام ارسالی ذخیره می گردد.'; +$messages['errorsaving'] = 'خطایی در ذخیره کردن رخ داده است.'; $messages['errormoving'] = 'پیغام(ها) منتقل نشدند.'; $messages['errorcopying'] = 'پیغام(ها) کپی نشدند.'; $messages['errordeleting'] = 'پیغام(ها) حذف نشدند.'; @@ -140,6 +142,7 @@ $messages['smtperror'] = 'خطای SMTP: $msg'; $messages['emailformaterror'] = 'پست الکترونیکی نامعتبر: $email'; $messages['toomanyrecipients'] = 'گیرندههای بیش از اندازه: تعداد گیرنده ها را به $max کاهش دهید.'; $messages['maxgroupmembersreached'] = 'تعداد اعضای گروه بیشتر از $max است.'; +$messages['internalerror'] = 'یک خطای داخلی رخ داده است. لطفا دوباره سعی کنید.'; $messages['contactdelerror'] = 'حذف مخاطب(ها) انجام شد.'; $messages['contactdeleted'] = 'مخاطب(ها) با موفقیت حذف شدند.'; $messages['contactrestoreerror'] = 'مخاطب(های) حذف شده بازگردانی نخواهند شد.'; diff --git a/program/localization/fi_FI/labels.inc b/program/localization/fi_FI/labels.inc index 8a9064028..1e5e26193 100644 --- a/program/localization/fi_FI/labels.inc +++ b/program/localization/fi_FI/labels.inc @@ -196,6 +196,13 @@ $labels['spellcheck'] = 'Oikeinkirjoitus'; $labels['checkspelling'] = 'Tarkista oikeinkirjoitus'; $labels['resumeediting'] = 'Jatka muokkausta'; $labels['revertto'] = 'Muuta takaisin'; +$labels['responses'] = 'Vastaukset'; +$labels['manageresponses'] = 'Hallitse vastauksia'; +$labels['savenewresponse'] = 'Tallenna uusi vastaus'; +$labels['editresponses'] = 'Muokkaa vastauksia'; +$labels['editresponse'] = 'Muokkaa vastausta'; +$labels['responsename'] = 'Nimi'; +$labels['responsetext'] = 'Vastausteksti'; $labels['attach'] = 'Liitä'; $labels['attachments'] = 'Liitetiedostot'; $labels['upload'] = 'Lisää'; @@ -315,6 +322,7 @@ $labels['import'] = 'Tuo'; $labels['importcontacts'] = 'Tuo yhteystiedot'; $labels['importfromfile'] = 'Tuo tiedostosta:'; $labels['importreplace'] = 'Korvaa koko osoitekirja'; +$labels['importgroupsall'] = 'Kaikki (luo ryhmät tarvittaessa)'; $labels['importdesc'] = 'Voit tuoda yhteystietoja olemassa olevasta osoitekirjasta.<br/>Tuettuja muotoja ovat <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> ja CSV (pilkuin erotetut arvot).'; $labels['done'] = 'Valmis'; $labels['settingsfor'] = 'Asetukset'; diff --git a/program/localization/fi_FI/messages.inc b/program/localization/fi_FI/messages.inc index 1b3c3ea49..a94339af1 100644 --- a/program/localization/fi_FI/messages.inc +++ b/program/localization/fi_FI/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Viesti lähetetty'; $messages['savingmessage'] = 'Tallennetaan viestiä...'; $messages['messagesaved'] = 'Viesti tallennettu "Luonnokset"-kansioon'; $messages['successfullysaved'] = 'Tallennus onnistui'; +$messages['savingresponse'] = 'Tallennetaan vastaustekstiä...'; +$messages['deleteresponseconfirm'] = 'Haluatko varmasti poistaa tämän vastaustekstin?'; $messages['addedsuccessfully'] = 'Yhteystieto lisätty osoitekirjaan'; $messages['contactexists'] = 'Samalla sähköpostiosoitteella on jo olemassa yhteystieto'; $messages['contactnameexists'] = 'Yhteystieto samalla nimellä on jo olemassa'; diff --git a/program/localization/fr_FR/labels.inc b/program/localization/fr_FR/labels.inc index dd0acf4f1..14d1066f9 100644 --- a/program/localization/fr_FR/labels.inc +++ b/program/localization/fr_FR/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Orthographe'; $labels['checkspelling'] = 'Vérifier l\'orthographe'; $labels['resumeediting'] = 'Retourner à l\'édition'; $labels['revertto'] = 'Revenir à'; +$labels['responses'] = 'Réponses'; +$labels['insertresponse'] = 'Insérer une réponse'; +$labels['manageresponses'] = 'Gérer les réponses'; +$labels['savenewresponse'] = 'Sauvegarder une nouvelle réponse'; +$labels['editresponses'] = 'Editer les réponses'; +$labels['editresponse'] = 'Editer la réponse'; +$labels['responsename'] = 'Nom'; +$labels['responsetext'] = 'Texte de la réponse'; $labels['attach'] = 'Joindre'; $labels['attachments'] = 'Fichiers joints'; $labels['upload'] = 'Transférer'; diff --git a/program/localization/hu_HU/labels.inc b/program/localization/hu_HU/labels.inc index 648ac759f..f8d6a1c23 100644 --- a/program/localization/hu_HU/labels.inc +++ b/program/localization/hu_HU/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Helyesírás ellenőrzés'; $labels['checkspelling'] = 'Helyesírás-ellenőrzés'; $labels['resumeediting'] = 'Helyesírás-ellenőrzés vége'; $labels['revertto'] = 'Visszaállítás erre'; +$labels['responses'] = 'Válaszok'; +$labels['insertresponse'] = 'Egy válasz beillesztése'; +$labels['manageresponses'] = 'Válaszok kezelése'; +$labels['savenewresponse'] = 'Új válasz mentése'; +$labels['editresponses'] = 'Válaszok szerkesztése'; +$labels['editresponse'] = 'Válasz szerkesztése'; +$labels['responsename'] = 'Név'; +$labels['responsetext'] = 'Válasz Szöveg'; $labels['attach'] = 'Csatolás'; $labels['attachments'] = 'Csatolmányok'; $labels['upload'] = 'Feltöltés'; diff --git a/program/localization/hu_HU/messages.inc b/program/localization/hu_HU/messages.inc index 3ca87a52f..79de6ed2b 100644 --- a/program/localization/hu_HU/messages.inc +++ b/program/localization/hu_HU/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Az üzenet elküldve'; $messages['savingmessage'] = 'Az üzenet mentése...'; $messages['messagesaved'] = 'Az üzenet elmentve a Piszkozatokhoz'; $messages['successfullysaved'] = 'A mentés sikerült'; +$messages['savingresponse'] = 'A válasz szövegének mentése...'; +$messages['deleteresponseconfirm'] = 'Biztosan törli ezt a válasz szöveget?'; $messages['addedsuccessfully'] = 'A kapcsolat hozzáadása a címjegyzékhez megtörtént'; $messages['contactexists'] = 'Ezzel az e-mail címmel már létezik kapcsolat'; $messages['contactnameexists'] = 'Ezzel a névvel már létezik kapcsolat'; @@ -54,6 +56,8 @@ $messages['contactnotfound'] = 'A kiválasztott kapcsolat nem található'; $messages['contactsearchonly'] = 'Adjon meg keresőkifejezéseket a kapcsolatok közti kereséshez'; $messages['sendingfailed'] = 'Az üzenet elküldése nem sikerült'; $messages['senttooquickly'] = 'Kérem várjon még $sec másodpercet az üzenet elküldése előtt'; +$messages['errorsavingsent'] = 'Hiba történt az elküldött üzenet mentése közben'; +$messages['errorsaving'] = 'A mentés során hiba lépett fel'; $messages['errormoving'] = 'Az üzenet(ek)et nem sikerült áthelyezni'; $messages['errorcopying'] = 'Az üzenet(ek)et nem sikerült másolni'; $messages['errordeleting'] = 'Az üzenet(ek)et nem sikerült törölni'; @@ -140,6 +144,7 @@ $messages['smtperror'] = 'SMTP hiba ($code): $msg'; $messages['emailformaterror'] = 'Helytelen formátumú e-mail cím: $email'; $messages['toomanyrecipients'] = 'Túl sok a címzett. Csökkentse a címzettek számát maximum $max címre!'; $messages['maxgroupmembersreached'] = 'A csoport létszáma meghaladja a maximum $max főt'; +$messages['internalerror'] = 'Belső hiba történt. Kérjük próbálja újra!'; $messages['contactdelerror'] = 'Hiba a kapcsolat(ok) törlésekor'; $messages['contactdeleted'] = 'Kapcsolat(ok) sikeresen törölve'; $messages['contactrestoreerror'] = 'Nem sikerült a törölt kapcsolat(ok) helyreállítása'; diff --git a/program/localization/it_IT/messages.inc b/program/localization/it_IT/messages.inc index c5a81044e..0fd084f1b 100644 --- a/program/localization/it_IT/messages.inc +++ b/program/localization/it_IT/messages.inc @@ -54,6 +54,8 @@ $messages['contactnotfound'] = 'Il contatto richiesto non è stato trovato'; $messages['contactsearchonly'] = 'Inserisci dei termini per cercare i contatti'; $messages['sendingfailed'] = 'Impossibile inviare il messaggio'; $messages['senttooquickly'] = 'Per favore, attendi $sec secondi prima di inviare questo messaggio'; +$messages['errorsavingsent'] = 'Si è verificato un errore nel savare il messaggio inviato.'; +$messages['errorsaving'] = 'Si è verificato un errore nel salvataggio.'; $messages['errormoving'] = 'Impossibile spostare il messaggio'; $messages['errorcopying'] = 'Impossibile copiare il messaggio'; $messages['errordeleting'] = 'Impossibile eliminare il messaggio'; @@ -140,6 +142,7 @@ $messages['smtperror'] = 'Errore SMTP: $msg'; $messages['emailformaterror'] = 'Indirizzo e-mail non corretto: $email'; $messages['toomanyrecipients'] = 'Numero eccessivo di destinatari, ridurlo a $max'; $messages['maxgroupmembersreached'] = 'Il numero dei membri del gruppo eccede il massimo di $max'; +$messages['internalerror'] = 'Si è verificato un errore interno. Riprovare più tardi.'; $messages['contactdelerror'] = 'Impossibile eliminare il/i contatto/i'; $messages['contactdeleted'] = 'Contatto/i correttamente eliminato/i'; $messages['contactrestoreerror'] = 'Impossibile ripristinare il/i contatto/i cancellato/i'; diff --git a/program/localization/ja_JP/labels.inc b/program/localization/ja_JP/labels.inc index aadc8fce0..ef52695bb 100644 --- a/program/localization/ja_JP/labels.inc +++ b/program/localization/ja_JP/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'スペル'; $labels['checkspelling'] = 'スペルチェック'; $labels['resumeediting'] = '編集を再開'; $labels['revertto'] = '元に戻す'; +$labels['responses'] = '回答'; +$labels['insertresponse'] = '回答を挿入'; +$labels['manageresponses'] = '回答を管理'; +$labels['savenewresponse'] = '新しい回答を保存'; +$labels['editresponses'] = '回答を編集'; +$labels['editresponse'] = '回答を編集'; +$labels['responsename'] = '名前'; +$labels['responsetext'] = '回答の文章'; $labels['attach'] = '添付'; $labels['attachments'] = '添付ファイル'; $labels['upload'] = 'アップロード'; diff --git a/program/localization/ja_JP/messages.inc b/program/localization/ja_JP/messages.inc index fb03bc0f8..abe5a6e7a 100644 --- a/program/localization/ja_JP/messages.inc +++ b/program/localization/ja_JP/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'メッセージを送信しました。'; $messages['savingmessage'] = 'メッセージを保存中...'; $messages['messagesaved'] = 'メッセージを下書きに保存しました。'; $messages['successfullysaved'] = '保存しました。'; +$messages['savingresponse'] = '回答の文章を保存中...'; +$messages['deleteresponseconfirm'] = 'この回答の文章を本当に削除しますか?'; $messages['addedsuccessfully'] = '連絡先をアドレス帳に追加しました。'; $messages['contactexists'] = '同じメールアドレスの連絡先が既に存在します。'; $messages['contactnameexists'] = '同じ名前の連絡先が既に存在します。'; diff --git a/program/localization/lb_LU/labels.inc b/program/localization/lb_LU/labels.inc index d32a263a1..cbd5a12a8 100644 --- a/program/localization/lb_LU/labels.inc +++ b/program/localization/lb_LU/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Orthographie'; $labels['checkspelling'] = 'Orthographie kontrolléieren'; $labels['resumeediting'] = 'Weider editéieren'; $labels['revertto'] = 'Zréck bei'; +$labels['responses'] = 'Äntwerten'; +$labels['insertresponse'] = 'Äntwert afügen'; +$labels['manageresponses'] = 'Äntwerte geréieren'; +$labels['savenewresponse'] = 'Nei Äntwert späicheren'; +$labels['editresponses'] = 'Äntwerten Editéieren'; +$labels['editresponse'] = 'Äntwert editéieren'; +$labels['responsename'] = 'Numm'; +$labels['responsetext'] = 'Äntwert-Text'; $labels['attach'] = 'Drunhänken'; $labels['attachments'] = 'Unhäng'; $labels['upload'] = 'Eroplueden'; @@ -316,7 +324,11 @@ $labels['searchdelete'] = 'Sich läschen'; $labels['import'] = 'Importéieren'; $labels['importcontacts'] = 'Kontakter importéieren'; $labels['importfromfile'] = 'Aus Fichier importéieren:'; +$labels['importtarget'] = 'Kontakter dobäisetze bei'; $labels['importreplace'] = 'Dat ganzt Adressbuch ersetzen'; +$labels['importgroups'] = 'Gruppen-Zouweisung importéieren'; +$labels['importgroupsall'] = 'All (nei Gruppen uleeën falls néideg)'; +$labels['importgroupsexisting'] = 'Just fir Gruppen déi schon existéieren'; $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'; $labels['settingsfor'] = 'Astellunge fir'; diff --git a/program/localization/lb_LU/messages.inc b/program/localization/lb_LU/messages.inc index 8ef0b2f6c..fc053b59e 100644 --- a/program/localization/lb_LU/messages.inc +++ b/program/localization/lb_LU/messages.inc @@ -44,6 +44,8 @@ $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['savingresponse'] = 'Äntwert-Text gëtt gespäichert...'; +$messages['deleteresponseconfirm'] = 'Wëlls du dësen Äntwert-Text wierklech läschen?'; $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.'; @@ -54,6 +56,8 @@ $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 geschéckte Message ass e Feeler opgetruden.'; +$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.'; @@ -140,6 +144,7 @@ $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.'; diff --git a/program/localization/lv_LV/labels.inc b/program/localization/lv_LV/labels.inc index 95afc4c49..0f80350bb 100644 --- a/program/localization/lv_LV/labels.inc +++ b/program/localization/lv_LV/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Izrunāt'; $labels['checkspelling'] = 'Pārbaudīt pareizrakstību'; $labels['resumeediting'] = 'Turpināt rediģēšanu'; $labels['revertto'] = 'Atgriezt uz'; +$labels['responses'] = 'Atbildes'; +$labels['insertresponse'] = 'Ievietot atbildi'; +$labels['manageresponses'] = 'Pārvaldīt atbildes'; +$labels['savenewresponse'] = 'Saglabāt jauno atbildi'; +$labels['editresponses'] = 'Rediģēt atbildes'; +$labels['editresponse'] = 'Rediģēt atbildi'; +$labels['responsename'] = 'Vārds'; +$labels['responsetext'] = 'Atbildes teksts'; $labels['attach'] = 'Pievienot'; $labels['attachments'] = 'Pielikumi'; $labels['upload'] = 'Augšupielādēt'; @@ -318,6 +326,7 @@ $labels['importcontacts'] = 'Importēt kontaktus'; $labels['importfromfile'] = 'Importēt no faila:'; $labels['importtarget'] = 'Kontaktus pievienot'; $labels['importreplace'] = 'Aizvietot visu adrešu grāmatu'; +$labels['importgroups'] = 'Importēt grupu piesaistes'; $labels['importgroupsall'] = 'Visus (ja nepieciešams, izveidojiet grupas)'; $labels['importgroupsexisting'] = 'Tikai esošām grupām'; $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.'; diff --git a/program/localization/lv_LV/messages.inc b/program/localization/lv_LV/messages.inc index f27b01b84..55cff4134 100644 --- a/program/localization/lv_LV/messages.inc +++ b/program/localization/lv_LV/messages.inc @@ -44,6 +44,8 @@ $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'] = 'Veiksmīgi saglabāts.'; +$messages['savingresponse'] = 'Tiek saglabāts atbildes teksts ...'; +$messages['deleteresponseconfirm'] = 'Vai Jūs tiešām gribat dzēst šo atbildes tekstu?'; $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ē.'; @@ -54,6 +56,8 @@ $messages['contactnotfound'] = 'Pieprasītais kontakts nav atrasts'; $messages['contactsearchonly'] = 'Lai atrastu kontaktus, ievadiet meklēšanas kritērijus'; $messages['sendingfailed'] = 'Vēstule netika nosūtīta'; $messages['senttooquickly'] = 'Lūdzu uzgaidiet $sec sekundi(-es) pirms sūtiet šo vēstuli'; +$messages['errorsavingsent'] = 'Saglabājot nosūtīto vēstuli notika kļūda - vēstule netika saglabāta'; +$messages['errorsaving'] = 'Saglabājot vēstuli notika kļūda - vēstule netika saglabāta'; $messages['errormoving'] = 'Vēstule(s) netika pārvietota(s)'; $messages['errorcopying'] = 'Vēstules pārkopēt neizdevās'; $messages['errordeleting'] = 'Vēstules izdzēst neizdevās'; @@ -140,6 +144,7 @@ $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'] = 'Atgadījās 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.'; diff --git a/program/localization/nl_NL/labels.inc b/program/localization/nl_NL/labels.inc index f0e4a74b4..b5f273659 100644 --- a/program/localization/nl_NL/labels.inc +++ b/program/localization/nl_NL/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Spelling'; $labels['checkspelling'] = 'Controleer spelling'; $labels['resumeediting'] = 'Doorgaan met opstellen'; $labels['revertto'] = 'Terugwijzigen in'; +$labels['responses'] = 'Reacties'; +$labels['insertresponse'] = 'Reactie invoegen'; +$labels['manageresponses'] = 'Reacties beheren'; +$labels['savenewresponse'] = 'Nieuwe reactie opslaan'; +$labels['editresponses'] = 'Bewerk reactie'; +$labels['editresponse'] = 'Bewerk reactie'; +$labels['responsename'] = 'Naam'; +$labels['responsetext'] = 'Reactie'; $labels['attach'] = 'Bijvoegen'; $labels['attachments'] = 'Bijlagen'; $labels['upload'] = 'Toevoegen'; diff --git a/program/localization/nl_NL/messages.inc b/program/localization/nl_NL/messages.inc index 22f9e0f6b..f6081bd8e 100644 --- a/program/localization/nl_NL/messages.inc +++ b/program/localization/nl_NL/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Bericht succesvol verstuurd.'; $messages['savingmessage'] = 'Bericht wordt opgeslagen...'; $messages['messagesaved'] = 'Bericht opgeslagen in Concepten.'; $messages['successfullysaved'] = 'Succesvol opgeslagen.'; +$messages['savingresponse'] = 'Reactie wordt opgeslagen...'; +$messages['deleteresponseconfirm'] = 'Weet u zeker dat u deze reactie wilt verwijderen?'; $messages['addedsuccessfully'] = 'Contactpersoon succesvol toegevoegd aan het adresboek.'; $messages['contactexists'] = 'Er bestaat al een contactpersoon met dit e-mailadres.'; $messages['contactnameexists'] = 'Er bestaat al een contactpersoon met deze naam.'; diff --git a/program/localization/pt_BR/labels.inc b/program/localization/pt_BR/labels.inc index 13db63e99..e42b1ce95 100644 --- a/program/localization/pt_BR/labels.inc +++ b/program/localization/pt_BR/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Revisar'; $labels['checkspelling'] = 'Verificar ortografia'; $labels['resumeediting'] = 'Continuar a edição'; $labels['revertto'] = 'Reverter para'; +$labels['responses'] = 'Respostas'; +$labels['insertresponse'] = 'Inserir uma resposta'; +$labels['manageresponses'] = 'Gerenciar respostas'; +$labels['savenewresponse'] = 'Salvar nova resposta'; +$labels['editresponses'] = 'Editar respostas'; +$labels['editresponse'] = 'Editar resposta'; +$labels['responsename'] = 'Nome'; +$labels['responsetext'] = 'Texto da resposta'; $labels['attach'] = 'Anexar'; $labels['attachments'] = 'Anexos'; $labels['upload'] = 'Enviar arquivo'; diff --git a/program/localization/pt_BR/messages.inc b/program/localization/pt_BR/messages.inc index 2f5782373..823dad22e 100644 --- a/program/localization/pt_BR/messages.inc +++ b/program/localization/pt_BR/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Mensagem enviada com sucesso'; $messages['savingmessage'] = 'Salvando Mensagem...'; $messages['messagesaved'] = 'Mensagem salva em Rascunhos'; $messages['successfullysaved'] = 'Salvo com sucesso'; +$messages['savingresponse'] = 'Salvando texto de resposta...'; +$messages['deleteresponseconfirm'] = 'Você realmente deseja apagar este texto de resposta?'; $messages['addedsuccessfully'] = 'Contato incluído com sucesso no catálogo de endereços.'; $messages['contactexists'] = 'Já existe um contato com esse mesmo e-mail.'; $messages['contactnameexists'] = 'Já existe um contato com o mesmo nome.'; @@ -54,6 +56,8 @@ $messages['contactnotfound'] = 'O contato solicitado não foi encontrado.'; $messages['contactsearchonly'] = 'Informe os termos de pesquisa para localizar os contatos'; $messages['sendingfailed'] = 'Falha no envio da mensagem.'; $messages['senttooquickly'] = 'Aguarde $sec s para enviar a mensagem.'; +$messages['errorsavingsent'] = 'Ocorreu um erro ao salvar a mensagem enviada.'; +$messages['errorsaving'] = 'Ocorreu um erro ao salvar.'; $messages['errormoving'] = 'Não foi possível mover a(s) mensagem(ns).'; $messages['errorcopying'] = 'Não foi possível copiar a(s) mensagem(ns).'; $messages['errordeleting'] = 'Não foi possível apagar a(s) mensagem(ns).'; @@ -140,6 +144,7 @@ $messages['smtperror'] = 'Erro SMTP: $msg'; $messages['emailformaterror'] = 'Endereço de e-mail inválido: $email'; $messages['toomanyrecipients'] = 'Há muitos destinatários. Reduza o número de destinatários para $max.'; $messages['maxgroupmembersreached'] = 'O número de membros do grupo excede o máximo de $max'; +$messages['internalerror'] = 'Ocorreu um erro interno. Por favor tente novamente.'; $messages['contactdelerror'] = 'Não foi possível excluir o(s) contato(s).'; $messages['contactdeleted'] = 'Contato(s) excluído(s) com sucesso.'; $messages['contactrestoreerror'] = 'Não foi possivel recuperar o(s) contato(s) excluído(s).'; diff --git a/program/localization/pt_PT/labels.inc b/program/localization/pt_PT/labels.inc index b12830031..b6db8a41e 100644 --- a/program/localization/pt_PT/labels.inc +++ b/program/localization/pt_PT/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Corrector Ortográfico'; $labels['checkspelling'] = 'Verificar ortografia'; $labels['resumeediting'] = 'Continuar a edição'; $labels['revertto'] = 'Reverter para'; +$labels['responses'] = 'Respostas'; +$labels['insertresponse'] = 'Insira uma resposta'; +$labels['manageresponses'] = 'Gerir respostas'; +$labels['savenewresponse'] = 'Gravar nova resposta'; +$labels['editresponses'] = 'Editar respostas'; +$labels['editresponse'] = 'Editar resposta'; +$labels['responsename'] = 'Nome'; +$labels['responsetext'] = 'Texto da resposta'; $labels['attach'] = 'Anexar'; $labels['attachments'] = 'Anexos'; $labels['upload'] = 'Carregar'; diff --git a/program/localization/pt_PT/messages.inc b/program/localization/pt_PT/messages.inc index 06e78198d..fed7fa09e 100644 --- a/program/localization/pt_PT/messages.inc +++ b/program/localization/pt_PT/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Mensagem enviada com sucesso'; $messages['savingmessage'] = 'A guardar mensagem...'; $messages['messagesaved'] = 'Mensagem guardada como rascunho'; $messages['successfullysaved'] = 'Guardado com sucesso'; +$messages['savingresponse'] = 'A guardar texto de resposta...'; +$messages['deleteresponseconfirm'] = 'Deseja realmente apagar este texto de resposta?'; $messages['addedsuccessfully'] = 'Contacto adicionado com sucesso'; $messages['contactexists'] = 'Já existe um contacto com este e-mail'; $messages['contactnameexists'] = 'Já existe um contacto com este nome.'; diff --git a/program/localization/ru_RU/messages.inc b/program/localization/ru_RU/messages.inc index d8da5ee5c..2509ba49b 100644 --- a/program/localization/ru_RU/messages.inc +++ b/program/localization/ru_RU/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Сообщение отправлено.'; $messages['savingmessage'] = 'Сохранение сообщения...'; $messages['messagesaved'] = 'Сохранено в Черновиках.'; $messages['successfullysaved'] = 'Сохранено.'; +$messages['savingresponse'] = 'Сохранение текста ответа...'; +$messages['deleteresponseconfirm'] = 'Вы действительно хотите удалить этот текст ответа?'; $messages['addedsuccessfully'] = 'Контакт добавлен в адресную книгу.'; $messages['contactexists'] = 'Контакт с этим адресом e-mail уже существует.'; $messages['contactnameexists'] = 'Контакт с таким именем уже существует.'; diff --git a/program/localization/sk_SK/labels.inc b/program/localization/sk_SK/labels.inc index 36d9850a0..93bca166f 100644 --- a/program/localization/sk_SK/labels.inc +++ b/program/localization/sk_SK/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Pravopis'; $labels['checkspelling'] = 'Skontrolovať pravopis'; $labels['resumeediting'] = 'Pokračovať v úpravách'; $labels['revertto'] = 'Vrátiť sa na'; +$labels['responses'] = 'Odpovede'; +$labels['insertresponse'] = 'Vložiť odpoveď'; +$labels['manageresponses'] = 'Spravovať odpovede'; +$labels['savenewresponse'] = 'Uložiť novú odpoveď'; +$labels['editresponses'] = 'Upraviť odpovede'; +$labels['editresponse'] = 'Upraviť odpoveď'; +$labels['responsename'] = 'Meno'; +$labels['responsetext'] = 'Text odpovede'; $labels['attach'] = 'Priložiť'; $labels['attachments'] = 'Prílohy'; $labels['upload'] = 'Nahrať'; diff --git a/program/localization/sk_SK/messages.inc b/program/localization/sk_SK/messages.inc index db830c2a7..71d5d52c1 100644 --- a/program/localization/sk_SK/messages.inc +++ b/program/localization/sk_SK/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Správa bola úspešne odoslaná'; $messages['savingmessage'] = 'Správa sa ukladá...'; $messages['messagesaved'] = 'Správa bola uložená medzi Rozpísané správy'; $messages['successfullysaved'] = 'Úspešne uložená'; +$messages['savingresponse'] = 'Ukladanie textu odpovede...'; +$messages['deleteresponseconfirm'] = 'Naozaj chcete vymazať text odpovede?'; $messages['addedsuccessfully'] = 'Kontakt bol pridaný do adresára'; $messages['contactexists'] = 'Kontakt s touto e-mailovou adresou už existuje'; $messages['contactnameexists'] = 'Kontakt s rovnakým menom už existuje.'; @@ -54,6 +56,8 @@ $messages['contactnotfound'] = 'Požadovaný kontakt nebol nájdený'; $messages['contactsearchonly'] = 'Zadaj nejaký vyhľadávací výraz pre hľadanie kontaktov.'; $messages['sendingfailed'] = 'Odosielanie správy zlyhalo'; $messages['senttooquickly'] = 'Počkajte $sec sekúnd pred odoslaním tejto správy'; +$messages['errorsavingsent'] = 'Počas ukladania odoslanej správy nastala chyba.'; +$messages['errorsaving'] = 'Počas ukladania nastala chyba.'; $messages['errormoving'] = 'Správa sa nedá presunúť'; $messages['errorcopying'] = 'Správa sa nedá skopírovať'; $messages['errordeleting'] = 'Správa sa nedá zmazať'; @@ -140,6 +144,7 @@ $messages['smtperror'] = 'Chyba SMTP: $msg'; $messages['emailformaterror'] = 'Neplatná e-mailová adresa: $email'; $messages['toomanyrecipients'] = 'Príliš veľa príjemcov. Zmenšite počet príjemcov na $max.'; $messages['maxgroupmembersreached'] = 'Počet členov skupiny dosiahol maxima z $max'; +$messages['internalerror'] = 'Došlo k internej chybe systému. Prosím skúste to ešte raz.'; $messages['contactdelerror'] = 'Nemôžem vymazať kontakt(y)'; $messages['contactdeleted'] = 'Kontakt(y) bol vymazaný'; $messages['contactrestoreerror'] = 'Nemôžem obnoviť zmazané kontakty'; diff --git a/program/localization/sl_SI/labels.inc b/program/localization/sl_SI/labels.inc index f93684d69..f1e9010d4 100644 --- a/program/localization/sl_SI/labels.inc +++ b/program/localization/sl_SI/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Črkovanje'; $labels['checkspelling'] = 'Preglej pravopis'; $labels['resumeediting'] = 'Nadaljuj z urejanjem'; $labels['revertto'] = 'Razveljavi'; +$labels['responses'] = 'Odgovori'; +$labels['insertresponse'] = 'Vnesi odgovor'; +$labels['manageresponses'] = 'Uredi odgovore'; +$labels['savenewresponse'] = 'Shrani nove odgovore'; +$labels['editresponses'] = 'Uredi odgovore'; +$labels['editresponse'] = 'Uredi odgovor'; +$labels['responsename'] = 'Ime'; +$labels['responsetext'] = 'Tekst za odgovor'; $labels['attach'] = 'Pripni'; $labels['attachments'] = 'Priponke'; $labels['upload'] = 'Naloži'; @@ -316,7 +324,11 @@ $labels['searchdelete'] = 'Izbriši iskanje'; $labels['import'] = 'Uvozi'; $labels['importcontacts'] = 'Uvozi stike'; $labels['importfromfile'] = 'Uvozi iz datoteke:'; +$labels['importtarget'] = 'Dodaj stike v'; $labels['importreplace'] = 'Zamenjaj celoten imenik'; +$labels['importgroups'] = 'Vnesi skupinske zadolžitve'; +$labels['importgroupsall'] = 'Vse (ustvari skupine, če je potrebno)'; +$labels['importgroupsexisting'] = 'Samo za obstoječe skupine'; $labels['importdesc'] = 'Stike lahko naložite iz obstoječega imenika. <br/>Trenutno je podprt uvoz stikov v zapisu <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> ali v CSV (z vejico ločene vrednosti) zapisu.'; $labels['done'] = 'Dokončano'; $labels['settingsfor'] = 'Nastavitve za'; diff --git a/program/localization/sl_SI/messages.inc b/program/localization/sl_SI/messages.inc index f1beffc0f..3d1ea677c 100644 --- a/program/localization/sl_SI/messages.inc +++ b/program/localization/sl_SI/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Sporočilo je bilo uspešno poslano.'; $messages['savingmessage'] = 'Shranjevanje sporočila...'; $messages['messagesaved'] = 'Sporočilo je bilo shranjeno v Osnutke'; $messages['successfullysaved'] = 'Uspešno shranjeno.'; +$messages['savingresponse'] = 'Shranjevanje odgovora...'; +$messages['deleteresponseconfirm'] = 'Ste prepričani, da želite izbrisati ta odgovor?'; $messages['addedsuccessfully'] = 'Stik je bil uspešno dodan v imenik.'; $messages['contactexists'] = 'Stik s tem elektronskim naslovom že obstaja.'; $messages['contactnameexists'] = 'Stik s tem imenom že obstaja'; @@ -54,6 +56,8 @@ $messages['contactnotfound'] = 'Iskanega stika ni bilo mogoče najti.'; $messages['contactsearchonly'] = 'Vpišite iskalni parameter za iskanje stika'; $messages['sendingfailed'] = 'Sporočila ni bilo mogoče poslati.'; $messages['senttooquickly'] = 'Počakajte $sec sekund in nato znova poskusite s pošiljanjem sporočila.'; +$messages['errorsavingsent'] = 'Pri shranjevanju poslanega sporočila je prišlo do napake.'; +$messages['errorsaving'] = 'Pri shranjevanju je prišlo do napake.'; $messages['errormoving'] = 'Sporočila ni bilo mogoče premakniti.'; $messages['errorcopying'] = 'Sporočila ni bilo mogoče kopirati.'; $messages['errordeleting'] = 'Sporočila ni bilo mogoče izbrisati.'; @@ -140,6 +144,7 @@ $messages['smtperror'] = 'Napaka pri pošiljanju:$msg'; $messages['emailformaterror'] = 'Nepravilen elektronski naslov: $email'; $messages['toomanyrecipients'] = 'Navedli ste preveč prejemnikov. Zmanjšajte število prejemnikov na $max'; $messages['maxgroupmembersreached'] = 'Število članov skupine presega največje dovoljeno število $max.'; +$messages['internalerror'] = 'Prišlo je do napake. Poskusite znova.'; $messages['contactdelerror'] = 'Stika/ov ni bilo mogoče izbrisati'; $messages['contactdeleted'] = 'Stik/i so bili uspešno izbrisani'; $messages['contactrestoreerror'] = 'Ni bilo mogoče obnoviti izbrisanih stikov.'; diff --git a/program/localization/sv_SE/labels.inc b/program/localization/sv_SE/labels.inc index 48f71ab57..8116afeff 100644 --- a/program/localization/sv_SE/labels.inc +++ b/program/localization/sv_SE/labels.inc @@ -197,6 +197,14 @@ $labels['spellcheck'] = 'Rättstava'; $labels['checkspelling'] = 'Kontrollera stavning'; $labels['resumeediting'] = 'Återuppta redigering'; $labels['revertto'] = 'Återgå till'; +$labels['responses'] = 'Responser'; +$labels['insertresponse'] = 'Infoga respons'; +$labels['manageresponses'] = 'Hantera responser'; +$labels['savenewresponse'] = 'Spara ny respons'; +$labels['editresponses'] = 'Ändra responser'; +$labels['editresponse'] = 'Ändra respons'; +$labels['responsename'] = 'Namn'; +$labels['responsetext'] = 'Responstext'; $labels['attach'] = 'Bifoga'; $labels['attachments'] = 'Bilagor'; $labels['upload'] = 'Bifoga'; diff --git a/program/localization/sv_SE/messages.inc b/program/localization/sv_SE/messages.inc index 2773ae4c7..16bbd5a23 100644 --- a/program/localization/sv_SE/messages.inc +++ b/program/localization/sv_SE/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Meddelandet har skickats.'; $messages['savingmessage'] = 'Sparar meddelande...'; $messages['messagesaved'] = 'Meddelandet har sparats i Utkast'; $messages['successfullysaved'] = 'Informationen har sparats.'; +$messages['savingresponse'] = 'Sparar responstext...'; +$messages['deleteresponseconfirm'] = 'Vill du verkligen ta bort denna responstext?'; $messages['addedsuccessfully'] = 'Kontakten har lagts till i adressboken.'; $messages['contactexists'] = 'En kontakt med den här adressen finns redan'; $messages['contactnameexists'] = 'En kontakt med det här namnet finns redan'; @@ -54,6 +56,8 @@ $messages['contactnotfound'] = 'Efterfrågad kontakt hittades inte'; $messages['contactsearchonly'] = 'Ange sökord för att hitta kontakter'; $messages['sendingfailed'] = 'Meddelandet kunde inte skickas'; $messages['senttooquickly'] = 'Vänta ytterligare $sec sekunder med att skicka meddelandet'; +$messages['errorsavingsent'] = 'Ett fel inträffade när det skickade meddelandet skulle sparas'; +$messages['errorsaving'] = 'Meddelandet kunde inte sparas'; $messages['errormoving'] = 'Meddelandet kunde inte flyttas'; $messages['errorcopying'] = 'Meddelandet kunde inte kopieras'; $messages['errordeleting'] = 'Meddelandet kunde inte tas bort'; @@ -140,6 +144,7 @@ $messages['smtperror'] = 'SMTP-fel: $msg'; $messages['emailformaterror'] = 'Felaktig adress: $email'; $messages['toomanyrecipients'] = 'Förmånga mottagare. Minska antalet till högst $max'; $messages['maxgroupmembersreached'] = 'Antalet gruppmedlemmar får inte överstiga $max'; +$messages['internalerror'] = 'Ett internt fel uppstod. Försök igen.'; $messages['contactdelerror'] = 'Kontakt kunde inte tas bort'; $messages['contactdeleted'] = 'Kontakt borttagen.'; $messages['contactrestoreerror'] = 'Borttagna kontakter kunde inte återskapas'; diff --git a/program/localization/tr_TR/messages.inc b/program/localization/tr_TR/messages.inc index 0b2ac1e46..182fc966b 100644 --- a/program/localization/tr_TR/messages.inc +++ b/program/localization/tr_TR/messages.inc @@ -44,6 +44,8 @@ $messages['messagesent'] = 'Posta gönderildi'; $messages['savingmessage'] = 'Posta kaydediliyor...'; $messages['messagesaved'] = 'Posta taslaklara kaydedildi'; $messages['successfullysaved'] = 'Kaydedildi'; +$messages['savingresponse'] = 'Yanıt metni kaydediliyor...'; +$messages['deleteresponseconfirm'] = 'Yanıt metnini gerçekten silmek istiyor musunuz?'; $messages['addedsuccessfully'] = 'Kişi adres defterine eklendi'; $messages['contactexists'] = 'Rehberde bu e-posta adresine sahip biri zaten var'; $messages['contactnameexists'] = 'Rehberde bu ada sahip biri zaten var.'; @@ -54,6 +56,8 @@ $messages['contactnotfound'] = 'İstenen kişi bulunamadı'; $messages['contactsearchonly'] = 'Kişi aramak için arama terimleri giriniz'; $messages['sendingfailed'] = 'Posta gönderilemedi'; $messages['senttooquickly'] = 'Lütfen bu postayı göndermeden önce $sec saniye bekleyin'; +$messages['errorsavingsent'] = 'Gönderilen postayı kaydederken hata oluştu.'; +$messages['errorsaving'] = 'Kaydederken bir hata oluştu.'; $messages['errormoving'] = 'Posta taşınamadı'; $messages['errorcopying'] = 'Posta kopyalanamadı'; $messages['errordeleting'] = 'Posta silinemedi'; @@ -140,6 +144,7 @@ $messages['smtperror'] = 'SMTP Hatası: $msg'; $messages['emailformaterror'] = 'Hatalı e-posta adresi: $email'; $messages['toomanyrecipients'] = 'Çok fazla alıcı. En fazla $max alıcı girebilirsiniz.'; $messages['maxgroupmembersreached'] = 'Grup üyelerinin sayısı $max sınırını aşıyor.'; +$messages['internalerror'] = 'Dahili bir hata oluştu. Lütfen tekrar deneyin.'; $messages['contactdelerror'] = 'Kişi(ler) silinemedi'; $messages['contactdeleted'] = 'Kişi(ler) silindi'; $messages['contactrestoreerror'] = 'Silinen kişi(ler) geri getirilemiyor.'; diff --git a/program/localization/uk_UA/messages.inc b/program/localization/uk_UA/messages.inc index 669190c2e..620e1520b 100644 --- a/program/localization/uk_UA/messages.inc +++ b/program/localization/uk_UA/messages.inc @@ -53,6 +53,7 @@ $messages['contactnotfound'] = 'Запитаний контакт не знай $messages['contactsearchonly'] = 'Введіть деякі критерії пошуку, щоб знайти контакти'; $messages['sendingfailed'] = 'Не вдалося відправити листа'; $messages['senttooquickly'] = 'Будь ласка, зачекайте $sec секунд для відправки листа'; +$messages['errorsavingsent'] = 'Помилка при збереженні відправленого повідомлення.'; $messages['errormoving'] = 'Не вдалося перемістити листи'; $messages['errorcopying'] = 'Не вдалося зкопіювати листи'; $messages['errordeleting'] = 'Не вдалося видалити листи'; @@ -96,6 +97,7 @@ $messages['converting'] = 'Видалення форматування...'; $messages['messageopenerror'] = 'Не вдалося завантажити повідомлення з сервера'; $messages['fileuploaderror'] = 'Не вдалося вкласти файл'; $messages['filesizeerror'] = 'Розмір вибраного файлу перевищує максимально дозволений ($size)'; +$messages['copyerror'] = 'Не вдалося скопіювати жодного контакту.'; $messages['sourceisreadonly'] = 'Дане джерело адрес доступне лише для читання'; $messages['errorsavingcontact'] = 'Неможливо зберегти адресу контакту'; $messages['movingmessage'] = 'Переміщення листа...'; diff --git a/program/steps/addressbook/save.inc b/program/steps/addressbook/save.inc index 2adc53bcf..7911802b9 100644 --- a/program/steps/addressbook/save.inc +++ b/program/steps/addressbook/save.inc @@ -80,8 +80,8 @@ foreach ($GLOBALS['CONTACT_COLTYPES'] as $col => $colprop) { // normalize the submitted date strings if ($colprop['type'] == 'date') { - if ($timestamp = rcube_utils::strtotime($a_record[$col])) { - $a_record[$col] = date('Y-m-d', $timestamp); + if ($a_record[$col] && ($dt = rcube_utils::anytodatetime($a_record[$col]))) { + $a_record[$col] = $dt->format('Y-m-d'); } else { unset($a_record[$col]); diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index dc2452506..646d2bcd1 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -109,7 +109,8 @@ if (!is_array($COMPOSE)) $OUTPUT->add_label('nosubject', 'nosenderwarning', 'norecipientwarning', 'nosubjectwarning', 'cancel', 'nobodywarning', 'notsentwarning', 'notuploadedwarning', 'savingmessage', 'sendingmessage', 'messagesaved', 'converting', 'editorwarning', 'searching', 'uploading', 'uploadingmany', - 'fileuploaderror', 'sendmessage'); + 'fileuploaderror', 'sendmessage', 'savenewresponse', 'responsename', 'responsetext', 'save', + 'savingresponse'); $OUTPUT->set_env('compose_id', $COMPOSE['id']); $OUTPUT->set_pagetitle(rcube_label('compose')); @@ -852,29 +853,14 @@ function rcmail_compose_body($attrib) // Set language list if (!empty($CONFIG['enable_spellcheck'])) { - $engine = $RCMAIL->config->get('spellcheck_engine','googie'); + $engine = new rcube_spellchecker(); $dictionary = (bool) $RCMAIL->config->get('spellcheck_dictionary'); - $spellcheck_langs = (array) $RCMAIL->config->get('spellcheck_languages', - array('da'=>'Dansk', 'de'=>'Deutsch', 'en' => 'English', 'es'=>'Español', - 'fr'=>'Français', 'it'=>'Italiano', 'nl'=>'Nederlands', 'pl'=>'Polski', - 'pt'=>'Português', 'ru'=>'Русский', 'fi'=>'Suomi', 'sv'=>'Svenska')); - - // googie works only with two-letter codes - if ($engine == 'googie') { - $lang = strtolower(substr($_SESSION['language'], 0, 2)); - - $spellcheck_langs_googie = array(); - foreach ($spellcheck_langs as $key => $name) - $spellcheck_langs_googie[strtolower(substr($key,0,2))] = $name; - $spellcheck_langs = $spellcheck_langs_googie; - } - else { - $lang = $_SESSION['language']; + $spellcheck_langs = $engine->languages(); + $lang = $_SESSION['language']; - // if not found in the list, try with two-letter code - if (!$spellcheck_langs[$lang]) - $lang = strtolower(substr($lang, 0, 2)); - } + // if not found in the list, try with two-letter code + if (!$spellcheck_langs[$lang]) + $lang = strtolower(substr($lang, 0, 2)); if (!$spellcheck_langs[$lang]) $lang = 'en'; @@ -1757,6 +1743,38 @@ function compose_file_drop_area($attrib) } +/** + * + */ +function rcmail_compose_responses_list($attrib) +{ + global $RCMAIL, $OUTPUT; + + $attrib += array('id' => 'rcmresponseslist', 'tagname' => 'ul', 'cols' => 1); + + $jsenv = array(); + $list = new html_table($attrib); + foreach ($RCMAIL->get_compose_responses(true) as $response) { + $key = $response['key']; + $item = html::a(array( + 'href '=> '#'.urlencode($response['name']), + 'class' => rtrim('insertresponse ' . $attrib['itemclass']), + 'unselectable' => 'on', + 'rel' => $key, + ), Q($response['name'])); + + $jsenv[$key] = $response; + $list->add(array(), $item); + } + + // set client env + $OUTPUT->set_env('textresponses', $jsenv); + $OUTPUT->add_gui_object('responseslist', $attrib['id']); + + return $list->show(); +} + + // register UI objects $OUTPUT->add_handlers(array( 'composeheaders' => 'rcmail_compose_headers', @@ -1773,6 +1791,7 @@ $OUTPUT->add_handlers(array( 'storetarget' => 'rcmail_store_target_selection', 'addressbooks' => 'rcmail_addressbook_list', 'addresslist' => 'rcmail_contacts_list', + 'responseslist' => 'rcmail_compose_responses_list', )); $OUTPUT->send('compose'); diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 48afecb60..78a977b82 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -97,6 +97,7 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') { $OUTPUT->set_env('delimiter', $delimiter); $OUTPUT->set_env('threading', $threading); $OUTPUT->set_env('threads', $threading || $RCMAIL->storage->get_capability('THREAD')); + $OUTPUT->set_env('reply_all_mode', (int) $RCMAIL->config->get('reply_all_mode')); $OUTPUT->set_env('preview_pane_mark_read', $RCMAIL->config->get('preview_pane_mark_read', 0)); if ($RCMAIL->storage->get_capability('QUOTA')) { $OUTPUT->set_env('quota', true); @@ -1775,28 +1776,34 @@ function rcmail_identity_select($MESSAGE, $identities = null, $compose_mode = 'r } } - $from_idx = null; - $found_idx = null; - $default_identity = 0; // default identity is always first on the list + // decode From: address + $from = rcube_mime::decode_address_list($MESSAGE->headers->from, null, true, $MESSAGE->headers->charset); + $from = array_shift($from); + $from['mailto'] = strtolower($from['mailto']); + + $from_idx = null; + $found_idx = array('to' => null, 'from' => null); + $check_from = in_array($compose_mode, array('draft', 'edit', 'reply')); // Select identity foreach ($identities as $idx => $ident) { - // use From header - if (in_array($compose_mode, array('draft', 'edit'))) { - if ($MESSAGE->headers->from == $ident['ident']) { + // use From: header when in edit/draft or reply-to-self + if ($check_from && $from['mailto'] == strtolower($ident['email_ascii'])) { + // remember first matching identity address + if ($found_idx['from'] === null) { + $found_idx['from'] = $idx; + } + // match identity name + if ($from['name'] && $ident['name'] && $from['name'] == $ident['name']) { $from_idx = $idx; break; } } - // reply to yourself - else if ($compose_mode == 'reply' && $MESSAGE->headers->from == $ident['ident']) { - $from_idx = $idx; - break; - } - // use replied message recipients + // use replied/forwarded message recipients else if (($found = array_search(strtolower($ident['email_ascii']), $a_recipients)) !== false) { - if ($found_idx === null) { - $found_idx = $idx; + // remember first matching identity address + if ($found_idx['to'] === null) { + $found_idx['to'] = $idx; } // match identity name if ($a_names[$found] && $ident['name'] && $a_names[$found] == $ident['name']) { @@ -1806,22 +1813,27 @@ function rcmail_identity_select($MESSAGE, $identities = null, $compose_mode = 'r } } - // If matching by name+address doesn't found any matches, get first found address (identity) + // If matching by name+address didn't find any matches, + // get first found identity (address) if any if ($from_idx === null) { - $from_idx = $found_idx; + $from_idx = $found_idx['from'] !== null ? $found_idx['from'] : $found_idx['to']; } // Try Return-Path if ($from_idx === null && ($return_path = $MESSAGE->headers->others['return-path'])) { + $return_path = array_map('strtolower', (array) $return_path); + foreach ($identities as $idx => $ident) { // Return-Path header contains an email address, but on some mailing list // it can be e.g. <pear-dev-return-55250-local=domain.tld@lists.php.net> // where local@domain.tld is the address we're looking for (#1489241) - $ident1 = $ident['email_ascii']; + $ident1 = strtolower($ident['email_ascii']); $ident2 = str_replace('@', '=', $ident1); + $ident1 = '<' . $ident1 . '>'; + $ident2 = '-' . $ident2 . '@'; - foreach ((array)$return_path as $path) { - if (stripos($path, $ident1) !== false || stripos($path, $ident2)) { + foreach ($return_path as $path) { + if ($path == $ident1 || stripos($path, $ident2)) { $from_idx = $idx; break 2; } @@ -1835,7 +1847,8 @@ function rcmail_identity_select($MESSAGE, $identities = null, $compose_mode = 'r $selected = $plugin['selected']; - return $identities[$selected !== null ? $selected : $default_identity]; + // default identity is always first on the list + return $identities[$selected !== null ? $selected : 0]; } // Fixes some content-type names diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index ccb8978be..52b02ecff 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -615,22 +615,39 @@ else { } // add stored attachments, if any -if (is_array($COMPOSE['attachments'])) -{ +if (is_array($COMPOSE['attachments'])) { foreach ($COMPOSE['attachments'] as $id => $attachment) { // This hook retrieves the attachment contents from the file storage backend $attachment = $RCMAIL->plugins->exec_hook('attachment_get', $attachment); - $dispurl = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile' . preg_quote($attachment['id']) . '[\s\'"]*/'; - $message_body = $MAIL_MIME->getHTMLBody(); - if ($isHtml && (preg_match($dispurl, $message_body) > 0)) { - $message_body = preg_replace($dispurl, ' src="'.$attachment['name'].'" ', $message_body); + if ($isHtml) { + $dispurl = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile' . preg_quote($attachment['id']) . '[\s\'"]*/'; + $message_body = $MAIL_MIME->getHTMLBody(); + $is_inline = preg_match($dispurl, $message_body); + } + else { + $is_inline = false; + } + + // inline image + if ($is_inline) { + // Mail_Mime does not support many inline attachments with the same name (#1489406) + // we'll generate cid: urls here to workaround this + $cid = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true)); + if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $from, $matches)) { + $cid .= $matches[1]; + } else { + $cid .= '@localhost'; + } + + $message_body = preg_replace($dispurl, ' src="cid:' . $cid . '" ', $message_body); + $MAIL_MIME->setHTMLBody($message_body); if ($attachment['data']) - $MAIL_MIME->addHTMLImage($attachment['data'], $attachment['mimetype'], $attachment['name'], false); + $MAIL_MIME->addHTMLImage($attachment['data'], $attachment['mimetype'], $attachment['name'], false, $cid); else - $MAIL_MIME->addHTMLImage($attachment['path'], $attachment['mimetype'], $attachment['name'], true); + $MAIL_MIME->addHTMLImage($attachment['path'], $attachment['mimetype'], $attachment['name'], true, $cid); } else { $ctype = str_replace('image/pjpeg', 'image/jpeg', $attachment['mimetype']); // #1484914 diff --git a/program/steps/settings/edit_response.inc b/program/steps/settings/edit_response.inc new file mode 100644 index 000000000..49856775a --- /dev/null +++ b/program/steps/settings/edit_response.inc @@ -0,0 +1,107 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/steps/settings/edit_response.inc | + | | + | This file is part of the Roundcube Webmail client | + | Copyright (C) 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: | + | Show edit form for a canned response record or to add a new one | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ +*/ + +$responses = $RCMAIL->get_compose_responses(); + +// edit-response +if (($key = get_input_value('_key', RCUBE_INPUT_GPC))) { + foreach ($responses as $i => $response) { + if ($response['key'] == $key) { + $RESPONSE_RECORD = $response; + $RESPONSE_RECORD['index'] = $i; + break; + } + } +} + +// save response +if ($RCMAIL->action == 'save-response' && isset($_POST['_name']) && !$RESPONSE_RECORD['static']) { + $name = trim(get_input_value('_name', RCUBE_INPUT_POST)); + $text = trim(get_input_value('_text', RCUBE_INPUT_POST)); + + if (!empty($name) && !empty($text)) { + $dupes = 0; + foreach ($responses as $i => $resp) { + if ($RESPONSE_RECORD && $RESPONSE_RECORD['index'] === $i) + continue; + if (strcasecmp($name, preg_replace('/\s\(\d+\)$/', '', $resp['name'])) == 0) + $dupes++; + } + if ($dupes) { // require a unique name + $name .= ' (' . ++$dupes . ')'; + } + + $response = array('name' => $name, 'text' => $text, 'format' => 'text', 'key' => substr(md5($name), 0, 16)); + if ($RESPONSE_RECORD && $responses[$RESPONSE_RECORD['index']]) { + $responses[$RESPONSE_RECORD['index']] = $response; + } + else { + $responses[] = $response; + } + + $responses = array_filter($responses, function($item){ return empty($item['static']); }); + if ($RCMAIL->user->save_prefs(array('compose_responses' => array_values($responses)))) { + $RCMAIL->output->show_message('successfullysaved', 'confirmation'); + $RCMAIL->output->command('parent.update_response_row', $response, $key); + $RCMAIL->overwrite_action('edit-response'); + $RESPONSE_RECORD = $response; + } + } + else { + $RCMAIL->output->show_message('formincomplete', 'error'); + } +} + + +function rcube_response_form($attrib) +{ + global $RCMAIL, $OUTPUT, $RESPONSE_RECORD; + + // Set form tags and hidden fields + $disabled = !empty($RESPONSE_RECORD['static']); + $key = $RESPONSE_RECORD['key']; + list($form_start, $form_end) = get_form_tags($attrib, 'save-response', $key, array('name' => '_key', 'value' => $key)); + unset($attrib['form'], $attrib['id']); + + // return the complete edit form as table + $out = "$form_start\n"; + + $table = new html_table(array('cols' => 2)); + $label = rcube_label('responsename'); + + $table->add('title', html::label('ffname', Q(rcube_label('responsename')))); + $table->add(null, rcube_output::get_edit_field('name', $RESPONSE_RECORD['name'], array('id' => 'ffname', 'size' => $attrib['size'], 'disabled' => $disabled), 'text')); + + $table->add('title', html::label('fftext', Q(rcube_label('responsetext')))); + $table->add(null, rcube_output::get_edit_field('text', $RESPONSE_RECORD['text'], array('id' => 'fftext', 'size' => $attrib['textareacols'], 'rows' => $attrib['textarearows'], 'disabled' => $disabled), 'textarea')); + + $out .= $table->show($attrib); + $out .= $form_end; + + return $out; +} + +$OUTPUT->set_env('readonly', !empty($RESPONSE_RECORD['static'])); +$OUTPUT->add_handler('responseform', 'rcube_response_form'); +$OUTPUT->set_pagetitle(rcube_label(($RCMAIL->action=='add-response' ? 'savenewresponse' : 'editresponse'))); + +$OUTPUT->send('responseedit'); + diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc index af278e5fa..c922aca08 100644 --- a/program/steps/settings/func.inc +++ b/program/steps/settings/func.inc @@ -869,6 +869,24 @@ function rcmail_user_prefs($current = null) $select_default_font_size->show($RCMAIL->config->get('default_font_size', 1)) ); } + + if (!isset($no_override['reply_all_mode'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_reply_all_mode'; + $select = new html_select(array('name' => '_reply_all_mode', 'id' => $field_id)); + + $select->add(rcube_label('replyalldefault'), 0); + $select->add(rcube_label('replyalllist'), 1); + + $blocks['main']['options']['reply_all_mode'] = array( + 'title' => html::label($field_id, Q(rcube_label('replyallmode'))), + 'content' => $select->show(intval($config['reply_all_mode'])), + ); + } + break; // Addressbook config @@ -1260,6 +1278,7 @@ function rcmail_settings_tabs($attrib) array('command' => 'preferences', 'type' => 'link', 'label' => 'preferences', 'title' => 'editpreferences'), array('command' => 'folders', 'type' => 'link', 'label' => 'folders', 'title' => 'managefolders'), array('command' => 'identities', 'type' => 'link', 'label' => 'identities', 'title' => 'manageidentities'), + array('command' => 'responses', 'type' => 'link', 'label' => 'responses', 'title' => 'editresponses'), ); // get all identites from DB and define list of cols to be displayed @@ -1321,4 +1340,7 @@ $RCMAIL->register_action_map(array( 'purge' => 'folders.inc', 'folder-size' => 'folders.inc', 'add-identity' => 'edit_identity.inc', + 'add-response' => 'edit_response.inc', + 'save-response' => 'edit_response.inc', + 'delete-response' => 'responses.inc', )); diff --git a/program/steps/settings/responses.inc b/program/steps/settings/responses.inc new file mode 100644 index 000000000..cfc4148c3 --- /dev/null +++ b/program/steps/settings/responses.inc @@ -0,0 +1,128 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/steps/settings/responses.inc | + | | + | This file is part of the Roundcube Webmail client | + | Copyright (C) 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: | + | Manage and save canned response texts | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ +*/ + + +if (!empty($_POST['_insert'])) { + $name = trim(get_input_value('_name', RCUBE_INPUT_POST)); + $text = trim(get_input_value('_text', RCUBE_INPUT_POST)); + + if (!empty($name) && !empty($text)) { + $dupes = 0; + $responses = $RCMAIL->get_compose_responses(false, true); + foreach ($responses as $resp) { + if (strcasecmp($name, preg_replace('/\s\(\d+\)$/', '', $resp['name'])) == 0) + $dupes++; + } + if ($dupes) { // require a unique name + $name .= ' (' . ++$dupes . ')'; + } + + $response = array('name' => $name, 'text' => $text, 'format' => 'text', 'key' => substr(md5($name), 0, 16)); + $responses[] = $response; + + if ($RCMAIL->user->save_prefs(array('compose_responses' => $responses))) { + $RCMAIL->output->command('add_response_item', $response); + $RCMAIL->output->command('display_message', rcube_label('successfullysaved'), 'confirmation'); + } + else { + $RCMAIL->output->command('display_message', rcube_label('errorsaving'), 'error'); + } + } + + // send response + $RCMAIL->output->send(); +} + + +if ($RCMAIL->action == 'delete-response') { + if ($key = get_input_value('_key', RCUBE_INPUT_GPC)) { + $responses = $RCMAIL->get_compose_responses(false, true); + foreach ($responses as $i => $response) { + if (empty($response['key'])) + $response['key'] = substr(md5($response['name']), 0, 16); + if ($response['key'] == $key) { + unset($responses[$i]); + $deleted = $RCMAIL->user->save_prefs(array('compose_responses' => $responses)); + break; + } + } + } + + if ($deleted) { + $RCMAIL->output->command('display_message', rcube_label('deletedsuccessfully'), 'confirmation'); + $RCMAIL->output->command('remove_response', $key); + } + + if ($RCMAIL->output->ajax_call) { + $RCMAIL->output->send(); + } +} + + +$OUTPUT->set_pagetitle(rcube_label('responses')); +$OUTPUT->include_script('list.js'); + + +/** + * + */ +function rcmail_responses_list($attrib) +{ + global $RCMAIL, $OUTPUT; + + $attrib += array('id' => 'rcmresponseslist', 'tagname' => 'table', 'cols' => 1); + + $plugin = $RCMAIL->plugins->exec_hook('responses_list', array( + 'list' => $RCMAIL->get_compose_responses(true), + 'cols' => array('name') + )); + + $out = rcube_table_output($attrib, $plugin['list'], $plugin['cols'], 'key'); + + // set client env + $OUTPUT->add_gui_object('responseslist', $attrib['id']); + $OUTPUT->set_env('readonly_responses', array_values(array_map(function($rec){ return $rec['key']; }, + array_filter($plugin['list'], function($item){ return !empty($item['static']); })))); + + return $out; +} + + +// similar function as /steps/addressbook/func.inc::rcmail_contact_frame() +function rcmail_response_frame($attrib) +{ + global $OUTPUT; + + if (!$attrib['id']) { + $attrib['id'] = 'rcmResponseFrame'; + } + + $OUTPUT->set_env('contentframe', $attrib['id']); + return $OUTPUT->frame($attrib, true); +} + +$OUTPUT->add_handlers(array( + 'responseframe' => 'rcmail_response_frame', + 'responseslist' => 'rcmail_responses_list', +)); +$OUTPUT->add_label('deleteresponseconfirm'); + +$OUTPUT->send('responses'); diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc index 717c7ad8c..bcd05bb85 100644 --- a/program/steps/settings/save_prefs.inc +++ b/program/steps/settings/save_prefs.inc @@ -90,6 +90,7 @@ switch ($CURR_SECTION) 'strip_existing_sig' => isset($_POST['_strip_existing_sig']), 'default_font' => get_input_value('_default_font', RCUBE_INPUT_POST), 'default_font_size' => get_input_value('_default_font_size', RCUBE_INPUT_POST), + 'reply_all_mode' => intval($_POST['_reply_all_mode']), 'forward_attachment' => !empty($_POST['_forward_attachment']), ); diff --git a/program/steps/utils/save_pref.inc b/program/steps/utils/save_pref.inc index 7def8733d..7c30be71b 100644 --- a/program/steps/utils/save_pref.inc +++ b/program/steps/utils/save_pref.inc @@ -5,7 +5,7 @@ | program/steps/utils/save_pref.inc | | | | This file is part of the Roundcube Webmail client | - | Copyright (C) 2005-2010, The Roundcube Dev Team | + | 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. | @@ -19,16 +19,26 @@ +-----------------------------------------------------------------------+ */ -$name = get_input_value('_name', RCUBE_INPUT_POST); -$value = get_input_value('_value', RCUBE_INPUT_POST); +$name = get_input_value('_name', RCUBE_INPUT_POST); +$value = get_input_value('_value', RCUBE_INPUT_POST); +$sessname = get_input_value('_session', RCUBE_INPUT_POST); + +// Whitelisted preferences and session variables, others +// can be added by plugins $whitelist = array( 'preview_pane', 'list_cols', 'collapsed_folders', 'collapsed_abooks', ); +$whitelist_sess = array( + 'list_attrib/columns', +); + +$whitelist = array_merge($whitelist, $RCMAIL->plugins->allowed_prefs); +$whitelist_sess = array_merge($whitelist_sess, $RCMAIL->plugins->allowed_session_prefs); -if (!in_array($name, array_merge($whitelist, $RCMAIL->plugins->allowed_prefs))) { +if (!in_array($name, $whitelist) || ($sessname && !in_array($sessname, $whitelist_sess))) { raise_error(array('code' => 500, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => sprintf("Hack attempt detected (user: %s)", $RCMAIL->get_user_name())), @@ -42,7 +52,7 @@ if (!in_array($name, array_merge($whitelist, $RCMAIL->plugins->allowed_prefs))) $RCMAIL->user->save_prefs(array($name => $value)); // update also session if requested -if ($sessname = get_input_value('_session', RCUBE_INPUT_POST)) { +if ($sessname) { // Support multidimensional arrays... $vars = explode('/', $sessname); @@ -57,5 +67,3 @@ if ($sessname = get_input_value('_session', RCUBE_INPUT_POST)) { $OUTPUT->reset(); $OUTPUT->send(); - - diff --git a/program/steps/utils/spell.inc b/program/steps/utils/spell.inc index 1c68e8328..595cfd6f2 100644 --- a/program/steps/utils/spell.inc +++ b/program/steps/utils/spell.inc @@ -47,6 +47,9 @@ if ($err = $spellchecker->error()) { 'file' => __FILE__, 'line' => __LINE__, 'message' => "Spell check engine error: " . trim($err)), true, false); + + header("HTTP/1.0 500 Internal Server Error"); + exit; } // set response length |