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