001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.struts;
016    
017    import com.liferay.portal.kernel.exception.LayoutPermissionException;
018    import com.liferay.portal.kernel.exception.PortletActiveException;
019    import com.liferay.portal.kernel.exception.UserActiveException;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.model.Layout;
023    import com.liferay.portal.kernel.model.LayoutConstants;
024    import com.liferay.portal.kernel.model.PasswordPolicy;
025    import com.liferay.portal.kernel.model.Portlet;
026    import com.liferay.portal.kernel.model.PortletPreferencesIds;
027    import com.liferay.portal.kernel.model.User;
028    import com.liferay.portal.kernel.model.UserTracker;
029    import com.liferay.portal.kernel.model.UserTrackerPath;
030    import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
031    import com.liferay.portal.kernel.portlet.InvokerPortlet;
032    import com.liferay.portal.kernel.portlet.PortletConfigFactoryUtil;
033    import com.liferay.portal.kernel.portlet.PortletInstanceFactoryUtil;
034    import com.liferay.portal.kernel.portlet.PortletPreferencesFactoryUtil;
035    import com.liferay.portal.kernel.security.auth.InterruptedPortletRequestWhitelistUtil;
036    import com.liferay.portal.kernel.security.auth.PrincipalException;
037    import com.liferay.portal.kernel.security.permission.ActionKeys;
038    import com.liferay.portal.kernel.security.permission.PermissionChecker;
039    import com.liferay.portal.kernel.service.LayoutLocalServiceUtil;
040    import com.liferay.portal.kernel.service.PortletLocalServiceUtil;
041    import com.liferay.portal.kernel.service.PortletPreferencesLocalServiceUtil;
042    import com.liferay.portal.kernel.service.permission.PortletPermissionUtil;
043    import com.liferay.portal.kernel.service.persistence.UserTrackerPathUtil;
044    import com.liferay.portal.kernel.servlet.DynamicServletRequest;
045    import com.liferay.portal.kernel.servlet.HttpMethods;
046    import com.liferay.portal.kernel.servlet.SessionErrors;
047    import com.liferay.portal.kernel.struts.LastPath;
048    import com.liferay.portal.kernel.theme.ThemeDisplay;
049    import com.liferay.portal.kernel.util.CharPool;
050    import com.liferay.portal.kernel.util.GetterUtil;
051    import com.liferay.portal.kernel.util.HttpUtil;
052    import com.liferay.portal.kernel.util.JavaConstants;
053    import com.liferay.portal.kernel.util.ParamUtil;
054    import com.liferay.portal.kernel.util.PortalUtil;
055    import com.liferay.portal.kernel.util.PropsKeys;
056    import com.liferay.portal.kernel.util.StringBundler;
057    import com.liferay.portal.kernel.util.StringPool;
058    import com.liferay.portal.kernel.util.StringUtil;
059    import com.liferay.portal.kernel.util.Validator;
060    import com.liferay.portal.kernel.util.WebKeys;
061    import com.liferay.portal.liveusers.LiveUsers;
062    import com.liferay.portal.util.PropsUtil;
063    import com.liferay.portal.util.PropsValues;
064    import com.liferay.portlet.PortletURLImpl;
065    import com.liferay.portlet.RenderRequestFactory;
066    import com.liferay.portlet.RenderRequestImpl;
067    import com.liferay.portlet.RenderResponseFactory;
068    import com.liferay.portlet.RenderResponseImpl;
069    
070    import java.io.IOException;
071    
072    import java.util.Date;
073    import java.util.HashSet;
074    import java.util.LinkedHashMap;
075    import java.util.Map;
076    import java.util.Set;
077    import java.util.regex.Matcher;
078    import java.util.regex.Pattern;
079    
080    import javax.portlet.PortletConfig;
081    import javax.portlet.PortletContext;
082    import javax.portlet.PortletMode;
083    import javax.portlet.PortletPreferences;
084    import javax.portlet.PortletRequest;
085    import javax.portlet.WindowState;
086    
087    import javax.servlet.ServletContext;
088    import javax.servlet.ServletException;
089    import javax.servlet.http.HttpServletRequest;
090    import javax.servlet.http.HttpServletResponse;
091    import javax.servlet.http.HttpSession;
092    import javax.servlet.jsp.PageContext;
093    
094    import org.apache.struts.Globals;
095    import org.apache.struts.action.Action;
096    import org.apache.struts.action.ActionForm;
097    import org.apache.struts.action.ActionMapping;
098    import org.apache.struts.config.ActionConfig;
099    import org.apache.struts.config.ForwardConfig;
100    import org.apache.struts.tiles.TilesRequestProcessor;
101    import org.apache.struts.util.MessageResources;
102    
103    /**
104     * @author Brian Wing Shun Chan
105     * @author Jorge Ferrer
106     * @author Wesley Gong
107     * @author Mika Koivisto
108     */
109    public class PortalRequestProcessor extends TilesRequestProcessor {
110    
111            public PortalRequestProcessor() {
112    
113                    // auth.forward.last.path.
114    
115                    _lastPaths = new HashSet<>();
116    
117                    _lastPaths.add(_PATH_PORTAL_LAYOUT);
118    
119                    addPaths(_lastPaths, PropsKeys.AUTH_FORWARD_LAST_PATHS);
120    
121                    // auth.public.path.
122    
123                    _publicPaths = new HashSet<>();
124    
125                    _publicPaths.add(_PATH_C);
126                    _publicPaths.add(_PATH_PORTAL_API_JSONWS);
127                    _publicPaths.add(_PATH_PORTAL_FLASH);
128                    _publicPaths.add(_PATH_PORTAL_J_LOGIN);
129                    _publicPaths.add(_PATH_PORTAL_LAYOUT);
130                    _publicPaths.add(_PATH_PORTAL_LICENSE);
131                    _publicPaths.add(_PATH_PORTAL_LOGIN);
132                    _publicPaths.add(_PATH_PORTAL_RENDER_PORTLET);
133                    _publicPaths.add(_PATH_PORTAL_RESILIENCY);
134                    _publicPaths.add(_PATH_PORTAL_TCK);
135                    _publicPaths.add(_PATH_PORTAL_UPDATE_LANGUAGE);
136                    _publicPaths.add(_PATH_PORTAL_UPDATE_PASSWORD);
137                    _publicPaths.add(_PATH_PORTAL_VERIFY_EMAIL_ADDRESS);
138                    _publicPaths.add(PropsValues.AUTH_LOGIN_DISABLED_PATH);
139    
140                    _trackerIgnorePaths = new HashSet<>();
141    
142                    addPaths(_trackerIgnorePaths, PropsKeys.SESSION_TRACKER_IGNORE_PATHS);
143            }
144    
145            @Override
146            public void process(
147                            HttpServletRequest request, HttpServletResponse response)
148                    throws IOException, ServletException {
149    
150                    String path = super.processPath(request, response);
151    
152                    ActionMapping actionMapping =
153                            (ActionMapping)moduleConfig.findActionConfig(path);
154    
155                    Action action = StrutsActionRegistryUtil.getAction(path);
156    
157                    if ((actionMapping == null) && (action == null)) {
158                            String lastPath = getLastPath(request);
159    
160                            if (_log.isDebugEnabled()) {
161                                    _log.debug("Last path " + lastPath);
162                            }
163    
164                            response.sendRedirect(lastPath);
165    
166                            return;
167                    }
168    
169                    super.process(request, response);
170    
171                    try {
172                            if (isPortletPath(path)) {
173                                    cleanUp(request);
174                            }
175                    }
176                    catch (Exception e) {
177                            _log.error(e, e);
178                    }
179            }
180    
181            protected void addPaths(Set<String> paths, String propsKey) {
182                    String[] pathsArray = PropsUtil.getArray(propsKey);
183    
184                    for (String path : pathsArray) {
185                            paths.add(path);
186                    }
187            }
188    
189            protected void callParentDoForward(
190                            String uri, HttpServletRequest request,
191                            HttpServletResponse response)
192                    throws IOException, ServletException {
193    
194                    super.doForward(uri, request, response);
195            }
196    
197            protected HttpServletRequest callParentProcessMultipart(
198                    HttpServletRequest request) {
199    
200                    return super.processMultipart(request);
201            }
202    
203            protected String callParentProcessPath(
204                            HttpServletRequest request, HttpServletResponse response)
205                    throws IOException {
206    
207                    return super.processPath(request, response);
208            }
209    
210            protected boolean callParentProcessRoles(
211                            HttpServletRequest request, HttpServletResponse response,
212                            ActionMapping actionMapping)
213                    throws IOException, ServletException {
214    
215                    return super.processRoles(request, response, actionMapping);
216            }
217    
218            protected void cleanUp(HttpServletRequest request) throws Exception {
219    
220                    // Clean up portlet objects that may have been created by defineObjects
221                    // for portlets that are called directly from a Struts path
222    
223                    RenderRequestImpl renderRequestImpl =
224                            (RenderRequestImpl)request.getAttribute(
225                                    JavaConstants.JAVAX_PORTLET_REQUEST);
226    
227                    if (renderRequestImpl != null) {
228                            renderRequestImpl.cleanUp();
229                    }
230            }
231    
232            protected void defineObjects(
233                            HttpServletRequest request, HttpServletResponse response,
234                            Portlet portlet)
235                    throws Exception {
236    
237                    String portletId = portlet.getPortletId();
238    
239                    ServletContext servletContext = (ServletContext)request.getAttribute(
240                            WebKeys.CTX);
241    
242                    InvokerPortlet invokerPortlet = PortletInstanceFactoryUtil.create(
243                            portlet, servletContext);
244    
245                    PortletPreferencesIds portletPreferencesIds =
246                            PortletPreferencesFactoryUtil.getPortletPreferencesIds(
247                                    request, portletId);
248    
249                    PortletPreferences portletPreferences =
250                            PortletPreferencesLocalServiceUtil.getStrictPreferences(
251                                    portletPreferencesIds);
252    
253                    PortletConfig portletConfig = PortletConfigFactoryUtil.create(
254                            portlet, servletContext);
255    
256                    PortletContext portletContext = portletConfig.getPortletContext();
257    
258                    RenderRequestImpl renderRequestImpl = RenderRequestFactory.create(
259                            request, portlet, invokerPortlet, portletContext,
260                            WindowState.MAXIMIZED, PortletMode.VIEW, portletPreferences);
261    
262                    RenderResponseImpl renderResponseImpl = RenderResponseFactory.create(
263                            renderRequestImpl, response, portletId, portlet.getCompanyId());
264    
265                    renderRequestImpl.defineObjects(portletConfig, renderResponseImpl);
266    
267                    request.setAttribute(WebKeys.PORTLET_STRUTS_EXECUTE, Boolean.TRUE);
268            }
269    
270            @Override
271            protected void doForward(
272                            String uri, HttpServletRequest request,
273                            HttpServletResponse response)
274                    throws ServletException {
275    
276                    StrutsUtil.forward(uri, getServletContext(), request, response);
277            }
278    
279            @Override
280            protected void doInclude(
281                            String uri, HttpServletRequest request,
282                            HttpServletResponse response)
283                    throws ServletException {
284    
285                    StrutsUtil.include(uri, getServletContext(), request, response);
286            }
287    
288            protected String getFriendlyTrackerPath(
289                            String path, ThemeDisplay themeDisplay, HttpServletRequest request)
290                    throws Exception {
291    
292                    if (!path.equals(_PATH_PORTAL_LAYOUT)) {
293                            return null;
294                    }
295    
296                    long plid = ParamUtil.getLong(request, "p_l_id");
297    
298                    if (plid == 0) {
299                            return null;
300                    }
301    
302                    Layout layout = LayoutLocalServiceUtil.getLayout(plid);
303    
304                    String layoutFriendlyURL = PortalUtil.getLayoutFriendlyURL(
305                            layout, themeDisplay);
306    
307                    String portletId = ParamUtil.getString(request, "p_p_id");
308    
309                    if (Validator.isNull(portletId)) {
310                            return layoutFriendlyURL;
311                    }
312    
313                    long companyId = PortalUtil.getCompanyId(request);
314    
315                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
316                            companyId, portletId);
317    
318                    if (portlet == null) {
319                            String strutsPath = path.substring(
320                                    1, path.lastIndexOf(CharPool.SLASH));
321    
322                            portlet = PortletLocalServiceUtil.getPortletByStrutsPath(
323                                    companyId, strutsPath);
324                    }
325    
326                    if ((portlet == null) || !portlet.isActive()) {
327                            return layoutFriendlyURL.concat(StringPool.QUESTION).concat(
328                                    request.getQueryString());
329                    }
330    
331                    String namespace = PortalUtil.getPortletNamespace(portletId);
332    
333                    FriendlyURLMapper friendlyURLMapper =
334                            portlet.getFriendlyURLMapperInstance();
335    
336                    if (friendlyURLMapper == null) {
337                            return layoutFriendlyURL.concat(StringPool.QUESTION).concat(
338                                    request.getQueryString());
339                    }
340    
341                    PortletURLImpl portletURL = new PortletURLImpl(
342                            request, portletId, plid, PortletRequest.RENDER_PHASE);
343    
344                    Map<String, String[]> parameterMap = request.getParameterMap();
345    
346                    for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
347                            String key = entry.getKey();
348    
349                            if (key.startsWith(namespace)) {
350                                    key = key.substring(namespace.length());
351    
352                                    portletURL.setParameter(key, entry.getValue());
353                            }
354                    }
355    
356                    String portletFriendlyURL = friendlyURLMapper.buildPath(portletURL);
357    
358                    if (portletFriendlyURL != null) {
359                            return layoutFriendlyURL.concat(portletFriendlyURL);
360                    }
361                    else {
362                            return layoutFriendlyURL.concat(StringPool.QUESTION).concat(
363                                    request.getQueryString());
364                    }
365            }
366    
367            protected String getLastPath(HttpServletRequest request) {
368                    HttpSession session = request.getSession();
369    
370                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
371                            WebKeys.THEME_DISPLAY);
372    
373                    Boolean httpsInitial = (Boolean)session.getAttribute(
374                            WebKeys.HTTPS_INITIAL);
375    
376                    String portalURL = null;
377    
378                    if (PropsValues.COMPANY_SECURITY_AUTH_REQUIRES_HTTPS &&
379                            !PropsValues.SESSION_ENABLE_PHISHING_PROTECTION &&
380                            (httpsInitial != null) && !httpsInitial.booleanValue()) {
381    
382                            portalURL = PortalUtil.getPortalURL(request, false);
383                    }
384                    else {
385                            portalURL = PortalUtil.getPortalURL(request);
386                    }
387    
388                    StringBundler sb = new StringBundler(7);
389    
390                    sb.append(portalURL);
391                    sb.append(themeDisplay.getPathMain());
392                    sb.append(_PATH_PORTAL_LAYOUT);
393    
394                    if (!PropsValues.AUTH_FORWARD_BY_LAST_PATH) {
395                            if (request.getRemoteUser() != null) {
396    
397                                    // If we do not forward by last path and the user is logged in,
398                                    // forward to the user's default layout to prevent a lagging
399                                    // loop
400    
401                                    sb.append(StringPool.QUESTION);
402                                    sb.append("p_l_id");
403                                    sb.append(StringPool.EQUAL);
404                                    sb.append(LayoutConstants.DEFAULT_PLID);
405                            }
406    
407                            return sb.toString();
408                    }
409    
410                    LastPath lastPath = (LastPath)session.getAttribute(WebKeys.LAST_PATH);
411    
412                    if (lastPath == null) {
413                            return sb.toString();
414                    }
415    
416                    String parameters = lastPath.getParameters();
417    
418                    // Only test for existing mappings for last paths that were set when the
419                    // user accessed a layout directly instead of through its friendly URL
420    
421                    if (lastPath.getContextPath().equals(themeDisplay.getPathMain())) {
422                            ActionMapping actionMapping =
423                                    (ActionMapping)moduleConfig.findActionConfig(
424                                            lastPath.getPath());
425    
426                            if ((actionMapping == null) || parameters.isEmpty()) {
427                                    return sb.toString();
428                            }
429                    }
430    
431                    StringBundler lastPathSB = new StringBundler(4);
432    
433                    lastPathSB.append(portalURL);
434                    lastPathSB.append(lastPath.getContextPath());
435                    lastPathSB.append(lastPath.getPath());
436                    lastPathSB.append(parameters);
437    
438                    return lastPathSB.toString();
439            }
440    
441            protected boolean isPortletPath(String path) {
442                    if ((path != null) && !path.equals(_PATH_C) &&
443                            !path.startsWith(_PATH_COMMON) &&
444                            !path.contains(_PATH_J_SECURITY_CHECK) &&
445                            !path.startsWith(_PATH_PORTAL)) {
446    
447                            return true;
448                    }
449                    else {
450                            return false;
451                    }
452            }
453    
454            protected boolean isPublicPath(String path) {
455                    if ((path != null) &&
456                            (_publicPaths.contains(path) || path.startsWith(_PATH_COMMON) ||
457                             AuthPublicPathRegistry.contains(path))) {
458    
459                            return true;
460                    }
461                    else {
462                            return false;
463                    }
464            }
465    
466            @Override
467            protected Action processActionCreate(
468                            HttpServletRequest request, HttpServletResponse response,
469                            ActionMapping actionMapping)
470                    throws IOException {
471    
472                    ActionAdapter actionAdapter =
473                            (ActionAdapter)StrutsActionRegistryUtil.getAction(
474                                    actionMapping.getPath());
475    
476                    if (actionAdapter != null) {
477                            ActionConfig actionConfig = moduleConfig.findActionConfig(
478                                    actionMapping.getPath());
479    
480                            if (actionConfig != null) {
481                                    Action originalAction = super.processActionCreate(
482                                            request, response, actionMapping);
483    
484                                    actionAdapter.setOriginalAction(originalAction);
485                            }
486    
487                            return actionAdapter;
488                    }
489    
490                    return super.processActionCreate(request, response, actionMapping);
491            }
492    
493            @Override
494            protected ActionMapping processMapping(
495                            HttpServletRequest request, HttpServletResponse response,
496                            String path)
497                    throws IOException {
498    
499                    if (path == null) {
500                            return null;
501                    }
502    
503                    Action action = StrutsActionRegistryUtil.getAction(path);
504    
505                    if (action != null) {
506                            ActionMapping actionMapping =
507                                    (ActionMapping)moduleConfig.findActionConfig(path);
508    
509                            if (actionMapping == null) {
510                                    actionMapping = new ActionMapping();
511    
512                                    actionMapping.setModuleConfig(moduleConfig);
513                                    actionMapping.setPath(path);
514    
515                                    request.setAttribute(Globals.MAPPING_KEY, actionMapping);
516                            }
517    
518                            return actionMapping;
519                    }
520    
521                    ActionMapping actionMapping = super.processMapping(
522                            request, response, path);
523    
524                    if (actionMapping == null) {
525                            MessageResources messageResources = getInternal();
526    
527                            String msg = messageResources.getMessage("processInvalid");
528    
529                            _log.error("User ID " + request.getRemoteUser());
530                            _log.error("Current URL " + PortalUtil.getCurrentURL(request));
531                            _log.error("Referer " + request.getHeader("Referer"));
532                            _log.error("Remote address " + request.getRemoteAddr());
533    
534                            _log.error(msg + " " + path);
535                    }
536    
537                    return actionMapping;
538            }
539    
540            @Override
541            protected HttpServletRequest processMultipart(HttpServletRequest request) {
542    
543                    // Disable Struts from automatically wrapping a multipart request
544    
545                    return request;
546            }
547    
548            @Override
549            protected String processPath(
550                            HttpServletRequest request, HttpServletResponse response)
551                    throws IOException {
552    
553                    String path = GetterUtil.getString(
554                            super.processPath(request, response));
555    
556                    HttpSession session = request.getSession();
557    
558                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
559                            WebKeys.THEME_DISPLAY);
560    
561                    // Current users
562    
563                    UserTracker userTracker = LiveUsers.getUserTracker(
564                            themeDisplay.getCompanyId(), session.getId());
565    
566                    if ((userTracker != null) && !path.equals(_PATH_C) &&
567                            !path.contains(_PATH_J_SECURITY_CHECK) &&
568                            !path.contains(_PATH_PORTAL_PROTECTED) &&
569                            !_trackerIgnorePaths.contains(path)) {
570    
571                            String fullPath = null;
572    
573                            try {
574                                    if (PropsValues.SESSION_TRACKER_FRIENDLY_PATHS_ENABLED) {
575                                            fullPath = getFriendlyTrackerPath(
576                                                    path, themeDisplay, request);
577                                    }
578                            }
579                            catch (Exception e) {
580                                    _log.error(e, e);
581                            }
582    
583                            String fullPathWithoutQueryString = fullPath;
584    
585                            if (Validator.isNull(fullPath)) {
586                                    String queryString = request.getQueryString();
587    
588                                    fullPathWithoutQueryString = path;
589    
590                                    if (Validator.isNotNull(queryString)) {
591                                            fullPath = path.concat(StringPool.QUESTION).concat(
592                                                    queryString);
593                                    }
594                                    else {
595                                            fullPath = path;
596                                    }
597                            }
598    
599                            int pos = fullPathWithoutQueryString.indexOf(StringPool.QUESTION);
600    
601                            if (pos != -1) {
602                                    fullPathWithoutQueryString =
603                                            fullPathWithoutQueryString.substring(0, pos);
604                            }
605    
606                            if (!_trackerIgnorePaths.contains(fullPathWithoutQueryString)) {
607                                    UserTrackerPath userTrackerPath = UserTrackerPathUtil.create(0);
608    
609                                    userTrackerPath.setUserTrackerId(
610                                            userTracker.getUserTrackerId());
611                                    userTrackerPath.setPath(fullPath);
612                                    userTrackerPath.setPathDate(new Date());
613    
614                                    userTracker.addPath(userTrackerPath);
615                            }
616                    }
617    
618                    String remoteUser = request.getRemoteUser();
619    
620                    User user = null;
621    
622                    try {
623                            user = PortalUtil.getUser(request);
624                    }
625                    catch (Exception e) {
626                    }
627    
628                    // Last path
629    
630                    if (_lastPaths.contains(path) && !_trackerIgnorePaths.contains(path)) {
631                            boolean saveLastPath = ParamUtil.getBoolean(
632                                    request, "saveLastPath", true);
633    
634                            if (themeDisplay.isLifecycleResource() ||
635                                    themeDisplay.isStateExclusive() ||
636                                    themeDisplay.isStatePopUp() ||
637                                    !StringUtil.equalsIgnoreCase(
638                                            request.getMethod(), HttpMethods.GET)) {
639    
640                                    saveLastPath = false;
641                            }
642    
643                            // Save last path
644    
645                            if (saveLastPath) {
646    
647                                    // Was a last path set by another servlet that dispatched to the
648                                    // MainServlet? If so, use that last path instead.
649    
650                                    LastPath lastPath = (LastPath)request.getAttribute(
651                                            WebKeys.LAST_PATH);
652    
653                                    if (lastPath == null) {
654                                            lastPath = new LastPath(
655                                                    themeDisplay.getPathMain(), path,
656                                                    HttpUtil.parameterMapToString(
657                                                            request.getParameterMap()));
658                                    }
659    
660                                    session.setAttribute(WebKeys.LAST_PATH, lastPath);
661                            }
662                    }
663    
664                    // Setup wizard
665    
666                    if (PropsValues.SETUP_WIZARD_ENABLED) {
667                            if (!path.equals(_PATH_PORTAL_LICENSE) &&
668                                    !path.equals(_PATH_PORTAL_STATUS)) {
669    
670                                    return _PATH_PORTAL_SETUP_WIZARD;
671                            }
672                    }
673                    else if (path.equals(_PATH_PORTAL_SETUP_WIZARD)) {
674                            return _PATH_PORTAL_LAYOUT;
675                    }
676    
677                    // Authenticated users can always log out
678    
679                    if (((remoteUser != null) || (user != null)) &&
680                            path.equals(_PATH_PORTAL_LOGOUT)) {
681    
682                            return path;
683                    }
684    
685                    // Authenticated users can always extend or confirm their session
686    
687                    if (((remoteUser != null) || (user != null)) &&
688                            (path.equals(_PATH_PORTAL_EXPIRE_SESSION) ||
689                             path.equals(_PATH_PORTAL_EXTEND_SESSION))) {
690    
691                            return path;
692                    }
693    
694                    // Authenticated users can always agree to terms of use
695    
696                    if (((remoteUser != null) || (user != null)) &&
697                            path.equals(_PATH_PORTAL_UPDATE_TERMS_OF_USE)) {
698    
699                            return path;
700                    }
701    
702                    // Authenticated users must still exist in the system
703    
704                    if ((remoteUser != null) && (user == null)) {
705                            return _PATH_PORTAL_LOGOUT;
706                    }
707    
708                    // Authenticated users must be active
709    
710                    if ((user != null) && !user.isActive()) {
711                            SessionErrors.add(request, UserActiveException.class.getName());
712    
713                            return _PATH_PORTAL_ERROR;
714                    }
715    
716                    long companyId = PortalUtil.getCompanyId(request);
717                    String portletId = ParamUtil.getString(request, "p_p_id");
718    
719                    if (!path.equals(_PATH_PORTAL_JSON_SERVICE) &&
720                            !path.equals(_PATH_PORTAL_RENDER_PORTLET) &&
721                            !ParamUtil.getBoolean(request, "wsrp") &&
722                            !themeDisplay.isImpersonated() &&
723                            !InterruptedPortletRequestWhitelistUtil.
724                                    isPortletInvocationWhitelisted(
725                                            companyId, portletId,
726                                            PortalUtil.getStrutsAction(request))) {
727    
728                            // Authenticated users should agree to Terms of Use
729    
730                            if ((user != null) && !user.isTermsOfUseComplete()) {
731                                    return _PATH_PORTAL_TERMS_OF_USE;
732                            }
733    
734                            // Authenticated users should have a verified email address
735    
736                            if ((user != null) && !user.isEmailAddressVerificationComplete()) {
737                                    if (path.equals(_PATH_PORTAL_UPDATE_EMAIL_ADDRESS)) {
738                                            return _PATH_PORTAL_UPDATE_EMAIL_ADDRESS;
739                                    }
740    
741                                    return _PATH_PORTAL_VERIFY_EMAIL_ADDRESS;
742                            }
743    
744                            // Authenticated users must have a current password
745    
746                            if ((user != null) && user.isPasswordReset()) {
747                                    try {
748                                            PasswordPolicy passwordPolicy = user.getPasswordPolicy();
749    
750                                            if ((passwordPolicy == null) ||
751                                                    passwordPolicy.isChangeRequired()) {
752    
753                                                    return _PATH_PORTAL_UPDATE_PASSWORD;
754                                            }
755                                    }
756                                    catch (Exception e) {
757                                            _log.error(e, e);
758    
759                                            return _PATH_PORTAL_UPDATE_PASSWORD;
760                                    }
761                            }
762                            else if ((user != null) && !user.isPasswordReset() &&
763                                             path.equals(_PATH_PORTAL_UPDATE_PASSWORD)) {
764    
765                                    return null;
766                            }
767    
768                            // Authenticated users must have an email address
769    
770                            if ((user != null) && !user.isEmailAddressComplete()) {
771                                    return _PATH_PORTAL_UPDATE_EMAIL_ADDRESS;
772                            }
773    
774                            // Authenticated users should have a reminder query
775    
776                            if ((user != null) && !user.isDefaultUser() &&
777                                    !user.isReminderQueryComplete()) {
778    
779                                    return _PATH_PORTAL_UPDATE_REMINDER_QUERY;
780                            }
781                    }
782    
783                    // Users must sign in
784    
785                    if (!isPublicPath(path)) {
786                            if (user == null) {
787                                    SessionErrors.add(request, PrincipalException.class.getName());
788    
789                                    return _PATH_PORTAL_LOGIN;
790                            }
791                    }
792    
793                    ActionMapping actionMapping =
794                            (ActionMapping)moduleConfig.findActionConfig(path);
795    
796                    if (actionMapping == null) {
797                            Action strutsAction = StrutsActionRegistryUtil.getAction(path);
798    
799                            if (strutsAction == null) {
800                                    return null;
801                            }
802                    }
803                    else {
804                            path = actionMapping.getPath();
805                    }
806    
807                    // Define the portlet objects
808    
809                    if (isPortletPath(path)) {
810                            try {
811                                    Portlet portlet = null;
812    
813                                    if (Validator.isNotNull(portletId)) {
814                                            portlet = PortletLocalServiceUtil.getPortletById(
815                                                    companyId, portletId);
816                                    }
817    
818                                    if (portlet == null) {
819                                            String strutsPath = path.substring(
820                                                    1, path.lastIndexOf(CharPool.SLASH));
821    
822                                            portlet = PortletLocalServiceUtil.getPortletByStrutsPath(
823                                                    companyId, strutsPath);
824                                    }
825    
826                                    if ((portlet != null) && portlet.isActive()) {
827                                            defineObjects(request, response, portlet);
828                                    }
829                            }
830                            catch (Exception e) {
831                                    request.setAttribute(PageContext.EXCEPTION, e);
832    
833                                    path = _PATH_COMMON_ERROR;
834                            }
835                    }
836    
837                    // Authenticated users must have access to at least one layout
838    
839                    if (SessionErrors.contains(
840                                    request, LayoutPermissionException.class.getName())) {
841    
842                            return _PATH_PORTAL_ERROR;
843                    }
844    
845                    return path;
846            }
847    
848            @Override
849            protected void processPopulate(
850                            HttpServletRequest request, HttpServletResponse response,
851                            ActionForm actionForm, ActionMapping actionMapping)
852                    throws ServletException {
853    
854                    if (actionForm == null) {
855                            return;
856                    }
857    
858                    boolean hasIgnoredParameter = false;
859    
860                    Map<String, String[]> oldParameterMap = request.getParameterMap();
861    
862                    Map<String, String[]> newParameterMap = new LinkedHashMap<>(
863                            oldParameterMap.size());
864    
865                    for (Map.Entry<String, String[]> entry : oldParameterMap.entrySet()) {
866                            String name = entry.getKey();
867    
868                            Matcher matcher = _strutsPortletIgnoredParamtersPattern.matcher(
869                                    name);
870    
871                            if (matcher.matches()) {
872                                    hasIgnoredParameter = true;
873                            }
874                            else {
875                                    newParameterMap.put(name, entry.getValue());
876                            }
877                    }
878    
879                    if (hasIgnoredParameter) {
880                            request = new DynamicServletRequest(
881                                    request, newParameterMap, false);
882                    }
883    
884                    super.processPopulate(request, response, actionForm, actionMapping);
885            }
886    
887            @Override
888            protected boolean processRoles(
889                            HttpServletRequest request, HttpServletResponse response,
890                            ActionMapping actionMapping)
891                    throws IOException, ServletException {
892    
893                    String path = actionMapping.getPath();
894    
895                    if (isPublicPath(path)) {
896                            return true;
897                    }
898    
899                    boolean authorized = true;
900    
901                    User user = null;
902    
903                    try {
904                            user = PortalUtil.getUser(request);
905                    }
906                    catch (Exception e) {
907                    }
908    
909                    if ((user != null) && isPortletPath(path)) {
910                            try {
911    
912                                    // Authenticated users can always log out
913    
914                                    if (path.equals(_PATH_PORTAL_LOGOUT)) {
915                                            return true;
916                                    }
917    
918                                    Portlet portlet = null;
919    
920                                    String portletId = ParamUtil.getString(request, "p_p_id");
921    
922                                    if (Validator.isNotNull(portletId)) {
923                                            portlet = PortletLocalServiceUtil.getPortletById(
924                                                    user.getCompanyId(), portletId);
925                                    }
926    
927                                    String strutsPath = path.substring(
928                                            1, path.lastIndexOf(CharPool.SLASH));
929    
930                                    if (portlet != null) {
931                                            if (!strutsPath.equals(portlet.getStrutsPath())) {
932                                                    throw new PrincipalException.MustBePortletStrutsPath(
933                                                            strutsPath, portletId);
934                                            }
935                                    }
936                                    else {
937                                            portlet = PortletLocalServiceUtil.getPortletByStrutsPath(
938                                                    user.getCompanyId(), strutsPath);
939                                    }
940    
941                                    if ((portlet != null) && portlet.isActive() &&
942                                            !portlet.isSystem()) {
943    
944                                            ThemeDisplay themeDisplay =
945                                                    (ThemeDisplay)request.getAttribute(
946                                                            WebKeys.THEME_DISPLAY);
947    
948                                            Layout layout = themeDisplay.getLayout();
949                                            PermissionChecker permissionChecker =
950                                                    themeDisplay.getPermissionChecker();
951    
952                                            if (!PortletPermissionUtil.contains(
953                                                            permissionChecker, layout, portlet,
954                                                            ActionKeys.VIEW)) {
955    
956                                                    throw new PrincipalException.MustHavePermission(
957                                                            permissionChecker, Portlet.class.getName(),
958                                                            portlet.getPortletId(), ActionKeys.VIEW);
959                                            }
960                                    }
961                                    else if ((portlet != null) && !portlet.isActive()) {
962                                            SessionErrors.add(
963                                                    request, PortletActiveException.class.getName());
964    
965                                            authorized = false;
966                                    }
967                            }
968                            catch (Exception e) {
969                                    SessionErrors.add(request, PrincipalException.class.getName());
970    
971                                    authorized = false;
972                            }
973                    }
974    
975                    if (!authorized) {
976                            ForwardConfig forwardConfig = actionMapping.findForward(
977                                    _PATH_PORTAL_ERROR);
978    
979                            processForwardConfig(request, response, forwardConfig);
980    
981                            return false;
982                    }
983                    else {
984                            return true;
985                    }
986            }
987    
988            private static final String _PATH_C = "/c";
989    
990            private static final String _PATH_COMMON = "/common";
991    
992            private static final String _PATH_COMMON_ERROR = "/common/error";
993    
994            private static final String _PATH_J_SECURITY_CHECK = "/j_security_check";
995    
996            private static final String _PATH_PORTAL = "/portal";
997    
998            private static final String _PATH_PORTAL_API_JSONWS = "/portal/api/jsonws";
999    
1000            private static final String _PATH_PORTAL_ERROR = "/portal/error";
1001    
1002            private static final String _PATH_PORTAL_EXPIRE_SESSION =
1003                    "/portal/expire_session";
1004    
1005            private static final String _PATH_PORTAL_EXTEND_SESSION =
1006                    "/portal/extend_session";
1007    
1008            private static final String _PATH_PORTAL_FLASH = "/portal/flash";
1009    
1010            private static final String _PATH_PORTAL_J_LOGIN = "/portal/j_login";
1011    
1012            private static final String _PATH_PORTAL_JSON_SERVICE =
1013                    "/portal/json_service";
1014    
1015            private static final String _PATH_PORTAL_LAYOUT = "/portal/layout";
1016    
1017            private static final String _PATH_PORTAL_LICENSE = "/portal/license";
1018    
1019            private static final String _PATH_PORTAL_LOGIN = "/portal/login";
1020    
1021            private static final String _PATH_PORTAL_LOGOUT = "/portal/logout";
1022    
1023            private static final String _PATH_PORTAL_PROTECTED = "/portal/protected";
1024    
1025            private static final String _PATH_PORTAL_RENDER_PORTLET =
1026                    "/portal/render_portlet";
1027    
1028            private static final String _PATH_PORTAL_RESILIENCY = "/portal/resiliency";
1029    
1030            private static final String _PATH_PORTAL_SETUP_WIZARD =
1031                    "/portal/setup_wizard";
1032    
1033            private static final String _PATH_PORTAL_STATUS = "/portal/status";
1034    
1035            private static final String _PATH_PORTAL_TCK = "/portal/tck";
1036    
1037            private static final String _PATH_PORTAL_TERMS_OF_USE =
1038                    "/portal/terms_of_use";
1039    
1040            private static final String _PATH_PORTAL_UPDATE_EMAIL_ADDRESS =
1041                    "/portal/update_email_address";
1042    
1043            private static final String _PATH_PORTAL_UPDATE_LANGUAGE =
1044                    "/portal/update_language";
1045    
1046            private static final String _PATH_PORTAL_UPDATE_PASSWORD =
1047                    "/portal/update_password";
1048    
1049            private static final String _PATH_PORTAL_UPDATE_REMINDER_QUERY =
1050                    "/portal/update_reminder_query";
1051    
1052            private static final String _PATH_PORTAL_UPDATE_TERMS_OF_USE =
1053                    "/portal/update_terms_of_use";
1054    
1055            private static final String _PATH_PORTAL_VERIFY_EMAIL_ADDRESS =
1056                    "/portal/verify_email_address";
1057    
1058            private static final Log _log = LogFactoryUtil.getLog(
1059                    PortalRequestProcessor.class);
1060    
1061            private static final Pattern _strutsPortletIgnoredParamtersPattern =
1062                    Pattern.compile(PropsValues.STRUTS_PORTLET_IGNORED_PARAMETERS_REGEXP);
1063    
1064            private final Set<String> _lastPaths;
1065            private final Set<String> _publicPaths;
1066            private final Set<String> _trackerIgnorePaths;
1067    
1068    }