001package jmri.web.servlet.permission;
002
003import java.io.*;
004import java.net.URLDecoder;
005import java.nio.charset.StandardCharsets;
006
007import static jmri.web.servlet.ServletUtil.UTF8_TEXT_HTML;
008
009import javax.servlet.ServletException;
010import javax.servlet.annotation.WebServlet;
011import javax.servlet.http.*;
012
013import jmri.*;
014import jmri.util.FileUtil;
015import jmri.web.servlet.ServletUtil;
016
017import org.openide.util.lookup.ServiceProvider;
018
019/**
020 *
021 * @author Randall Wood (C) 2014, 2016
022 * @author mstevetodd (C) 2017
023 * @author Daniel Bergqvist (C) 2024
024 */
025@WebServlet(name = "PermissionServlet",
026        urlPatterns = {"/permission"})
027@ServiceProvider(service = HttpServlet.class)
028public class PermissionServlet extends HttpServlet {
029
030    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
031
032        String theRequest = request.getRequestURI().substring("/permission/".length());
033        // log.error("Request: {}", theRequest);
034
035        switch (theRequest) {
036            case "login":
037                login(request, response);
038                break;
039            case "logout":
040                logout(request, response);
041                break;
042//            case "status":
043//                status(request, response);
044//                break;
045            default:
046                response.sendError(HttpServletResponse.SC_NOT_FOUND);
047        }
048    }
049
050    private static void sendPage(String page, String message,
051            HttpServletRequest request, HttpServletResponse response)
052            throws IOException {
053
054        //print the html, using the replacement values listed to fill in the calculated stuff
055        response.setHeader("Connection", "Keep-Alive"); // NOI18N
056        response.setContentType(UTF8_TEXT_HTML);
057        response.getWriter().print(String.format(request.getLocale(),
058                FileUtil.readURL(FileUtil.findURL(Bundle.getMessage(request.getLocale(), page))),
059                Bundle.getMessage(request.getLocale(), "PermissionTitle"),                              // page title is parm 1
060                InstanceManager.getDefault(ServletUtil.class).getNavBar(request.getLocale(), "/permission"), // navbar is parm 2
061                InstanceManager.getDefault(ServletUtil.class).getRailroadName(false),                   // railroad name is parm 3
062                InstanceManager.getDefault(ServletUtil.class).getFooter(request.getLocale(), "/permission"), // footer is parm 4
063                message                                                                                 // Response message
064        ));
065    }
066
067    private void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
068        if (request.getContentLength() > 0) {
069            StringBuilder textBuilder = new StringBuilder();
070            try (BufferedReader reader = new BufferedReader(new InputStreamReader(
071                    request.getInputStream(), StandardCharsets.UTF_8))) {
072                int c;
073                while ((c = reader.read()) != -1) {
074                    textBuilder.append((char) c);
075                }
076            }
077
078            PermissionManager mngr = InstanceManager.getDefault(PermissionManager.class);
079
080            String username = null;
081            String password = null;
082
083            for (String param : textBuilder.toString().split("&")) {
084                String[] parts = param.split("=");
085                switch (parts[0]) {
086                    case "username":
087                        username = URLDecoder.decode(parts[1], StandardCharsets.UTF_8);
088                        break;
089                    case "password":
090                        if (parts.length > 1)
091                            password = URLDecoder.decode(parts[1], StandardCharsets.UTF_8);
092                        else
093                            password = "";
094                        break;
095                    default:
096                        throw new IllegalArgumentException("Unknown parameter: \""+parts[0]+"\" with value \""+parts[1]+"\"");
097                }
098            }
099
100            if (username != null && password != null) {
101                // log.warn("Login with {} and {}", username, password);
102
103                if (mngr.isAGuestUser(username)) {
104                    String message = Bundle.getMessage("GuestMessage");
105                    sendPage("Response.html", message, request, response);
106                    return;
107                }
108
109                String sessId = PermissionServlet.getSessionId(request);
110                if (sessId == null) sessId = "";
111
112                StringBuilder sessionId = new StringBuilder(sessId);
113
114                boolean result = mngr.remoteLogin(sessionId, request.getLocale(), username, password);
115
116                if (result) {
117                    setSessionId(sessionId.toString(), response);
118                }
119                String message = result ? Bundle.getMessage("LoginSuccessful") : Bundle.getMessage("BadUsernameOrPassword");
120                sendPage("Response.html", message, request, response);
121
122                return;
123            }
124        }
125
126        //print the html, using the replacement values listed to fill in the calculated stuff
127        response.setHeader("Connection", "Keep-Alive"); // NOI18N
128        response.setContentType(UTF8_TEXT_HTML);
129        response.getWriter().print(String.format(request.getLocale(),
130                FileUtil.readURL(FileUtil.findURL(Bundle.getMessage(request.getLocale(), "Login.html"))),
131                Bundle.getMessage(request.getLocale(), "PermissionTitle"),                              // page title is parm 1
132                InstanceManager.getDefault(ServletUtil.class).getNavBar(request.getLocale(), "/permission"), // navbar is parm 2
133                InstanceManager.getDefault(ServletUtil.class).getRailroadName(false),                   // railroad name is parm 3
134                InstanceManager.getDefault(ServletUtil.class).getFooter(request.getLocale(), "/permission") // footer is parm 4
135        ));
136    }
137
138    private void logout(HttpServletRequest request, HttpServletResponse response) throws IOException {
139        String sessionId = PermissionServlet.getSessionId(request);
140        InstanceManager.getDefault(PermissionManager.class).remoteLogout(sessionId);
141        sendPage("Response.html", Bundle.getMessage("LogoutSuccessful"), request, response);
142    }
143/*
144    private void status(HttpServletRequest request, HttpServletResponse response) throws IOException {
145
146        log.error("Context path: {}", request.getContextPath());
147        log.error("Servlet path: {}", request.getServletPath());
148        log.error("Query string: {}", request.getQueryString());
149        log.error("Request URI: {}", request.getRequestURI());
150        log.error("Request URL: {}", request.getRequestURL().toString());
151
152//        request.getContentLength();
153//        request.getInputStream();
154//        request.getMethod();
155    }
156*/
157    public static void permissionDenied(HttpServletRequest request, HttpServletResponse response) throws IOException {
158        String session = "";
159        InstanceManager.getDefault(PermissionManager.class).remoteLogout(session);
160        sendPage("Response.html", Bundle.getMessage("PermissionDenied"), request, response);
161    }
162
163    public static String getSessionId(HttpServletRequest request) {
164        Cookie[] cookies = request.getCookies();
165        if (cookies == null) return null;
166        for (Cookie c : cookies) {
167            if ("sessionId".equals(c.getName())) {
168                return c.getValue();
169            }
170        }
171        return null;
172    }
173
174    public static void setSessionId(String sessionId, HttpServletResponse response) {
175        Cookie cookie = new Cookie("sessionId", sessionId);
176        cookie.setPath("/");
177        response.addCookie(cookie);
178    }
179
180// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
181    /**
182     * Handles the HTTP <code>GET</code> method.
183     *
184     * @param request  servlet request
185     * @param response servlet response
186     * @throws ServletException if a servlet-specific error occurs
187     * @throws IOException      if an I/O error occurs
188     */
189    @Override
190    protected void doGet(HttpServletRequest request, HttpServletResponse response)
191            throws ServletException, IOException {
192        processRequest(request, response);
193    }
194
195    /**
196     * Handles the HTTP <code>POST</code> method.
197     *
198     * @param request  servlet request
199     * @param response servlet response
200     * @throws ServletException if a servlet-specific error occurs
201     * @throws IOException      if an I/O error occurs
202     */
203    @Override
204    protected void doPost(HttpServletRequest request, HttpServletResponse response)
205            throws ServletException, IOException {
206        processRequest(request, response);
207    }
208
209    /**
210     * Returns a short description of the servlet.
211     *
212     * @return a String containing servlet description
213     */
214    @Override
215    public String getServletInfo() {
216        return "About Servlet";
217    }// </editor-fold>
218
219//    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PermissionServlet.class);
220
221}