001/*
002 * (C) Copyright 2011-2015 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     tdelprat, jcarsique
016 *
017 */
018
019package org.nuxeo.wizard;
020
021import java.io.File;
022import java.io.IOException;
023import java.lang.reflect.Method;
024import java.net.InetAddress;
025import java.net.URLEncoder;
026import java.net.UnknownHostException;
027import java.sql.SQLException;
028import java.util.ArrayList;
029import java.util.Arrays;
030import java.util.Enumeration;
031import java.util.HashMap;
032import java.util.Hashtable;
033import java.util.List;
034import java.util.Map;
035
036import javax.naming.AuthenticationException;
037import javax.naming.NameNotFoundException;
038import javax.naming.NamingEnumeration;
039import javax.naming.NamingException;
040import javax.naming.directory.Attributes;
041import javax.naming.directory.DirContext;
042import javax.naming.directory.InitialDirContext;
043import javax.naming.directory.SearchControls;
044import javax.naming.directory.SearchResult;
045import javax.servlet.ServletException;
046import javax.servlet.http.HttpServlet;
047import javax.servlet.http.HttpServletRequest;
048import javax.servlet.http.HttpServletResponse;
049
050import org.apache.commons.codec.binary.Base64;
051import org.apache.commons.logging.Log;
052import org.apache.commons.logging.LogFactory;
053import org.nuxeo.launcher.commons.DatabaseDriverException;
054import org.nuxeo.launcher.config.ConfigurationException;
055import org.nuxeo.launcher.config.ConfigurationGenerator;
056import org.nuxeo.wizard.context.Context;
057import org.nuxeo.wizard.context.ParamCollector;
058import org.nuxeo.wizard.download.DownloadablePackageOptions;
059import org.nuxeo.wizard.download.PackageDownloader;
060import org.nuxeo.wizard.helpers.ConnectRegistrationHelper;
061import org.nuxeo.wizard.helpers.IPValidator;
062import org.nuxeo.wizard.helpers.NumberValidator;
063import org.nuxeo.wizard.helpers.PackageDownloaderHelper;
064import org.nuxeo.wizard.nav.Page;
065import org.nuxeo.wizard.nav.SimpleNavigationHandler;
066
067/**
068 * Main entry point : find the right handler and start jsp rendering
069 *
070 * @author Tiry (tdelprat@nuxeo.com)
071 * @since 5.4.2
072 */
073public class RouterServlet extends HttpServlet {
074
075    private static final long serialVersionUID = 1L;
076
077    protected static Log log = LogFactory.getLog(RouterServlet.class);
078
079    protected SimpleNavigationHandler navHandler = SimpleNavigationHandler.instance();
080
081    public static final String CONNECT_TOKEN_KEY = "ConnectRegistrationToken";
082
083    protected String getAction(HttpServletRequest req) {
084        String uri = req.getRequestURI();
085
086        int idx = uri.indexOf("?");
087        if (idx > 0) {
088            uri = uri.substring(0, idx - 1);
089        }
090        String action = uri.replace(req.getContextPath() + "/router/", "");
091        if (action.startsWith("/")) {
092            action = action.substring(1);
093        }
094        return action;
095    }
096
097    @Override
098    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
099
100        // process action
101        handleAction(getAction(req), req, resp);
102    }
103
104    @Override
105    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
106
107        // store posted data
108        Context.instance(req).getCollector().collectConfigurationParams(req);
109
110        doGet(req, resp);
111    }
112
113    protected Method findhandler(Page currentPage, String verb) {
114
115        String methodName = "handle" + currentPage.getAction() + verb;
116        Method method = null;
117        try {
118            method = this.getClass().getMethod(methodName, Page.class, HttpServletRequest.class,
119                    HttpServletResponse.class);
120        } catch (Exception e) {
121            // fall back to default Handler lookup
122            methodName = "handleDefault" + verb;
123            try {
124                method = this.getClass().getMethod(methodName, Page.class, HttpServletRequest.class,
125                        HttpServletResponse.class);
126            } catch (Exception e2) {
127                log.error("Unable to resolve default handler for " + verb, e);
128            }
129        }
130        return method;
131    }
132
133    protected void handleAction(String action, HttpServletRequest req, HttpServletResponse resp)
134            throws ServletException, IOException {
135
136        // locate page
137        Page currentPage = navHandler.getCurrentPage(action);
138        if (currentPage == null) {
139            resp.sendError(404, "Action " + action + " is not supported");
140            return;
141        }
142
143        // find action handler
144        Method handler = findhandler(currentPage, req.getMethod());
145        if (handler == null) {
146            resp.sendError(500, "No handler found for " + action);
147            return;
148        }
149
150        // execute handler => triggers rendering
151        try {
152            handler.invoke(this, currentPage, req, resp);
153        } catch (Exception e) {
154            log.error("Error during handler execution", e);
155            req.setAttribute("error", e);
156            req.getRequestDispatcher("/error.jsp").forward(req, resp);
157        }
158    }
159
160    // default handlers
161
162    public void handleDefaultGET(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
163            throws ServletException, IOException {
164        currentPage.dispatchToJSP(req, resp);
165    }
166
167    public void handleDefaultPOST(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
168            throws ServletException, IOException {
169        // XXX validate data
170        currentPage.next().dispatchToJSP(req, resp, true);
171    }
172
173    // custom handlers
174
175    public void handleConnectGET(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
176            throws ServletException, IOException {
177
178        Context ctx = Context.instance(req);
179
180        // compute CB url
181        String cbUrl = req.getRequestURL().toString();
182        cbUrl = cbUrl.replace("/router/" + currentPage.getAction(), "/ConnectCallback?cb=yes");
183        // In order to avoid any issue with badly configured reverse proxies
184        // => get url from the client side
185        if (ctx.getBaseUrl() != null) {
186            cbUrl = ctx.getBaseUrl() + "ConnectCallback?cb=yes";
187        }
188        cbUrl = URLEncoder.encode(cbUrl, "UTF-8");
189
190        req.setAttribute("callBackUrl", cbUrl);
191
192        handleDefaultGET(currentPage, req, resp);
193    }
194
195    public void handleConnectCallbackGET(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
196            throws ServletException, IOException {
197
198        String token = req.getParameter(CONNECT_TOKEN_KEY);
199        String action = req.getParameter("action");
200        String targetNav = null;
201
202        if (action == null || action.isEmpty()) {
203            action = "skip";
204        }
205        if (action.equals("register") && (token == null || token.isEmpty())) {
206            action = "skip";
207        }
208
209        if ("register".equals(action)) {
210            // store the registration info
211            Map<String, String> connectMap = new HashMap<>();
212            Context context = Context.instance(req);
213            if (token != null) {
214                String tokenData = new String(Base64.decodeBase64(token));
215                String[] tokenDataLines = tokenData.split("\n");
216                for (String line : tokenDataLines) {
217                    String[] parts = line.split(":");
218                    if (parts.length > 1) {
219                        connectMap.put(parts[0], parts[1]);
220                    }
221                }
222                context.storeConnectMap(connectMap);
223            }
224
225            // Save CLID
226            if (context.isConnectRegistrationDone()) {
227                // save Connect registration
228                ConnectRegistrationHelper.saveConnectRegistrationFile(context);
229            }
230
231            // deactivate the confirm form
232            SimpleNavigationHandler.instance().deactivatePage("ConnectFinish");
233            // go to the next page
234            targetNav = currentPage.next().getAction();
235
236        } else if ("skip".equals(action)) {
237            // activate the confirm form
238            SimpleNavigationHandler.instance().activatePage("ConnectFinish");
239            // go to it
240            targetNav = currentPage.next().getAction();
241        } else if ("prev".equals(action)) {
242            targetNav = currentPage.prev().prev().getAction();
243        }
244
245        String targetUrl = req.getContextPath() + "/" + targetNav;
246
247        req.setAttribute("targetUrl", targetUrl);
248        handleDefaultGET(currentPage, req, resp);
249    }
250
251    public void handleConnectFinishGET(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
252            throws ServletException, IOException {
253
254        // get the connect Token and decode associated infos
255        String token = req.getParameter(CONNECT_TOKEN_KEY);
256        Map<String, String> connectMap = new HashMap<>();
257        if (token != null) {
258            String tokenData = new String(Base64.decodeBase64(token));
259            String[] tokenDataLines = tokenData.split("\n");
260            for (String line : tokenDataLines) {
261                String[] parts = line.split(":");
262                if (parts.length > 1) {
263                    connectMap.put(parts[0], parts[1]);
264                }
265            }
266            Context.instance(req).storeConnectMap(connectMap);
267        }
268
269        handleDefaultGET(currentPage, req, resp);
270    }
271
272    public void handleDBPOST(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
273            throws ServletException, IOException {
274
275        Context ctx = Context.instance(req);
276        ParamCollector collector = ctx.getCollector();
277
278        String templateDbName = collector.getConfigurationParam(ConfigurationGenerator.PARAM_TEMPLATE_DBNAME);
279        if ("true".equals(req.getParameter("refresh"))) {
280            String templateName = templateDbName;
281            collector.changeDBTemplate(templateName);
282            currentPage.dispatchToJSP(req, resp);
283            return;
284        }
285
286        // Check relational database
287        if (!Arrays.asList("default", "mongodb").contains(templateDbName)) {
288            if (collector.getConfigurationParam("nuxeo.db.name").isEmpty()) {
289                ctx.trackError("nuxeo.db.name", "error.dbname.required");
290            }
291            if (collector.getConfigurationParam("nuxeo.db.user").isEmpty()) {
292                ctx.trackError("nuxeo.db.user", "error.dbuser.required");
293            }
294            if (collector.getConfigurationParam("nuxeo.db.password").isEmpty()) {
295                ctx.trackError("nuxeo.db.password", "error.dbpassword.required");
296            }
297            if (collector.getConfigurationParam("nuxeo.db.host").isEmpty()) {
298                ctx.trackError("nuxeo.db.host", "error.dbhost.required");
299            }
300            if (collector.getConfigurationParam("nuxeo.db.port").isEmpty()) {
301                ctx.trackError("nuxeo.db.port", "error.dbport.required");
302            } else {
303                if (!NumberValidator.validate(collector.getConfigurationParam("nuxeo.db.port"))) {
304                    ctx.trackError("nuxeo.db.port", "error.invalid.port");
305                } else {
306                    int dbPort = Integer.parseInt(collector.getConfigurationParam("nuxeo.db.port"));
307                    if (dbPort < 1024 || dbPort > 65536) {
308                        ctx.trackError("nuxeo.db.port", "error.invalid.port");
309                    }
310                }
311            }
312            ConfigurationGenerator cg = collector.getConfigurationGenerator();
313            try {
314                cg.checkDatabaseConnection(
315                        templateDbName,
316                        collector.getConfigurationParam("nuxeo.db.name"),
317                        collector.getConfigurationParam("nuxeo.db.user"),
318                        collector.getConfigurationParam("nuxeo.db.password"),
319                        collector.getConfigurationParam("nuxeo.db.host"),
320                        collector.getConfigurationParam("nuxeo.db.port"));
321            } catch (DatabaseDriverException e) {
322                ctx.trackError("nuxeo.db.name", "error.db.driver.notfound");
323                log.warn(e);
324            } catch (SQLException e) {
325                ctx.trackError("nuxeo.db.name", "error.db.connection");
326                log.warn(e);
327            }
328        }
329
330        // Check mongodb database
331        if (templateDbName.equals("mongodb")) {
332            if (collector.getConfigurationParam("nuxeo.mongodb.dbname").isEmpty()) {
333                ctx.trackError("nuxeo.mongodb.dbname", "error.dbname.required");
334            }
335            if (collector.getConfigurationParam("nuxeo.mongodb.server").isEmpty()) {
336                ctx.trackError("nuxeo.mongodb.server", "error.dbhost.required");
337            }
338        }
339
340        if (ctx.hasErrors()) {
341            currentPage.dispatchToJSP(req, resp);
342        } else {
343            currentPage.next().dispatchToJSP(req, resp, true);
344        }
345
346    }
347
348    public void handleUserPOST(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
349            throws ServletException, IOException {
350
351        Context ctx = Context.instance(req);
352        ParamCollector collector = ctx.getCollector();
353
354        String refreshParam = req.getParameter("refresh");
355        String directoryType = collector.getConfigurationParam("nuxeo.directory.type");
356
357        if ("true".equals(refreshParam)) {
358            // String templateName =
359            // collector.getConfigurationParam(ConfigurationGenerator.PARAM_TEMPLATE_USERNAME);
360            // collector.changeUserTemplate(templateName);
361            currentPage.dispatchToJSP(req, resp);
362            return;
363        }
364
365        if ("checkNetwork".equals(refreshParam) || "checkAuth".equals(refreshParam)
366                || "checkUserLdapParam".equals(refreshParam) || "checkGroupLdapParam".equals(refreshParam)) {
367            try {
368                if ("checkNetwork".equals(refreshParam)) {
369                    bindLdapConnection(collector, false);
370                    ctx.trackInfo("nuxeo.ldap.url", "info.host.found");
371                } else if ("checkAuth".equals(refreshParam)) {
372                    bindLdapConnection(collector, true);
373                    ctx.trackInfo("nuxeo.ldap.auth", "info.auth.success");
374                } else {
375                    DirContext dirContext = new InitialDirContext(getContextEnv(collector, true));
376                    String searchScope;
377                    String searchBaseDn;
378                    String searchClass;
379                    String searchFilter;
380                    if ("checkUserLdapParam".equals(refreshParam)) {
381                        searchBaseDn = collector.getConfigurationParam("nuxeo.ldap.user.searchBaseDn");
382                        searchScope = collector.getConfigurationParam("nuxeo.ldap.user.searchScope");
383                        searchClass = collector.getConfigurationParam("nuxeo.ldap.user.searchClass");
384                        searchFilter = collector.getConfigurationParam("nuxeo.ldap.user.searchFilter");
385                    } else {
386                        searchBaseDn = collector.getConfigurationParam("nuxeo.ldap.group.searchBaseDn");
387                        searchScope = collector.getConfigurationParam("nuxeo.ldap.group.searchScope");
388                        searchFilter = collector.getConfigurationParam("nuxeo.ldap.group.searchFilter");
389                        searchClass = "";
390                    }
391
392                    SearchControls scts = new SearchControls();
393                    if ("onelevel".equals(searchScope)) {
394                        scts.setSearchScope(SearchControls.ONELEVEL_SCOPE);
395                    } else {
396                        scts.setSearchScope(SearchControls.SUBTREE_SCOPE);
397                    }
398                    String filter = String.format("(&(%s)(objectClass=%s))", searchFilter.isEmpty() ? "objectClass=*"
399                            : searchFilter, searchClass.isEmpty() ? "*" : searchClass);
400                    NamingEnumeration<SearchResult> results;
401                    try {
402                        results = dirContext.search(searchBaseDn, filter, scts);
403                        if (!results.hasMore()) {
404                            ctx.trackError("nuxeo.ldap.search", "error.ldap.noresult");
405                        } else {
406                            SearchResult result = results.next();
407                            if (searchBaseDn.equalsIgnoreCase(result.getNameInNamespace()) && results.hasMore()) {
408                                // try not to display the root of the search
409                                // base DN
410                                result = results.next();
411                            }
412                            ctx.trackInfo("dn", result.getNameInNamespace());
413                            Attributes attributes = result.getAttributes();
414                            NamingEnumeration<String> ids = attributes.getIDs();
415                            String id;
416                            StringBuilder sb;
417                            while (ids.hasMore()) {
418                                id = ids.next();
419                                NamingEnumeration<?> values = attributes.get(id).getAll();
420                                sb = new StringBuilder();
421                                while (values.hasMore()) {
422                                    sb.append(values.next()).append(" , ");
423                                }
424                                ctx.trackInfo(id, sb.substring(0, sb.length() - 3));
425                            }
426                        }
427                    } catch (NameNotFoundException e) {
428                        ctx.trackError("nuxeo.ldap.search", "error.ldap.searchBaseDn");
429                        log.warn(e);
430                    }
431                    dirContext.close();
432                }
433            } catch (AuthenticationException e) {
434                ctx.trackError("nuxeo.ldap.auth", "error.auth.failed");
435                log.warn(e);
436            } catch (NamingException e) {
437                ctx.trackError("nuxeo.ldap.url", "error.host.not.found");
438                log.warn(e);
439            }
440        }
441
442        // Form submit
443        if (!"default".equals(directoryType) && refreshParam.isEmpty()) {
444            // first check bind to LDAP server
445            try {
446                bindLdapConnection(collector, true);
447            } catch (NamingException e) {
448                ctx.trackError("nuxeo.ldap.auth", "error.ldap.bind.failed");
449                log.warn(e);
450            }
451
452            // then check mandatory fields
453            if (collector.getConfigurationParam("nuxeo.ldap.user.searchBaseDn").isEmpty()) {
454                ctx.trackError("nuxeo.ldap.user.searchBaseDn", "error.user.searchBaseDn.required");
455            }
456            if (collector.getConfigurationParam("nuxeo.ldap.user.mapping.rdn").isEmpty()) {
457                ctx.trackError("nuxeo.ldap.user.mapping.rdn", "error.user.rdn.required");
458            }
459            if (collector.getConfigurationParam("nuxeo.ldap.user.mapping.username").isEmpty()) {
460                ctx.trackError("nuxeo.ldap.user.mapping.username", "error.user.username.required");
461            }
462            if (collector.getConfigurationParam("nuxeo.ldap.user.mapping.password").isEmpty()) {
463                ctx.trackError("nuxeo.ldap.user.mapping.password", "error.user.password.required");
464            }
465            if (collector.getConfigurationParam("nuxeo.ldap.user.mapping.firstname").isEmpty()) {
466                ctx.trackError("nuxeo.ldap.user.mapping.firstname", "error.user.firstname.required");
467            }
468            if (collector.getConfigurationParam("nuxeo.ldap.user.mapping.lastname").isEmpty()) {
469                ctx.trackError("nuxeo.ldap.user.mapping.lastname", "error.user.lastname.required");
470            }
471            String userGroupStorage = collector.getConfigurationParam("nuxeo.user.group.storage");
472            if (!"userLdapOnly".equals(userGroupStorage) && !"multiUserSqlGroup".equals(userGroupStorage)) {
473                if (collector.getConfigurationParam("nuxeo.ldap.group.searchBaseDn").isEmpty()) {
474                    ctx.trackError("nuxeo.ldap.group.searchBaseDn", "error.group.searchBaseDn.required");
475                }
476                if (collector.getConfigurationParam("nuxeo.ldap.group.mapping.rdn").isEmpty()) {
477                    ctx.trackError("nuxeo.ldap.group.mapping.rdn", "error.group.rdn.required");
478                }
479                if (collector.getConfigurationParam("nuxeo.ldap.group.mapping.name").isEmpty()) {
480                    ctx.trackError("nuxeo.ldap.group.mapping.name", "error.group.name.required");
481                }
482            }
483            if ("true".equals(collector.getConfigurationParam("nuxeo.user.emergency.enable"))) {
484                if (collector.getConfigurationParam("nuxeo.user.emergency.username").isEmpty()) {
485                    ctx.trackError("nuxeo.user.emergency.username", "error.emergency.username.required");
486                }
487                if (collector.getConfigurationParam("nuxeo.user.emergency.password").isEmpty()) {
488                    ctx.trackError("nuxeo.user.emergency.password", "error.emergency.password.required");
489                }
490            }
491        }
492
493        if (ctx.hasErrors() || ctx.hasInfos()) {
494            currentPage.dispatchToJSP(req, resp);
495        } else {
496            currentPage.next().dispatchToJSP(req, resp, true);
497        }
498    }
499
500    private Hashtable<Object, Object> getContextEnv(ParamCollector collector, boolean checkAuth) {
501        String ldapUrl = collector.getConfigurationParam("nuxeo.ldap.url");
502        String ldapBindDn = collector.getConfigurationParam("nuxeo.ldap.binddn");
503        String ldapBindPassword = collector.getConfigurationParam("nuxeo.ldap.bindpassword");
504        ConfigurationGenerator cg = collector.getConfigurationGenerator();
505        return cg.getContextEnv(ldapUrl, ldapBindDn, ldapBindPassword, checkAuth);
506    }
507
508    private void bindLdapConnection(ParamCollector collector, boolean authenticate) throws NamingException {
509        ConfigurationGenerator cg = collector.getConfigurationGenerator();
510        cg.checkLdapConnection(getContextEnv(collector, authenticate));
511    }
512
513    public void handleSmtpPOST(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
514            throws ServletException, IOException {
515
516        Context ctx = Context.instance(req);
517        ParamCollector collector = ctx.getCollector();
518
519        if (collector.getConfigurationParam("mail.transport.auth").equals("true")) {
520            if (collector.getConfigurationParam("mail.transport.user").isEmpty()) {
521                ctx.trackError("mail.transport.user", "error.mail.transport.user.required");
522            }
523            if (collector.getConfigurationParam("mail.transport.password").isEmpty()) {
524                ctx.trackError("mail.transport.password", "error.mail.transport.password.required");
525            }
526        }
527
528        if (!collector.getConfigurationParam("mail.transport.port").isEmpty()) {
529            if (!NumberValidator.validate(collector.getConfigurationParam("mail.transport.port"))) {
530                ctx.trackError("mail.transport.port", "error.mail.transport.port.mustbeanumber");
531            }
532        }
533
534        if (ctx.hasErrors()) {
535            currentPage.dispatchToJSP(req, resp);
536        } else {
537            currentPage.next().dispatchToJSP(req, resp, true);
538        }
539
540    }
541
542    public void handleRecapPOST(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
543            throws ServletException, IOException {
544
545        Context ctx = Context.instance(req);
546        ParamCollector collector = ctx.getCollector();
547        ConfigurationGenerator cg = collector.getConfigurationGenerator();
548
549        // Mark package selection done
550        PackageDownloaderHelper.markPackageSelectionDone(ctx);
551
552        Map<String, String> changedParameters = collector.getConfigurationParams();
553        changedParameters.put(ConfigurationGenerator.PARAM_WIZARD_DONE, "true");
554        try {
555            // save config
556            cg.saveFilteredConfiguration(changedParameters);
557
558            // // => page will trigger the restart
559            // new Page("", "reStarting.jsp").dispatchToJSP(req, resp);
560            currentPage.next().dispatchToJSP(req, resp, true);
561        } catch (ConfigurationException e) {
562            log.error("Could not save wizard parameters.", e);
563            currentPage.dispatchToJSP(req, resp);
564        }
565    }
566
567    public void handleGeneralPOST(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
568            throws ServletException, IOException {
569
570        Context ctx = Context.instance(req);
571        ParamCollector collector = ctx.getCollector();
572        String bindAddress = collector.getConfigurationParamValue("nuxeo.bind.address");
573        if (bindAddress != null && !bindAddress.isEmpty()) {
574            if (!IPValidator.validate(bindAddress)) {
575                ctx.trackError("nuxeo.bind.address", "error.invalid.ip");
576            }
577            try {
578                InetAddress inetAddress = InetAddress.getByName(bindAddress);
579                ConfigurationGenerator.checkAddressReachable(inetAddress);
580            } catch (UnknownHostException e) {
581                ctx.trackError("nuxeo.bind.address", "error.invalid.ip");
582            } catch (ConfigurationException e) {
583                ctx.trackError("nuxeo.bind.address", "error.already.used.ip");
584            }
585        }
586
587        if (ctx.hasErrors()) {
588            currentPage.dispatchToJSP(req, resp);
589        } else {
590            currentPage.next().dispatchToJSP(req, resp, true);
591        }
592    }
593
594    public void handleHomeGET(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
595            throws ServletException, IOException {
596
597        Context ctx = Context.instance(req);
598        if (PackageDownloaderHelper.isPackageSelectionDone(ctx)) {
599            navHandler.deactivatePage("PackagesSelection");
600            navHandler.deactivatePage("PackagesDownload");
601            navHandler.activatePage("PackagesSelectionDone");
602        }
603
604        handleDefaultGET(currentPage, req, resp);
605    }
606
607    public void handleHomePOST(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
608            throws ServletException, IOException {
609
610        String baseUrl = req.getParameter("baseUrl");
611        if (baseUrl != null && !baseUrl.isEmpty()) {
612            if (baseUrl.endsWith("Home")) {
613                baseUrl = baseUrl.substring(0, baseUrl.length() - 4);
614                Context.instance(req).setBaseUrl(baseUrl);
615            }
616        }
617
618        String browserInternetAccess = req.getParameter("browserInternetAccess");
619        if ("true".equals(browserInternetAccess)) {
620            Context.instance(req).setBrowserInternetAccess(true);
621            SimpleNavigationHandler.instance().deactivatePage("NetworkBlocked");
622            SimpleNavigationHandler.instance().activatePage("Connect");
623        } else {
624            Context.instance(req).setBrowserInternetAccess(false);
625            SimpleNavigationHandler.instance().activatePage("NetworkBlocked");
626            SimpleNavigationHandler.instance().deactivatePage("Connect");
627        }
628
629        currentPage.next().dispatchToJSP(req, resp, true);
630    }
631
632    public void handleProxyPOST(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
633            throws ServletException, IOException {
634
635        Context ctx = Context.instance(req);
636        ParamCollector collector = ctx.getCollector();
637        String proxyType = collector.getConfigurationParamValue("nuxeo.http.proxy.type");
638        if ("none".equals(proxyType)) {
639            collector.addConfigurationParam("nuxeo.http.proxy.type", null);
640            collector.addConfigurationParam("nuxeo.http.proxy.login", null);
641            collector.addConfigurationParam("nuxeo.http.proxy.password", null);
642            collector.addConfigurationParam("nuxeo.http.proxy.host", null);
643            collector.addConfigurationParam("nuxeo.http.proxy.port", null);
644            collector.addConfigurationParam("nuxeo.http.proxy.ntml.host", null);
645            collector.addConfigurationParam("nuxeo.http.proxy.ntml.domain", null);
646            if (!PackageDownloaderHelper.isPackageSelectionDone(ctx)) {
647                PackageDownloader.instance().setProxy(null, 0, null, null, null, null);
648            }
649        } else {
650            if (!NumberValidator.validate(collector.getConfigurationParam("nuxeo.http.proxy.port"))) {
651                ctx.trackError("nuxeo.http.proxy.port", "error.nuxeo.http.proxy.port");
652            }
653            if (collector.getConfigurationParam("nuxeo.http.proxy.host").isEmpty()) {
654                ctx.trackError("nuxeo.http.proxy.host", "error.nuxeo.http.proxy.emptyHost");
655            }
656            if ("anonymous".equals(proxyType)) {
657                collector.addConfigurationParam("nuxeo.http.proxy.login", null);
658                collector.addConfigurationParam("nuxeo.http.proxy.password", null);
659                collector.addConfigurationParam("nuxeo.http.proxy.ntml.host", null);
660                collector.addConfigurationParam("nuxeo.http.proxy.ntml.domain", null);
661
662                if (!ctx.hasErrors()) {
663                    if (!PackageDownloaderHelper.isPackageSelectionDone(ctx)) {
664                        PackageDownloader.instance().setProxy(
665                                collector.getConfigurationParamValue("nuxeo.http.proxy.host"),
666                                Integer.parseInt(collector.getConfigurationParamValue("nuxeo.http.proxy.port")), null,
667                                null, null, null);
668                    }
669                }
670            } else {
671                if (collector.getConfigurationParam("nuxeo.http.proxy.login").isEmpty()) {
672                    ctx.trackError("nuxeo.http.proxy.login", "error.nuxeo.http.proxy.emptyLogin");
673                } else {
674                    if (!ctx.hasErrors()) {
675                        if (!PackageDownloaderHelper.isPackageSelectionDone(ctx)) {
676                            PackageDownloader.instance().setProxy(
677                                    collector.getConfigurationParamValue("nuxeo.http.proxy.host"),
678                                    Integer.parseInt(collector.getConfigurationParamValue("nuxeo.http.proxy.port")),
679                                    collector.getConfigurationParamValue("nuxeo.http.proxy.login"),
680                                    collector.getConfigurationParamValue("nuxeo.http.proxy.password"),
681                                    collector.getConfigurationParamValue("nuxeo.http.proxy.ntlm.host"),
682                                    collector.getConfigurationParamValue("nuxeo.http.proxy.ntml.domain"));
683                        }
684                    }
685                }
686            }
687        }
688
689        if (ctx.hasErrors()) {
690            currentPage.dispatchToJSP(req, resp);
691        } else {
692            currentPage.next().dispatchToJSP(req, resp, true);
693        }
694    }
695
696    public void handleResetGET(Page currentPage, HttpServletRequest req, HttpServletResponse resp) throws IOException {
697
698        // reset
699        Context.reset();
700        SimpleNavigationHandler.reset();
701        PackageDownloader.reset();
702
703        // return to first page
704        String target = "/" + req.getContextPath() + "/"
705                + SimpleNavigationHandler.instance().getDefaultPage().getAction();
706        if (target.startsWith("//")) {
707            target = target.substring(1);
708        }
709        resp.sendRedirect(target);
710    }
711
712    public void handlePackageOptionsResourceGET(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
713            throws IOException {
714
715        DownloadablePackageOptions options = PackageDownloader.instance().getPackageOptions();
716        resp.setContentType("text/json");
717        resp.getWriter().write(options.asJson());
718
719    }
720
721    public void handlePackagesSelectionGET(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
722            throws ServletException, IOException {
723
724        handleDefaultGET(currentPage, req, resp);
725    }
726
727    public void handlePackagesSelectionPOST(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
728            throws ServletException, IOException {
729        List<String> options = new ArrayList<>();
730        Enumeration<String> params = req.getParameterNames();
731        while (params.hasMoreElements()) {
732            String p = params.nextElement();
733            if ("on".equals(req.getParameter(p))) {
734                options.add(p);
735            }
736        }
737
738        PackageDownloader.instance().selectOptions(options);
739
740        currentPage.next().dispatchToJSP(req, resp, true);
741    }
742
743    public void handlePackagesDownloadGET(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
744            throws ServletException, IOException {
745        if ("true".equals(req.getParameter("startDownload"))) {
746            PackageDownloader.instance().startDownload();
747        } else if (req.getParameter("reStartDownload") != null) {
748            PackageDownloader.instance().reStartDownload(req.getParameter("reStartDownload"));
749        }
750        currentPage.dispatchToJSP(req, resp);
751    }
752
753    public void handlePackagesDownloadPOST(Page currentPage, HttpServletRequest req, HttpServletResponse resp)
754            throws ServletException, IOException {
755        ParamCollector collector = Context.instance(req).getCollector();
756
757        String installationFilePath = new File(
758                collector.getConfigurationParam(org.nuxeo.common.Environment.NUXEO_DATA_DIR),
759                ConfigurationGenerator.INSTALL_AFTER_RESTART).getAbsolutePath();
760
761        PackageDownloader.instance().scheduleDownloadedPackagesForInstallation(installationFilePath);
762        PackageDownloader.reset();
763
764        currentPage.next().dispatchToJSP(req, resp, true);
765    }
766
767}