001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.workplace.list;
029
030import org.opencms.i18n.CmsEncoder;
031import org.opencms.util.CmsStringUtil;
032import org.opencms.workplace.CmsWorkplace;
033
034import java.util.ArrayList;
035import java.util.Iterator;
036import java.util.List;
037import java.util.Map;
038
039/**
040 * Displays an advanced search form over several columns.<p>
041 *
042 * @since 7.6
043 */
044public class CmsListMultiSearchAction extends CmsListSearchAction {
045
046    /** The string to delimit key and value. */
047    public static final String KEY_VAL_DELIM = "#";
048
049    /** The string to delimit each column-value pair. */
050    public static final String PARAM_DELIM = "|";
051
052    /** the html id prefix for the input element of the search bar. */
053    public static final String SEARCH_COL_INPUT_ID = "listColFilter";
054
055    /**
056     * Default constructor.<p>
057     *
058     * @param column the first column to search in
059     *
060     * @see #addColumn(CmsListColumnDefinition)
061     */
062    public CmsListMultiSearchAction(CmsListColumnDefinition column) {
063
064        super(column);
065    }
066
067    /**
068     * @see org.opencms.workplace.list.CmsListSearchAction#barHtml(org.opencms.workplace.CmsWorkplace)
069     */
070    @Override
071    public String barHtml(CmsWorkplace wp) {
072
073        if (wp == null) {
074            wp = getWp();
075        }
076        StringBuffer html = new StringBuffer(1024);
077        html.append("\t\t<input type='hidden' name='");
078        html.append(SEARCH_BAR_INPUT_ID);
079        html.append("' id='");
080        html.append(SEARCH_BAR_INPUT_ID);
081        html.append("' value='");
082        String searchFilter = "";
083        if (wp instanceof A_CmsListDialog) {
084            searchFilter = ((A_CmsListDialog)wp).getList().getSearchFilter();
085        }
086        Map<String, String> colVals = CmsStringUtil.splitAsMap(searchFilter, PARAM_DELIM, KEY_VAL_DELIM);
087        // http://www.securityfocus.com/archive/1/490498: searchfilter cross site scripting vulnerability:
088        html.append(CmsStringUtil.escapeJavaScript(CmsEncoder.escapeXml(searchFilter)));
089        html.append("' >\n");
090        Iterator<CmsListColumnDefinition> it = getColumns().iterator();
091        while (it.hasNext()) {
092            CmsListColumnDefinition colDef = it.next();
093            html.append("\t\t<input type='text' name='");
094            html.append(SEARCH_COL_INPUT_ID).append(colDef.getId());
095            html.append("' id='");
096            html.append(SEARCH_COL_INPUT_ID).append(colDef.getId());
097            html.append("' value='");
098            String val = colVals.get(colDef.getId());
099            if (val == null) {
100                val = "";
101            }
102            html.append(CmsStringUtil.escapeJavaScript(CmsEncoder.escapeXml(val)));
103            html.append("' title='");
104            html.append(CmsStringUtil.escapeJavaScript(colDef.getName().key(wp.getLocale())));
105            html.append("' size='20' maxlength='245' style='vertical-align: bottom;' >\n");
106        }
107        html.append(buttonHtml(wp));
108        if (getShowAllAction() != null) {
109            html.append("&nbsp;&nbsp;");
110            html.append(getShowAllAction().buttonHtml());
111        }
112        // load script
113        html.append("<script >\n");
114        html.append("var LIST_SEARCH_DATA = {\n");
115        html.append("SEARCH_BAR_INPUT_ID: \"").append(SEARCH_BAR_INPUT_ID).append("\",\n");
116        html.append("FORM: \"").append(getListId() + "-form").append("\",\n");
117        html.append("COLUMNS: [");
118        it = getColumns().iterator();
119        while (it.hasNext()) {
120            CmsListColumnDefinition colDef = it.next();
121            html.append("\"").append(colDef.getId()).append("\"");
122            if (it.hasNext()) {
123                html.append(", ");
124            }
125        }
126        html.append("]\n");
127        html.append("};\n");
128        html.append("</script>\n");
129
130        return html.toString();
131    }
132
133    /**
134     * @see org.opencms.workplace.list.CmsListSearchAction#filter(java.util.List, java.lang.String)
135     */
136    @Override
137    public List<CmsListItem> filter(List<CmsListItem> items, String searchFilter) {
138
139        if (CmsStringUtil.isEmptyOrWhitespaceOnly(searchFilter)) {
140            return items;
141        }
142        Map<String, String> colVals = CmsStringUtil.splitAsMap(searchFilter, PARAM_DELIM, KEY_VAL_DELIM);
143        List<CmsListItem> res = new ArrayList<CmsListItem>();
144        Iterator<CmsListItem> itItems = items.iterator();
145        while (itItems.hasNext()) {
146            CmsListItem item = itItems.next();
147            if (res.contains(item)) {
148                continue;
149            }
150            boolean matched = true;
151            Iterator<CmsListColumnDefinition> itCols = getColumns().iterator();
152            while (matched && itCols.hasNext()) {
153                CmsListColumnDefinition col = itCols.next();
154                if (item.get(col.getId()) == null) {
155                    matched = false;
156                    continue;
157                }
158                String colFilter = colVals.get(col.getId());
159
160                if ((colFilter != null) && (item.get(col.getId()).toString().indexOf(colFilter) < 0)) {
161                    matched = false;
162                }
163            }
164            if (matched) {
165                res.add(item);
166            }
167        }
168        return res;
169    }
170}