changeset 34:50ac5484d514

one fix to distro
author Charlie Root
date Sun, 27 May 2018 16:53:56 -0400
parents d41c01c5c933
children 05c4c32948af
files plugins/advanced_search/.gitignore plugins/advanced_search/README.md plugins/advanced_search/advanced_search.js plugins/advanced_search/advanced_search.min.js plugins/advanced_search/advanced_search.php plugins/advanced_search/advanced_search.php.orig plugins/advanced_search/advanced_search.php~ plugins/advanced_search/composer.json plugins/advanced_search/config-default.inc.php plugins/advanced_search/localization/de_DE.inc plugins/advanced_search/localization/en_US.inc plugins/advanced_search/localization/fr_FR.inc plugins/advanced_search/localization/it_IT.inc plugins/advanced_search/localization/pl_PL.inc plugins/advanced_search/localization/ru_RU.inc plugins/advanced_search/skins/classic/advanced_search.css plugins/advanced_search/skins/larry/advanced_search.css plugins/advanced_search/skins/larry/images/icon-loupe.png plugins/advanced_search/skins/larry/images/menu_location_a.jpg plugins/advanced_search/skins/larry/images/menu_location_b.jpg plugins/advanced_search/skins/larry/images/show_mbox_col.jpg plugins/advanced_search/skins/larry/images/show_mbox_row.jpg
diffstat 22 files changed, 4696 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/.gitignore	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,2 @@
+*.swp
+config.inc.php
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/README.md	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,77 @@
+
+Advanced Search Plugin for Roundcube
+====================================
+
+## Getting It
+
+You can download direct from GitHub or consider using
+the [plugin repository for Roundcube](http://plugins.roundcube.net/)
+
+## Usage
+
+After install, 'Advanced search' will show up under the 'more' menu.
+
+Please use the _'stable'_ brach for deployment.
+
+Advantages:
+
+* This version should be tested and bug-free
+* It uses minified versions of the JavaScript
+
+## Requirements
+Version 2.0.0 requires Roundcube 0.9.4 or later
+
+## License
+
+This plugin is released under the GNU General Public License Version 3
+or later (http://www.gnu.org/licenses/gpl.html).
+
+Even if skins might contain some programming work, they are not considered
+as a linked part of the plugin and therefore skins DO NOT fall under the
+provisions of the GPL license. See the README file located in the core skins
+folder for details on the skin license.
+
+## Download
+
+### GIT :
+* Clone the GitHub repository to 'advanced_search':
+
+ >     git clone git://github.com/GMS-SA/roundcube-advanced-search.git advanced_search
+
+* Change to the 'stable' branch:
+
+ >     cd advanced_search
+ >     git checkout -b stable origin/stable
+
+### ZIP :
+* Swap branches to 'stable'
+* Click on the 'ZIP' download icon
+* Rename the unziped directory 'advanced_search'
+
+## Install
+
+* Place the 'advanced_search' plugin folder into the plugins directory of Roundcube.
+* If using git and not wanting all the '.git' repository data in your live webmail:
+
+ >     cd advanced_search
+ >     git archive --format=tar --prefix=advanced_search/ stable | tar -x -C /path/to/roundcube/plugins/
+
+  This will give you a git-free copy of the stable branch.
+* Add advanced_search to $rcmail_config['plugins'] in your Roundcube config
+
+* To override defaults, copy the config-default.inc.php file to config.inc.php and modify
+
+## Upgrade
+If upgrading from 1.2.0 or lower, you *must* review the config file.
+
+## Configuration
+
+* Available search criterias 
+* Targeted roundcube menu for the advanced search
+
+## Credits
+
+* Wilwert Claude
+* Ludovicy Steve
+* Moules Chris
+* [Global Media Systems](http://www.gms.lu)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/advanced_search.js	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,726 @@
+(function($) {
+    /**
+     * The fontend scripts for an advanced search.
+     *
+     * @version 2.1.6
+     * @licence GNU GPLv3+
+     * @author  Wilwert Claude
+     * @author  Ludovicy Steve
+     * @author  Chris Moules
+     * @website http://www.gms.lu
+     */
+
+    $.stack = {
+        /**
+         * This object is used to buffer all the server side information which doesn't change. So the script
+         * doesn't have to send an ajax-request for every new added row.
+         *
+         * @name stack
+         * @namespace
+         */
+        date_criteria: {},
+        flag_criteria: {},
+        email_criteria: {},
+        row: null,
+        messages: null
+    };
+
+    var search_loading = '';
+
+    $(document).on("change", "#button_display_option", function(e) {
+        var img = $('img', $(this).closest('p'));
+        var src = img.attr('src');
+        if(this.value == 'messagemenu') {
+            src = src.replace('menu_location_b.jpg', 'menu_location_a.jpg');
+        } else {
+            src = src.replace('menu_location_a.jpg', 'menu_location_b.jpg');
+        }
+        img.attr('src', src);
+    });
+
+    $(document).on("change", "#_show_message_mbox_info, #_show_message_label_header", function(e) {
+        var img = $('img', $(this).closest('p'));
+        if($(this).is(':checked')) {
+            img.removeClass('disabled');
+        } else {
+            img.addClass('disabled');
+        }
+    });
+
+    /**
+     * The callback function of the initial dialog call. It creates the dialog and buffers the serverside
+     * informations into an object.
+     *
+     * @param {object} r The serverside informations
+     */
+    rcmail.addEventListener('plugin.show', function(r) {
+        $.stack.date_criteria = r.date_criteria;
+        $.stack.flag_criteria = r.flag_criteria;
+        $.stack.email_criteria = r.email_criteria;
+        $.stack.row = r.row;
+        $.stack.html = r.html;
+
+        var $html = $(r.html);
+        var saved_searches_label = rcmail.gettext('saved_searches', 'advanced_search');
+        var saved_searches = '<span class="saved_searches"> <label for="select_saved_search">' + saved_searches_label + ': <select name="select_saved_search" id="select_saved_search"><option value=""></option></select></label></span>';
+        title = $('<div>' + r.title + saved_searches + '<div>');
+        var saved_searches_select = $('[name=select_saved_search]', title);
+        if (r.saved_searches.length) {
+            var i;
+            for (i in r.saved_searches) {
+                saved_searches_select.append('<option value="' + r.saved_searches[i] + '">' + r.saved_searches[i] + '</option>');
+            }
+        }
+        $html.dialog({
+            width: 640,
+            height: 300,
+            resizable: true,
+            draggable: true,
+            title: title,
+            dialogClass: "advanced_search_dialog",
+            close: function() {
+                $('body').css('overflow', 'auto');
+            },
+            create: function() {
+                $('body').css('overflow', 'hidden');
+            }
+        });
+
+        saved_searches_select.bind("blur click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select", function(e) {
+            e.stopPropagation(); 
+        });
+
+        saved_searches_select.bind("mouseenter", function(e) {
+            saved_searches_select.focus();
+        });
+
+        saved_searches_select.bind('change', function(e) {
+            var search_name = $(this).val();
+            if (search_name == "") {
+                $('#adsearch-popup').html($.stack.html);
+            } else {
+                rcmail.http_request('plugin.get_saved_search', { search_name : search_name });
+                $('[name=delete]', '#adsearch-popup').show();
+            }
+        });
+
+    });
+
+    rcmail.addEventListener('plugin.load_saved_search', function(search) {
+        var $form = $("#adsearch-popup form"),
+            $tr = $('tr', $('tbody', $form)).not(':first').not(':last'),
+            $last = $('tr:last', $('tbody', $form));
+            saved_search = search.search,
+            data = [];
+        $tr.remove();
+        $("[name=folder]", $form).val(search.folder);
+        $("[name=subfolder]", $form).prop('checked', search.sub_folders == "true");
+        $('span.sub-folders', $form).css('display', search.folder == 'all' ? 'none' : 'inline');
+
+        var i = 0;
+        for (i; i < saved_search.length; i++) {
+            var row;
+            if (i == 0) {
+                row = $('<tr>' + $("tr:eq(1)", $.stack.html).html() + '</tr>');
+            } else {
+                row = $($.stack.row);
+            }
+            $("[name=method]", row).val(saved_search[i].method);
+            $("[name=filter]", row).val(saved_search[i].filter);
+            $("[name=not]", row).prop('checked', saved_search[i]['not'] == "true");
+            $("[name=filter-exclude]", row).prop('checked', saved_search[i]['excluded'] == "true");
+            $last.before(row);
+            $("[name=filter]", row).trigger("change");
+            $("[name=filter-val]", row).val(saved_search[i]['filter-val']);
+        }
+    });
+//messagelistcontainer table thead 
+    rcmail.addEventListener('plugin.advanced_search_add_header', function(evt) {
+        if($("#messagelistcontainer #rcavbox1").length == 0) {
+            var Mbox = rcmail.gettext('mbox', 'advanced_search');
+            $("#messagelistcontainer table.fixedcopy thead tr:first").append('<td class="mbox" id="rcavbox1"><span class="mbox">' + Mbox + '</span></td>');
+            $("#messagelistcontainer table#messagelist thead tr:first").append('<td class="mbox" id="rcavbox2"><span class="mbox">' + Mbox + '</span></td>');
+        }
+    });
+
+    rcmail.addEventListener('plugin.advanced_search_del_header', function(evt) {
+        $("#messagelistcontainer #rcavbox1").remove();
+        $("#messagelistcontainer #rcavbox2").remove();
+    });
+
+    rcube_webmail.prototype.advanced_search_add_mbox = function (mbox, count, showMbox) {
+        if (!this.gui_objects.messagelist || !this.message_list) {
+            return false;
+        }
+
+        var colspan = showMbox == true ? 9 : 8;
+        $(rcmail.message_list.list).append('<tr class="aslabel_mbox"><td><span class="aslabel_found">' + count + '</span></td><td colspan="' + colspan + '">' + mbox + '</td></tr>');
+    }
+
+    rcube_webmail.prototype.advanced_search_active = function(param) {
+        var page = param.replace('_page=', '');
+        rcmail.http_request('plugin.trigger_search_pagination', { _page : page });
+    }
+
+    /**
+     * Builds the search to send to the server
+     */
+    var get_search_data = function()
+    {
+        var $form = $("#adsearch-popup form"),
+            $tr = $('tr', $('tbody', $form)).not(':first').not(':last'),
+            data = [];
+
+        if ($tr.length) {
+            $tr.each(function() {
+                    var item = {not: $('input[name=not]', $(this)).prop('checked'),
+                                excluded: $('input[name=filter-exclude]', $(this)).prop('checked'),
+                                filter: $('option:selected', $('select[name=filter]', $(this))).val(),
+                                'filter-val': $('input[name=filter-val]', $(this)).val()};
+
+                    if ($('select[name=method]', $(this)).length) {
+                        item.method = $('option:selected', $('select[name=method]', $(this))).val();
+                    }
+
+                    data.push(item);
+            });
+        }
+
+        return data;
+    }
+
+    /**
+     * The onclick event handler for the search button. This generates the search query and sends them
+     * to the server. It also stores the wrapped set of the old rows into an object for later cleanup.
+     *
+     * @param {object} e The event element
+     */
+     $(document).on("click", 'input[name=search]', function(e) {
+        e.preventDefault();
+
+        rcmail.clear_message_list();
+
+        $.stack.messages = $('tr', $('tbody', '#messagelist'));
+
+        var $form = $("#adsearch-popup form");
+        search_loading = rcmail.set_busy(true, 'loading');
+        rcmail.http_request('plugin.trigger_search',
+                            {search: get_search_data(),
+                             current_folder: rcmail.env.mailbox,
+                             folder: $('select[name=folder]', $form).val(),
+                             sub_folders: $('input[name=subfolder]', $form).prop('checked')});
+
+        $("#adsearch-popup").closest('div.ui-dialog-content').dialog('close');
+    });
+
+    /**
+     * The onclick event handler of the "reset search" button, which resets the advanced search
+     * back to its initial state.
+     *
+     * @param {object} e The event element
+     */
+    $(document).on("click", 'input[name=reset]', function(e) {
+        e.preventDefault();
+        $('#adsearch-popup').html($.stack.html);
+        $('[name=select_saved_search]').val("");
+    });
+
+    /**
+     * The onclick event handler for the "add" button. This adds one new row to the query dialog
+     *
+     * @param {object} e The event element
+     */
+    $(document).on("click", 'button[name=add]', function(e) {
+        e.preventDefault();
+
+        $(this).closest('tr').after($.stack.row);
+    });
+
+    /**
+     * The onclick event handler for the "delete" button. This removes the containing row from
+     * the query dialog
+     *
+     * @param {object} e The event element
+     */
+    $(document).on("click", 'button[name=delete]', function(e) {
+        e.preventDefault();
+
+        $(this).closest('tr').remove();
+    });
+
+    /**
+     * The change event handler for the filter selector.
+     * Make the input field context relevent.
+     *
+     * @param {object} e The event element
+     */
+    $(document).on("click", 'select[name=filter]', function(e) {
+        var $row_input = $(this).nextUntil('tr', 'input[name=filter-val]'),
+            old_avs_type = $row_input.data("avs_type");
+
+        if ($.inArray($(this).val(), $.stack.date_criteria) >= 0) {
+            if(old_avs_type !== "date") {
+                $row_input.val('');
+                $row_input.datepicker({dateFormat: rcmail.env.date_format});
+            }
+
+            $row_input.data("avs_type", "date");
+        } else if ($.inArray($(this).val(), $.stack.email_criteria) >= 0) {
+            if(old_avs_type !== "email") {
+                rcmail.init_address_input_events($row_input, "");
+                rcmail.addEventListener('autocomplete_insert', function(e){
+                    e.field.value = e.insert.replace(/.*<(\S*?@\S*?)>.*/, "$1");
+                });
+            }
+
+            $row_input.data("avs_type", "email");
+        } else if ($.inArray($(this).val(), $.stack.flag_criteria) >= 0) {
+            if (old_avs_type !== "flag_criteria") {
+                $row_input.val('');
+                $row_input.hide();
+            }
+
+            $row_input.data("avs_type", "flag_criteria");
+        } else {
+            $row_input.data("avs_type", "none");
+        }
+
+        switch (old_avs_type) {
+            case "date":
+                if (($row_input.data("avs_type") !== "date") && $row_input.hasClass("hasDatepicker")) {
+                    $row_input.datepicker("destroy");
+                }
+            break;
+            case "email":
+                if (($row_input.data("avs_type") !== "email")) {
+                    $row_input.removeAttr("autocomplete");
+                    $row_input.unbind('keydown');
+                    $row_input.unbind('keypress');
+                }
+            break;
+            case "flag_criteria":
+                if (($row_input.data("avs_type") !== "flag_criteria") && !$row_input.is(":visible")) {
+                    $row_input.show();
+                }
+            break;
+        }
+    });
+
+    /**
+     * The change event handler for the folder select box. It makes the subfolder checkbox invisible
+     * when selecting the "all folders" option
+     *
+     * @param {object} e The event element
+     */
+    $(document).on("click", 'select[name=folder]', function(e) {
+        $('span.sub-folders', $(this).closest('form')).css('display', $(this).val() == 'all' ? 'none' : 'inline');
+    });
+
+    /**
+     * The onclick event handler for the menu entry of the advanced search. This makes the initial call
+     * of the advanced search and fires a query to the server to get every important information.
+     *
+     * @param {object} e The event element
+     */
+    $(document).on("click", 'a.icon.advanced-search, a.button.advanced-search', function(e) {
+        e.preventDefault();
+
+        if (!$('#adsearch-popup').length) {
+            rcmail.http_request('plugin.display_advanced_search');
+        } else {
+            $("#adsearch-popup").closest('div.ui-dialog-content').dialog('open');
+        }
+    });
+
+    /**
+     * Stop propagation of keydown and keypress events.
+     * This should stop these events being processed by other listeners in the mailbox.
+     *
+     * @param {object} e The event element
+     */
+    $(document).on("keydown keypress", "#adsearch-popup", function(e) {
+        e.stopPropagation();
+    });
+
+    $(document).on("click", "#adsearch-popup input.delete_search", function(e) {
+        e.stopPropagation();
+        e.preventDefault();
+        var search_name = $("[name=select_saved_search]").val();
+        var txt = {};
+        txt['cancel'] = rcmail.get_label('advanced_search.cancel');
+        txt['delete'] = rcmail.get_label('advanced_search.delete');
+        $( "<p><strong>" + search_name + "</strong></p>" ).dialog({
+            resizable: true,
+            height:180,
+            modal: true,
+            title: rcmail.gettext('advanced_search.deletesearch'),
+            buttons: [
+                {
+                    text: txt['delete'],
+                    click: function() {
+                        rcmail.http_request('plugin.delete_search', {search_name: search_name});
+                        $("[value=" + search_name + "]", "[name=select_saved_search]").remove();
+                        $("[name=select_saved_search]").val("").trigger("change");
+                        $( this ).dialog( "close" );
+                    },
+                },
+                {
+                    text: txt['cancel'],
+                    click: function() {
+                        $( this ).dialog( "close" );
+                    }
+                }]
+
+        });
+    });
+
+    $(document).on("click", "#save_the_search", function(e) {
+        e.stopPropagation();
+        e.preventDefault();
+        var labelName = rcmail.gettext('name', 'advanced_search');
+        var labelSave = rcmail.gettext('save', 'advanced_search');
+        var labelCancel = rcmail.gettext('cancel', 'advanced_search');
+        var save_search = '<table>'
+                        + '  <tr><td>' + labelName + ' </td><td><input type="text" name="search_name" /></td></tr>'
+                        + '  <tr><td></td><td><input type="submit" class="button mainaction" value="' + labelSave  + '" /> <input type="reset" class="button reset" value="' + labelCancel + '" /></td></tr>'
+                        + '</table>';
+        save_search = $(save_search);
+        $("[name=search_name]", save_search).val($("[name=select_saved_search]").val());
+
+        save_search.dialog({
+                    title: rcmail.gettext('advanced_search.save_the_search'),
+                    dialogClass: 'saveTheSearch',
+                    close: function() {
+                        $(this).remove();
+                    },
+                    width: $("#adsearch-popup").width(),
+                    height: $("#adsearch-popup").height(),
+                    modal: true
+                  });
+       $(".mainaction", save_search).bind('click', function(e) {
+           e.preventDefault();
+           e.stopPropagation();
+           var search_name = $("[name=search_name]", save_search).val();
+           var $form = $("#adsearch-popup form");
+           rcmail.http_request('plugin.save_search',
+                            {search: get_search_data(),
+                             search_name: search_name,
+                             folder: $('select[name=folder]', $form).val(),
+                             sub_folders: $('input[name=subfolder]', $form).prop('checked')});
+           var isNewSearch = true;
+           $("[name=select_saved_search] option").each(function(e) {
+               if ($(this).attr("value") == search_name) {
+                   isNewSearch = false;
+               }
+           });
+           if (isNewSearch) {
+               $("[name=select_saved_search]").append('<option value="' + search_name + '">' + search_name + '</option>');
+               $("[name=select_saved_search]").val(search_name);
+           }
+           save_search.dialog('close');
+       });
+
+       $(".reset", save_search).bind('click', function(e) {
+           e.preventDefault();
+           e.stopPropagation();
+           save_search.dialog('close');
+       });
+
+    });
+
+    var advanced_search_redirect_draft_messages = function(check) {
+        if (rcmail.env.search_request == "advanced_search_active") {
+            if (rcmail.task == 'mail') {
+                uid = rcmail.get_single_uid();
+                if (uid && (!rcmail.env.uid || uid != rcmail.env.uid || check)) {
+                    if ((rcmail.env.mailbox == rcmail.env.drafts_mailbox) || check) {
+                        url = {
+                            _mbox: this.env.mailbox,
+                            _search: 'advanced_search_active'
+                        };
+                        url[this.env.mailbox == this.env.drafts_mailbox ? '_draft_uid' : '_uid'] = uid;
+                        this.goto_url('compose', url, true);
+                    }
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    var advanced_search_perform_action = function(props, action) {
+
+        var raw_selection = rcmail.message_list.get_selection();
+        var md5_folders = rcmail.env.as_md5_folders;
+        var i;
+        var selections = {};
+        for (i in raw_selection) {
+            raw_selection[i];
+            var parts = raw_selection[i].split('__MB__');
+            var mid = parts[0];
+            var md5Mbox = parts[1];
+            var mbox = md5_folders[md5Mbox];
+            if (!selections[mbox]) {
+                selections[mbox] = [];
+            }
+            selections[mbox].push(mid);
+        }
+
+        if (i != undefined) {
+            // show wait message
+            if (rcmail.env.action == 'show') {
+                lock = rcmail.set_busy(true, 'movingmessage');
+            } else {
+                rcmail.show_contentframe(false);
+            }
+            // Hide message command buttons until a message is selected
+            rcmail.enable_command(rcmail.env.message_commands, false);
+            var j;
+            for (j in selections) {
+                rcmail.select_folder(j, '', true);
+                rcmail.env.mailbox = j;
+                var uids = selections[j].join(',');
+                var lock = false,
+                    post_data = rcmail.selection_post_data({
+                        _target_mbox: props.id,
+                        _uid: uids
+                    });
+                rcmail._with_selected_messages(action, post_data, lock);
+            }
+            // Make sure we have no selection
+            rcmail.env.uid = undefined;
+            rcmail.message_list.selection = [];
+        }
+
+    }
+
+    var advanced_search_check_multi_mbox = function () {
+        var raw_selection = rcmail.message_list.get_selection();
+        var md5_folders = rcmail.env.as_md5_folders;
+        var i;
+        var mcount = 0;
+        var selections = {};
+        for (i in raw_selection) {
+            raw_selection[i];
+            var parts = raw_selection[i].split('__MB__');
+            var mid = parts[0];
+            var md5Mbox = parts[1];
+            var mbox = md5_folders[md5Mbox];
+            if (!selections[mbox]) {
+                selections[mbox] = [];
+                mcount++;
+            }
+            selections[mbox].push(mid);
+        }
+
+        return {
+            isMulti: mcount > 1,
+            selections: selections
+        };
+    }
+
+    /**
+     * The roundcube init funtion, which registers and enables the advanced search command.
+     */
+    rcmail.addEventListener('init', function() {
+        rcmail.register_command('plugin.advanced_search', true, true);
+        rcmail.enable_command('plugin.advanced_search', true);
+
+        rcmail.addEventListener('plugin.search_complete', function(r) {
+            rcmail.set_busy(false, 'loading', search_loading);
+            /* Start registering event listeners for handling drag/drop, marking, flagging etc... */
+            rcmail.addEventListener('beforeedit', function (command) {
+                rcmail.env.framed = true;
+                if (advanced_search_redirect_draft_messages(true)) {
+                    return false;
+                }
+            });
+
+            rcmail.message_list.addEventListener('dblclick', function (o) {
+                advanced_search_redirect_draft_messages();
+            });
+
+            rcmail.message_list.addEventListener('select', function (list) {
+                if (rcmail.env.search_request == "advanced_search_active") {
+                    if (list.selection.length == 1) {
+                        var parts = list.selection[0].split('__MB__');
+                        var mid = parts[0];
+                        var md5Mbox = parts[1];
+                        var mbox = rcmail.env.as_md5_folders[md5Mbox];
+                        rcmail.env.uid = mid;
+                        if (rcmail.env.mailbox != mbox) {
+                            var ex = [];
+                            li = rcmail.get_folder_li(mbox, '', true);
+                            parent = $(li).parents(".mailbox");
+                            parent.each(function () {
+                                div = $(this.getElementsByTagName('div')[0]);
+                                a = $(this.getElementsByTagName('a')[0]);
+                                if (div.hasClass('collapsed')) {
+                                    ex.push($(a).attr("rel"));
+                                }
+                            });
+                            for (var i = ex.length - 1; i >= 0; i--) {
+                                rcmail.command('collapse-folder', ex[i]);
+                            }
+                            rcmail.select_folder(mbox, '', true);
+                            rcmail.env.mailbox = mbox;
+                        }
+                        return false;
+                    }
+                }
+            });
+
+            rcmail.addEventListener('beforemoveto', function (props) {
+                if (rcmail.env.search_request == 'advanced_search_active') {
+                    advanced_search_perform_action(props, 'moveto');
+
+                    return false;
+                }
+            });
+
+            rcmail.addEventListener('beforedelete', function (props) {
+                if (rcmail.env.search_request == 'advanced_search_active') {
+                    advanced_search_perform_action(props, 'delete');
+
+                    return false;
+                }
+            });
+
+            rcmail.addEventListener('beforemark', function (flag) {
+                if (rcmail.env.search_request == 'advanced_search_active') {
+                    var res = advanced_search_check_multi_mbox();
+                    //Update on server
+                    var i;
+                    var sel = res.selections;
+                    for (i in sel) {
+                        var uids = sel[i].join(',');
+                        var lock = false;
+                        var post_data = {
+                            _uid: uids,
+                            _flag: flag,
+                            _mbox: i,
+                            _remote: 1
+                        };
+                        rcmail.http_post('mark', post_data, lock);
+                    }
+                    var raw_selection = rcmail.message_list.get_selection();
+                    for(i in raw_selection) {
+                        var key = raw_selection[i];
+                        switch (flag) {
+                            case 'read':
+                                rcmail.message_list.rows[key].unread = 0;
+                                break;
+                            case 'unread':
+                                rcmail.message_list.rows[key].unread = 1;
+                                break;
+                            case 'flagged':
+                                rcmail.message_list.rows[key].flagged = 1;
+                                break;
+                            case 'unflagged':
+                                rcmail.message_list.rows[key].flagged = 0;
+                                break;
+                        }
+                    }
+                    //Refresh ui
+                    var messages = [];
+                    var selections = rcmail.message_list.get_selection();
+                    var j;
+                    for (j in selections) {
+                        messages.push('#rcmrow' + selections[j]);
+                    }
+                    var selector = messages.join(', ');
+                    var selection = $(selector);
+                    switch (flag) {
+                    case 'read':
+                        selection.removeClass('unread');
+                        break;
+                    case 'unread':
+                        selection.addClass('unread');
+                        break;
+                    case 'flagged':
+                        selection.addClass('flagged');
+                        $("td.flag span", selection).removeClass('unflagged').addClass('flagged');
+                        break;
+                    case 'unflagged':
+                        selection.removeClass('flagged');
+                        $("td.flag span", selection).removeClass('flagged').addClass('unflagged');
+                        break;
+                    default:
+                        break;
+                    }
+                    return false;
+                }
+            });
+
+            rcmail.addEventListener('beforeforward', function (props) {
+                if (rcmail.env.search_request == 'advanced_search_active' && rcmail.message_list.selection.length > 1) {
+                    var res = advanced_search_check_multi_mbox();
+                    if (res.isMulti == true) {
+                        //Selections from more then one folder
+                        return false;
+                    } else {
+                        //Only one folder, redirecting
+                        var i, url, sel = res.selections;
+                        for (i in sel) {
+                            url = '&_forward_uid=' + sel[i].join(',') + '&_mbox=' + i;
+                        }
+                        url += '&_attachment=1&_action=compose';
+                        window.location = location.pathname + rcmail.env.comm_path + url;
+
+                        return false;
+                    }
+                }
+            });
+
+            rcmail.addEventListener('beforeforward-attachment', function (props) {
+                if (rcmail.env.search_request == 'advanced_search_active' && rcmail.message_list.selection.length > 1) {
+                    var res = advanced_search_check_multi_mbox();
+                    if (res.isMulti == true) {
+                        //Selections from more then one folder
+                        return false;
+                    } else {
+                        //Only one folder, redirecting
+                        var i, url, sel = res.selections;
+                        for (i in sel) {
+                            url = '&_forward_uid=' + sel[i].join(',') + '&_mbox=' + i;
+                        }
+                        url += '&_attachment=1&_action=compose';
+                        window.location = location.pathname + rcmail.env.comm_path + url;
+
+                        return false;
+                    }
+                }
+            });
+
+            rcmail.addEventListener('beforetoggle_flag', function (props) {
+                if (rcmail.env.search_request == 'advanced_search_active') {
+                    var flag = $(props).hasClass('unflagged') ? 'flagged' : 'unflagged';
+                    var tr = $(props).closest('tr');
+                    var id = tr.attr('id').replace('rcmrow', '');
+                    var parts = id.split('__MB__');
+                    var lock = false;
+                    var mbox = rcmail.env.as_md5_folders[parts[1]];
+                    var post_data = {
+                        _uid: parts[0],
+                        _flag: flag,
+                        _mbox: mbox,
+                        _remote: 1
+                    };
+                    rcmail.http_post('mark', post_data, lock);
+                    if (flag == 'flagged') {
+                        tr.addClass('flagged');
+                        $("td.flag span", tr).removeClass('unflagged').addClass('flagged');
+                        rcmail.message_list.rows[id].flagged = 1;
+                    } else {
+                        tr.removeClass('flagged');
+                        $("td.flag span", tr).removeClass('flagged').addClass('unflagged');
+                        rcmail.message_list.rows[id].flagged = 0;
+                    }
+                    return false;
+                }
+            });
+            /* End registering event listeners */
+        });
+
+    });
+})(jQuery);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/advanced_search.min.js	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,1 @@
+(function($){$.stack={date_criteria:{},flag_criteria:{},email_criteria:{},row:null,messages:null};var search_loading="";$(document).on("change","#button_display_option",function(e){var img=$("img",$(this).closest("p"));var src=img.attr("src");if(this.value=="messagemenu"){src=src.replace("menu_location_b.jpg","menu_location_a.jpg")}else{src=src.replace("menu_location_a.jpg","menu_location_b.jpg")}img.attr("src",src)});$(document).on("change","#_show_message_mbox_info, #_show_message_label_header",function(e){var img=$("img",$(this).closest("p"));if($(this).is(":checked")){img.removeClass("disabled")}else{img.addClass("disabled")}});rcmail.addEventListener("plugin.show",function(r){$.stack.date_criteria=r.date_criteria;$.stack.flag_criteria=r.flag_criteria;$.stack.email_criteria=r.email_criteria;$.stack.row=r.row;$.stack.html=r.html;var $html=$(r.html);var saved_searches_label=rcmail.gettext("saved_searches","advanced_search");var saved_searches='<span class="saved_searches"> <label for="select_saved_search">'+saved_searches_label+': <select name="select_saved_search" id="select_saved_search"><option value=""></option></select></label></span>';title=$("<div>"+r.title+saved_searches+"<div>");var saved_searches_select=$("[name=select_saved_search]",title);if(r.saved_searches.length){var i;for(i in r.saved_searches){saved_searches_select.append('<option value="'+r.saved_searches[i]+'">'+r.saved_searches[i]+"</option>")}}$html.dialog({width:640,height:300,resizable:true,draggable:true,title:title,dialogClass:"advanced_search_dialog",close:function(){$("body").css("overflow","auto")},create:function(){$("body").css("overflow","hidden")}});saved_searches_select.bind("blur click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select",function(e){e.stopPropagation()});saved_searches_select.bind("mouseenter",function(e){saved_searches_select.focus()});saved_searches_select.bind("change",function(e){var search_name=$(this).val();if(search_name==""){$("#adsearch-popup").html($.stack.html)}else{rcmail.http_request("plugin.get_saved_search",{search_name:search_name});$("[name=delete]","#adsearch-popup").show()}})});rcmail.addEventListener("plugin.load_saved_search",function(search){var $form=$("#adsearch-popup form"),$tr=$("tr",$("tbody",$form)).not(":first").not(":last"),$last=$("tr:last",$("tbody",$form));saved_search=search.search,data=[];$tr.remove();$("[name=folder]",$form).val(search.folder);$("[name=subfolder]",$form).prop("checked",search.sub_folders=="true");$("span.sub-folders",$form).css("display",search.folder=="all"?"none":"inline");var i=0;for(i;i<saved_search.length;i++){var row;if(i==0){row=$("<tr>"+$("tr:eq(1)",$.stack.html).html()+"</tr>")}else{row=$($.stack.row)}$("[name=method]",row).val(saved_search[i].method);$("[name=filter]",row).val(saved_search[i].filter);$("[name=not]",row).prop("checked",saved_search[i]["not"]=="true");$("[name=filter-exclude]",row).prop("checked",saved_search[i]["excluded"]=="true");$last.before(row);$("[name=filter]",row).trigger("change");$("[name=filter-val]",row).val(saved_search[i]["filter-val"])}});rcmail.addEventListener("plugin.advanced_search_add_header",function(evt){if($("#messagelistcontainer #rcavbox1").length==0){var Mbox=rcmail.gettext("mbox","advanced_search");$("#messagelistcontainer table.fixedcopy thead tr:first").append('<td class="mbox" id="rcavbox1"><span class="mbox">'+Mbox+"</span></td>");$("#messagelistcontainer table#messagelist thead tr:first").append('<td class="mbox" id="rcavbox2"><span class="mbox">'+Mbox+"</span></td>")}});rcmail.addEventListener("plugin.advanced_search_del_header",function(evt){$("#messagelistcontainer #rcavbox1").remove();$("#messagelistcontainer #rcavbox2").remove()});rcube_webmail.prototype.advanced_search_add_mbox=function(mbox,count,showMbox){if(!this.gui_objects.messagelist||!this.message_list){return false}var colspan=showMbox==true?9:8;$(rcmail.message_list.list).append('<tr class="aslabel_mbox"><td><span class="aslabel_found">'+count+'</span></td><td colspan="'+colspan+'">'+mbox+"</td></tr>")};rcube_webmail.prototype.advanced_search_active=function(param){var page=param.replace("_page=","");rcmail.http_request("plugin.trigger_search_pagination",{_page:page})};var get_search_data=function(){var $form=$("#adsearch-popup form"),$tr=$("tr",$("tbody",$form)).not(":first").not(":last"),data=[];if($tr.length){$tr.each(function(){var item={not:$("input[name=not]",$(this)).prop("checked"),excluded:$("input[name=filter-exclude]",$(this)).prop("checked"),filter:$("option:selected",$("select[name=filter]",$(this))).val(),"filter-val":$("input[name=filter-val]",$(this)).val()};if($("select[name=method]",$(this)).length){item.method=$("option:selected",$("select[name=method]",$(this))).val()}data.push(item)})}return data};$(document).on("click","input[name=search]",function(e){e.preventDefault();rcmail.clear_message_list();$.stack.messages=$("tr",$("tbody","#messagelist"));var $form=$("#adsearch-popup form");search_loading=rcmail.set_busy(true,"loading");rcmail.http_request("plugin.trigger_search",{search:get_search_data(),current_folder:rcmail.env.mailbox,folder:$("select[name=folder]",$form).val(),sub_folders:$("input[name=subfolder]",$form).prop("checked")});$("#adsearch-popup").closest("div.ui-dialog-content").dialog("close")});$(document).on("click","input[name=reset]",function(e){e.preventDefault();$("#adsearch-popup").html($.stack.html);$("[name=select_saved_search]").val("")});$(document).on("click","button[name=add]",function(e){e.preventDefault();$(this).closest("tr").after($.stack.row)});$(document).on("click","button[name=delete]",function(e){e.preventDefault();$(this).closest("tr").remove()});$(document).on("click","select[name=filter]",function(e){var $row_input=$(this).nextUntil("tr","input[name=filter-val]"),old_avs_type=$row_input.data("avs_type");if($.inArray($(this).val(),$.stack.date_criteria)>=0){if(old_avs_type!=="date"){$row_input.val("");$row_input.datepicker({dateFormat:rcmail.env.date_format})}$row_input.data("avs_type","date")}else if($.inArray($(this).val(),$.stack.email_criteria)>=0){if(old_avs_type!=="email"){rcmail.init_address_input_events($row_input,"");rcmail.addEventListener("autocomplete_insert",function(e){e.field.value=e.insert.replace(/.*<(\S*?@\S*?)>.*/,"$1")})}$row_input.data("avs_type","email")}else if($.inArray($(this).val(),$.stack.flag_criteria)>=0){if(old_avs_type!=="flag_criteria"){$row_input.val("");$row_input.hide()}$row_input.data("avs_type","flag_criteria")}else{$row_input.data("avs_type","none")}switch(old_avs_type){case"date":if($row_input.data("avs_type")!=="date"&&$row_input.hasClass("hasDatepicker")){$row_input.datepicker("destroy")}break;case"email":if($row_input.data("avs_type")!=="email"){$row_input.removeAttr("autocomplete");$row_input.unbind("keydown");$row_input.unbind("keypress")}break;case"flag_criteria":if($row_input.data("avs_type")!=="flag_criteria"&&!$row_input.is(":visible")){$row_input.show()}break}});$(document).on("click","select[name=folder]",function(e){$("span.sub-folders",$(this).closest("form")).css("display",$(this).val()=="all"?"none":"inline")});$(document).on("click","a.icon.advanced-search, a.button.advanced-search",function(e){e.preventDefault();if(!$("#adsearch-popup").length){rcmail.http_request("plugin.display_advanced_search")}else{$("#adsearch-popup").closest("div.ui-dialog-content").dialog("open")}});$(document).on("keydown keypress","#adsearch-popup",function(e){e.stopPropagation()});$(document).on("click","#adsearch-popup input.delete_search",function(e){e.stopPropagation();e.preventDefault();var search_name=$("[name=select_saved_search]").val();var txt={};txt["cancel"]=rcmail.get_label("advanced_search.cancel");txt["delete"]=rcmail.get_label("advanced_search.delete");$("<p><strong>"+search_name+"</strong></p>").dialog({resizable:true,height:180,modal:true,title:rcmail.gettext("advanced_search.deletesearch"),buttons:[{text:txt["delete"],click:function(){rcmail.http_request("plugin.delete_search",{search_name:search_name});$("[value="+search_name+"]","[name=select_saved_search]").remove();$("[name=select_saved_search]").val("").trigger("change");$(this).dialog("close")}},{text:txt["cancel"],click:function(){$(this).dialog("close")}}]})});$(document).on("click","#save_the_search",function(e){e.stopPropagation();e.preventDefault();var labelName=rcmail.gettext("name","advanced_search");var labelSave=rcmail.gettext("save","advanced_search");var labelCancel=rcmail.gettext("cancel","advanced_search");var save_search="<table>"+"  <tr><td>"+labelName+' </td><td><input type="text" name="search_name" /></td></tr>'+'  <tr><td></td><td><input type="submit" class="button mainaction" value="'+labelSave+'" /> <input type="reset" class="button reset" value="'+labelCancel+'" /></td></tr>'+"</table>";save_search=$(save_search);$("[name=search_name]",save_search).val($("[name=select_saved_search]").val());save_search.dialog({title:rcmail.gettext("advanced_search.save_the_search"),dialogClass:"saveTheSearch",close:function(){$(this).remove()},width:$("#adsearch-popup").width(),height:$("#adsearch-popup").height(),modal:true});$(".mainaction",save_search).bind("click",function(e){e.preventDefault();e.stopPropagation();var search_name=$("[name=search_name]",save_search).val();var $form=$("#adsearch-popup form");rcmail.http_request("plugin.save_search",{search:get_search_data(),search_name:search_name,folder:$("select[name=folder]",$form).val(),sub_folders:$("input[name=subfolder]",$form).prop("checked")});var isNewSearch=true;$("[name=select_saved_search] option").each(function(e){if($(this).attr("value")==search_name){isNewSearch=false}});if(isNewSearch){$("[name=select_saved_search]").append('<option value="'+search_name+'">'+search_name+"</option>");$("[name=select_saved_search]").val(search_name)}save_search.dialog("close")});$(".reset",save_search).bind("click",function(e){e.preventDefault();e.stopPropagation();save_search.dialog("close")})});var advanced_search_redirect_draft_messages=function(check){if(rcmail.env.search_request=="advanced_search_active"){if(rcmail.task=="mail"){uid=rcmail.get_single_uid();if(uid&&(!rcmail.env.uid||uid!=rcmail.env.uid||check)){if(rcmail.env.mailbox==rcmail.env.drafts_mailbox||check){url={_mbox:this.env.mailbox,_search:"advanced_search_active"};url[this.env.mailbox==this.env.drafts_mailbox?"_draft_uid":"_uid"]=uid;this.goto_url("compose",url,true)}}}return true}return false};var advanced_search_perform_action=function(props,action){var raw_selection=rcmail.message_list.get_selection();var md5_folders=rcmail.env.as_md5_folders;var i;var selections={};for(i in raw_selection){raw_selection[i];var parts=raw_selection[i].split("__MB__");var mid=parts[0];var md5Mbox=parts[1];var mbox=md5_folders[md5Mbox];if(!selections[mbox]){selections[mbox]=[]}selections[mbox].push(mid)}if(i!=undefined){if(rcmail.env.action=="show"){lock=rcmail.set_busy(true,"movingmessage")}else{rcmail.show_contentframe(false)}rcmail.enable_command(rcmail.env.message_commands,false);var j;for(j in selections){rcmail.select_folder(j,"",true);rcmail.env.mailbox=j;var uids=selections[j].join(",");var lock=false,post_data=rcmail.selection_post_data({_target_mbox:props.id,_uid:uids});rcmail._with_selected_messages(action,post_data,lock)}rcmail.env.uid=undefined;rcmail.message_list.selection=[]}};var advanced_search_check_multi_mbox=function(){var raw_selection=rcmail.message_list.get_selection();var md5_folders=rcmail.env.as_md5_folders;var i;var mcount=0;var selections={};for(i in raw_selection){raw_selection[i];var parts=raw_selection[i].split("__MB__");var mid=parts[0];var md5Mbox=parts[1];var mbox=md5_folders[md5Mbox];if(!selections[mbox]){selections[mbox]=[];mcount++}selections[mbox].push(mid)}return{isMulti:mcount>1,selections:selections}};rcmail.addEventListener("init",function(){rcmail.register_command("plugin.advanced_search",true,true);rcmail.enable_command("plugin.advanced_search",true);rcmail.addEventListener("plugin.search_complete",function(r){rcmail.set_busy(false,"loading",search_loading);rcmail.addEventListener("beforeedit",function(command){rcmail.env.framed=true;if(advanced_search_redirect_draft_messages(true)){return false}});rcmail.message_list.addEventListener("dblclick",function(o){advanced_search_redirect_draft_messages()});rcmail.message_list.addEventListener("select",function(list){if(rcmail.env.search_request=="advanced_search_active"){if(list.selection.length==1){var parts=list.selection[0].split("__MB__");var mid=parts[0];var md5Mbox=parts[1];var mbox=rcmail.env.as_md5_folders[md5Mbox];rcmail.env.uid=mid;if(rcmail.env.mailbox!=mbox){var ex=[];li=rcmail.get_folder_li(mbox,"",true);parent=$(li).parents(".mailbox");parent.each(function(){div=$(this.getElementsByTagName("div")[0]);a=$(this.getElementsByTagName("a")[0]);if(div.hasClass("collapsed")){ex.push($(a).attr("rel"))}});for(var i=ex.length-1;i>=0;i--){rcmail.command("collapse-folder",ex[i])}rcmail.select_folder(mbox,"",true);rcmail.env.mailbox=mbox}return false}}});rcmail.addEventListener("beforemoveto",function(props){if(rcmail.env.search_request=="advanced_search_active"){advanced_search_perform_action(props,"moveto");return false}});rcmail.addEventListener("beforedelete",function(props){if(rcmail.env.search_request=="advanced_search_active"){advanced_search_perform_action(props,"delete");return false}});rcmail.addEventListener("beforemark",function(flag){if(rcmail.env.search_request=="advanced_search_active"){var res=advanced_search_check_multi_mbox();var i;var sel=res.selections;for(i in sel){var uids=sel[i].join(",");var lock=false;var post_data={_uid:uids,_flag:flag,_mbox:i,_remote:1};rcmail.http_post("mark",post_data,lock)}var raw_selection=rcmail.message_list.get_selection();for(i in raw_selection){var key=raw_selection[i];switch(flag){case"read":rcmail.message_list.rows[key].unread=0;break;case"unread":rcmail.message_list.rows[key].unread=1;break;case"flagged":rcmail.message_list.rows[key].flagged=1;break;case"unflagged":rcmail.message_list.rows[key].flagged=0;break}}var messages=[];var selections=rcmail.message_list.get_selection();var j;for(j in selections){messages.push("#rcmrow"+selections[j])}var selector=messages.join(", ");var selection=$(selector);switch(flag){case"read":selection.removeClass("unread");break;case"unread":selection.addClass("unread");break;case"flagged":selection.addClass("flagged");$("td.flag span",selection).removeClass("unflagged").addClass("flagged");break;case"unflagged":selection.removeClass("flagged");$("td.flag span",selection).removeClass("flagged").addClass("unflagged");break;default:break}return false}});rcmail.addEventListener("beforeforward",function(props){if(rcmail.env.search_request=="advanced_search_active"&&rcmail.message_list.selection.length>1){var res=advanced_search_check_multi_mbox();if(res.isMulti==true){return false}else{var i,url,sel=res.selections;for(i in sel){url="&_forward_uid="+sel[i].join(",")+"&_mbox="+i}url+="&_attachment=1&_action=compose";window.location=location.pathname+rcmail.env.comm_path+url;return false}}});rcmail.addEventListener("beforeforward-attachment",function(props){if(rcmail.env.search_request=="advanced_search_active"&&rcmail.message_list.selection.length>1){var res=advanced_search_check_multi_mbox();if(res.isMulti==true){return false}else{var i,url,sel=res.selections;for(i in sel){url="&_forward_uid="+sel[i].join(",")+"&_mbox="+i}url+="&_attachment=1&_action=compose";window.location=location.pathname+rcmail.env.comm_path+url;return false}}});rcmail.addEventListener("beforetoggle_flag",function(props){if(rcmail.env.search_request=="advanced_search_active"){var flag=$(props).hasClass("unflagged")?"flagged":"unflagged";var tr=$(props).closest("tr");var id=tr.attr("id").replace("rcmrow","");var parts=id.split("__MB__");var lock=false;var mbox=rcmail.env.as_md5_folders[parts[1]];var post_data={_uid:parts[0],_flag:flag,_mbox:mbox,_remote:1};rcmail.http_post("mark",post_data,lock);if(flag=="flagged"){tr.addClass("flagged");$("td.flag span",tr).removeClass("unflagged").addClass("flagged");rcmail.message_list.rows[id].flagged=1}else{tr.removeClass("flagged");$("td.flag span",tr).removeClass("flagged").addClass("unflagged");rcmail.message_list.rows[id].flagged=0}return false}})})})})(jQuery);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/advanced_search.php	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,1088 @@
+<?php
+/**
+ * Processing an advanced search over an E-Mail Account
+ *
+ * @version 2.1.5
+ * @licence GNU GPLv3+
+ * @author  Wilwert Claude
+ * @author  Ludovicy Steve
+ * @author  Chris Moules
+ * @website http://www.gms.lu
+ *
+ * Updated by Alex S Grebenschikov (www.poralix.com)
+ * to make it compatible with RoundCube 1.3.0
+ * Last modified: Tue Aug  1 06:41:46 CEST 2017
+ *
+ */
+
+class advanced_search extends rcube_plugin
+{
+
+    /**
+     * Instance of rcmail
+     *
+     * @var object
+     * @access private
+     */
+    private $rc;
+
+    public $task = 'mail|settings';
+
+    /**
+     * Plugin config
+     *
+     * @var array
+     * @access private
+     */
+    private $config;
+
+    /**
+     * Localization strings
+     *
+     * @var array
+     * @access private
+     */
+    private $i18n_strings = array();
+
+    /**
+     * Initialisation of the plugin
+     *
+     * @access public
+     * @return null
+     */
+    public function init()
+    {
+        $this->rc = rcmail::get_instance();
+        $this->load_config("config-default.inc.php");
+        $this->load_config();
+        $this->config = $this->rc->config->get('advanced_search_plugin');
+        $this->register_action('plugin.display_advanced_search', array($this, 'display_advanced_search'));
+        $this->register_action('plugin.trigger_search', array($this, 'trigger_search'));
+        $this->register_action('plugin.trigger_search_pagination', array($this, 'trigger_search_pagination'));
+        $this->register_action('plugin.save_search', array($this, 'save_search'));
+        $this->register_action('plugin.delete_search', array($this, 'delete_search'));
+        $this->register_action('plugin.get_saved_search', array($this, 'get_saved_search'));
+
+        $this->skin = $this->rc->config->get('skin');
+        $this->add_texts('localization', true);
+        $this->populate_i18n();
+        if(isset($this->config['criteria'])) {
+            foreach($this->config['criteria'] as $key => $translation) {
+                $this->config['criteria'][$key] = $this->gettext($key);
+            }
+        }
+        $this->include_script('advanced_search.js');
+
+        if ($this->rc->task == 'mail') {
+            $file = 'skins/' . $this->skin . '/advanced_search.css';
+
+            if (file_exists($this->home . '/' . $file)) {
+                $this->include_stylesheet($file);
+            } else {
+                $this->include_stylesheet('skins/default/advanced_search.css');
+            }
+
+            if (empty($this->rc->action)) {
+                $this->add_menu_entry();
+            }
+        } elseif ($this->rc->task == 'settings') {
+            $this->add_hook('preferences_list', array($this, 'preferences_list'));
+            $this->add_hook('preferences_save', array($this, 'preferences_save'));
+            $this->add_hook('preferences_sections_list', array($this, 'preferences_section'));
+            $file = 'skins/' . $this->skin . '/advanced_search.css';
+            if (file_exists($this->home . '/' . $file)) {
+                $this->include_stylesheet($file);
+            } else {
+                $this->include_stylesheet('skins/default/advanced_search.css');
+            }
+        }
+
+        $this->add_hook('startup', array($this, 'startup'));
+    }
+
+
+    public function startup($args)
+    {
+        $search = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GET);
+        if (!isset($search)) {
+            $search = rcube_utils::get_input_value('_search', rcube_utils::INPUT_POST);
+        }
+        $rsearch = $search == 'advanced_search_active';
+        $uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GET);
+        $draft_uid = rcube_utils::get_input_value('_draft_uid', rcube_utils::INPUT_GET);
+        $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GET);
+        $page = rcube_utils::get_input_value('_page', rcube_utils::INPUT_GET);
+        $sort = rcube_utils::get_input_value('_sort', rcube_utils::INPUT_GET);
+
+        if (!empty($uid)) {
+            $parts = explode('__MB__', $uid);
+            if (count($parts) == 2) {
+                $search = 'advanced_search_active';
+            }
+        }
+        if (!empty($draft_uid)) {
+            $parts = explode('__MB__', $draft_uid);
+            if (count($parts) == 2) {
+                $search = 'advanced_search_active';
+            }
+        }
+
+        if ($search == 'advanced_search_active') {
+            if ($args['action'] == 'show' && !empty($uid)) {
+                $parts = explode('__MB__', $uid);
+                $uid = $parts[0];
+                $this->rc->output->redirect(array('_task' => 'mail', '_action' => $args['action'], '_mbox' => $mbox, '_uid' => $uid));
+            }
+            if ($args['action'] == 'compose') {
+                $draft_uid = rcube_utils::get_input_value('_draft_uid', rcube_utils::INPUT_GET);
+                $parts = explode('__MB__', $draft_uid);
+                $draft_uid = $parts[0];
+                if (!empty($draft_uid)) {
+                    $this->rc->output->redirect(array('_task' => 'mail', '_action' => $args['action'], '_mbox' => $mbox, '_draft_uid' => $draft_uid));
+                }
+            }
+            if ($args['action'] == 'list' && $rsearch) {
+                $this->rc->output->command('advanced_search_active', '_page=' . $page . '&_sort=' . $sort);
+                $this->rc->output->send();
+                $args['abort'] = true;
+            }
+            if ($args['action'] == 'mark') {
+                $flag = rcube_utils::get_input_value('_flag', rcube_utils::INPUT_POST);
+                $uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST);
+
+                $post_str = '_flag=' . $flag . '&_uid=' . $uid;
+                if ($quiet = rcube_utils::get_input_value('_quiet', rcube_utils::INPUT_POST)) {
+                    $post_str .= '&_quiet=' . $quiet;
+                }
+                if ($from = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST)) {
+                    $post_str .= '&_from=' . $from;
+                }
+                if ($count = rcube_utils::get_input_value('_count', rcube_utils::INPUT_POST)) {
+                    $post_str .= '&_count=' . $count;
+                }
+                if ($ruid = rcube_utils::get_input_value('_ruid', rcube_utils::INPUT_POST)) {
+                    $post_str .= '&_ruid=' . $ruid;
+                }
+                $this->rc->output->command('label_mark', $post_str);
+                $this->rc->output->send();
+                $args['abort'] = true;
+            }
+
+        } else {
+            if ($args['action'] != 'plugin.get_saved_search' && $args['action'] != 'plugin.save_search' && $args['action'] != 'plugin.delete_search') {
+                $this->rc->output->command('plugin.advanced_search_del_header', array());
+            }
+        }
+    }
+
+    /**
+     * This function populates an array with localization texts.
+     * This is needed as ew are using a lot of localizations from core.
+     * The core localizations are not avalable directly in JS
+     *
+     * @access private
+     * @return null
+     */
+    private function populate_i18n()
+    {
+        $core = array('advsearch', 'search', 'resetsearch', 'addfield', 'delete', 'cancel');
+
+        foreach ($core as $label) {
+            $this->i18n_strings[$label] = $this->rc->gettext($label);
+        }
+
+        $local = array('in', 'and', 'or', 'not', 'where', 'exclude', 'andsubfolders', 'allfolders', 'save_the_search', 'has_been_saved', 'deletesearch', 'has_been_deleted');
+
+        foreach ($local as $label) {
+            $this->i18n_strings[$label] = $this->gettext($label);
+        }
+    }
+
+    /**
+     * This adds a button into the configured menu to use the advanced search
+     *
+     * @access public
+     * @return null
+     */
+    public function add_menu_entry()
+    {
+        $displayOptions = $this->rc->config->get('advanced_search_display_options', array());
+        $target_menu = (isset($displayOptions['target_menu']) && !empty($displayOptions['target_menu'])) ? $displayOptions['target_menu'] : $this->config['target_menu'];
+        if ($target_menu != 'toolbar') {
+            $this->api->add_content(
+                html::tag(
+                    'li',
+                    null,
+                    $this->api->output->button(
+                        array(
+                            'command'    => 'plugin.advanced_search',
+                            'label'      => 'advsearch',
+                            'type'       => 'link',
+                            'classact'   => 'icon advanced-search active',
+                            'class'      => 'icon advanced-search',
+                            'innerclass' => 'icon advanced-search'
+                        )
+                    )
+                ),
+                $target_menu
+            );
+        } else {
+            $this->api->add_content(
+                $this->api->output->button(
+                    array(
+                        'command'    => 'plugin.advanced_search',
+                        'title'      => 'advsearch',
+                        'label'      => 'search',
+                        'type'       => 'link',
+                        'classact'   => 'button advanced-search active',
+                        'class'      => 'button advanced-search',
+                        'innerclass' => 'button advanced-search',
+                    )
+                ),
+                $target_menu
+            );
+        }
+    }
+
+    /**
+     * This function quotes some specific values based on their data type
+     *
+     * @param mixed $input The value to get quoted
+     * @access public
+     * @return The quoted value
+     */
+    public function quote($value)
+    {
+        if (getType($value) == 'string') {
+            if (!preg_match('/"/', $value)) {
+                $value = preg_replace('/^"/', '', $value);
+                $value = preg_replace('/"$/', '', $value);
+                $value = preg_replace('/"/', '\\"', $value);
+            }
+
+            $value = '"' . $value . '"';
+        }
+
+        return $value;
+    }
+
+    /**
+     * This function generates the IMAP compatible search query based on the request data (by javascript)
+     *
+     * @param array $input The raw criteria data sent by javascript
+     * @access private
+     * @return string or int
+     */
+    private function process_search_part($search_part)
+    {
+        $command_str = '';
+        $flag = false;
+
+        // Check for valid input
+        if (!array_key_exists($search_part['filter'], $this->config['criteria'])) {
+            $this->rc->output->show_message($this->gettext('internalerror'), 'error');
+
+            return 0;
+        }
+        if (in_array($search_part['filter'], $this->config['flag_criteria'])) {
+            $flag = true;
+        }
+        if (!$flag && !(isset($search_part['filter-val']) && $search_part['filter-val'] != '')) {
+            return 1;
+        }
+
+        // Negate part
+        if ($search_part['not'] == 'true') {
+            $command_str .= 'NOT ';
+        }
+
+        $command_str .= $search_part['filter'];
+
+        if (!$flag) {
+            if (in_array($search_part['filter'], $this->config['date_criteria'])) {
+                // Take date format from user environment
+                $date_format = $this->rc->config->get('date_format', 'Y-m-d');
+                // Try to use PHP5.2+ DateTime but fallback to ugly old method
+                if (class_exists('DateTime')) {
+                    $date = DateTime::createFromFormat($date_format, $search_part['filter-val']);
+                    $command_str .= ' ' . $this->quote($date->format("d-M-Y"));
+                } else {
+                    $date_format = preg_replace('/(\w)/', '%$1', $date_format);
+                    $date_array = strptime($search_part['filter-val'], $date_format);
+                    $unix_ts = mktime($date_array['tm_hour'], $date_array['tm_min'], $date_array['tm_sec'], $date_array['tm_mon']+1, $date_array['tm_mday'], $date_array['tm_year']+1900);
+                    $command_str .= ' ' . $this->quote(date("d-M-Y", $unix_ts));
+                }
+            } elseif (in_array($search_part['filter'], $this->config['email_criteria'])) {
+                // Strip possible ',' added by autocomplete
+                $command_str .= ' ' . $this->quote(trim($search_part['filter-val'], " \t,"));
+            } else {
+                // Don't try to use a value for a binary flag object
+                $command_str .= ' ' . $this->quote($search_part['filter-val']);
+            }
+        }
+
+        return $command_str;
+    }
+
+    /**
+     * This function generates the IMAP compatible search query based on the request data (by javascript)
+     *
+     * @param array $input The raw criteria data sent by javascript
+     * @access public
+     * @return The final search command
+     */
+    public function get_search_query($input)
+    {
+        $command = array();
+
+        foreach ($input as $search_part) {
+            // Skip excluded parts
+            if ($search_part['excluded'] == 'true') {
+                continue;
+            }
+            if (! $part_command = $this->process_search_part($search_part)) {
+                return 0;
+            }
+            // Skip invalid parts
+            if ($part_command === 1) {
+                continue;
+            }
+
+            $command[] = array('method' => isset($search_part['method']) ? $search_part['method'] : 'and',
+                               'command' => $part_command);
+        }
+
+        $command_string = $this->build_search_string($command);
+
+        return $command_string;
+    }
+
+    /**
+     * This function converts the preconfigured query parts (as array) into an IMAP compatible string
+     *
+     * @param array $command_array An array containing the advanced search criteria
+     * @access public
+     * @return The command string
+     */
+    private function build_search_string($command_array)
+    {
+        $command = array();
+        $paranthesis = 0;
+        $prev_method = null;
+        $next_method = null;
+        $cnt = count($command_array);
+
+        foreach ($command_array as $k => $v) {
+            $part = '';
+            $next_method = 'unknown';
+
+            // Lookup next method
+            if ($k < $cnt-1) {
+                $next_method = $command_array[$k+1]['method'];
+            }
+
+            // If previous option was OR, close any open brakets
+            if ($paranthesis > 0 && $prev_method == 'or' && $v['method'] != 'or') {
+                for (; $paranthesis > 0; $paranthesis--) {
+                    $part .= ')';
+                }
+            }
+
+            // If there are two consecutive ORs, add brakets
+            // If the next option is a new OR, add the prefix here
+            // If the next option is _not_ an OR, and the current option is AND, prefix ALL
+            if ($next_method == 'or') {
+                if ($v['method'] == 'or') {
+                    $part .= ' (';
+                    $paranthesis++;
+                }
+                $part .= 'OR ';
+            } elseif ($v['method'] == 'and') {
+                $part .= 'ALL ';
+            }
+
+            $part .= $v['command'];
+
+            // If this is the end of the query, and we have open brakets, close them
+            if ($k == $cnt-1 && $paranthesis > 0) {
+                for (; $paranthesis > 0; $paranthesis--) {
+                    $part .= ')';
+                }
+            }
+
+            $prev_method = $v['method'];
+            $command[] = $part;
+        }
+
+        $command = implode(' ', $command);
+
+        return $command;
+    }
+
+    /**
+     * This functions sends the initial data to the client side where a form (in dialog) is built for the advanced search
+     *
+     * @access public
+     * @return null
+     */
+    public function display_advanced_search()
+    {
+        $ret = array('html' => $this->generate_searchbox(),
+                     'row' => $this->add_row(),
+                     'saved_searches' => $this->get_saved_search_names(),
+                     'title' => $this->i18n_strings['advsearch'],
+                     'date_criteria' => $this->config['date_criteria'],
+                     'flag_criteria' => $this->config['flag_criteria'],
+                     'email_criteria' => $this->config['email_criteria']);
+
+        $this->rc->output->command('plugin.show', $ret);
+    }
+
+    public function generate_searchbox()
+    {
+        $search_button = new html_inputfield(array('type' => 'submit', 'name' => 'search', 'class' => 'button mainaction', 'value' => $this->i18n_strings['search']));
+        $reset_button = new html_inputfield(array('type' => 'reset', 'name' => 'reset', 'class' => 'button reset', 'value' => $this->i18n_strings['resetsearch']));
+        $save_button = html::tag('input', array('type' => 'submit', 'name' => 'save_the_search', id=> 'save_the_search', 'class' => 'button save_search', 'value' => $this->i18n_strings['save_the_search']));
+        $delete_button = new html_inputfield(array('type' => 'submit', 'name' => 'delete', 'style' => 'display: none;', 'class' => 'button delete_search', 'value' => $this->i18n_strings['deletesearch']));
+
+        $layout_table = new html_table();
+        $layout_table->add(null, $search_button->show());
+        $folderConfig = array('name' => 'folder');
+        $layout_table->add(
+            null,
+            $this->i18n_strings['in'] . ': ' .
+            $this->folder_selector($folderConfig)->show($this->rc->storage->get_folder()) .
+            html::span(
+                array('class' => 'sub-folders'),
+                $this->i18n_strings['andsubfolders'] . ': ' .
+                html::tag(
+                    'input',
+                    array('type' => 'checkbox', 'name' => 'subfolder'),
+                    null
+                )
+            ) .
+            $this->i19n_strings['where']
+        );
+        $first_row = $this->add_row(true);
+        $layout_table->add_row();
+        $layout_table->add(array('class' => 'adv-search-and-or'), null);
+        $layout_table->add(null, $first_row);
+        $layout_table->add_row();
+        $layout_table->add(null, $search_button->show());
+        $layout_table->add(null, $save_button . ' ' . $reset_button->show() . ' ' . $delete_button->show());
+
+        return html::tag(
+            'div',
+            array('id' => 'adsearch-popup'),
+            html::tag(
+                'form',
+                array('method' => 'post', 'action' => '#'),
+                $layout_table->show()
+            )
+        );
+    }
+
+    /**
+     * This function is used to render the html of the advanced search form and also
+     * the later following rows are created by this function
+     *
+     * @param array   $folders Array of folders
+     * @param boolean $first   True if form gets created, False to create a new row
+     * @access public
+     * @return string The final html
+     */
+    public function add_row($first = false)
+    {
+        $row_html = '';
+        $optgroups = '';
+
+        $criteria = $this->config['criteria'];
+        $all_criteria = array(
+            $this->gettext('Common') => $this->config['prefered_criteria'],
+            $this->gettext('Addresses') => $this->config['email_criteria'],
+            $this->gettext('Dates') => $this->config['date_criteria'],
+            $this->gettext('Flags') => $this->config['flag_criteria'],
+            $this->gettext('Other') => $this->config['other_criteria'],
+        );
+
+        foreach ($all_criteria as $label => $specific_criteria) {
+            $options = '';
+
+            foreach ($specific_criteria as $value) {
+                $options .= html::tag('option', array('value' => $value), $criteria[$value]);
+            }
+
+            $optgroups .= html::tag('optgroup', array('label' => $label), $options);
+        }
+
+        $tmp = html::tag('select', array('name' => 'filter'), $optgroups);
+        $tmp .= $this->i18n_strings['not'] . ':' . html::tag('input', array('type' => 'checkbox', 'name' => 'not'), null);
+        $tmp .= html::tag('input', array('type' => 'text', 'name' => 'filter-val'));
+        $tmp .= $this->i18n_strings['exclude'] . ':' . html::tag('input', array('type' => 'checkbox', 'name' => 'filter-exclude'), null);
+        $tmp .= html::tag('button', array('name' => 'add', 'class' => 'add'), $this->i18n_strings['addfield']);
+
+        if ($first) {
+            $row_html = $tmp;
+        } else {
+            $and_or_select = new html_select(array('name' => 'method'));
+            $and_or_select->add($this->i18n_strings['and'], 'and');
+            $and_or_select->add($this->i18n_strings['or'], 'or');
+            $tmp .= html::tag('button', array('name' => 'delete', 'class' => 'delete'), $this->i18n_strings['delete']);
+            $row_html = html::tag(
+                'tr',
+                null,
+                html::tag(
+                    'td',
+                    array('class' => 'adv-search-and-or'),
+                    $and_or_select->show()
+                ) .
+                html::tag(
+                    'td',
+                    null,
+                    $tmp
+                )
+            );
+        }
+
+        return $row_html;
+    }
+
+    /**
+     * Return folders list as html_select object
+     *
+     * This is a copy of the core function and adapted to fit
+     * the needs of the advanced_search function
+     *
+     * @param array $p Named parameters
+     *
+     * @return html_select HTML drop-down object
+     */
+    public function folder_selector($p = array())
+    {
+        $p += array('maxlength' => 100, 'realnames' => false, 'is_escaped' => true);
+        $a_mailboxes = array();
+        $storage = $this->rc->get_storage();
+
+        $list = $storage->list_folders_subscribed();
+        $delimiter = $storage->get_hierarchy_delimiter();
+
+        foreach ($list as $folder) {
+            $this->rc->build_folder_tree($a_mailboxes, $folder, $delimiter);
+        }
+
+        $select = new html_select($p);
+        $select->add($this->i18n_strings['allfolders'], "all");
+
+        $this->rc->render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p);
+
+        return $select;
+    }
+
+    public function trigger_search_pagination($param)
+    {
+        $_GET['search'] = $_SESSION['av_search'];
+        $_GET['folder'] = $_SESSION['av_folder'];
+        $_GET['sub_folders'] = $_SESSION['av_sub_folders'];
+        $this->trigger_search(true);
+    }
+
+    /**
+     * Here is where the actual query is fired to the imap server and the result is evaluated and sent back to the client side
+     *
+     * @access public
+     * @return null
+     */
+    public function trigger_search($inPagination = false)
+    {
+        $search = rcube_utils::get_input_value('search', rcube_utils::INPUT_GPC);
+        // reset list_page and old search results
+        $this->rc->storage->set_page(1);
+        $this->rc->storage->set_search_set(null);
+        $page = rcube_utils::get_input_value('_page', rcube_utils::INPUT_GPC);
+        $page = $page ? $page : 1;
+        $pagesize = $this->rc->storage->get_pagesize();
+
+        if (!empty($search)) {
+            $mbox = rcube_utils::get_input_value('folder', rcube_utils::INPUT_GPC);
+            $imap_charset = RCMAIL_CHARSET;
+            $sort_column = rcmail_sort_column();
+            $search_str = $this->get_search_query($search);
+            $sub_folders = rcube_utils::get_input_value('sub_folders', rcube_utils::INPUT_GPC) == 'true';
+            $folders = array();
+            $result_h = array();
+            $count = 0;
+            $new_id = 1;
+            $current_mbox = $this->rc->storage->get_folder();
+            $uid_list = array();
+            //Store information in session for pagination
+            $_SESSION['av_search'] = $search;
+            $_SESSION['av_folder'] = $mbox;
+            $_SESSION['av_sub_folders'] = rcube_utils::get_input_value('sub_folders', rcube_utils::INPUT_GPC);
+            $nosub = $sub_folders;
+            $folders = $this->rc->get_storage()->list_folders_subscribed();
+            if (empty($folders) || ($sub_folders === false && $mbox !== 'all')) {
+                $folders = array($mbox);
+            } elseif ($mbox !== 'all') {
+                if ($sub_folders === false) {
+                    $folders = array($mbox);
+                } else {
+                    $folders = $this->rc->get_storage()->list_folders_subscribed_direct($mbox);
+                }
+            }
+            $md5folders = array();
+            foreach ($folders as $folder) {
+                $md5folders[md5($folder)] = $folder;
+            }
+            $this->rc->output->set_env('as_md5_folders', $md5folders);
+
+            if ($search_str) {
+                $res = $this->perform_search($search_str, $folders, $page);
+                $count = $res['count'];
+            }
+
+
+            if ($count > 0) {
+                $_SESSION['advanced_search']['uid_list'] = $uid_list;
+                if ($search_str && $inPagination == false) {
+                    $this->rc->output->show_message('searchsuccessful', 'confirmation', array('nr' => $count));
+                }
+            } elseif ($err_code = $this->rc->storage->get_error_code()) {
+                rcmail_display_server_error();
+            } else {
+                $this->rc->output->show_message('searchnomatch', 'notice');
+            }
+
+            $current_folder = rcube_utils::get_input_value('current_folder', rcube_utils::INPUT_GPC);
+
+            $this->rc->output->set_env('search_request', 'advanced_search_active');
+            $this->rc->output->set_env('messagecount', $count);
+            $this->rc->output->set_env('pagecount', ceil($count / $pagesize));
+            $this->rc->output->set_env('exists', $this->rc->storage->count($current_folder, 'EXISTS'));
+            $this->rc->output->command('set_rowcount', rcmail_get_messagecount_text($count, $page));
+            $this->rc->output->command('plugin.search_complete');
+            $this->rc->output->send();
+        }
+    }
+
+    /**
+     * return javascript commands to add rows to the message list
+     */
+    public function rcmail_js_message_list($a_headers, $insert_top = false, $a_show_cols = null, $avmbox = false, $avcols = array(), $showMboxColumn = false)
+    {
+        global $CONFIG, $RCMAIL, $OUTPUT;
+        $uid_mboxes = array();
+
+        if (empty($a_show_cols)) {
+            if (!empty($_SESSION['list_attrib']['columns'])) {
+                $a_show_cols = $_SESSION['list_attrib']['columns'];
+            } else {
+                $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
+            }
+        } else {
+            if (!is_array($a_show_cols)) {
+                $a_show_cols = preg_split('/[\s,;]+/', strip_quotes($a_show_cols));
+            }
+            $head_replace = true;
+        }
+
+        $mbox = $RCMAIL->storage->get_folder();
+
+        // make sure 'threads' and 'subject' columns are present
+        if (!in_array('subject', $a_show_cols)) {
+            array_unshift($a_show_cols, 'subject');
+        }
+        if (!in_array('threads', $a_show_cols)) {
+            array_unshift($a_show_cols, 'threads');
+        }
+        $_SESSION['list_attrib']['columns'] = $a_show_cols;
+
+        // Make sure there are no duplicated columns (#1486999)
+        $a_show_cols = array_merge($a_show_cols, $avcols);
+        $a_show_cols = array_unique($a_show_cols);
+
+        // Plugins may set header's list_cols/list_flags and other rcube_message_header variables
+        // and list columns
+        $plugin = $RCMAIL->plugins->exec_hook(
+            'messages_list',
+            array('messages' => $a_headers, 'cols' => $a_show_cols)
+        );
+        $a_show_cols = $plugin['cols'];
+        $a_headers   = $plugin['messages'];
+        $thead = $head_replace ? rcmail_message_list_head($_SESSION['list_attrib'], $a_show_cols) : null;
+
+        // get name of smart From/To column in folder context
+        if (($f = array_search('fromto', $a_show_cols)) !== false) {
+            $smart_col = rcmail_message_list_smart_column_name();
+        }
+        if ($this->coltypesSet == false) {
+            $OUTPUT->command('set_message_coltypes', $a_show_cols, $thead, $smart_col);
+            if ($showMboxColumn === true) {
+                $OUTPUT->command('plugin.advanced_search_add_header', array());
+            }
+            $this->coltypesSet = true;
+        }
+
+        if (empty($a_headers)) {
+            return;
+        }
+
+        // remove 'threads', 'attachment', 'flag', 'status' columns, we don't need them here
+        foreach (array('threads', 'attachment', 'flag', 'status', 'priority') as $col) {
+            if (($key = array_search($col, $a_show_cols)) !== false) {
+                unset($a_show_cols[$key]);
+            }
+        }
+
+        // loop through message headers
+        foreach ($a_headers as $n => $header) {
+            if (empty($header)) {
+                continue;
+            }
+            $a_msg_cols = array();
+            $a_msg_flags = array();
+            // format each col; similar as in rcmail_message_list()
+            foreach ($a_show_cols as $col) {
+                $col_name = $col == 'fromto' ? $smart_col : $col;
+
+                if (in_array($col_name, array('from', 'to', 'cc', 'replyto'))) {
+                    $cont = rcmail_address_string($header->$col_name, 3, false, null, $header->charset);
+                } elseif ($col == 'subject') {
+                    $cont = trim(rcube_mime::decode_header($header->$col, $header->charset));
+                    if (!$cont) {
+                        $cont = $this->gettext('nosubject');
+                    }
+                    $cont = rcube::Q($cont);
+                } elseif ($col == 'size') {
+                    $cont = $this->rc->show_bytes($header->$col);
+                } elseif ($col == 'date') {
+                    $cont = rcube_utils::format_datestr($header->date,$date_format);
+                } else {
+                    $cont = rcube::Q($header->$col);
+                }
+                $a_msg_cols[$col] = $cont;
+            }
+
+            $a_msg_flags = array_change_key_case(array_map('intval', (array) $header->flags));
+            if ($header->depth) {
+                $a_msg_flags['depth'] = $header->depth;
+            } elseif ($header->has_children) {
+                $roots[] = $header->uid;
+            }
+            if ($header->parent_uid) {
+                $a_msg_flags['parent_uid'] = $header->parent_uid;
+            }
+            if ($header->has_children) {
+                $a_msg_flags['has_children'] = $header->has_children;
+            }
+            if ($header->unread_children) {
+                $a_msg_flags['unread_children'] = $header->unread_children;
+            }
+            if ($header->others['list-post']) {
+                $a_msg_flags['ml'] = 1;
+            }
+            if ($header->priority) {
+                $a_msg_flags['prio'] = (int) $header->priority;
+            }
+            $a_msg_flags['ctype'] = rcube::Q($header->ctype);
+            $a_msg_flags['mbox'] = $mbox;
+            if (!empty($header->list_flags) && is_array($header->list_flags)) {
+                $a_msg_flags = array_merge($a_msg_flags, $header->list_flags);
+            }
+            if (!empty($header->list_cols) && is_array($header->list_cols)) {
+                $a_msg_cols = array_merge($a_msg_cols, $header->list_cols);
+            }
+            if ($showMboxColumn === true) {
+                $a_msg_flags['avmbox'] = $avmbox;
+            }
+
+            $OUTPUT->command(
+                'add_message_row',
+                $header->uid . '__MB__' . md5($mbox),
+                $a_msg_cols,
+                $a_msg_flags,
+                $insert_top
+            );
+            $id = $header->uid . '__MB__' . md5($mbox);
+            $uid_mboxes[$id] = array('uid' => $header->uid, 'mbox' => $mbox, 'md5mbox' => md5($mbox));
+        }
+
+        if ($RCMAIL->storage->get_threading()) {
+            $OUTPUT->command('init_threads', (array) $roots, $mbox);
+        }
+
+        return $uid_mboxes;
+    }
+
+
+    private function do_pagination($folders, $onPage)
+    {
+        $perPage = $this->rc->storage->get_pagesize();
+        $from = $perPage * $onPage - $perPage + 1;
+        $to = $from + $perPage - 1;
+        $got = 0;
+        $pos = 0;
+        $cbox = "";
+        $boxStart = 0;
+        $boxStop = 0;
+        $fetch = array();
+        foreach ($folders as $box => $num) {
+            $i = $num;
+            if ($box != $cbox) {
+                $boxStart = 0;
+                $boxStop = 0;
+                $cbox = $box;
+            }
+            while ($i--) {
+                $pos++;
+                $boxStart++;
+                if ($pos >= $from && $pos <= $to) {
+                    if (!isset($fetch[$box])) {
+                        $fetch[$box] = array("from" => $boxStart);
+                    }
+                    $fetch[$box]['to'] = $boxStart;
+                    $got++;
+                }
+            }
+            if ($got >= $perPage) {
+                break;
+            }
+        }
+
+        return $fetch;
+    }
+
+    /**
+     * Save advanced search preferences
+     *
+     * @access  public
+     */
+    public function preferences_save($args)
+    {
+        if ($args['section'] != 'advancedsearch') {
+            return;
+        }
+        $rcmail = rcmail::get_instance();
+
+        $displayOptions = array();
+        $displayOptions['_show_message_label_header'] = rcube_utils::get_input_value('_show_message_label_header', rcube_utils::INPUT_POST) == 1 ? true : false;
+        $displayOptions['_show_message_mbox_info'] = rcube_utils::get_input_value('_show_message_mbox_info', rcube_utils::INPUT_POST) == 1 ? true : false;
+        $displayOptions['target_menu'] = rcube_utils::get_input_value('button_display_option', rcube_utils::INPUT_POST);
+
+        $args['prefs']['advanced_search_display_options'] = $displayOptions;
+
+        return($args);
+    }
+
+    /**
+     * Add a section advanced search to the preferences section list
+     *
+     * @access  public
+     */
+    public function preferences_section($args)
+    {
+        $args['list']['advancedsearch'] = array(
+            'id' => 'advancedsearch',
+            'section' => rcube::Q($this->gettext('advancedsearch'))
+        );
+
+        return($args);
+    }
+
+    /**
+     * Display advanced search configuration in user preferences tab
+     *
+     * @access  public
+     */
+    public function preferences_list($args)
+    {
+        if ($args['section'] == 'advancedsearch') {
+
+            $this->rc = rcmail::get_instance();
+            $args['blocks']['label_display_options'] = array('options' => array(), 'name' => rcube::Q($this->gettext('label_display_options')));
+
+            $displayOptions = $this->rc->config->get('advanced_search_display_options', array());
+            $target_menu = (isset($displayOptions['target_menu']) && !empty($displayOptions['target_menu'])) ? $displayOptions['target_menu'] : $this->config['target_menu'];
+            $options = '';
+            $optarg = array('value' => 'messagemenu');
+            if ($target_menu == 'messagemenu') {
+                $optarg['selected'] = 'selected';
+                $target_image = 'menu_location_a.jpg';
+            }
+            $options .= html::tag('option', $optarg, rcube::Q($this->gettext('display_in_messagemenu')));
+            $optarg = array('value' => 'toolbar');
+            if ($target_menu == 'toolbar') {
+                $optarg['selected'] = 'selected';
+                $target_image = 'menu_location_b.jpg';
+            }
+            $options .= html::tag('option', $optarg,rcube::Q($this->gettext('display_in_toolbar')));
+            $select = html::tag('select', array('name' => 'button_display_option', 'id' => 'button_display_option'), $options);
+
+            $label1 = html::label('_show_message_label_header', rcube::Q($this->gettext('mailbox_headers_in_results')));
+            $label2 = html::label('_show_message_mbox_info', rcube::Q($this->gettext('mailbox_info_in_results')));
+            $label3 = html::label('button_display_option', rcube::Q($this->gettext('show_advanced_search')));
+
+            $arg1 = array('name' => '_show_message_label_header', 'id' => '_show_message_label_header', 'type' => 'checkbox', 'title' => "", 'class' => 'watermark linput', 'value' => 1);
+            if (isset($displayOptions['_show_message_label_header']) && $displayOptions['_show_message_label_header'] === true) {
+                $arg1['checked'] = 'checked';
+                $img1class = 'enabled';
+            } else {
+                $img1class = 'disabled';            
+            }
+            $check1 = html::tag('input', $arg1);
+            $arg2 = array('name' => '_show_message_mbox_info', 'id' => '_show_message_mbox_info', 'type' => 'checkbox', 'title' => "", 'class' => 'watermark linput', 'value' => 1);
+            if (isset($displayOptions['_show_message_mbox_info']) && $displayOptions['_show_message_mbox_info'] === true) {
+                $arg2['checked'] = 'checked';
+                $img2class = 'enabled';
+            } else {
+                $img2class = 'disabled';
+            }
+
+            $img1 = html::img(array('src' => $this->url('skins/larry/images/show_mbox_row.jpg'), 'class' => $img1class));
+            $img2 = html::img(array('src' => $this->url('skins/larry/images/show_mbox_col.jpg'), 'class' => $img2class));
+            $img3 = html::img(array('src' => $this->url('skins/larry/images/' . $target_image)));
+
+            $check2 = html::tag('input', $arg2);
+            $args['blocks']['label_display_options']['options'][0] = array('title' => '', 'content' => '<p class="avsearchpref"><span>' . $check1 . ' ' . $label1 . '</span> ' . $img1 . '</p>');
+            $args['blocks']['label_display_options']['options'][1] = array('title' => '', 'content' => '<p class="avsearchpref"><span>' . $check2 . ' ' . $label2 . '</span> ' . $img2 . '</p>');
+            $args['blocks']['label_display_options']['options'][2] = array('title' => '', 'content' => '<p class="avsearchpref"><span>' . $label3 . ' ' . $select . '</span> ' . $img3 . '</p>');
+        }
+
+        return($args);
+    }
+
+    private function perform_search($search_string, $folders, $page = 1)
+    {
+        // Search all folders and build a final set
+        if ($folders[0] == 'all' || empty($folders)) {
+            $folders_search = $this->rc->imap->list_folders_subscribed();
+        } else {
+            $folders_search = $folders;
+        }
+        $count = 0;
+        $folder_count = array();
+        foreach ($folders_search as $mbox) {
+            $this->rc->storage->set_folder($mbox);
+            $this->rc->storage->search($mbox, $search_string, RCMAIL_CHARSET, $_SESSION['sort_col']);
+            $result = array();
+            $fcount = $this->rc->storage->count($mbox, 'ALL', !empty($_REQUEST['_refresh']));
+            $count += $fcount;
+            $folder_count[$mbox] = $fcount;
+        }
+        foreach ($folder_count as $k => $v) {
+            if ($v == 0) {
+                unset($folder_count[$k]);
+            }
+        }
+        $fetch = $this->do_pagination($folder_count, $page);
+        $mails = array();
+        $currentMailbox = "";
+        $displayOptions = $this->rc->config->get('advanced_search_display_options', array());
+        $showMboxColumn = isset($displayOptions['_show_message_mbox_info']) && $displayOptions['_show_message_mbox_info'] ? true : false;
+        $uid_mboxes = array();
+        foreach ($fetch as $mailbox => $data) {
+            if ($currentMailbox != $mailbox) {
+                $currentMailbox = $mailbox;
+                if (isset($displayOptions['_show_message_label_header']) && $displayOptions['_show_message_label_header'] === true) {
+                    $this->rc->output->command('advanced_search_add_mbox', $mailbox, $folder_count[$mailbox], $showMboxColumn);
+                }
+            }
+            $uid_mboxes = array_merge($uid_mboxes, $this->getMails($mailbox, $data, $search_string, $showMboxColumn));
+        }
+
+        return array('result' => array(), 'count' => $count, 'uid_mboxes' => $uid_mboxes);
+    }
+
+    private function getMails($mailbox, $data, $search_string, $showMboxColumn)
+    {
+        $pageSize = $this->rc->storage->get_pagesize();
+        $msgNum = $data['from'];
+        $startPage =  ceil($msgNum/$pageSize);
+        $msgMod = $msgNum % $pageSize;
+        $multiPage = "false";
+        $firstArrayElement = $msgMod == 0 ? ($pageSize-1) : ($msgMod-1);
+        $quantity = $data['to'] - $data['from'];
+        if ($data['from'] + $quantity > $pageSize) {
+            $multiPage = "true";
+        }
+        $this->rc->storage->set_folder($mailbox);
+        $this->rc->storage->search($mailbox, $search_string, RCMAIL_CHARSET, $_SESSION['sort_col']);
+        $messages = $this->rc->storage->list_messages('', $startPage);
+        if ($multiPage) {
+            $messages = array_merge($messages, $this->rc->storage->list_messages('', $startPage+1));
+        }
+        //FIRST: 0 QUANTITY: 2
+        $sliceTo = $quantity + 1;
+        $mslice = array_slice($messages, $firstArrayElement, $sliceTo, true);
+        $messages = $mslice;
+        $avbox = array();
+        $showAvmbox = false;
+        foreach ($messages as $set_flag) {
+            $set_flag->flags['skip_mbox_check'] = true;
+            if ($showMboxColumn === true) {
+                $set_flag->avmbox = $mailbox;
+                $avbox[] = 'avmbox';
+                $showAvmbox = true;
+            }
+        }
+        $uid_mboxes = $this->rcmail_js_message_list($messages, false, null, $showAvmbox, $avbox, $showMboxColumn);
+
+        return $uid_mboxes;
+    }
+
+    public function save_search()
+    {
+        $search_name = rcube_utils::get_input_value('search_name', rcube_utils::INPUT_GPC);
+        if ($search_name) {
+            $search = array();
+            $search['search'] = rcube_utils::get_input_value('search', rcube_utils::INPUT_GPC);
+            $search['search_name'] = $search_name;
+            $search['folder'] = rcube_utils::get_input_value('folder', rcube_utils::INPUT_GPC);
+            $search['sub_folders'] = rcube_utils::get_input_value('sub_folders', rcube_utils::INPUT_GPC);
+            $prefs = (array)$this->rc->user->get_prefs();
+            if (!isset($prefs['advanced_search'])) {
+                $prefs['advanced_search'] = array();
+            }
+            $prefs['advanced_search'][$search_name] = $search;
+            $this->rc->user->save_prefs(array('advanced_search' => $prefs['advanced_search']));
+            $this->rc->output->show_message('"<i>' . $search_name . '</i>" ' . $this->i18n_strings['has_been_saved'], 'confirmation');
+        }
+    }
+
+    public function delete_search()
+    {
+        $search_name = rcube_utils::get_input_value('search_name', rcube_utils::INPUT_GPC);
+        if ($search_name) {
+            $prefs = (array)$this->rc->user->get_prefs();
+            unset($prefs['advanced_search'][$search_name]);
+            $this->rc->user->save_prefs(array('advanced_search' => $prefs['advanced_search']));
+            $this->rc->output->show_message('"<i>' . $search_name . '</i>" ' . $this->i18n_strings['has_been_deleted'], 'notice');
+        }
+    }
+
+    public function get_saved_search()
+    {
+        $search_name = rcube_utils::get_input_value('search_name', rcube_utils::INPUT_GPC);
+        $prefs = (array)$this->rc->user->get_prefs();
+        if (!isset($prefs['advanced_search'])) {
+            $prefs['advanced_search'] = array();
+        }
+
+        $search = isset($prefs['advanced_search'][$search_name]) ? $prefs['advanced_search'][$search_name] : false;
+        $this->rc->output->command('plugin.load_saved_search', $search);
+        $this->rc->output->send();
+    }
+
+    private function get_saved_search_names()
+    {
+        $prefs = (array)$this->rc->user->get_prefs();
+        if (!isset($prefs['advanced_search'])) {
+            $prefs['advanced_search'] = array();
+        }
+        $names = array();
+        foreach($prefs['advanced_search'] as $name => $search) {
+            $names[] = $name;
+        }
+
+        return $names;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/advanced_search.php.orig	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,1083 @@
+<?php
+/**
+ * Processing an advanced search over an E-Mail Account
+ *
+ * @version 2.1.6
+ * @licence GNU GPLv3+
+ * @author  Wilwert Claude
+ * @author  Ludovicy Steve
+ * @author  Chris Moules
+ * @website http://www.gms.lu
+ */
+
+class advanced_search extends rcube_plugin
+{
+
+    /**
+     * Instance of rcmail
+     *
+     * @var object
+     * @access private
+     */
+    private $rc;
+
+    public $task = 'mail|settings';
+
+    /**
+     * Plugin config
+     *
+     * @var array
+     * @access private
+     */
+    private $config;
+
+    /**
+     * Localization strings
+     *
+     * @var array
+     * @access private
+     */
+    private $i18n_strings = array();
+
+    /**
+     * Initialisation of the plugin
+     *
+     * @access public
+     * @return null
+     */
+    public function init()
+    {
+        $this->rc = rcmail::get_instance();
+        $this->load_config("config-default.inc.php");
+        $this->load_config();
+        $this->config = $this->rc->config->get('advanced_search_plugin');
+        $this->register_action('plugin.display_advanced_search', array($this, 'display_advanced_search'));
+        $this->register_action('plugin.trigger_search', array($this, 'trigger_search'));
+        $this->register_action('plugin.trigger_search_pagination', array($this, 'trigger_search_pagination'));
+        $this->register_action('plugin.save_search', array($this, 'save_search'));
+        $this->register_action('plugin.delete_search', array($this, 'delete_search'));
+        $this->register_action('plugin.get_saved_search', array($this, 'get_saved_search'));
+
+        $this->skin = $this->rc->config->get('skin');
+        $this->add_texts('localization', true);
+        $this->populate_i18n();
+        if(isset($this->config['criteria'])) {
+            foreach($this->config['criteria'] as $key => $translation) {
+                $this->config['criteria'][$key] = $this->gettext($key);
+            }
+        }
+        $this->include_script('advanced_search.min.js');
+
+        if ($this->rc->task == 'mail') {
+            $file = 'skins/' . $this->skin . '/advanced_search.css';
+
+            if (file_exists($this->home . '/' . $file)) {
+                $this->include_stylesheet($file);
+            } else {
+                $this->include_stylesheet('skins/default/advanced_search.css');
+            }
+
+            if (empty($this->rc->action)) {
+                $this->add_menu_entry();
+            }
+        } elseif ($this->rc->task == 'settings') {
+            $this->add_hook('preferences_list', array($this, 'preferences_list'));
+            $this->add_hook('preferences_save', array($this, 'preferences_save'));
+            $this->add_hook('preferences_sections_list', array($this, 'preferences_section'));
+            $file = 'skins/' . $this->skin . '/advanced_search.css';
+            if (file_exists($this->home . '/' . $file)) {
+                $this->include_stylesheet($file);
+            } else {
+                $this->include_stylesheet('skins/default/advanced_search.css');
+            }
+        }
+
+        $this->add_hook('startup', array($this, 'startup'));
+    }
+
+
+    public function startup($args)
+    {
+        $search = get_input_value('_search', RCUBE_INPUT_GET);
+        if (!isset($search)) {
+            $search = get_input_value('_search', RCUBE_INPUT_POST);
+        }
+        $rsearch = $search == 'advanced_search_active';
+        $uid = get_input_value('_uid', RCUBE_INPUT_GET);
+        $draft_uid = get_input_value('_draft_uid', RCUBE_INPUT_GET);
+        $mbox = get_input_value('_mbox', RCUBE_INPUT_GET);
+        $page = get_input_value('_page', RCUBE_INPUT_GET);
+        $sort = get_input_value('_sort', RCUBE_INPUT_GET);
+
+        if (!empty($uid)) {
+            $parts = explode('__MB__', $uid);
+            if (count($parts) == 2) {
+                $search = 'advanced_search_active';
+            }
+        }
+        if (!empty($draft_uid)) {
+            $parts = explode('__MB__', $draft_uid);
+            if (count($parts) == 2) {
+                $search = 'advanced_search_active';
+            }
+        }
+
+        if ($search == 'advanced_search_active') {
+            if ($args['action'] == 'show' && !empty($uid)) {
+                $parts = explode('__MB__', $uid);
+                $uid = $parts[0];
+                $this->rc->output->redirect(array('_task' => 'mail', '_action' => $args['action'], '_mbox' => $mbox, '_uid' => $uid));
+            }
+            if ($args['action'] == 'compose') {
+                $draft_uid = get_input_value('_draft_uid', RCUBE_INPUT_GET);
+                $parts = explode('__MB__', $draft_uid);
+                $draft_uid = $parts[0];
+                if (!empty($draft_uid)) {
+                    $this->rc->output->redirect(array('_task' => 'mail', '_action' => $args['action'], '_mbox' => $mbox, '_draft_uid' => $draft_uid));
+                }
+            }
+            if ($args['action'] == 'list' && $rsearch) {
+                $this->rc->output->command('advanced_search_active', '_page=' . $page . '&_sort=' . $sort);
+                $this->rc->output->send();
+                $args['abort'] = true;
+            }
+            if ($args['action'] == 'mark') {
+                $flag = get_input_value('_flag', RCUBE_INPUT_POST);
+                $uid = get_input_value('_uid', RCUBE_INPUT_POST);
+
+                $post_str = '_flag=' . $flag . '&_uid=' . $uid;
+                if ($quiet = get_input_value('_quiet', RCUBE_INPUT_POST)) {
+                    $post_str .= '&_quiet=' . $quiet;
+                }
+                if ($from = get_input_value('_from', RCUBE_INPUT_POST)) {
+                    $post_str .= '&_from=' . $from;
+                }
+                if ($count = get_input_value('_count', RCUBE_INPUT_POST)) {
+                    $post_str .= '&_count=' . $count;
+                }
+                if ($ruid = get_input_value('_ruid', RCUBE_INPUT_POST)) {
+                    $post_str .= '&_ruid=' . $ruid;
+                }
+                $this->rc->output->command('label_mark', $post_str);
+                $this->rc->output->send();
+                $args['abort'] = true;
+            }
+
+        } else {
+            if ($args['action'] != 'plugin.get_saved_search' && $args['action'] != 'plugin.save_search' && $args['action'] != 'plugin.delete_search') {
+                $this->rc->output->command('plugin.advanced_search_del_header', array());
+            }
+        }
+    }
+
+    /**
+     * This function populates an array with localization texts.
+     * This is needed as ew are using a lot of localizations from core.
+     * The core localizations are not avalable directly in JS
+     *
+     * @access private
+     * @return null
+     */
+    private function populate_i18n()
+    {
+        $core = array('advsearch', 'search', 'resetsearch', 'addfield', 'delete', 'cancel');
+
+        foreach ($core as $label) {
+            $this->i18n_strings[$label] = $this->rc->gettext($label);
+        }
+
+        $local = array('in', 'and', 'or', 'not', 'where', 'exclude', 'andsubfolders', 'allfolders', 'save_the_search', 'has_been_saved', 'deletesearch', 'has_been_deleted');
+
+        foreach ($local as $label) {
+            $this->i18n_strings[$label] = $this->gettext($label);
+        }
+    }
+
+    /**
+     * This adds a button into the configured menu to use the advanced search
+     *
+     * @access public
+     * @return null
+     */
+    public function add_menu_entry()
+    {
+        $displayOptions = $this->rc->config->get('advanced_search_display_options', array());
+        $target_menu = (isset($displayOptions['target_menu']) && !empty($displayOptions['target_menu'])) ? $displayOptions['target_menu'] : $this->config['target_menu'];
+        if ($target_menu != 'toolbar') {
+            $this->api->add_content(
+                html::tag(
+                    'li',
+                    null,
+                    $this->api->output->button(
+                        array(
+                            'command'    => 'plugin.advanced_search',
+                            'label'      => 'advsearch',
+                            'type'       => 'link',
+                            'classact'   => 'icon advanced-search active',
+                            'class'      => 'icon advanced-search',
+                            'innerclass' => 'icon advanced-search'
+                        )
+                    )
+                ),
+                $target_menu
+            );
+        } else {
+            $this->api->add_content(
+                $this->api->output->button(
+                    array(
+                        'command'    => 'plugin.advanced_search',
+                        'title'      => 'advsearch',
+                        'label'      => 'search',
+                        'type'       => 'link',
+                        'classact'   => 'button advanced-search active',
+                        'class'      => 'button advanced-search',
+                        'innerclass' => 'button advanced-search',
+                    )
+                ),
+                $target_menu
+            );
+        }
+    }
+
+    /**
+     * This function quotes some specific values based on their data type
+     *
+     * @param mixed $input The value to get quoted
+     * @access public
+     * @return The quoted value
+     */
+    public function quote($value)
+    {
+        if (getType($value) == 'string') {
+            if (!preg_match('/"/', $value)) {
+                $value = preg_replace('/^"/', '', $value);
+                $value = preg_replace('/"$/', '', $value);
+                $value = preg_replace('/"/', '\\"', $value);
+            }
+
+            $value = '"' . $value . '"';
+        }
+
+        return $value;
+    }
+
+    /**
+     * This function generates the IMAP compatible search query based on the request data (by javascript)
+     *
+     * @param array $input The raw criteria data sent by javascript
+     * @access private
+     * @return string or int
+     */
+    private function process_search_part($search_part)
+    {
+        $command_str = '';
+        $flag = false;
+
+        // Check for valid input
+        if (!array_key_exists($search_part['filter'], $this->config['criteria'])) {
+            $this->rc->output->show_message($this->gettext('internalerror'), 'error');
+
+            return 0;
+        }
+        if (in_array($search_part['filter'], $this->config['flag_criteria'])) {
+            $flag = true;
+        }
+        if (!$flag && !(isset($search_part['filter-val']) && $search_part['filter-val'] != '')) {
+            return 1;
+        }
+
+        // Negate part
+        if ($search_part['not'] == 'true') {
+            $command_str .= 'NOT ';
+        }
+
+        $command_str .= $search_part['filter'];
+
+        if (!$flag) {
+            if (in_array($search_part['filter'], $this->config['date_criteria'])) {
+                // Take date format from user environment
+                $date_format = $this->rc->config->get('date_format', 'Y-m-d');
+                // Try to use PHP5.2+ DateTime but fallback to ugly old method
+                if (class_exists('DateTime')) {
+                    $date = DateTime::createFromFormat($date_format, $search_part['filter-val']);
+                    $command_str .= ' ' . $this->quote($date->format("d-M-Y"));
+                } else {
+                    $date_format = preg_replace('/(\w)/', '%$1', $date_format);
+                    $date_array = strptime($search_part['filter-val'], $date_format);
+                    $unix_ts = mktime($date_array['tm_hour'], $date_array['tm_min'], $date_array['tm_sec'], $date_array['tm_mon']+1, $date_array['tm_mday'], $date_array['tm_year']+1900);
+                    $command_str .= ' ' . $this->quote(date("d-M-Y", $unix_ts));
+                }
+            } elseif (in_array($search_part['filter'], $this->config['email_criteria'])) {
+                // Strip possible ',' added by autocomplete
+                $command_str .= ' ' . $this->quote(trim($search_part['filter-val'], " \t,"));
+            } else {
+                // Don't try to use a value for a binary flag object
+                $command_str .= ' ' . $this->quote($search_part['filter-val']);
+            }
+        }
+
+        return $command_str;
+    }
+
+    /**
+     * This function generates the IMAP compatible search query based on the request data (by javascript)
+     *
+     * @param array $input The raw criteria data sent by javascript
+     * @access public
+     * @return The final search command
+     */
+    public function get_search_query($input)
+    {
+        $command = array();
+
+        foreach ($input as $search_part) {
+            // Skip excluded parts
+            if ($search_part['excluded'] == 'true') {
+                continue;
+            }
+            if (! $part_command = $this->process_search_part($search_part)) {
+                return 0;
+            }
+            // Skip invalid parts
+            if ($part_command === 1) {
+                continue;
+            }
+
+            $command[] = array('method' => isset($search_part['method']) ? $search_part['method'] : 'and',
+                               'command' => $part_command);
+        }
+
+        $command_string = $this->build_search_string($command);
+
+        return $command_string;
+    }
+
+    /**
+     * This function converts the preconfigured query parts (as array) into an IMAP compatible string
+     *
+     * @param array $command_array An array containing the advanced search criteria
+     * @access public
+     * @return The command string
+     */
+    private function build_search_string($command_array)
+    {
+        $command = array();
+        $paranthesis = 0;
+        $prev_method = null;
+        $next_method = null;
+        $cnt = count($command_array);
+
+        foreach ($command_array as $k => $v) {
+            $part = '';
+            $next_method = 'unknown';
+
+            // Lookup next method
+            if ($k < $cnt-1) {
+                $next_method = $command_array[$k+1]['method'];
+            }
+
+            // If previous option was OR, close any open brakets
+            if ($paranthesis > 0 && $prev_method == 'or' && $v['method'] != 'or') {
+                for (; $paranthesis > 0; $paranthesis--) {
+                    $part .= ')';
+                }
+            }
+
+            // If there are two consecutive ORs, add brakets
+            // If the next option is a new OR, add the prefix here
+            // If the next option is _not_ an OR, and the current option is AND, prefix ALL
+            if ($next_method == 'or') {
+                if ($v['method'] == 'or') {
+                    $part .= ' (';
+                    $paranthesis++;
+                }
+                $part .= 'OR ';
+            } elseif ($v['method'] == 'and') {
+                $part .= 'ALL ';
+            }
+
+            $part .= $v['command'];
+
+            // If this is the end of the query, and we have open brakets, close them
+            if ($k == $cnt-1 && $paranthesis > 0) {
+                for (; $paranthesis > 0; $paranthesis--) {
+                    $part .= ')';
+                }
+            }
+
+            $prev_method = $v['method'];
+            $command[] = $part;
+        }
+
+        $command = implode(' ', $command);
+
+        return $command;
+    }
+
+    /**
+     * This functions sends the initial data to the client side where a form (in dialog) is built for the advanced search
+     *
+     * @access public
+     * @return null
+     */
+    public function display_advanced_search()
+    {
+        $ret = array('html' => $this->generate_searchbox(),
+                     'row' => $this->add_row(),
+                     'saved_searches' => $this->get_saved_search_names(),
+                     'title' => $this->i18n_strings['advsearch'],
+                     'date_criteria' => $this->config['date_criteria'],
+                     'flag_criteria' => $this->config['flag_criteria'],
+                     'email_criteria' => $this->config['email_criteria']);
+
+        $this->rc->output->command('plugin.show', $ret);
+    }
+
+    public function generate_searchbox()
+    {
+        $search_button = new html_inputfield(array('type' => 'submit', 'name' => 'search', 'class' => 'button mainaction', 'value' => $this->i18n_strings['search']));
+        $reset_button = new html_inputfield(array('type' => 'reset', 'name' => 'reset', 'class' => 'button reset', 'value' => $this->i18n_strings['resetsearch']));
+        $save_button = html::tag('input', array('type' => 'submit', 'name' => 'save_the_search', id=> 'save_the_search', 'class' => 'button save_search', 'value' => $this->i18n_strings['save_the_search']));
+        $delete_button = new html_inputfield(array('type' => 'submit', 'name' => 'delete', 'style' => 'display: none;', 'class' => 'button delete_search', 'value' => $this->i18n_strings['deletesearch']));
+
+        $layout_table = new html_table();
+        $layout_table->add(null, $search_button->show());
+        $folderConfig = array('name' => 'folder');
+        $layout_table->add(
+            null,
+            $this->i18n_strings['in'] . ': ' .
+            $this->folder_selector($folderConfig)->show($this->rc->storage->get_folder()) .
+            html::span(
+                array('class' => 'sub-folders'),
+                $this->i18n_strings['andsubfolders'] . ': ' .
+                html::tag(
+                    'input',
+                    array('type' => 'checkbox', 'name' => 'subfolder'),
+                    null
+                )
+            ) .
+            $this->i19n_strings['where']
+        );
+        $first_row = $this->add_row(true);
+        $layout_table->add_row();
+        $layout_table->add(array('class' => 'adv-search-and-or'), null);
+        $layout_table->add(null, $first_row);
+        $layout_table->add_row();
+        $layout_table->add(null, $search_button->show());
+        $layout_table->add(null, $save_button . ' ' . $reset_button->show() . ' ' . $delete_button->show());
+
+        return html::tag(
+            'div',
+            array('id' => 'adsearch-popup'),
+            html::tag(
+                'form',
+                array('method' => 'post', 'action' => '#'),
+                $layout_table->show()
+            )
+        );
+    }
+
+    /**
+     * This function is used to render the html of the advanced search form and also
+     * the later following rows are created by this function
+     *
+     * @param array   $folders Array of folders
+     * @param boolean $first   True if form gets created, False to create a new row
+     * @access public
+     * @return string The final html
+     */
+    public function add_row($first = false)
+    {
+        $row_html = '';
+        $optgroups = '';
+
+        $criteria = $this->config['criteria'];
+        $all_criteria = array(
+            $this->gettext('Common') => $this->config['prefered_criteria'],
+            $this->gettext('Addresses') => $this->config['email_criteria'],
+            $this->gettext('Dates') => $this->config['date_criteria'],
+            $this->gettext('Flags') => $this->config['flag_criteria'],
+            $this->gettext('Other') => $this->config['other_criteria'],
+        );
+
+        foreach ($all_criteria as $label => $specific_criteria) {
+            $options = '';
+
+            foreach ($specific_criteria as $value) {
+                $options .= html::tag('option', array('value' => $value), $criteria[$value]);
+            }
+
+            $optgroups .= html::tag('optgroup', array('label' => $label), $options);
+        }
+
+        $tmp = html::tag('select', array('name' => 'filter'), $optgroups);
+        $tmp .= $this->i18n_strings['not'] . ':' . html::tag('input', array('type' => 'checkbox', 'name' => 'not'), null);
+        $tmp .= html::tag('input', array('type' => 'text', 'name' => 'filter-val'));
+        $tmp .= $this->i18n_strings['exclude'] . ':' . html::tag('input', array('type' => 'checkbox', 'name' => 'filter-exclude'), null);
+        $tmp .= html::tag('button', array('name' => 'add', 'class' => 'add'), $this->i18n_strings['addfield']);
+
+        if ($first) {
+            $row_html = $tmp;
+        } else {
+            $and_or_select = new html_select(array('name' => 'method'));
+            $and_or_select->add($this->i18n_strings['and'], 'and');
+            $and_or_select->add($this->i18n_strings['or'], 'or');
+            $tmp .= html::tag('button', array('name' => 'delete', 'class' => 'delete'), $this->i18n_strings['delete']);
+            $row_html = html::tag(
+                'tr',
+                null,
+                html::tag(
+                    'td',
+                    array('class' => 'adv-search-and-or'),
+                    $and_or_select->show()
+                ) .
+                html::tag(
+                    'td',
+                    null,
+                    $tmp
+                )
+            );
+        }
+
+        return $row_html;
+    }
+
+    /**
+     * Return folders list as html_select object
+     *
+     * This is a copy of the core function and adapted to fit
+     * the needs of the advanced_search function
+     *
+     * @param array $p Named parameters
+     *
+     * @return html_select HTML drop-down object
+     */
+    public function folder_selector($p = array())
+    {
+        $p += array('maxlength' => 100, 'realnames' => false, 'is_escaped' => true);
+        $a_mailboxes = array();
+        $storage = $this->rc->get_storage();
+
+        $list = $storage->list_folders_subscribed();
+        $delimiter = $storage->get_hierarchy_delimiter();
+
+        foreach ($list as $folder) {
+            $this->rc->build_folder_tree($a_mailboxes, $folder, $delimiter);
+        }
+
+        $select = new html_select($p);
+        $select->add($this->i18n_strings['allfolders'], "all");
+
+        $this->rc->render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p);
+
+        return $select;
+    }
+
+    public function trigger_search_pagination($param)
+    {
+        $_GET['search'] = $_SESSION['av_search'];
+        $_GET['folder'] = $_SESSION['av_folder'];
+        $_GET['sub_folders'] = $_SESSION['av_sub_folders'];
+        $this->trigger_search(true);
+    }
+
+    /**
+     * Here is where the actual query is fired to the imap server and the result is evaluated and sent back to the client side
+     *
+     * @access public
+     * @return null
+     */
+    public function trigger_search($inPagination = false)
+    {
+        $search = get_input_value('search', RCUBE_INPUT_GPC);
+        // reset list_page and old search results
+        $this->rc->storage->set_page(1);
+        $this->rc->storage->set_search_set(null);
+        $page = get_input_value('_page', RCUBE_INPUT_GPC);
+        $page = $page ? $page : 1;
+        $pagesize = $this->rc->storage->get_pagesize();
+
+        if (!empty($search)) {
+            $mbox = get_input_value('folder', RCUBE_INPUT_GPC);
+            $imap_charset = RCMAIL_CHARSET;
+            $sort_column = rcmail_sort_column();
+            $search_str = $this->get_search_query($search);
+            $sub_folders = get_input_value('sub_folders', RCUBE_INPUT_GPC) == 'true';
+            $folders = array();
+            $result_h = array();
+            $count = 0;
+            $new_id = 1;
+            $current_mbox = $this->rc->storage->get_folder();
+            $uid_list = array();
+            //Store information in session for pagination
+            $_SESSION['av_search'] = $search;
+            $_SESSION['av_folder'] = $mbox;
+            $_SESSION['av_sub_folders'] = get_input_value('sub_folders', RCUBE_INPUT_GPC);
+            $nosub = $sub_folders;
+            $folders = $this->rc->get_storage()->list_folders_subscribed();
+            if (empty($folders) || ($sub_folders === false && $mbox !== 'all')) {
+                $folders = array($mbox);
+            } elseif ($mbox !== 'all') {
+                if ($sub_folders === false) {
+                    $folders = array($mbox);
+                } else {
+                    $folders = $this->rc->get_storage()->list_folders_subscribed_direct($mbox);
+                }
+            }
+            $md5folders = array();
+            foreach ($folders as $folder) {
+                $md5folders[md5($folder)] = $folder;
+            }
+            $this->rc->output->set_env('as_md5_folders', $md5folders);
+
+            if ($search_str) {
+                $res = $this->perform_search($search_str, $folders, $page);
+                $count = $res['count'];
+            }
+
+
+            if ($count > 0) {
+                $_SESSION['advanced_search']['uid_list'] = $uid_list;
+                if ($search_str && $inPagination == false) {
+                    $this->rc->output->show_message('searchsuccessful', 'confirmation', array('nr' => $count));
+                }
+            } elseif ($err_code = $this->rc->storage->get_error_code()) {
+                rcmail_display_server_error();
+            } else {
+                $this->rc->output->show_message('searchnomatch', 'notice');
+            }
+
+            $current_folder = get_input_value('current_folder', RCUBE_INPUT_GPC);
+
+            $this->rc->output->set_env('search_request', 'advanced_search_active');
+            $this->rc->output->set_env('messagecount', $count);
+            $this->rc->output->set_env('pagecount', ceil($count / $pagesize));
+            $this->rc->output->set_env('exists', $this->rc->storage->count($current_folder, 'EXISTS'));
+            $this->rc->output->command('set_rowcount', rcmail_get_messagecount_text($count, $page));
+            $this->rc->output->command('plugin.search_complete');
+            $this->rc->output->send();
+        }
+    }
+
+    /**
+     * return javascript commands to add rows to the message list
+     */
+    public function rcmail_js_message_list($a_headers, $insert_top = false, $a_show_cols = null, $avmbox = false, $avcols = array(), $showMboxColumn = false)
+    {
+        global $CONFIG, $RCMAIL, $OUTPUT;
+        $uid_mboxes = array();
+
+        if (empty($a_show_cols)) {
+            if (!empty($_SESSION['list_attrib']['columns'])) {
+                $a_show_cols = $_SESSION['list_attrib']['columns'];
+            } else {
+                $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
+            }
+        } else {
+            if (!is_array($a_show_cols)) {
+                $a_show_cols = preg_split('/[\s,;]+/', strip_quotes($a_show_cols));
+            }
+            $head_replace = true;
+        }
+
+        $mbox = $RCMAIL->storage->get_folder();
+
+        // make sure 'threads' and 'subject' columns are present
+        if (!in_array('subject', $a_show_cols)) {
+            array_unshift($a_show_cols, 'subject');
+        }
+        if (!in_array('threads', $a_show_cols)) {
+            array_unshift($a_show_cols, 'threads');
+        }
+        $_SESSION['list_attrib']['columns'] = $a_show_cols;
+
+        // Make sure there are no duplicated columns (#1486999)
+        $a_show_cols = array_merge($a_show_cols, $avcols);
+        $a_show_cols = array_unique($a_show_cols);
+
+        // Plugins may set header's list_cols/list_flags and other rcube_message_header variables
+        // and list columns
+        $plugin = $RCMAIL->plugins->exec_hook(
+            'messages_list',
+            array('messages' => $a_headers, 'cols' => $a_show_cols)
+        );
+        $a_show_cols = $plugin['cols'];
+        $a_headers   = $plugin['messages'];
+        $thead = $head_replace ? rcmail_message_list_head($_SESSION['list_attrib'], $a_show_cols) : null;
+
+        // get name of smart From/To column in folder context
+        if (($f = array_search('fromto', $a_show_cols)) !== false) {
+            $smart_col = rcmail_message_list_smart_column_name();
+        }
+        if ($this->coltypesSet == false) {
+            $OUTPUT->command('set_message_coltypes', $a_show_cols, $thead, $smart_col);
+            if ($showMboxColumn === true) {
+                $OUTPUT->command('plugin.advanced_search_add_header', array());
+            }
+            $this->coltypesSet = true;
+        }
+
+        if (empty($a_headers)) {
+            return;
+        }
+
+        // remove 'threads', 'attachment', 'flag', 'status' columns, we don't need them here
+        foreach (array('threads', 'attachment', 'flag', 'status', 'priority') as $col) {
+            if (($key = array_search($col, $a_show_cols)) !== false) {
+                unset($a_show_cols[$key]);
+            }
+        }
+
+        // loop through message headers
+        foreach ($a_headers as $n => $header) {
+            if (empty($header)) {
+                continue;
+            }
+            $a_msg_cols = array();
+            $a_msg_flags = array();
+            // format each col; similar as in rcmail_message_list()
+            foreach ($a_show_cols as $col) {
+                $col_name = $col == 'fromto' ? $smart_col : $col;
+
+                if (in_array($col_name, array('from', 'to', 'cc', 'replyto'))) {
+                    $cont = rcmail_address_string($header->$col_name, 3, false, null, $header->charset);
+                } elseif ($col == 'subject') {
+                    $cont = trim(rcube_mime::decode_header($header->$col, $header->charset));
+                    if (!$cont) {
+                        $cont = rcube_label('nosubject');
+                    }
+                    $cont = Q($cont);
+                } elseif ($col == 'size') {
+                    $cont = show_bytes($header->$col);
+                } elseif ($col == 'date') {
+                    $cont = format_date($header->date);
+                } else {
+                    $cont = Q($header->$col);
+                }
+                $a_msg_cols[$col] = $cont;
+            }
+
+            $a_msg_flags = array_change_key_case(array_map('intval', (array) $header->flags));
+            if ($header->depth) {
+                $a_msg_flags['depth'] = $header->depth;
+            } elseif ($header->has_children) {
+                $roots[] = $header->uid;
+            }
+            if ($header->parent_uid) {
+                $a_msg_flags['parent_uid'] = $header->parent_uid;
+            }
+            if ($header->has_children) {
+                $a_msg_flags['has_children'] = $header->has_children;
+            }
+            if ($header->unread_children) {
+                $a_msg_flags['unread_children'] = $header->unread_children;
+            }
+            if ($header->others['list-post']) {
+                $a_msg_flags['ml'] = 1;
+            }
+            if ($header->priority) {
+                $a_msg_flags['prio'] = (int) $header->priority;
+            }
+            $a_msg_flags['ctype'] = Q($header->ctype);
+            $a_msg_flags['mbox'] = $mbox;
+            if (!empty($header->list_flags) && is_array($header->list_flags)) {
+                $a_msg_flags = array_merge($a_msg_flags, $header->list_flags);
+            }
+            if (!empty($header->list_cols) && is_array($header->list_cols)) {
+                $a_msg_cols = array_merge($a_msg_cols, $header->list_cols);
+            }
+            if ($showMboxColumn === true) {
+                $a_msg_flags['avmbox'] = $avmbox;
+            }
+
+            $OUTPUT->command(
+                'add_message_row',
+                $header->uid . '__MB__' . md5($mbox),
+                $a_msg_cols,
+                $a_msg_flags,
+                $insert_top
+            );
+            $id = $header->uid . '__MB__' . md5($mbox);
+            $uid_mboxes[$id] = array('uid' => $header->uid, 'mbox' => $mbox, 'md5mbox' => md5($mbox));
+        }
+
+        if ($RCMAIL->storage->get_threading()) {
+            $OUTPUT->command('init_threads', (array) $roots, $mbox);
+        }
+
+        return $uid_mboxes;
+    }
+
+
+    private function do_pagination($folders, $onPage)
+    {
+        $perPage = $this->rc->storage->get_pagesize();
+        $from = $perPage * $onPage - $perPage + 1;
+        $to = $from + $perPage - 1;
+        $got = 0;
+        $pos = 0;
+        $cbox = "";
+        $boxStart = 0;
+        $boxStop = 0;
+        $fetch = array();
+        foreach ($folders as $box => $num) {
+            $i = $num;
+            if ($box != $cbox) {
+                $boxStart = 0;
+                $boxStop = 0;
+                $cbox = $box;
+            }
+            while ($i--) {
+                $pos++;
+                $boxStart++;
+                if ($pos >= $from && $pos <= $to) {
+                    if (!isset($fetch[$box])) {
+                        $fetch[$box] = array("from" => $boxStart);
+                    }
+                    $fetch[$box]['to'] = $boxStart;
+                    $got++;
+                }
+            }
+            if ($got >= $perPage) {
+                break;
+            }
+        }
+
+        return $fetch;
+    }
+
+    /**
+     * Save advanced search preferences
+     *
+     * @access  public
+     */
+    public function preferences_save($args)
+    {
+        if ($args['section'] != 'advancedsearch') {
+            return;
+        }
+        $rcmail = rcmail::get_instance();
+
+        $displayOptions = array();
+        $displayOptions['_show_message_label_header'] = get_input_value('_show_message_label_header', RCUBE_INPUT_POST) == 1 ? true : false;
+        $displayOptions['_show_message_mbox_info'] = get_input_value('_show_message_mbox_info', RCUBE_INPUT_POST) == 1 ? true : false;
+        $displayOptions['target_menu'] = get_input_value('button_display_option', RCUBE_INPUT_POST);
+
+        $args['prefs']['advanced_search_display_options'] = $displayOptions;
+
+        return($args);
+    }
+
+    /**
+     * Add a section advanced search to the preferences section list
+     *
+     * @access  public
+     */
+    public function preferences_section($args)
+    {
+        $args['list']['advancedsearch'] = array(
+            'id' => 'advancedsearch',
+            'section' => Q($this->gettext('advancedsearch'))
+        );
+
+        return($args);
+    }
+
+    /**
+     * Display advanced search configuration in user preferences tab
+     *
+     * @access  public
+     */
+    public function preferences_list($args)
+    {
+        if ($args['section'] == 'advancedsearch') {
+
+            $this->rc = rcmail::get_instance();
+            $args['blocks']['label_display_options'] = array('options' => array(), 'name' => Q($this->gettext('label_display_options')));
+
+            $displayOptions = $this->rc->config->get('advanced_search_display_options', array());
+            $target_menu = (isset($displayOptions['target_menu']) && !empty($displayOptions['target_menu'])) ? $displayOptions['target_menu'] : $this->config['target_menu'];
+            $options = '';
+            $optarg = array('value' => 'messagemenu');
+            if ($target_menu == 'messagemenu') {
+                $optarg['selected'] = 'selected';
+                $target_image = 'menu_location_a.jpg';
+            }
+            $options .= html::tag('option', $optarg, Q($this->gettext('display_in_messagemenu')));
+            $optarg = array('value' => 'toolbar');
+            if ($target_menu == 'toolbar') {
+                $optarg['selected'] = 'selected';
+                $target_image = 'menu_location_b.jpg';
+            }
+            $options .= html::tag('option', $optarg, Q($this->gettext('display_in_toolbar')));
+            $select = html::tag('select', array('name' => 'button_display_option', 'id' => 'button_display_option'), $options);
+
+            $label1 = html::label('_show_message_label_header', Q($this->gettext('mailbox_headers_in_results')));
+            $label2 = html::label('_show_message_mbox_info', Q($this->gettext('mailbox_info_in_results')));
+            $label3 = html::label('button_display_option', Q($this->gettext('show_advanced_search')));
+
+            $arg1 = array('name' => '_show_message_label_header', 'id' => '_show_message_label_header', 'type' => 'checkbox', 'title' => "", 'class' => 'watermark linput', 'value' => 1);
+            if (isset($displayOptions['_show_message_label_header']) && $displayOptions['_show_message_label_header'] === true) {
+                $arg1['checked'] = 'checked';
+                $img1class = 'enabled';
+            } else {
+                $img1class = 'disabled';            
+            }
+            $check1 = html::tag('input', $arg1);
+            $arg2 = array('name' => '_show_message_mbox_info', 'id' => '_show_message_mbox_info', 'type' => 'checkbox', 'title' => "", 'class' => 'watermark linput', 'value' => 1);
+            if (isset($displayOptions['_show_message_mbox_info']) && $displayOptions['_show_message_mbox_info'] === true) {
+                $arg2['checked'] = 'checked';
+                $img2class = 'enabled';
+            } else {
+                $img2class = 'disabled';
+            }
+
+            $img1 = html::img(array('src' => $this->url('skins/larry/images/show_mbox_row.jpg'), 'class' => $img1class));
+            $img2 = html::img(array('src' => $this->url('skins/larry/images/show_mbox_col.jpg'), 'class' => $img2class));
+            $img3 = html::img(array('src' => $this->url('skins/larry/images/' . $target_image)));
+
+            $check2 = html::tag('input', $arg2);
+            $args['blocks']['label_display_options']['options'][0] = array('title' => '', 'content' => '<p class="avsearchpref"><span>' . $check1 . ' ' . $label1 . '</span> ' . $img1 . '</p>');
+            $args['blocks']['label_display_options']['options'][1] = array('title' => '', 'content' => '<p class="avsearchpref"><span>' . $check2 . ' ' . $label2 . '</span> ' . $img2 . '</p>');
+            $args['blocks']['label_display_options']['options'][2] = array('title' => '', 'content' => '<p class="avsearchpref"><span>' . $label3 . ' ' . $select . '</span> ' . $img3 . '</p>');
+        }
+
+        return($args);
+    }
+
+    private function perform_search($search_string, $folders, $page = 1)
+    {
+        // Search all folders and build a final set
+        if ($folders[0] == 'all' || empty($folders)) {
+            $folders_search = $this->rc->imap->list_folders_subscribed();
+        } else {
+            $folders_search = $folders;
+        }
+        $count = 0;
+        $folder_count = array();
+        foreach ($folders_search as $mbox) {
+            $this->rc->storage->set_folder($mbox);
+            $this->rc->storage->search($mbox, $search_string, RCMAIL_CHARSET, $_SESSION['sort_col']);
+            $result = array();
+            $fcount = $this->rc->storage->count($mbox, 'ALL', !empty($_REQUEST['_refresh']));
+            $count += $fcount;
+            $folder_count[$mbox] = $fcount;
+        }
+        foreach ($folder_count as $k => $v) {
+            if ($v == 0) {
+                unset($folder_count[$k]);
+            }
+        }
+        $fetch = $this->do_pagination($folder_count, $page);
+        $mails = array();
+        $currentMailbox = "";
+        $displayOptions = $this->rc->config->get('advanced_search_display_options', array());
+        $showMboxColumn = isset($displayOptions['_show_message_mbox_info']) && $displayOptions['_show_message_mbox_info'] ? true : false;
+        $uid_mboxes = array();
+        foreach ($fetch as $mailbox => $data) {
+            if ($currentMailbox != $mailbox) {
+                $currentMailbox = $mailbox;
+                if (isset($displayOptions['_show_message_label_header']) && $displayOptions['_show_message_label_header'] === true) {
+                    $this->rc->output->command('advanced_search_add_mbox', $mailbox, $folder_count[$mailbox], $showMboxColumn);
+                }
+            }
+            $uid_mboxes = array_merge($uid_mboxes, $this->getMails($mailbox, $data, $search_string, $showMboxColumn));
+        }
+
+        return array('result' => array(), 'count' => $count, 'uid_mboxes' => $uid_mboxes);
+    }
+
+    private function getMails($mailbox, $data, $search_string, $showMboxColumn)
+    {
+        $pageSize = $this->rc->storage->get_pagesize();
+        $msgNum = $data['from'];
+        $startPage =  ceil($msgNum/$pageSize);
+        $msgMod = $msgNum % $pageSize;
+        $multiPage = "false";
+        $firstArrayElement = $msgMod == 0 ? ($pageSize-1) : ($msgMod-1);
+        $quantity = $data['to'] - $data['from'];
+        if ($data['from'] + $quantity > $pageSize) {
+            $multiPage = "true";
+        }
+        $this->rc->storage->set_folder($mailbox);
+        $this->rc->storage->search($mailbox, $search_string, RCMAIL_CHARSET, $_SESSION['sort_col']);
+        $messages = $this->rc->storage->list_messages('', $startPage);
+        if ($multiPage) {
+            $messages = array_merge($messages, $this->rc->storage->list_messages('', $startPage+1));
+        }
+        //FIRST: 0 QUANTITY: 2
+        $sliceTo = $quantity + 1;
+        $mslice = array_slice($messages, $firstArrayElement, $sliceTo, true);
+        $messages = $mslice;
+        $avbox = array();
+        $showAvmbox = false;
+        foreach ($messages as $set_flag) {
+            $set_flag->flags['skip_mbox_check'] = true;
+            if ($showMboxColumn === true) {
+                $set_flag->avmbox = $mailbox;
+                $avbox[] = 'avmbox';
+                $showAvmbox = true;
+            }
+        }
+        $uid_mboxes = $this->rcmail_js_message_list($messages, false, null, $showAvmbox, $avbox, $showMboxColumn);
+
+        return $uid_mboxes;
+    }
+
+    public function save_search()
+    {
+        $search_name = get_input_value('search_name', RCUBE_INPUT_GPC);
+        if ($search_name) {
+            $search = array();
+            $search['search'] = get_input_value('search', RCUBE_INPUT_GPC);
+            $search['search_name'] = $search_name;
+            $search['folder'] = get_input_value('folder', RCUBE_INPUT_GPC);
+            $search['sub_folders'] = get_input_value('sub_folders', RCUBE_INPUT_GPC);
+            $prefs = (array)$this->rc->user->get_prefs();
+            if (!isset($prefs['advanced_search'])) {
+                $prefs['advanced_search'] = array();
+            }
+            $prefs['advanced_search'][$search_name] = $search;
+            $this->rc->user->save_prefs(array('advanced_search' => $prefs['advanced_search']));
+            $this->rc->output->show_message('"<i>' . $search_name . '</i>" ' . $this->i18n_strings['has_been_saved'], 'confirmation');
+        }
+    }
+
+    public function delete_search()
+    {
+        $search_name = get_input_value('search_name', RCUBE_INPUT_GPC);
+        if ($search_name) {
+            $prefs = (array)$this->rc->user->get_prefs();
+            unset($prefs['advanced_search'][$search_name]);
+            $this->rc->user->save_prefs(array('advanced_search' => $prefs['advanced_search']));
+            $this->rc->output->show_message('"<i>' . $search_name . '</i>" ' . $this->i18n_strings['has_been_deleted'], 'notice');
+        }
+    }
+
+    public function get_saved_search()
+    {
+        $search_name = get_input_value('search_name', RCUBE_INPUT_GPC);
+        $prefs = (array)$this->rc->user->get_prefs();
+        if (!isset($prefs['advanced_search'])) {
+            $prefs['advanced_search'] = array();
+        }
+
+        $search = isset($prefs['advanced_search'][$search_name]) ? $prefs['advanced_search'][$search_name] : false;
+        $this->rc->output->command('plugin.load_saved_search', $search);
+        $this->rc->output->send();
+    }
+
+    private function get_saved_search_names()
+    {
+        $prefs = (array)$this->rc->user->get_prefs();
+        if (!isset($prefs['advanced_search'])) {
+            $prefs['advanced_search'] = array();
+        }
+        $names = array();
+        foreach($prefs['advanced_search'] as $name => $search) {
+            $names[] = $name;
+        }
+
+        return $names;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/advanced_search.php~	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,1088 @@
+<?php
+/**
+ * Processing an advanced search over an E-Mail Account
+ *
+ * @version 2.1.5
+ * @licence GNU GPLv3+
+ * @author  Wilwert Claude
+ * @author  Ludovicy Steve
+ * @author  Chris Moules
+ * @website http://www.gms.lu
+ *
+ * Updated by Alex S Grebenschikov (www.poralix.com)
+ * to make it compatible with RoundCube 1.3.0
+ * Last modified: Tue Aug  1 06:41:46 CEST 2017
+ *
+ */
+
+class advanced_search extends rcube_plugin
+{
+
+    /**
+     * Instance of rcmail
+     *
+     * @var object
+     * @access private
+     */
+    private $rc;
+
+    public $task = 'mail|settings';
+
+    /**
+     * Plugin config
+     *
+     * @var array
+     * @access private
+     */
+    private $config;
+
+    /**
+     * Localization strings
+     *
+     * @var array
+     * @access private
+     */
+    private $i18n_strings = array();
+
+    /**
+     * Initialisation of the plugin
+     *
+     * @access public
+     * @return null
+     */
+    public function init()
+    {
+        $this->rc = rcmail::get_instance();
+        $this->load_config("config-default.inc.php");
+        $this->load_config();
+        $this->config = $this->rc->config->get('advanced_search_plugin');
+        $this->register_action('plugin.display_advanced_search', array($this, 'display_advanced_search'));
+        $this->register_action('plugin.trigger_search', array($this, 'trigger_search'));
+        $this->register_action('plugin.trigger_search_pagination', array($this, 'trigger_search_pagination'));
+        $this->register_action('plugin.save_search', array($this, 'save_search'));
+        $this->register_action('plugin.delete_search', array($this, 'delete_search'));
+        $this->register_action('plugin.get_saved_search', array($this, 'get_saved_search'));
+
+        $this->skin = $this->rc->config->get('skin');
+        $this->add_texts('localization', true);
+        $this->populate_i18n();
+        if(isset($this->config['criteria'])) {
+            foreach($this->config['criteria'] as $key => $translation) {
+                $this->config['criteria'][$key] = $this->gettext($key);
+            }
+        }
+        $this->include_script('advanced_search.js');
+
+        if ($this->rc->task == 'mail') {
+            $file = 'skins/' . $this->skin . '/advanced_search.css';
+
+            if (file_exists($this->home . '/' . $file)) {
+                $this->include_stylesheet($file);
+            } else {
+                $this->include_stylesheet('skins/default/advanced_search.css');
+            }
+
+            if (empty($this->rc->action)) {
+                $this->add_menu_entry();
+            }
+        } elseif ($this->rc->task == 'settings') {
+            $this->add_hook('preferences_list', array($this, 'preferences_list'));
+            $this->add_hook('preferences_save', array($this, 'preferences_save'));
+            $this->add_hook('preferences_sections_list', array($this, 'preferences_section'));
+            $file = 'skins/' . $this->skin . '/advanced_search.css';
+            if (file_exists($this->home . '/' . $file)) {
+                $this->include_stylesheet($file);
+            } else {
+                $this->include_stylesheet('skins/default/advanced_search.css');
+            }
+        }
+
+        $this->add_hook('startup', array($this, 'startup'));
+    }
+
+
+    public function startup($args)
+    {
+        $search = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GET);
+        if (!isset($search)) {
+            $search = rcube_utils::get_input_value('_search', rcube_utils::INPUT_POST);
+        }
+        $rsearch = $search == 'advanced_search_active';
+        $uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GET);
+        $draft_uid = rcube_utils::get_input_value('_draft_uid', rcube_utils::INPUT_GET);
+        $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GET);
+        $page = rcube_utils::get_input_value('_page', rcube_utils::INPUT_GET);
+        $sort = rcube_utils::get_input_value('_sort', rcube_utils::INPUT_GET);
+
+        if (!empty($uid)) {
+            $parts = explode('__MB__', $uid);
+            if (count($parts) == 2) {
+                $search = 'advanced_search_active';
+            }
+        }
+        if (!empty($draft_uid)) {
+            $parts = explode('__MB__', $draft_uid);
+            if (count($parts) == 2) {
+                $search = 'advanced_search_active';
+            }
+        }
+
+        if ($search == 'advanced_search_active') {
+            if ($args['action'] == 'show' && !empty($uid)) {
+                $parts = explode('__MB__', $uid);
+                $uid = $parts[0];
+                $this->rc->output->redirect(array('_task' => 'mail', '_action' => $args['action'], '_mbox' => $mbox, '_uid' => $uid));
+            }
+            if ($args['action'] == 'compose') {
+                $draft_uid = rcube_utils::get_input_value('_draft_uid', rcube_utils::INPUT_GET);
+                $parts = explode('__MB__', $draft_uid);
+                $draft_uid = $parts[0];
+                if (!empty($draft_uid)) {
+                    $this->rc->output->redirect(array('_task' => 'mail', '_action' => $args['action'], '_mbox' => $mbox, '_draft_uid' => $draft_uid));
+                }
+            }
+            if ($args['action'] == 'list' && $rsearch) {
+                $this->rc->output->command('advanced_search_active', '_page=' . $page . '&_sort=' . $sort);
+                $this->rc->output->send();
+                $args['abort'] = true;
+            }
+            if ($args['action'] == 'mark') {
+                $flag = rcube_utils::get_input_value('_flag', rcube_utils::INPUT_POST);
+                $uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST);
+
+                $post_str = '_flag=' . $flag . '&_uid=' . $uid;
+                if ($quiet = rcube_utils::get_input_value('_quiet', rcube_utils::INPUT_POST)) {
+                    $post_str .= '&_quiet=' . $quiet;
+                }
+                if ($from = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST)) {
+                    $post_str .= '&_from=' . $from;
+                }
+                if ($count = rcube_utils::get_input_value('_count', rcube_utils::INPUT_POST)) {
+                    $post_str .= '&_count=' . $count;
+                }
+                if ($ruid = rcube_utils::get_input_value('_ruid', rcube_utils::INPUT_POST)) {
+                    $post_str .= '&_ruid=' . $ruid;
+                }
+                $this->rc->output->command('label_mark', $post_str);
+                $this->rc->output->send();
+                $args['abort'] = true;
+            }
+
+        } else {
+            if ($args['action'] != 'plugin.get_saved_search' && $args['action'] != 'plugin.save_search' && $args['action'] != 'plugin.delete_search') {
+                $this->rc->output->command('plugin.advanced_search_del_header', array());
+            }
+        }
+    }
+
+    /**
+     * This function populates an array with localization texts.
+     * This is needed as ew are using a lot of localizations from core.
+     * The core localizations are not avalable directly in JS
+     *
+     * @access private
+     * @return null
+     */
+    private function populate_i18n()
+    {
+        $core = array('advsearch', 'search', 'resetsearch', 'addfield', 'delete', 'cancel');
+
+        foreach ($core as $label) {
+            $this->i18n_strings[$label] = $this->rc->gettext($label);
+        }
+
+        $local = array('in', 'and', 'or', 'not', 'where', 'exclude', 'andsubfolders', 'allfolders', 'save_the_search', 'has_been_saved', 'deletesearch', 'has_been_deleted');
+
+        foreach ($local as $label) {
+            $this->i18n_strings[$label] = $this->gettext($label);
+        }
+    }
+
+    /**
+     * This adds a button into the configured menu to use the advanced search
+     *
+     * @access public
+     * @return null
+     */
+    public function add_menu_entry()
+    {
+        $displayOptions = $this->rc->config->get('advanced_search_display_options', array());
+        $target_menu = (isset($displayOptions['target_menu']) && !empty($displayOptions['target_menu'])) ? $displayOptions['target_menu'] : $this->config['target_menu'];
+        if ($target_menu != 'toolbar') {
+            $this->api->add_content(
+                html::tag(
+                    'li',
+                    null,
+                    $this->api->output->button(
+                        array(
+                            'command'    => 'plugin.advanced_search',
+                            'label'      => 'advsearch',
+                            'type'       => 'link',
+                            'classact'   => 'icon advanced-search active',
+                            'class'      => 'icon advanced-search',
+                            'innerclass' => 'icon advanced-search'
+                        )
+                    )
+                ),
+                $target_menu
+            );
+        } else {
+            $this->api->add_content(
+                $this->api->output->button(
+                    array(
+                        'command'    => 'plugin.advanced_search',
+                        'title'      => 'advsearch',
+                        'label'      => 'search',
+                        'type'       => 'link',
+                        'classact'   => 'button advanced-search active',
+                        'class'      => 'button advanced-search',
+                        'innerclass' => 'button advanced-search',
+                    )
+                ),
+                $target_menu
+            );
+        }
+    }
+
+    /**
+     * This function quotes some specific values based on their data type
+     *
+     * @param mixed $input The value to get quoted
+     * @access public
+     * @return The quoted value
+     */
+    public function quote($value)
+    {
+        if (getType($value) == 'string') {
+            if (!preg_match('/"/', $value)) {
+                $value = preg_replace('/^"/', '', $value);
+                $value = preg_replace('/"$/', '', $value);
+                $value = preg_replace('/"/', '\\"', $value);
+            }
+
+            $value = '"' . $value . '"';
+        }
+
+        return $value;
+    }
+
+    /**
+     * This function generates the IMAP compatible search query based on the request data (by javascript)
+     *
+     * @param array $input The raw criteria data sent by javascript
+     * @access private
+     * @return string or int
+     */
+    private function process_search_part($search_part)
+    {
+        $command_str = '';
+        $flag = false;
+
+        // Check for valid input
+        if (!array_key_exists($search_part['filter'], $this->config['criteria'])) {
+            $this->rc->output->show_message($this->gettext('internalerror'), 'error');
+
+            return 0;
+        }
+        if (in_array($search_part['filter'], $this->config['flag_criteria'])) {
+            $flag = true;
+        }
+        if (!$flag && !(isset($search_part['filter-val']) && $search_part['filter-val'] != '')) {
+            return 1;
+        }
+
+        // Negate part
+        if ($search_part['not'] == 'true') {
+            $command_str .= 'NOT ';
+        }
+
+        $command_str .= $search_part['filter'];
+
+        if (!$flag) {
+            if (in_array($search_part['filter'], $this->config['date_criteria'])) {
+                // Take date format from user environment
+                $date_format = $this->rc->config->get('date_format', 'Y-m-d');
+                // Try to use PHP5.2+ DateTime but fallback to ugly old method
+                if (class_exists('DateTime')) {
+                    $date = DateTime::createFromFormat($date_format, $search_part['filter-val']);
+                    $command_str .= ' ' . $this->quote($date->format("d-M-Y"));
+                } else {
+                    $date_format = preg_replace('/(\w)/', '%$1', $date_format);
+                    $date_array = strptime($search_part['filter-val'], $date_format);
+                    $unix_ts = mktime($date_array['tm_hour'], $date_array['tm_min'], $date_array['tm_sec'], $date_array['tm_mon']+1, $date_array['tm_mday'], $date_array['tm_year']+1900);
+                    $command_str .= ' ' . $this->quote(date("d-M-Y", $unix_ts));
+                }
+            } elseif (in_array($search_part['filter'], $this->config['email_criteria'])) {
+                // Strip possible ',' added by autocomplete
+                $command_str .= ' ' . $this->quote(trim($search_part['filter-val'], " \t,"));
+            } else {
+                // Don't try to use a value for a binary flag object
+                $command_str .= ' ' . $this->quote($search_part['filter-val']);
+            }
+        }
+
+        return $command_str;
+    }
+
+    /**
+     * This function generates the IMAP compatible search query based on the request data (by javascript)
+     *
+     * @param array $input The raw criteria data sent by javascript
+     * @access public
+     * @return The final search command
+     */
+    public function get_search_query($input)
+    {
+        $command = array();
+
+        foreach ($input as $search_part) {
+            // Skip excluded parts
+            if ($search_part['excluded'] == 'true') {
+                continue;
+            }
+            if (! $part_command = $this->process_search_part($search_part)) {
+                return 0;
+            }
+            // Skip invalid parts
+            if ($part_command === 1) {
+                continue;
+            }
+
+            $command[] = array('method' => isset($search_part['method']) ? $search_part['method'] : 'and',
+                               'command' => $part_command);
+        }
+
+        $command_string = $this->build_search_string($command);
+
+        return $command_string;
+    }
+
+    /**
+     * This function converts the preconfigured query parts (as array) into an IMAP compatible string
+     *
+     * @param array $command_array An array containing the advanced search criteria
+     * @access public
+     * @return The command string
+     */
+    private function build_search_string($command_array)
+    {
+        $command = array();
+        $paranthesis = 0;
+        $prev_method = null;
+        $next_method = null;
+        $cnt = count($command_array);
+
+        foreach ($command_array as $k => $v) {
+            $part = '';
+            $next_method = 'unknown';
+
+            // Lookup next method
+            if ($k < $cnt-1) {
+                $next_method = $command_array[$k+1]['method'];
+            }
+
+            // If previous option was OR, close any open brakets
+            if ($paranthesis > 0 && $prev_method == 'or' && $v['method'] != 'or') {
+                for (; $paranthesis > 0; $paranthesis--) {
+                    $part .= ')';
+                }
+            }
+
+            // If there are two consecutive ORs, add brakets
+            // If the next option is a new OR, add the prefix here
+            // If the next option is _not_ an OR, and the current option is AND, prefix ALL
+            if ($next_method == 'or') {
+                if ($v['method'] == 'or') {
+                    $part .= ' (';
+                    $paranthesis++;
+                }
+                $part .= 'OR ';
+            } elseif ($v['method'] == 'and') {
+                $part .= 'ALL ';
+            }
+
+            $part .= $v['command'];
+
+            // If this is the end of the query, and we have open brakets, close them
+            if ($k == $cnt-1 && $paranthesis > 0) {
+                for (; $paranthesis > 0; $paranthesis--) {
+                    $part .= ')';
+                }
+            }
+
+            $prev_method = $v['method'];
+            $command[] = $part;
+        }
+
+        $command = implode(' ', $command);
+
+        return $command;
+    }
+
+    /**
+     * This functions sends the initial data to the client side where a form (in dialog) is built for the advanced search
+     *
+     * @access public
+     * @return null
+     */
+    public function display_advanced_search()
+    {
+        $ret = array('html' => $this->generate_searchbox(),
+                     'row' => $this->add_row(),
+                     'saved_searches' => $this->get_saved_search_names(),
+                     'title' => $this->i18n_strings['advsearch'],
+                     'date_criteria' => $this->config['date_criteria'],
+                     'flag_criteria' => $this->config['flag_criteria'],
+                     'email_criteria' => $this->config['email_criteria']);
+
+        $this->rc->output->command('plugin.show', $ret);
+    }
+
+    public function generate_searchbox()
+    {
+        $search_button = new html_inputfield(array('type' => 'submit', 'name' => 'search', 'class' => 'button mainaction', 'value' => $this->i18n_strings['search']));
+        $reset_button = new html_inputfield(array('type' => 'reset', 'name' => 'reset', 'class' => 'button reset', 'value' => $this->i18n_strings['resetsearch']));
+        $save_button = html::tag('input', array('type' => 'submit', 'name' => 'save_the_search', id=> 'save_the_search', 'class' => 'button save_search', 'value' => $this->i18n_strings['save_the_search']));
+        $delete_button = new html_inputfield(array('type' => 'submit', 'name' => 'delete', 'style' => 'display: none;', 'class' => 'button delete_search', 'value' => $this->i18n_strings['deletesearch']));
+
+        $layout_table = new html_table();
+        $layout_table->add(null, $search_button->show());
+        $folderConfig = array('name' => 'folder');
+        $layout_table->add(
+            null,
+            $this->i18n_strings['in'] . ': ' .
+            $this->folder_selector($folderConfig)->show($this->rc->storage->get_folder()) .
+            html::span(
+                array('class' => 'sub-folders'),
+                $this->i18n_strings['andsubfolders'] . ': ' .
+                html::tag(
+                    'input',
+                    array('type' => 'checkbox', 'name' => 'subfolder'),
+                    null
+                )
+            ) .
+            $this->i19n_strings['where']
+        );
+        $first_row = $this->add_row(true);
+        $layout_table->add_row();
+        $layout_table->add(array('class' => 'adv-search-and-or'), null);
+        $layout_table->add(null, $first_row);
+        $layout_table->add_row();
+        $layout_table->add(null, $search_button->show());
+        $layout_table->add(null, $save_button . ' ' . $reset_button->show() . ' ' . $delete_button->show());
+
+        return html::tag(
+            'div',
+            array('id' => 'adsearch-popup'),
+            html::tag(
+                'form',
+                array('method' => 'post', 'action' => '#'),
+                $layout_table->show()
+            )
+        );
+    }
+
+    /**
+     * This function is used to render the html of the advanced search form and also
+     * the later following rows are created by this function
+     *
+     * @param array   $folders Array of folders
+     * @param boolean $first   True if form gets created, False to create a new row
+     * @access public
+     * @return string The final html
+     */
+    public function add_row($first = false)
+    {
+        $row_html = '';
+        $optgroups = '';
+
+        $criteria = $this->config['criteria'];
+        $all_criteria = array(
+            $this->gettext('Common') => $this->config['prefered_criteria'],
+            $this->gettext('Addresses') => $this->config['email_criteria'],
+            $this->gettext('Dates') => $this->config['date_criteria'],
+            $this->gettext('Flags') => $this->config['flag_criteria'],
+            $this->gettext('Other') => $this->config['other_criteria'],
+        );
+
+        foreach ($all_criteria as $label => $specific_criteria) {
+            $options = '';
+
+            foreach ($specific_criteria as $value) {
+                $options .= html::tag('option', array('value' => $value), $criteria[$value]);
+            }
+
+            $optgroups .= html::tag('optgroup', array('label' => $label), $options);
+        }
+
+        $tmp = html::tag('select', array('name' => 'filter'), $optgroups);
+        $tmp .= $this->i18n_strings['not'] . ':' . html::tag('input', array('type' => 'checkbox', 'name' => 'not'), null);
+        $tmp .= html::tag('input', array('type' => 'text', 'name' => 'filter-val'));
+        $tmp .= $this->i18n_strings['exclude'] . ':' . html::tag('input', array('type' => 'checkbox', 'name' => 'filter-exclude'), null);
+        $tmp .= html::tag('button', array('name' => 'add', 'class' => 'add'), $this->i18n_strings['addfield']);
+
+        if ($first) {
+            $row_html = $tmp;
+        } else {
+            $and_or_select = new html_select(array('name' => 'method'));
+            $and_or_select->add($this->i18n_strings['and'], 'and');
+            $and_or_select->add($this->i18n_strings['or'], 'or');
+            $tmp .= html::tag('button', array('name' => 'delete', 'class' => 'delete'), $this->i18n_strings['delete']);
+            $row_html = html::tag(
+                'tr',
+                null,
+                html::tag(
+                    'td',
+                    array('class' => 'adv-search-and-or'),
+                    $and_or_select->show()
+                ) .
+                html::tag(
+                    'td',
+                    null,
+                    $tmp
+                )
+            );
+        }
+
+        return $row_html;
+    }
+
+    /**
+     * Return folders list as html_select object
+     *
+     * This is a copy of the core function and adapted to fit
+     * the needs of the advanced_search function
+     *
+     * @param array $p Named parameters
+     *
+     * @return html_select HTML drop-down object
+     */
+    public function folder_selector($p = array())
+    {
+        $p += array('maxlength' => 100, 'realnames' => false, 'is_escaped' => true);
+        $a_mailboxes = array();
+        $storage = $this->rc->get_storage();
+
+        $list = $storage->list_folders_subscribed();
+        $delimiter = $storage->get_hierarchy_delimiter();
+
+        foreach ($list as $folder) {
+            $this->rc->build_folder_tree($a_mailboxes, $folder, $delimiter);
+        }
+
+        $select = new html_select($p);
+        $select->add($this->i18n_strings['allfolders'], "all");
+
+        $this->rc->render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p);
+
+        return $select;
+    }
+
+    public function trigger_search_pagination($param)
+    {
+        $_GET['search'] = $_SESSION['av_search'];
+        $_GET['folder'] = $_SESSION['av_folder'];
+        $_GET['sub_folders'] = $_SESSION['av_sub_folders'];
+        $this->trigger_search(true);
+    }
+
+    /**
+     * Here is where the actual query is fired to the imap server and the result is evaluated and sent back to the client side
+     *
+     * @access public
+     * @return null
+     */
+    public function trigger_search($inPagination = false)
+    {
+        $search = rcube_utils::get_input_value('search', rcube_utils::INPUT_GPC);
+        // reset list_page and old search results
+        $this->rc->storage->set_page(1);
+        $this->rc->storage->set_search_set(null);
+        $page = rcube_utils::get_input_value('_page', rcube_utils::INPUT_GPC);
+        $page = $page ? $page : 1;
+        $pagesize = $this->rc->storage->get_pagesize();
+
+        if (!empty($search)) {
+            $mbox = rcube_utils::get_input_value('folder', rcube_utils::INPUT_GPC);
+            $imap_charset = RCMAIL_CHARSET;
+            $sort_column = rcmail_sort_column();
+            $search_str = $this->get_search_query($search);
+            $sub_folders = rcube_utils::get_input_value('sub_folders', rcube_utils::INPUT_GPC) == 'true';
+            $folders = array();
+            $result_h = array();
+            $count = 0;
+            $new_id = 1;
+            $current_mbox = $this->rc->storage->get_folder();
+            $uid_list = array();
+            //Store information in session for pagination
+            $_SESSION['av_search'] = $search;
+            $_SESSION['av_folder'] = $mbox;
+            $_SESSION['av_sub_folders'] = rcube_utils::get_input_value('sub_folders', rcube_utils::INPUT_GPC);
+            $nosub = $sub_folders;
+            $folders = $this->rc->get_storage()->list_folders_subscribed();
+            if (empty($folders) || ($sub_folders === false && $mbox !== 'all')) {
+                $folders = array($mbox);
+            } elseif ($mbox !== 'all') {
+                if ($sub_folders === false) {
+                    $folders = array($mbox);
+                } else {
+                    $folders = $this->rc->get_storage()->list_folders_subscribed_direct($mbox);
+                }
+            }
+            $md5folders = array();
+            foreach ($folders as $folder) {
+                $md5folders[md5($folder)] = $folder;
+            }
+            $this->rc->output->set_env('as_md5_folders', $md5folders);
+
+            if ($search_str) {
+                $res = $this->perform_search($search_str, $folders, $page);
+                $count = $res['count'];
+            }
+
+
+            if ($count > 0) {
+                $_SESSION['advanced_search']['uid_list'] = $uid_list;
+                if ($search_str && $inPagination == false) {
+                    $this->rc->output->show_message('searchsuccessful', 'confirmation', array('nr' => $count));
+                }
+            } elseif ($err_code = $this->rc->storage->get_error_code()) {
+                rcmail_display_server_error();
+            } else {
+                $this->rc->output->show_message('searchnomatch', 'notice');
+            }
+
+            $current_folder = rcube_utils::get_input_value('current_folder', rcube_utils::INPUT_GPC);
+
+            $this->rc->output->set_env('search_request', 'advanced_search_active');
+            $this->rc->output->set_env('messagecount', $count);
+            $this->rc->output->set_env('pagecount', ceil($count / $pagesize));
+            $this->rc->output->set_env('exists', $this->rc->storage->count($current_folder, 'EXISTS'));
+            $this->rc->output->command('set_rowcount', rcmail_get_messagecount_text($count, $page));
+            $this->rc->output->command('plugin.search_complete');
+            $this->rc->output->send();
+        }
+    }
+
+    /**
+     * return javascript commands to add rows to the message list
+     */
+    public function rcmail_js_message_list($a_headers, $insert_top = false, $a_show_cols = null, $avmbox = false, $avcols = array(), $showMboxColumn = false)
+    {
+        global $CONFIG, $RCMAIL, $OUTPUT;
+        $uid_mboxes = array();
+
+        if (empty($a_show_cols)) {
+            if (!empty($_SESSION['list_attrib']['columns'])) {
+                $a_show_cols = $_SESSION['list_attrib']['columns'];
+            } else {
+                $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
+            }
+        } else {
+            if (!is_array($a_show_cols)) {
+                $a_show_cols = preg_split('/[\s,;]+/', strip_quotes($a_show_cols));
+            }
+            $head_replace = true;
+        }
+
+        $mbox = $RCMAIL->storage->get_folder();
+
+        // make sure 'threads' and 'subject' columns are present
+        if (!in_array('subject', $a_show_cols)) {
+            array_unshift($a_show_cols, 'subject');
+        }
+        if (!in_array('threads', $a_show_cols)) {
+            array_unshift($a_show_cols, 'threads');
+        }
+        $_SESSION['list_attrib']['columns'] = $a_show_cols;
+
+        // Make sure there are no duplicated columns (#1486999)
+        $a_show_cols = array_merge($a_show_cols, $avcols);
+        $a_show_cols = array_unique($a_show_cols);
+
+        // Plugins may set header's list_cols/list_flags and other rcube_message_header variables
+        // and list columns
+        $plugin = $RCMAIL->plugins->exec_hook(
+            'messages_list',
+            array('messages' => $a_headers, 'cols' => $a_show_cols)
+        );
+        $a_show_cols = $plugin['cols'];
+        $a_headers   = $plugin['messages'];
+        $thead = $head_replace ? rcmail_message_list_head($_SESSION['list_attrib'], $a_show_cols) : null;
+
+        // get name of smart From/To column in folder context
+        if (($f = array_search('fromto', $a_show_cols)) !== false) {
+            $smart_col = rcmail_message_list_smart_column_name();
+        }
+        if ($this->coltypesSet == false) {
+            $OUTPUT->command('set_message_coltypes', $a_show_cols, $thead, $smart_col);
+            if ($showMboxColumn === true) {
+                $OUTPUT->command('plugin.advanced_search_add_header', array());
+            }
+            $this->coltypesSet = true;
+        }
+
+        if (empty($a_headers)) {
+            return;
+        }
+
+        // remove 'threads', 'attachment', 'flag', 'status' columns, we don't need them here
+        foreach (array('threads', 'attachment', 'flag', 'status', 'priority') as $col) {
+            if (($key = array_search($col, $a_show_cols)) !== false) {
+                unset($a_show_cols[$key]);
+            }
+        }
+
+        // loop through message headers
+        foreach ($a_headers as $n => $header) {
+            if (empty($header)) {
+                continue;
+            }
+            $a_msg_cols = array();
+            $a_msg_flags = array();
+            // format each col; similar as in rcmail_message_list()
+            foreach ($a_show_cols as $col) {
+                $col_name = $col == 'fromto' ? $smart_col : $col;
+
+                if (in_array($col_name, array('from', 'to', 'cc', 'replyto'))) {
+                    $cont = rcmail_address_string($header->$col_name, 3, false, null, $header->charset);
+                } elseif ($col == 'subject') {
+                    $cont = trim(rcube_mime::decode_header($header->$col, $header->charset));
+                    if (!$cont) {
+                        $cont = rcube_label('nosubject');
+                    }
+                    $cont = rcube::Q($cont);
+                } elseif ($col == 'size') {
+                    $cont = $this->rc->show_bytes($header->$col);
+                } elseif ($col == 'date') {
+                    $cont = rcube_utils::format_datestr($header->date,$date_format);
+                } else {
+                    $cont = rcube::Q($header->$col);
+                }
+                $a_msg_cols[$col] = $cont;
+            }
+
+            $a_msg_flags = array_change_key_case(array_map('intval', (array) $header->flags));
+            if ($header->depth) {
+                $a_msg_flags['depth'] = $header->depth;
+            } elseif ($header->has_children) {
+                $roots[] = $header->uid;
+            }
+            if ($header->parent_uid) {
+                $a_msg_flags['parent_uid'] = $header->parent_uid;
+            }
+            if ($header->has_children) {
+                $a_msg_flags['has_children'] = $header->has_children;
+            }
+            if ($header->unread_children) {
+                $a_msg_flags['unread_children'] = $header->unread_children;
+            }
+            if ($header->others['list-post']) {
+                $a_msg_flags['ml'] = 1;
+            }
+            if ($header->priority) {
+                $a_msg_flags['prio'] = (int) $header->priority;
+            }
+            $a_msg_flags['ctype'] = rcube::Q($header->ctype);
+            $a_msg_flags['mbox'] = $mbox;
+            if (!empty($header->list_flags) && is_array($header->list_flags)) {
+                $a_msg_flags = array_merge($a_msg_flags, $header->list_flags);
+            }
+            if (!empty($header->list_cols) && is_array($header->list_cols)) {
+                $a_msg_cols = array_merge($a_msg_cols, $header->list_cols);
+            }
+            if ($showMboxColumn === true) {
+                $a_msg_flags['avmbox'] = $avmbox;
+            }
+
+            $OUTPUT->command(
+                'add_message_row',
+                $header->uid . '__MB__' . md5($mbox),
+                $a_msg_cols,
+                $a_msg_flags,
+                $insert_top
+            );
+            $id = $header->uid . '__MB__' . md5($mbox);
+            $uid_mboxes[$id] = array('uid' => $header->uid, 'mbox' => $mbox, 'md5mbox' => md5($mbox));
+        }
+
+        if ($RCMAIL->storage->get_threading()) {
+            $OUTPUT->command('init_threads', (array) $roots, $mbox);
+        }
+
+        return $uid_mboxes;
+    }
+
+
+    private function do_pagination($folders, $onPage)
+    {
+        $perPage = $this->rc->storage->get_pagesize();
+        $from = $perPage * $onPage - $perPage + 1;
+        $to = $from + $perPage - 1;
+        $got = 0;
+        $pos = 0;
+        $cbox = "";
+        $boxStart = 0;
+        $boxStop = 0;
+        $fetch = array();
+        foreach ($folders as $box => $num) {
+            $i = $num;
+            if ($box != $cbox) {
+                $boxStart = 0;
+                $boxStop = 0;
+                $cbox = $box;
+            }
+            while ($i--) {
+                $pos++;
+                $boxStart++;
+                if ($pos >= $from && $pos <= $to) {
+                    if (!isset($fetch[$box])) {
+                        $fetch[$box] = array("from" => $boxStart);
+                    }
+                    $fetch[$box]['to'] = $boxStart;
+                    $got++;
+                }
+            }
+            if ($got >= $perPage) {
+                break;
+            }
+        }
+
+        return $fetch;
+    }
+
+    /**
+     * Save advanced search preferences
+     *
+     * @access  public
+     */
+    public function preferences_save($args)
+    {
+        if ($args['section'] != 'advancedsearch') {
+            return;
+        }
+        $rcmail = rcmail::get_instance();
+
+        $displayOptions = array();
+        $displayOptions['_show_message_label_header'] = rcube_utils::get_input_value('_show_message_label_header', rcube_utils::INPUT_POST) == 1 ? true : false;
+        $displayOptions['_show_message_mbox_info'] = rcube_utils::get_input_value('_show_message_mbox_info', rcube_utils::INPUT_POST) == 1 ? true : false;
+        $displayOptions['target_menu'] = rcube_utils::get_input_value('button_display_option', rcube_utils::INPUT_POST);
+
+        $args['prefs']['advanced_search_display_options'] = $displayOptions;
+
+        return($args);
+    }
+
+    /**
+     * Add a section advanced search to the preferences section list
+     *
+     * @access  public
+     */
+    public function preferences_section($args)
+    {
+        $args['list']['advancedsearch'] = array(
+            'id' => 'advancedsearch',
+            'section' => rcube::Q($this->gettext('advancedsearch'))
+        );
+
+        return($args);
+    }
+
+    /**
+     * Display advanced search configuration in user preferences tab
+     *
+     * @access  public
+     */
+    public function preferences_list($args)
+    {
+        if ($args['section'] == 'advancedsearch') {
+
+            $this->rc = rcmail::get_instance();
+            $args['blocks']['label_display_options'] = array('options' => array(), 'name' => rcube::Q($this->gettext('label_display_options')));
+
+            $displayOptions = $this->rc->config->get('advanced_search_display_options', array());
+            $target_menu = (isset($displayOptions['target_menu']) && !empty($displayOptions['target_menu'])) ? $displayOptions['target_menu'] : $this->config['target_menu'];
+            $options = '';
+            $optarg = array('value' => 'messagemenu');
+            if ($target_menu == 'messagemenu') {
+                $optarg['selected'] = 'selected';
+                $target_image = 'menu_location_a.jpg';
+            }
+            $options .= html::tag('option', $optarg, rcube::Q($this->gettext('display_in_messagemenu')));
+            $optarg = array('value' => 'toolbar');
+            if ($target_menu == 'toolbar') {
+                $optarg['selected'] = 'selected';
+                $target_image = 'menu_location_b.jpg';
+            }
+            $options .= html::tag('option', $optarg,rcube::Q($this->gettext('display_in_toolbar')));
+            $select = html::tag('select', array('name' => 'button_display_option', 'id' => 'button_display_option'), $options);
+
+            $label1 = html::label('_show_message_label_header', rcube::Q($this->gettext('mailbox_headers_in_results')));
+            $label2 = html::label('_show_message_mbox_info', rcube::Q($this->gettext('mailbox_info_in_results')));
+            $label3 = html::label('button_display_option', rcube::Q($this->gettext('show_advanced_search')));
+
+            $arg1 = array('name' => '_show_message_label_header', 'id' => '_show_message_label_header', 'type' => 'checkbox', 'title' => "", 'class' => 'watermark linput', 'value' => 1);
+            if (isset($displayOptions['_show_message_label_header']) && $displayOptions['_show_message_label_header'] === true) {
+                $arg1['checked'] = 'checked';
+                $img1class = 'enabled';
+            } else {
+                $img1class = 'disabled';            
+            }
+            $check1 = html::tag('input', $arg1);
+            $arg2 = array('name' => '_show_message_mbox_info', 'id' => '_show_message_mbox_info', 'type' => 'checkbox', 'title' => "", 'class' => 'watermark linput', 'value' => 1);
+            if (isset($displayOptions['_show_message_mbox_info']) && $displayOptions['_show_message_mbox_info'] === true) {
+                $arg2['checked'] = 'checked';
+                $img2class = 'enabled';
+            } else {
+                $img2class = 'disabled';
+            }
+
+            $img1 = html::img(array('src' => $this->url('skins/larry/images/show_mbox_row.jpg'), 'class' => $img1class));
+            $img2 = html::img(array('src' => $this->url('skins/larry/images/show_mbox_col.jpg'), 'class' => $img2class));
+            $img3 = html::img(array('src' => $this->url('skins/larry/images/' . $target_image)));
+
+            $check2 = html::tag('input', $arg2);
+            $args['blocks']['label_display_options']['options'][0] = array('title' => '', 'content' => '<p class="avsearchpref"><span>' . $check1 . ' ' . $label1 . '</span> ' . $img1 . '</p>');
+            $args['blocks']['label_display_options']['options'][1] = array('title' => '', 'content' => '<p class="avsearchpref"><span>' . $check2 . ' ' . $label2 . '</span> ' . $img2 . '</p>');
+            $args['blocks']['label_display_options']['options'][2] = array('title' => '', 'content' => '<p class="avsearchpref"><span>' . $label3 . ' ' . $select . '</span> ' . $img3 . '</p>');
+        }
+
+        return($args);
+    }
+
+    private function perform_search($search_string, $folders, $page = 1)
+    {
+        // Search all folders and build a final set
+        if ($folders[0] == 'all' || empty($folders)) {
+            $folders_search = $this->rc->imap->list_folders_subscribed();
+        } else {
+            $folders_search = $folders;
+        }
+        $count = 0;
+        $folder_count = array();
+        foreach ($folders_search as $mbox) {
+            $this->rc->storage->set_folder($mbox);
+            $this->rc->storage->search($mbox, $search_string, RCMAIL_CHARSET, $_SESSION['sort_col']);
+            $result = array();
+            $fcount = $this->rc->storage->count($mbox, 'ALL', !empty($_REQUEST['_refresh']));
+            $count += $fcount;
+            $folder_count[$mbox] = $fcount;
+        }
+        foreach ($folder_count as $k => $v) {
+            if ($v == 0) {
+                unset($folder_count[$k]);
+            }
+        }
+        $fetch = $this->do_pagination($folder_count, $page);
+        $mails = array();
+        $currentMailbox = "";
+        $displayOptions = $this->rc->config->get('advanced_search_display_options', array());
+        $showMboxColumn = isset($displayOptions['_show_message_mbox_info']) && $displayOptions['_show_message_mbox_info'] ? true : false;
+        $uid_mboxes = array();
+        foreach ($fetch as $mailbox => $data) {
+            if ($currentMailbox != $mailbox) {
+                $currentMailbox = $mailbox;
+                if (isset($displayOptions['_show_message_label_header']) && $displayOptions['_show_message_label_header'] === true) {
+                    $this->rc->output->command('advanced_search_add_mbox', $mailbox, $folder_count[$mailbox], $showMboxColumn);
+                }
+            }
+            $uid_mboxes = array_merge($uid_mboxes, $this->getMails($mailbox, $data, $search_string, $showMboxColumn));
+        }
+
+        return array('result' => array(), 'count' => $count, 'uid_mboxes' => $uid_mboxes);
+    }
+
+    private function getMails($mailbox, $data, $search_string, $showMboxColumn)
+    {
+        $pageSize = $this->rc->storage->get_pagesize();
+        $msgNum = $data['from'];
+        $startPage =  ceil($msgNum/$pageSize);
+        $msgMod = $msgNum % $pageSize;
+        $multiPage = "false";
+        $firstArrayElement = $msgMod == 0 ? ($pageSize-1) : ($msgMod-1);
+        $quantity = $data['to'] - $data['from'];
+        if ($data['from'] + $quantity > $pageSize) {
+            $multiPage = "true";
+        }
+        $this->rc->storage->set_folder($mailbox);
+        $this->rc->storage->search($mailbox, $search_string, RCMAIL_CHARSET, $_SESSION['sort_col']);
+        $messages = $this->rc->storage->list_messages('', $startPage);
+        if ($multiPage) {
+            $messages = array_merge($messages, $this->rc->storage->list_messages('', $startPage+1));
+        }
+        //FIRST: 0 QUANTITY: 2
+        $sliceTo = $quantity + 1;
+        $mslice = array_slice($messages, $firstArrayElement, $sliceTo, true);
+        $messages = $mslice;
+        $avbox = array();
+        $showAvmbox = false;
+        foreach ($messages as $set_flag) {
+            $set_flag->flags['skip_mbox_check'] = true;
+            if ($showMboxColumn === true) {
+                $set_flag->avmbox = $mailbox;
+                $avbox[] = 'avmbox';
+                $showAvmbox = true;
+            }
+        }
+        $uid_mboxes = $this->rcmail_js_message_list($messages, false, null, $showAvmbox, $avbox, $showMboxColumn);
+
+        return $uid_mboxes;
+    }
+
+    public function save_search()
+    {
+        $search_name = rcube_utils::get_input_value('search_name', rcube_utils::INPUT_GPC);
+        if ($search_name) {
+            $search = array();
+            $search['search'] = rcube_utils::get_input_value('search', rcube_utils::INPUT_GPC);
+            $search['search_name'] = $search_name;
+            $search['folder'] = rcube_utils::get_input_value('folder', rcube_utils::INPUT_GPC);
+            $search['sub_folders'] = rcube_utils::get_input_value('sub_folders', rcube_utils::INPUT_GPC);
+            $prefs = (array)$this->rc->user->get_prefs();
+            if (!isset($prefs['advanced_search'])) {
+                $prefs['advanced_search'] = array();
+            }
+            $prefs['advanced_search'][$search_name] = $search;
+            $this->rc->user->save_prefs(array('advanced_search' => $prefs['advanced_search']));
+            $this->rc->output->show_message('"<i>' . $search_name . '</i>" ' . $this->i18n_strings['has_been_saved'], 'confirmation');
+        }
+    }
+
+    public function delete_search()
+    {
+        $search_name = rcube_utils::get_input_value('search_name', rcube_utils::INPUT_GPC);
+        if ($search_name) {
+            $prefs = (array)$this->rc->user->get_prefs();
+            unset($prefs['advanced_search'][$search_name]);
+            $this->rc->user->save_prefs(array('advanced_search' => $prefs['advanced_search']));
+            $this->rc->output->show_message('"<i>' . $search_name . '</i>" ' . $this->i18n_strings['has_been_deleted'], 'notice');
+        }
+    }
+
+    public function get_saved_search()
+    {
+        $search_name = rcube_utils::get_input_value('search_name', rcube_utils::INPUT_GPC);
+        $prefs = (array)$this->rc->user->get_prefs();
+        if (!isset($prefs['advanced_search'])) {
+            $prefs['advanced_search'] = array();
+        }
+
+        $search = isset($prefs['advanced_search'][$search_name]) ? $prefs['advanced_search'][$search_name] : false;
+        $this->rc->output->command('plugin.load_saved_search', $search);
+        $this->rc->output->send();
+    }
+
+    private function get_saved_search_names()
+    {
+        $prefs = (array)$this->rc->user->get_prefs();
+        if (!isset($prefs['advanced_search'])) {
+            $prefs['advanced_search'] = array();
+        }
+        $names = array();
+        foreach($prefs['advanced_search'] as $name => $search) {
+            $names[] = $name;
+        }
+
+        return $names;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/composer.json	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,23 @@
+{
+	"name": "gms-sa/advanced-search",
+	"type": "roundcube-plugin",
+	"description": "Advanced search allowing multiple search criteria and folder recursion",
+	"keywords": ["mail","search","advanced"],
+	"homepage": "http://github.com/GMS-SA/roundcube-advanced-search/tree/stable",
+	"license": "GPL-3.0",
+	"repositories": [
+		{
+			"type": "composer",
+			"url": "http://plugins.roundcube.net"
+		}
+	],
+	"require": {
+		"roundcube/plugin-installer": ">=0.1.2"
+	},
+    "extra": {
+        "roundcube": {
+            "min-version": "0.9.4",
+            "max-version": "1.0.9999"
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/config-default.inc.php	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,45 @@
+<?php
+
+$rcmail_config['advanced_search_plugin'] = array(
+    // The menu where to place the advanced search button by default
+    'target_menu' => 'messagemenu',
+
+    // Every criteria which takes a email as argument
+    'email_criteria' => array('HEADER FROM', 'HEADER TO', 'CC', 'BCC'),
+
+    // Every criteria which takes a date as argument
+    'date_criteria' => array('BEFORE', 'ON', 'SINCE', 'SENTBEFORE', 'SENTON', 'SENTSINCE'),
+
+    // Every criteria which doesn't take an argument
+    'flag_criteria' => array('ANSWERED', 'DELETED', 'DRAFT', 'FLAGGED', 'SEEN'),
+
+    // Prefered criteria to show on the top of lists
+    'prefered_criteria' => array('SUBJECT', 'BODY', 'HEADER FROM', 'HEADER TO', 'SENTSINCE', 'LARGER'),
+
+    // Other criteria, anything not in the above lists, except 'prefered_criteria'
+    'other_criteria' => array('SUBJECT', 'BODY', 'KEYWORD', 'LARGER', 'SMALLER'),
+
+    // All filter criteria
+    'criteria' => array(
+        'ANSWERED' => 'Answered',
+        'BCC' => 'Bcc',
+        'BEFORE' => 'Before',
+        'CC' => 'Cc',
+        'DELETED' => 'Deleted',
+        'DRAFT' => 'Draft',
+        'FLAGGED' => 'Flagged',
+        'KEYWORD' => 'Keyword',
+        'LARGER' => 'Larger Than',
+        'BODY' => 'Message Body',
+        'ON' => 'On',
+        'SEEN' => 'Read',
+        'SENTBEFORE' => 'Sent Before',
+        'HEADER FROM' => 'From',
+        'SENTON' => 'Sent On',
+        'SENTSINCE' => 'Sent Since',
+        'HEADER TO' => 'To',
+        'SINCE' => 'Since',
+        'SMALLER' => 'Smaller Than',
+        'SUBJECT' => 'Subject Contains'
+    )
+);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/localization/de_DE.inc	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,51 @@
+<?php
+    $labels = array();
+    $labels['in'] = 'In';
+    $labels['and'] = 'Und';
+    $labels['or'] = 'Oder';
+    $labels['not'] = 'Nicht';
+    $labels['where'] = 'Wo';
+    $labels['exclude'] = 'ausschließen';
+    $labels['andsubfolders'] = 'mit Unterordnern';
+    $labels['allfolders'] = 'Alle Ordner';
+    $labels['advancedsearch'] = 'Erweiterte Suche';
+    $labels['label_display_options'] = 'Anzeigeoptionen';
+    $labels['mailbox_headers_in_results'] = 'Ordnername als Reihe anzeigen';
+    $labels['mailbox_info_in_results'] = 'Ordnername als Kolonne anzeigen';
+    $labels['display_in_messagemenu'] = 'im Nachrichtenmenü anzeigen';
+    $labels['display_in_toolbar'] = 'als Button in der Toolbar anzeigen';
+    $labels['show_advanced_search'] = 'Erweiterte Suche';
+    $labels['saved_searches'] = 'Gespeicherte Suche';
+    $labels['save_the_search'] = 'Diese Suche speichern';
+    $labels['has_been_saved'] = 'wurde gespeichert';
+    $labels['has_been_deleted'] = 'wurde gelöscht';
+    $labels['cancel'] = 'Abbrechen';
+    $labels['delete'] = 'Löschen';
+    $labels['Common'] = 'Häufig genutzt';                          
+    $labels['Addresses'] = 'Adressen';                    
+    $labels['Dates'] = 'Daten';                       
+    $labels['Flags'] = 'Markierungen';                       
+    $labels['Other'] = 'Andere';
+    $labels['ANSWERED'] = 'Beantwortet';
+    $labels['BCC'] = 'Bcc';
+    $labels['BEFORE'] = 'Vor';
+    $labels['CC'] = 'Cc';
+    $labels['DELETED'] = 'Gelöscht';
+    $labels['DRAFT'] = 'Entwurf';
+    $labels['FLAGGED'] = 'Markiert';
+    $labels['KEYWORD'] = 'Schlüsselwort';
+    $labels['LARGER'] = 'Größer als';
+    $labels['BODY'] = 'Nachrichtentext';
+    $labels['ON'] = 'Am';
+    $labels['SEEN'] = 'Gelesen';
+    $labels['SENTBEFORE'] = 'Gesendet vor';
+    $labels['HEADER FROM'] = 'Von';
+    $labels['SENTON'] = 'Gesendet am';
+    $labels['SENTSINCE'] = 'Gesendet seit';
+    $labels['HEADER TO'] = 'An';
+    $labels['SINCE'] = 'Seit';
+    $labels['SMALLER'] = 'Kleiner als';
+    $labels['SUBJECT'] = 'Betreff enthält';
+    $labels['name'] = 'Name';
+    $labels['save'] = 'Speichern';
+    $labels['mbox'] = 'Ordner';
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/localization/en_US.inc	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,52 @@
+<?php
+    $labels = array();
+    $labels['in'] = 'In';
+    $labels['and'] = 'And';
+    $labels['or'] = 'Or';
+    $labels['not'] = 'Not';
+    $labels['where'] = 'Where';
+    $labels['exclude'] = 'Exclude';
+    $labels['andsubfolders'] = 'and subfolders';
+    $labels['allfolders'] = 'All Folders';
+    $labels['advancedsearch'] = 'Advanced search';
+    $labels['label_display_options'] = 'Display options in search results';
+    $labels['mailbox_headers_in_results'] = 'Show mailbox title as row';
+    $labels['mailbox_info_in_results'] = 'Show mailbox title as column';
+    $labels['display_in_messagemenu'] = 'in message menu';
+    $labels['display_in_toolbar'] = 'as button in toolbar';
+    $labels['show_advanced_search'] = 'Show advanced search';
+    $labels['saved_searches'] = 'Saved searches';
+    $labels['save_the_search'] = 'Save this search';
+    $labels['has_been_saved'] = 'has been saved';
+    $labels['deletesearch'] = 'Delete search';
+    $labels['has_been_deleted'] = 'has been deleted';
+    $labels['cancel'] = 'Cancel';
+    $labels['delete'] = 'Delete';
+    $labels['Common'] = 'Common';
+    $labels['Addresses'] = 'Addresses';
+    $labels['Dates'] = 'Dates';
+    $labels['Flags'] = 'Flags';
+    $labels['Other'] = 'Other';
+    $labels['ANSWERED'] = 'Answered';
+    $labels['BCC'] = 'Bcc';
+    $labels['BEFORE'] = 'Before';
+    $labels['CC'] = 'Cc';
+    $labels['DELETED'] = 'Deleted';
+    $labels['DRAFT'] = 'Draft';
+    $labels['FLAGGED'] = 'Flagged';
+    $labels['KEYWORD'] = 'Keyword';
+    $labels['LARGER'] = 'Larger Than';
+    $labels['BODY'] = 'Message Body';
+    $labels['ON'] = 'On';
+    $labels['SEEN'] = 'Read';
+    $labels['SENTBEFORE'] = 'Sent Before';
+    $labels['HEADER FROM'] = 'From';
+    $labels['SENTON'] = 'Sent On';
+    $labels['SENTSINCE'] = 'Sent Since';
+    $labels['HEADER TO'] = 'To';
+    $labels['SINCE'] = 'Since';
+    $labels['SMALLER'] = 'Smaller Than';
+    $labels['SUBJECT'] = 'Subject Contains';
+    $labels['name'] = 'Name';
+    $labels['save'] = 'Save';
+    $labels['mbox'] = 'Folder';
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/localization/fr_FR.inc	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,51 @@
+<?php
+    $labels = array();
+    $labels['in'] = 'Dans';
+    $labels['and'] = 'Et';
+    $labels['or'] = 'Ou';
+    $labels['not'] = 'Pas';
+    $labels['where'] = 'Ou';
+    $labels['exclude'] = 'Exclure';
+    $labels['andsubfolders'] = 'et sous-dossiers';
+    $labels['allfolders'] = 'Tous les dossiers';
+    $labels['advancedsearch'] = 'Recherche avancée';
+    $labels['label_display_options'] = 'Options d\'affichage';
+    $labels['mailbox_headers_in_results'] = 'Afficher le nom du dossier en tant que ligne';
+    $labels['mailbox_info_in_results'] = 'Afficher le nom du dossier en tant que colonne';
+    $labels['display_in_messagemenu'] = 'dans le menu des messages';
+    $labels['display_in_toolbar'] = 'en tant que bouton dans la Toolbar';
+    $labels['show_advanced_search'] = 'Afficher la recherche avancée';
+    $labels['saved_searches'] = 'Recherches sauvegardées';
+    $labels['save_the_search'] = 'Sauvegarder cette recherche';
+    $labels['has_been_saved'] = 'a été sauvegardée';
+    $labels['has_been_deleted'] = 'viens d\'être effacé';
+    $labels['cancel'] = 'Annuler';
+    $labels['delete'] = 'Supprimer';
+    $labels['Common'] = 'Populaire';
+    $labels['Addresses'] = 'Adresses';
+    $labels['Dates'] = 'Dates';
+    $labels['Flags'] = 'Marqueurs';
+    $labels['Other'] = 'Autres';
+    $labels['ANSWERED'] = 'Répondu';
+    $labels['BCC'] = 'Copie cachée à';
+    $labels['BEFORE'] = 'Datant d\'avant le';
+    $labels['CC'] = 'Copie à';
+    $labels['DELETED'] = 'Supprimé';
+    $labels['DRAFT'] = 'Brouillon';
+    $labels['FLAGGED'] = 'Marqué';
+    $labels['KEYWORD'] = 'Mot-clé';
+    $labels['LARGER'] = 'Plus gros que';
+    $labels['BODY'] = 'Corps du message';
+    $labels['ON'] = 'Datant du';
+    $labels['SEEN'] = 'Lu';
+    $labels['SENTBEFORE'] = 'Envoyé avant le';
+    $labels['HEADER FROM'] = 'Envoyé par';
+    $labels['SENTON'] = 'Envoyé le';
+    $labels['SENTSINCE'] = 'Envoyé après le';
+    $labels['HEADER TO'] = 'À';
+    $labels['SINCE'] = 'Datant d\'après le';
+    $labels['SMALLER'] = 'Plus petit que';
+    $labels['SUBJECT'] = 'Objet contenant';
+    $labels['name'] = 'Nom';
+    $labels['save'] = 'Sauvegarder';
+    $labels['mbox'] = 'Dossier';
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/localization/it_IT.inc	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,53 @@
+<?php
+    $labels = array();
+    $labels['in'] = 'In';
+    $labels['and'] = 'E';
+    $labels['or'] = 'O';
+    $labels['not'] = 'Non';
+    $labels['where'] = 'Dove';
+    $labels['exclude'] = 'Escludi';
+    $labels['andsubfolders'] = 'e sottocartelle';
+    $labels['allfolders'] = 'Tutte le Cartelle';
+    $labels['advancedsearch'] = 'Ricerca Avanzata';
+    $labels['label_display_options'] = 'Mostra le opzioni nei risultati';
+    $labels['mailbox_headers_in_results'] = 'Mostra il titolo della mailbox come riga';
+    $labels['mailbox_info_in_results'] = 'Mostra il titolo della mailbox come colonna';
+    $labels['display_in_messagemenu'] = 'nel menu del messaggio';
+    $labels['display_in_toolbar'] = 'come bottone nella toolbar';
+    $labels['show_advanced_search'] = 'Mostra la ricerca avanzata';
+    $labels['saved_searches'] = 'Ricerche salvate';
+    $labels['save_the_search'] = 'Salva questa ricerca';
+    $labels['has_been_saved'] = 'è stata salvata';
+    $labels['deletesearch'] = 'Cancella la ricerca';
+    $labels['has_been_deleted'] = 'è stata cancellata';
+    $labels['cancel'] = 'Annulla';
+    $labels['delete'] = 'Cancella';
+    $labels['Common'] = 'Comuni';
+    $labels['Addresses'] = 'Indirizzi';
+    $labels['Dates'] = 'Date';
+    $labels['Flags'] = 'Etichette';
+    $labels['Other'] = 'Altro';
+    $labels['ANSWERED'] = 'Risposto';
+    $labels['BCC'] = 'Bcc';
+    $labels['BEFORE'] = 'Prima';
+    $labels['CC'] = 'Cc';
+    $labels['DELETED'] = 'Cancellata';
+    $labels['DRAFT'] = 'Bozza';
+    $labels['FLAGGED'] = 'Etichettata';
+    $labels['KEYWORD'] = 'Parola chiave';
+    $labels['LARGER'] = 'Più grande di';
+    $labels['BODY'] = 'Corpo del Messaggio';
+    $labels['ON'] = 'Il';
+    $labels['SEEN'] = 'Letta';
+    $labels['SENTBEFORE'] = 'Inviata Prima';
+    $labels['HEADER FROM'] = 'Da';
+    $labels['SENTON'] = 'Inviata Il';
+    $labels['SENTSINCE'] = 'Inviata Dal';
+    $labels['HEADER TO'] = 'A';
+    $labels['SINCE'] = 'Dal';
+    $labels['SMALLER'] = 'Più piccola di';
+    $labels['SUBJECT'] = 'Soggetto Contiene';
+    $labels['name'] = 'Nome';
+    $labels['save'] = 'Salva';
+    $labels['mbox'] = 'Cartella';
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/localization/pl_PL.inc	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,52 @@
+<?php
+$labels = array();
+$labels['in'] = 'w';
+$labels['and'] = 'i';
+$labels['or'] = 'lub';
+$labels['not'] = 'nie';
+$labels['where'] = 'gdzie';
+$labels['exclude'] = 'wyklucz';
+$labels['andsubfolders'] = 'i podfolderach';
+$labels['allfolders'] = 'Wszystkie foldery';
+$labels['advancedsearch'] = 'Wyszukiwanie zaawansowane';
+$labels['label_display_options'] = 'Opcje w zaawansowanych wynikach wyszukiwania';
+$labels['mailbox_headers_in_results'] = 'Wyświetl nazwę folderu w rzędzie';
+$labels['mailbox_info_in_results'] = 'Wyświetl nazwę folderu w kolumnie';
+$labels['display_in_messagemenu'] = 'w menu wiadomości';
+$labels['display_in_toolbar'] = 'jako przycisk';
+$labels['show_advanced_search'] = 'Pokaż zaawansowane wyszukiwanie';
+$labels['saved_searches'] = 'Zachowane wyszukiwania';
+$labels['save_the_search'] = 'Zachowaj to wyszukiwanie';
+$labels['has_been_saved'] = 'zostało zachowane';
+$labels['deletesearch'] = 'Usuń wyszukiwanie';
+$labels['has_been_deleted'] = 'zostało usunięte';
+$labels['cancel'] = 'Anuluj';
+$labels['delete'] = 'Usuń';
+$labels['Common'] = 'Zwykłe';
+$labels['Addresses'] = 'Adresy';
+$labels['Dates'] = 'Daty';
+$labels['Flags'] = 'Flagi';
+$labels['Other'] = 'Inne';
+$labels['ANSWERED'] = 'Odpowiedziano';
+$labels['BCC'] = 'Bcc';
+$labels['BEFORE'] = 'Przed datą';
+$labels['CC'] = 'Cc';
+$labels['DELETED'] = 'Skasowana';
+$labels['DRAFT'] = 'Kopia robocza';
+$labels['FLAGGED'] = 'Oznaczona';
+$labels['KEYWORD'] = 'Słowo kluczowe';
+$labels['LARGER'] = 'Większe od';
+$labels['BODY'] = 'Treść wiadomości';
+$labels['ON'] = 'W dacie';
+$labels['SEEN'] = 'Przeczytana';
+$labels['SENTBEFORE'] = 'Wysłany przed datą';
+$labels['HEADER FROM'] = 'Od';
+$labels['SENTON'] = 'Wysłany w dacie';
+$labels['SENTSINCE'] = 'Wysłane od daty';
+$labels['HEADER TO'] = 'Do';
+$labels['SINCE'] = 'Od daty';
+$labels['SMALLER'] = 'Mniejsze od';
+$labels['SUBJECT'] = 'Temat zawiera';
+$labels['name'] = 'Nazwa';
+$labels['save'] = 'Zachowaj';
+$labels['mbox'] = 'Folder';
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/localization/ru_RU.inc	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,52 @@
+<?php
+    $labels = array();
+    $labels['in'] = 'В';
+    $labels['and'] = 'И';
+    $labels['or'] = 'Или';
+    $labels['not'] = 'Не';
+    $labels['where'] = 'Где';
+    $labels['exclude'] = 'Исключить';
+    $labels['andsubfolders'] = 'и подпапки';
+    $labels['allfolders'] = 'Все папки';
+    $labels['advancedsearch'] = 'Расширенный поиск';
+    $labels['label_display_options'] = 'Отображение резултатов поиска';
+    $labels['mailbox_headers_in_results'] = 'Название папки в строке';
+    $labels['mailbox_info_in_results'] = 'Название папки в колонке';
+    $labels['display_in_messagemenu'] = 'В меню сообщений';
+    $labels['display_in_toolbar'] = 'Кнопка на панели';
+    $labels['show_advanced_search'] = 'Показывать расширенный поиск';
+    $labels['saved_searches'] = 'Сохраненные';
+    $labels['save_the_search'] = 'Сохранить этот поиск';
+    $labels['has_been_saved'] = 'был сохранен';
+    $labels['deletesearch'] = 'Удалить поиск';
+    $labels['has_been_deleted'] = 'был удален';
+    $labels['cancel'] = 'Отменить';
+    $labels['delete'] = 'Удалить'; 
+    $labels['Common'] = 'Общее'; 
+    $labels['Addresses'] = 'Адреса';
+    $labels['Dates'] = 'Дата';
+    $labels['Flags'] = 'Метки';
+    $labels['Other'] = 'Другое';
+    $labels['ANSWERED'] = 'С ответом';
+    $labels['BCC'] = 'Скрытая копия';
+    $labels['BEFORE'] = 'Получено до';
+    $labels['CC'] = 'Копия'; 
+    $labels['DELETED'] = 'Удаленные';
+    $labels['DRAFT'] = 'Черновики';
+    $labels['FLAGGED'] = 'Помеченные';
+    $labels['KEYWORD'] = 'Метка';
+    $labels['LARGER'] = 'Размер больше';
+    $labels['BODY'] = 'Тело письма'; 
+    $labels['ON'] = 'Дата получения';  
+    $labels['SEEN'] = 'Прочитанные';
+    $labels['SENTBEFORE'] = 'Отправлено до';
+    $labels['HEADER FROM'] = 'От';  
+    $labels['SENTON'] = 'Дата отправки';
+    $labels['SENTSINCE'] = 'Отправлено после';
+    $labels['HEADER TO'] = 'Кому';
+    $labels['SINCE'] = 'Получено после'; 
+    $labels['SMALLER'] = 'Размер меньше';  
+    $labels['SUBJECT'] = 'Тема';
+    $labels['name'] = 'Название';
+    $labels['save'] = 'Сохранить';
+    $labels['mbox'] = 'Ящик';
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/skins/classic/advanced_search.css	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,34 @@
+#messagetoolbar > a.advanced-search span.advanced-search {
+    display: none;
+}
+
+.advanced_search_dialog .ui-dialog-title {
+    width: 100%;
+}
+
+.advanced_search_dialog .ui-dialog-title span.saved_searches {
+    border: 1px solid lightgray;
+    float: right;
+    display: block;
+    padding-right: 10px;
+    padding-left: 10px;
+    padding-bottom: 3px;
+    padding-top: 3px;
+    border-radius: 4px;
+    margin-right: 20px;
+}
+
+#rcavbox1, #rcavbox2 {
+    width: 30%;
+}
+
+#messagetoolbar a.advanced-search {
+    background: url(../../../../skins/classic/images/abook_toolbar.png) 0 0 no-repeat transparent;
+    background-position: -168px 0px;
+}
+
+#messagemenu a.advanced-search {
+    color: #a0a0a0;
+    text-decoration: none;
+    background: url(../../../../skins/classic/images/icons/glass.png) no-repeat 7px 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/advanced_search/skins/larry/advanced_search.css	Sun May 27 16:53:56 2018 -0400
@@ -0,0 +1,218 @@
+a.icon.advanced-search span.advanced-search {
+    background-image: url(images/icon-loupe.png) !important;
+    background-position: 0 !important;
+}
+
+a.button.advanced-search {
+    text-align: center;
+    font-size: 10px;
+    color: #555;
+    min-width: 50px;
+    max-width: 75px;
+    height: 13px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    padding: 28px 2px 0 2px;
+    text-shadow: 0px 1px 1px #eee;
+    box-shadow: none;
+    -moz-box-shadow: none;
+    -webkit-box-shadow: none;
+    -o-box-shadow: none;
+    background: url(../../../../skins/larry/images/buttons.png?v=abf1.36693) -100px 0 no-repeat transparent;
+    border: 0;
+    border-radius: 0;
+    background-position: center -970px;
+}
+
+.records-table tbody .aslabel_mbox td {
+    border-top: 1px solid #fff;
+    border-bottom: 1px solid #bbd3da;
+    cursor: default;
+    font-weight: normal;
+    background-color: #d9ecf4;
+    color: #376572;
+    text-shadow: 0px 1px 1px #fff;
+    text-decoration: none;
+    font-weight: bold;
+}
+
+.records-table tbody .aslabel_mbox .aslabel_found {
+    top: 3px;
+    right: 6px;
+    min-width: 1.8em;
+    padding: 2px 4px;
+    background: #82acb5;
+    background: -moz-linear-gradient(top, #82acb5 0%, #6a939f 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#82acb5), color-stop(100%,#6a939f));
+    background: -o-linear-gradient(top, #82acb5 0%, #6a939f 100%);
+    background: -ms-linear-gradient(top, #82acb5 0%, #6a939f 100%);
+    background: linear-gradient(top, #82acb5 0%, #6a939f 100%);
+    box-shadow: inset 0 1px 1px 0 #536d72;
+    -o-box-shadow: inset 0 1px 1px 0 #536d72;
+    -webkit-box-shadow: inset 0 1px 1px 0 #536d72;
+    -moz-box-shadow: inset 0 1px 1px 0 #536d72;
+    border-radius: 9px;
+    color: #fff;
+    text-align: center;
+    font-weight: bold;
+    text-shadow: none;
+    display: block;
+}
+
+#adsearch-popup button.add, #adsearch-popup button.delete{
+    display: inline-block;
+    margin: 0 2px;
+    padding: 2px 5px;
+    color: #525252;
+    text-shadow: 0px 1px 1px #fff;
+    border: 1px solid #c0c0c0;
+    border-radius: 4px;
+    background: #f7f7f7;
+    background: -moz-linear-gradient(top, #f9f9f9 0%, #e6e6e6 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f9f9f9), color-stop(100%,#e6e6e6));
+    background: -o-linear-gradient(top, #f9f9f9 0%, #e6e6e6 100%);
+    background: -ms-linear-gradient(top, #f9f9f9 0%, #e6e6e6 100%);
+    background: linear-gradient(top, #f9f9f9 0%, #e6e6e6 100%);
+    box-shadow: 0 1px 1px 0 rgba(140, 140, 140, 0.3);
+    -o-box-shadow: 0 1px 1px 0 rgba(140, 140, 140, 0.3);
+    -webkit-box-shadow: 0 1px 1px 0 rgba(140, 140, 140, 0.3);
+    -moz-box-shadow: 0 1px 1px 0 rgba(140, 140, 140, 0.3);
+    text-decoration: none;
+    outline: none;
+}
+
+#adv-search tbody tr {
+    padding: 4px 10px;
+    background: #eee;
+    border-bottom: 2px solid #fff;
+}
+
+#adv-search, #adv-search tr {
+    width: 100%;
+}
+
+td.adv-search-and-or {
+    width: 80px;
+    text-align: center;
+}
+
+#adsearch-popup .mainaction {
+    height: 24px;
+    padding-left: 10px;
+    padding-right: 10px;
+    margin-right: 10px;
+}
+
+#rcavbox1, #rcavbox2 {
+    width: 30%;
+}
+
+#rcmrowadvancedsearch td.section {
+    background-position: 6px -1650px !important;
+}
+
+#rcmrowadvancedsearch.selected td.section {
+    background-position: 6px -1674px !important;
+}
+
+p.avsearchpref span {
+    min-width: 280px;
+    display: block;
+    max-width: 280px;
+    float: left;
+    vertical-align: middle;
+}
+
+p.avsearchpref img {
+    border-radius: 10px;
+}
+
+p.avsearchpref img.disabled {
+    -webkit-filter: grayscale(100%);
+    -moz-filter: grayscale(100%);
+    filter: grayscale(100%);
+}
+
+button.save_search {
+    color: #ffffff;
+    background-color: #2f96b4;
+    border-radius: 4px;
+    height: 20px;
+    padding-left: 10px;
+    padding-right: 10px;
+    margin-right: 10px;
+}
+
+input.save_search {
+    padding: 0 10px 0 10px;
+    height: 20px;
+    background: #20b8fb;
+    border: none;
+    font-weight: bold;
+    color: #fff;
+    text-shadow: none;
+    background: #6193DF;
+    background: -moz-linear-gradient(top, #6193DF 0%, #2B84C0 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#6193DF), color-stop(100%,#2B84C0));
+    background: -o-linear-gradient(top, #6193DF 0%, #2B84C0 100%);
+    background: -ms-linear-gradient(top, #6193DF 0%, #2B84C0 100%);
+    background: linear-gradient(top, #6193DF 0%, #2B84C0 100%);
+}
+
+input.save_search:active {
+    background: #81C0EB;
+    background: -moz-linear-gradient(top, #6193DF 0%, #81C0EB 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#6193DF), color-stop(100%,#81C0EB));
+    background: -o-linear-gradient(top, #6193DF 0%, #81C0EB 100%);
+    background: -ms-linear-gradient(top, #6193DF 0%, #81C0EB 100%);
+    background: linear-gradient(top, #6193DF 0%, #81C0EB 100%);
+}
+
+input.delete_search {
+    padding: 0 10px 0 10px;
+    height: 19px;
+    background: #20b8fb;
+    border: none;
+    font-weight: bold;
+    color: #fff;
+    text-shadow: none;
+    background: #85190A;
+    background: -moz-linear-gradient(top, #85190A 0%, #CA361A 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#85190A), color-stop(100%,#CA361A));
+    background: -o-linear-gradient(top, #85190A 0%, #CA361A 100%);
+    background: -ms-linear-gradient(top, #85190A 0%, #CA361A 100%);
+    background: linear-gradient(top, #85190A 0%, #CA361A 100%);
+}
+
+input.delete_search:active {
+    background: #85190A;
+    background: -moz-linear-gradient(top, #85190A 0%, #F09F98 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#85190A), color-stop(100%,#F09F98));
+    background: -o-linear-gradient(top, #85190A 0%, #F09F98 100%);
+    background: -ms-linear-gradient(top, #85190A 0%, #F09F98 100%);
+    background: linear-gradient(top, #85190A 0%, #F09F98 100%);
+}
+
+
+.advanced_search_dialog .ui-dialog-title {
+    width: 100%;
+}
+
+.advanced_search_dialog .ui-dialog-title span.saved_searches {
+    border: 1px solid lightgray;
+    float: right;
+    display: block;
+    padding-right: 10px;
+    -moz-box-shadow: inset 0 0 5px #888;
+    -webkit-box-shadow: inset 0 0 5px#888;
+    box-shadow: inner 0 0 5px #888;
+    padding-left: 10px;
+    padding-bottom: 3px;
+    padding-top: 3px;
+    border-radius: 4px;
+}
+
+#adsearch-popup input[name="filter-val"] {
+    margin-right: 4px;
+}
Binary file plugins/advanced_search/skins/larry/images/icon-loupe.png has changed
Binary file plugins/advanced_search/skins/larry/images/menu_location_a.jpg has changed
Binary file plugins/advanced_search/skins/larry/images/menu_location_b.jpg has changed
Binary file plugins/advanced_search/skins/larry/images/show_mbox_col.jpg has changed
Binary file plugins/advanced_search/skins/larry/images/show_mbox_row.jpg has changed