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