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