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