001/*
002 * #%L
003 * Netarchivesuite - heritrix 3 monitor
004 * %%
005 * Copyright (C) 2005 - 2018 The Royal Danish Library, 
006 *             the National Library of France and the Austrian National Library.
007 * %%
008 * This program is free software: you can redistribute it and/or modify
009 * it under the terms of the GNU Lesser General Public License as
010 * published by the Free Software Foundation, either version 2.1 of the
011 * License, or (at your option) any later version.
012 * 
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Lesser Public License for more details.
017 * 
018 * You should have received a copy of the GNU General Lesser Public
019 * License along with this program.  If not, see
020 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
021 * #L%
022 */
023
024package dk.netarkivet.heritrix3.monitor.resources;
025
026import java.io.IOException;
027import java.util.Arrays;
028import java.util.List;
029import java.util.Locale;
030
031import javax.servlet.ServletContext;
032import javax.servlet.ServletOutputStream;
033import javax.servlet.http.HttpServletRequest;
034import javax.servlet.http.HttpServletResponse;
035
036import org.netarchivesuite.heritrix3wrapper.ScriptResult;
037
038import com.antiaction.common.filter.Caching;
039import com.antiaction.common.templateengine.TemplateBuilderFactory;
040
041import dk.netarkivet.heritrix3.monitor.Heritrix3JobMonitor;
042import dk.netarkivet.heritrix3.monitor.NASEnvironment;
043import dk.netarkivet.heritrix3.monitor.NASUser;
044import dk.netarkivet.heritrix3.monitor.ResourceAbstract;
045import dk.netarkivet.heritrix3.monitor.ResourceManagerAbstract;
046import dk.netarkivet.heritrix3.monitor.HttpLocaleHandler.HttpLocale;
047
048public class H3FilterResource implements ResourceAbstract {
049
050    private NASEnvironment environment;
051
052    protected int R_FILTER = -1;
053    
054    protected int R_BUDGET = -1;
055
056    @Override
057    public void resources_init(NASEnvironment environment) {
058        this.environment = environment;
059    }
060
061    @Override
062    public void resources_add(ResourceManagerAbstract resourceManager) {
063        R_FILTER = resourceManager.resource_add(this, "/job/<numeric>/filter/", false);
064    }
065
066    @Override
067    public void resource_service(ServletContext servletContext, NASUser nas_user, HttpServletRequest req, HttpServletResponse resp, HttpLocale httpLocale, int resource_id, List<Integer> numerics, String pathInfo) throws IOException {
068        if (NASEnvironment.contextPath == null) {
069            NASEnvironment.contextPath = req.getContextPath();
070        }
071        if (NASEnvironment.servicePath == null) {
072            NASEnvironment.servicePath = req.getContextPath() + req.getServletPath() + "/";
073        }
074        String method = req.getMethod().toUpperCase();
075        if(resource_id == R_FILTER) {
076                if ("GET".equals(method) || "POST".equals(method)) {
077                filter_add(req, resp, httpLocale, numerics);
078            }
079        }
080    }
081
082    public void filter_add(HttpServletRequest req, HttpServletResponse resp, HttpLocale httpLocale, List<Integer> numerics) throws IOException {
083        Locale locale = httpLocale.locale;
084        resp.setContentType("text/html; charset=UTF-8");
085        ServletOutputStream out = resp.getOutputStream();
086        Caching.caching_disable_headers(resp);
087
088        TemplateBuilderFactory<MasterTemplateBuilder> masterTplBuilderFactory = TemplateBuilderFactory.getInstance(environment.templateMaster, "master.tpl", "UTF-8", MasterTemplateBuilder.class);
089        MasterTemplateBuilder masterTplBuilder = masterTplBuilderFactory.getTemplateBuilder();
090
091        StringBuilder sb = new StringBuilder();
092
093        String regex = req.getParameter("regex");
094        if (regex == null) {
095            regex = "";
096        }
097        String[] removeIndexes = req.getParameterValues("removeIndex");
098        if(removeIndexes == null) {
099                removeIndexes = new String[0];
100        }
101        
102        String initials = "";
103        if(req.getParameter("add-filter") != null) {
104                initials = req.getParameter("initials1");
105        } else if(req.getParameter("remove-filter") != null) {
106                initials = req.getParameter("initials2");
107        }
108        if (initials == null) {
109                initials = "";
110        }
111
112        String script = environment.NAS_GROOVY_SCRIPT;
113
114        if (regex.length() > 0 && !initials.isEmpty()) {
115                String[] lines = regex.split(System.getProperty("line.separator"));
116                for(String line : lines) {
117                        if(line.endsWith(System.getProperty("line.separator")) || line.endsWith("\r") || line.endsWith("\n")) {
118                                line = line.substring(0, line.length() - 1);
119                        }
120                        script += "\ninitials = \"" + initials + "\"";
121                    script += "\naddFilter '" + line.replace("\\", "\\\\") + "'\n";
122                }
123        }
124        if(removeIndexes.length > 0 && !initials.isEmpty()) {
125                script += "\ninitials = \"" + initials + "\"";
126            script += "\nremoveFilters("+Arrays.toString(removeIndexes)+")\n";
127        }
128        script += "\nshowFilters()\n";
129
130        long jobId = numerics.get(0);
131        Heritrix3JobMonitor h3Job = environment.h3JobMonitorThread.getRunningH3Job(jobId);
132
133        if (h3Job != null && h3Job.isReady()) {
134            /* form control */
135            /* case submit for delete but no checked regex */
136            boolean keepRegexTextArea = false;
137            if (req.getParameter("remove-filter") != null && removeIndexes.length == 0) {
138                sb.append("<div class=\"notify notify-red\"><span class=\"symbol icon-error\"></span> Check RejectRules to delete!</div>");
139            }
140            /* case submit for add but no text */
141            if (req.getParameter("add-filter") != null && regex.isEmpty()) {
142                sb.append("<div class=\"notify notify-red\"><span class=\"symbol icon-error\"></span> RejectRules cannot be empty!</div>");
143            }
144            /* case no initials */
145            if ((req.getParameter("remove-filter") != null || req.getParameter("add-filter") != null) && initials.isEmpty()) {
146                sb.append("<div class=\"notify notify-red\"><span class=\"symbol icon-error\"></span> Initials required to add/delete RejectRules!</div>");
147                keepRegexTextArea = true;
148            }
149            
150            sb.append("<p>All URIs matching any of the following regular expressions will be rejected from the current job.</p>");
151
152            sb.append("<form class=\"form-horizontal\" action=\"?\" name=\"insert_form\" method=\"post\" enctype=\"application/x-www-form-urlencoded\" accept-charset=\"utf-8\">\n");
153            sb.append("<label for=\"regex\" style=\"cursor: default;\">Expressions to reject:</label>");
154            sb.append("<textarea rows=\"4\" cols=\"100\" id=\"regex\" name=\"regex\" placeholder=\"regex\">");
155            if(keepRegexTextArea) {
156                sb.append(regex);
157            }
158            sb.append("</textarea>\n");
159            sb.append("<label for=\"initials\">User initials:</label>");
160            sb.append("<input type=\"text\" id=\"initials1\" name=\"initials1\" value=\"" + initials  + "\" placeholder=\"initials\">\n");
161            sb.append("<button type=\"submit\" name=\"add-filter\" value=\"1\" class=\"btn btn-success\"><i class=\"icon-white icon-thumbs-up\"></i> Add</button>\n");
162            sb.append("<br/>\n");
163
164            ScriptResult scriptResult = h3Job.h3wrapper.ExecuteShellScriptInJob(h3Job.jobResult.job.shortName, "groovy", script);
165
166            if (scriptResult != null && scriptResult.script != null && scriptResult.script.htmlOutput != null) {
167                sb.append("<div style=\"font-size: 14px; font-weight: normal; line-height: 20px;\">\n");
168                sb.append("<p style=\"margin-top: 30px;\">Rejected regex:</p>\n");
169                sb.append(scriptResult.script.htmlOutput);
170                sb.append("</div>\n");
171                sb.append("<label for=\"initials\">User initials:</label>");
172                sb.append("<input type=\"text\" id=\"initials2\" name=\"initials2\" value=\"" + initials  + "\" placeholder=\"initials\">\n");
173                sb.append("<button type=\"submit\" name=\"remove-filter\" value=\"1\" class=\"btn btn-success\"><i class=\"icon-white icon-remove\"></i> Remove</button>");
174            }
175            
176            sb.append("</form>\n");
177        } else {
178            sb.append("Job ");
179            sb.append(jobId);
180            sb.append(" is not running.");
181        }
182
183        StringBuilder menuSb = masterTplBuilder.buildMenu(new StringBuilder(), req, locale, h3Job);
184
185        masterTplBuilder.insertContent("Job " + jobId + " RejectRules", menuSb.toString(), httpLocale.generateLanguageLinks(),
186                        "Job " + jobId + " RejectRules", sb.toString(), "").write(out);
187
188        out.flush();
189        out.close();
190    }
191    
192}