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.portlet;
016    
017    import com.liferay.portal.kernel.exception.SystemException;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
021    import com.liferay.portal.kernel.portlet.LiferayPortletConfig;
022    import com.liferay.portal.kernel.portlet.LiferayPortletURL;
023    import com.liferay.portal.kernel.portlet.LiferayWindowState;
024    import com.liferay.portal.kernel.portlet.PortletModeFactory;
025    import com.liferay.portal.kernel.portlet.PortletProvider;
026    import com.liferay.portal.kernel.portlet.PortletProviderUtil;
027    import com.liferay.portal.kernel.portlet.WindowStateFactory;
028    import com.liferay.portal.kernel.util.ArrayUtil;
029    import com.liferay.portal.kernel.util.Base64;
030    import com.liferay.portal.kernel.util.CharPool;
031    import com.liferay.portal.kernel.util.CookieKeys;
032    import com.liferay.portal.kernel.util.GetterUtil;
033    import com.liferay.portal.kernel.util.HtmlUtil;
034    import com.liferay.portal.kernel.util.Http;
035    import com.liferay.portal.kernel.util.HttpUtil;
036    import com.liferay.portal.kernel.util.MapUtil;
037    import com.liferay.portal.kernel.util.ParamUtil;
038    import com.liferay.portal.kernel.util.StringBundler;
039    import com.liferay.portal.kernel.util.StringPool;
040    import com.liferay.portal.kernel.util.Validator;
041    import com.liferay.portal.kernel.xml.QName;
042    import com.liferay.portal.model.Company;
043    import com.liferay.portal.model.Layout;
044    import com.liferay.portal.model.LayoutTypePortlet;
045    import com.liferay.portal.model.Portlet;
046    import com.liferay.portal.model.PortletApp;
047    import com.liferay.portal.model.PublicRenderParameter;
048    import com.liferay.portal.model.impl.VirtualLayout;
049    import com.liferay.portal.security.auth.AuthTokenUtil;
050    import com.liferay.portal.security.auth.AuthTokenWhitelistUtil;
051    import com.liferay.portal.security.lang.DoPrivilegedUtil;
052    import com.liferay.portal.service.LayoutLocalServiceUtil;
053    import com.liferay.portal.service.PortletLocalServiceUtil;
054    import com.liferay.portal.theme.PortletDisplay;
055    import com.liferay.portal.theme.ThemeDisplay;
056    import com.liferay.portal.util.PortalUtil;
057    import com.liferay.portal.util.PropsValues;
058    import com.liferay.portal.util.WebKeys;
059    import com.liferay.portlet.admin.util.PortalProductMenuApplicationType;
060    import com.liferay.portlet.social.util.FacebookUtil;
061    import com.liferay.util.Encryptor;
062    import com.liferay.util.EncryptorException;
063    
064    import java.io.IOException;
065    import java.io.Serializable;
066    import java.io.UnsupportedEncodingException;
067    import java.io.Writer;
068    
069    import java.security.Key;
070    import java.security.PrivilegedAction;
071    
072    import java.util.Collections;
073    import java.util.LinkedHashMap;
074    import java.util.LinkedHashSet;
075    import java.util.Map;
076    import java.util.Set;
077    
078    import javax.portlet.PortletMode;
079    import javax.portlet.PortletModeException;
080    import javax.portlet.PortletRequest;
081    import javax.portlet.PortletURL;
082    import javax.portlet.ResourceRequest;
083    import javax.portlet.ResourceURL;
084    import javax.portlet.WindowState;
085    import javax.portlet.WindowStateException;
086    
087    import javax.servlet.http.HttpServletRequest;
088    
089    /**
090     * @author Brian Wing Shun Chan
091     * @author Jorge Ferrer
092     * @author Connor McKay
093     */
094    public class PortletURLImpl
095            implements LiferayPortletURL, PortletURL, ResourceURL, Serializable {
096    
097            public PortletURLImpl(
098                    HttpServletRequest request, String portletId, Layout layout,
099                    String lifecycle) {
100    
101                    this(request, portletId, null, layout.getPlid(), lifecycle);
102    
103                    _layout = layout;
104            }
105    
106            public PortletURLImpl(
107                    HttpServletRequest request, String portletId, long plid,
108                    String lifecycle) {
109    
110                    this(request, portletId, null, plid, lifecycle);
111            }
112    
113            public PortletURLImpl(
114                    PortletRequest portletRequest, String portletId, Layout layout,
115                    String lifecycle) {
116    
117                    this(
118                            PortalUtil.getHttpServletRequest(portletRequest), portletId,
119                            portletRequest, layout.getPlid(), lifecycle);
120    
121                    _layout = layout;
122            }
123    
124            public PortletURLImpl(
125                    PortletRequest portletRequest, String portletId, long plid,
126                    String lifecycle) {
127    
128                    this(
129                            PortalUtil.getHttpServletRequest(portletRequest), portletId,
130                            portletRequest, plid, lifecycle);
131            }
132    
133            @Override
134            public void addParameterIncludedInPath(String name) {
135                    _parametersIncludedInPath.add(name);
136            }
137    
138            @Override
139            public void addProperty(String key, String value) {
140                    if (key == null) {
141                            throw new IllegalArgumentException();
142                    }
143            }
144    
145            @Override
146            public String getCacheability() {
147                    return _cacheability;
148            }
149    
150            public HttpServletRequest getHttpServletRequest() {
151                    return _request;
152            }
153    
154            public Layout getLayout() {
155                    if (_layout == null) {
156                            try {
157                                    if (_plid > 0) {
158                                            _layout = LayoutLocalServiceUtil.getLayout(_plid);
159                                    }
160                            }
161                            catch (Exception e) {
162                                    if (_log.isWarnEnabled()) {
163                                            _log.warn("Layout cannot be found for " + _plid);
164                                    }
165                            }
166                    }
167    
168                    return _layout;
169            }
170    
171            public String getLayoutFriendlyURL() {
172                    return _layoutFriendlyURL;
173            }
174    
175            @Override
176            public String getLifecycle() {
177                    return _lifecycle;
178            }
179    
180            public String getNamespace() {
181                    if (_namespace == null) {
182                            _namespace = PortalUtil.getPortletNamespace(_portletId);
183                    }
184    
185                    return _namespace;
186            }
187    
188            @Override
189            public String getParameter(String name) {
190                    String[] values = _params.get(name);
191    
192                    if (ArrayUtil.isNotEmpty(values)) {
193                            return values[0];
194                    }
195                    else {
196                            return null;
197                    }
198            }
199    
200            @Override
201            public Map<String, String[]> getParameterMap() {
202                    return _params;
203            }
204    
205            @Override
206            public Set<String> getParametersIncludedInPath() {
207                    return _parametersIncludedInPath;
208            }
209    
210            public long getPlid() {
211                    return _plid;
212            }
213    
214            public Portlet getPortlet() {
215                    if (_portlet == null) {
216                            try {
217                                    _portlet = PortletLocalServiceUtil.getPortletById(
218                                            PortalUtil.getCompanyId(_request), _portletId);
219                            }
220                            catch (SystemException se) {
221                                    _log.error(se.getMessage());
222                            }
223                    }
224    
225                    return _portlet;
226            }
227    
228            public String getPortletFriendlyURLPath() {
229                    String portletFriendlyURLPath = null;
230    
231                    Portlet portlet = getPortlet();
232    
233                    if (portlet != null) {
234                            if (portlet.isUndeployedPortlet()) {
235                                    return portletFriendlyURLPath;
236                            }
237    
238                            FriendlyURLMapper friendlyURLMapper =
239                                    portlet.getFriendlyURLMapperInstance();
240    
241                            if (friendlyURLMapper != null) {
242                                    portletFriendlyURLPath = friendlyURLMapper.buildPath(this);
243    
244                                    if (_log.isDebugEnabled()) {
245                                            _log.debug(
246                                                    "Portlet friendly URL path " + portletFriendlyURLPath);
247                                    }
248                            }
249                    }
250    
251                    return portletFriendlyURLPath;
252            }
253    
254            @Override
255            public String getPortletId() {
256                    return _portletId;
257            }
258    
259            @Override
260            public PortletMode getPortletMode() {
261                    if (_portletModeString == null) {
262                            return null;
263                    }
264    
265                    return PortletModeFactory.getPortletMode(_portletModeString);
266            }
267    
268            public PortletRequest getPortletRequest() {
269                    return _portletRequest;
270            }
271    
272            @Override
273            public Set<String> getRemovedParameterNames() {
274                    return _removedParameterNames;
275            }
276    
277            @Override
278            public Map<String, String> getReservedParameterMap() {
279                    if (_reservedParameters != null) {
280                            return _reservedParameters;
281                    }
282    
283                    _reservedParameters = new LinkedHashMap<>();
284    
285                    _reservedParameters.put("p_p_id", _portletId);
286    
287                    if (_lifecycle.equals(PortletRequest.ACTION_PHASE)) {
288                            _reservedParameters.put("p_p_lifecycle", "1");
289                    }
290                    else if (_lifecycle.equals(PortletRequest.RENDER_PHASE)) {
291                            _reservedParameters.put("p_p_lifecycle", "0");
292                    }
293                    else if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
294                            _reservedParameters.put("p_p_lifecycle", "2");
295                    }
296    
297                    if (_windowStateString != null) {
298                            _reservedParameters.put("p_p_state", _windowStateString);
299                    }
300    
301                    if (_windowStateRestoreCurrentView) {
302                            _reservedParameters.put("p_p_state_rcv", "1");
303                    }
304    
305                    if (_portletModeString != null) {
306                            _reservedParameters.put("p_p_mode", _portletModeString);
307                    }
308    
309                    if (_resourceID != null) {
310                            _reservedParameters.put("p_p_resource_id", _resourceID);
311                    }
312    
313                    if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
314                            _reservedParameters.put("p_p_cacheability", _cacheability);
315                    }
316    
317                    ThemeDisplay themeDisplay = (ThemeDisplay)_request.getAttribute(
318                            WebKeys.THEME_DISPLAY);
319    
320                    PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
321    
322                    if (Validator.isNotNull(portletDisplay.getColumnId())) {
323                            _reservedParameters.put("p_p_col_id", portletDisplay.getColumnId());
324                    }
325    
326                    if (portletDisplay.getColumnPos() > 0) {
327                            _reservedParameters.put(
328                                    "p_p_col_pos", String.valueOf(portletDisplay.getColumnPos()));
329                    }
330    
331                    if (portletDisplay.getColumnCount() > 0) {
332                            _reservedParameters.put(
333                                    "p_p_col_count",
334                                    String.valueOf(portletDisplay.getColumnCount()));
335                    }
336    
337                    _reservedParameters = Collections.unmodifiableMap(_reservedParameters);
338    
339                    return _reservedParameters;
340            }
341    
342            @Override
343            public String getResourceID() {
344                    return _resourceID;
345            }
346    
347            @Override
348            public WindowState getWindowState() {
349                    if (_windowStateString == null) {
350                            return null;
351                    }
352    
353                    return WindowStateFactory.getWindowState(_windowStateString);
354            }
355    
356            @Override
357            public boolean isAnchor() {
358                    return _anchor;
359            }
360    
361            @Override
362            public boolean isCopyCurrentRenderParameters() {
363                    return _copyCurrentRenderParameters;
364            }
365    
366            @Override
367            public boolean isEncrypt() {
368                    return _encrypt;
369            }
370    
371            @Override
372            public boolean isEscapeXml() {
373                    return _escapeXml;
374            }
375    
376            @Override
377            public boolean isParameterIncludedInPath(String name) {
378                    if (_parametersIncludedInPath.contains(name)) {
379                            return true;
380                    }
381                    else {
382                            return false;
383                    }
384            }
385    
386            @Override
387            public boolean isSecure() {
388                    return _secure;
389            }
390    
391            @Override
392            public void removePublicRenderParameter(String name) {
393                    if (name == null) {
394                            throw new IllegalArgumentException();
395                    }
396    
397                    Portlet portlet = getPortlet();
398    
399                    if (portlet == null) {
400                            return;
401                    }
402    
403                    PublicRenderParameter publicRenderParameter =
404                            portlet.getPublicRenderParameter(name);
405    
406                    if (publicRenderParameter == null) {
407                            if (_log.isWarnEnabled()) {
408                                    _log.warn("Public parameter " + name + "does not exist");
409                            }
410    
411                            return;
412                    }
413    
414                    QName qName = publicRenderParameter.getQName();
415    
416                    _removePublicRenderParameters.put(
417                            PortletQNameUtil.getRemovePublicRenderParameterName(qName),
418                            new String[] {"1"});
419            }
420    
421            @Override
422            public void setAnchor(boolean anchor) {
423                    _anchor = anchor;
424    
425                    clearCache();
426            }
427    
428            @Override
429            public void setCacheability(String cacheability) {
430                    if (cacheability == null) {
431                            throw new IllegalArgumentException("Cacheability is null");
432                    }
433    
434                    if (!cacheability.equals(FULL) && !cacheability.equals(PORTLET) &&
435                            !cacheability.equals(PAGE)) {
436    
437                            throw new IllegalArgumentException(
438                                    "Cacheability " + cacheability + " is not " + FULL + ", " +
439                                            PORTLET + ", or " + PAGE);
440                    }
441    
442                    if (_portletRequest instanceof ResourceRequest) {
443                            ResourceRequest resourceRequest = (ResourceRequest)_portletRequest;
444    
445                            String parentCacheability = resourceRequest.getCacheability();
446    
447                            if (parentCacheability.equals(FULL)) {
448                                    if (!cacheability.equals(FULL)) {
449                                            throw new IllegalStateException(
450                                                    "Unable to set a weaker cacheability " + cacheability);
451                                    }
452                            }
453                            else if (parentCacheability.equals(PORTLET)) {
454                                    if (!cacheability.equals(FULL) &&
455                                            !cacheability.equals(PORTLET)) {
456    
457                                            throw new IllegalStateException(
458                                                    "Unable to set a weaker cacheability " + cacheability);
459                                    }
460                            }
461                    }
462    
463                    _cacheability = cacheability;
464    
465                    clearCache();
466            }
467    
468            @Override
469            public void setCopyCurrentRenderParameters(
470                    boolean copyCurrentRenderParameters) {
471    
472                    _copyCurrentRenderParameters = copyCurrentRenderParameters;
473            }
474    
475            @Override
476            public void setDoAsGroupId(long doAsGroupId) {
477                    _doAsGroupId = doAsGroupId;
478    
479                    clearCache();
480            }
481    
482            @Override
483            public void setDoAsUserId(long doAsUserId) {
484                    _doAsUserId = doAsUserId;
485    
486                    clearCache();
487            }
488    
489            @Override
490            public void setDoAsUserLanguageId(String doAsUserLanguageId) {
491                    _doAsUserLanguageId = doAsUserLanguageId;
492    
493                    clearCache();
494            }
495    
496            @Override
497            public void setEncrypt(boolean encrypt) {
498                    _encrypt = encrypt;
499    
500                    clearCache();
501            }
502    
503            @Override
504            public void setEscapeXml(boolean escapeXml) {
505                    _escapeXml = escapeXml;
506    
507                    clearCache();
508            }
509    
510            @Override
511            public void setLifecycle(String lifecycle) {
512                    _lifecycle = lifecycle;
513    
514                    clearCache();
515            }
516    
517            @Override
518            public void setParameter(String name, String value) {
519                    setParameter(name, value, PropsValues.PORTLET_URL_APPEND_PARAMETERS);
520            }
521    
522            @Override
523            public void setParameter(String name, String value, boolean append) {
524                    if ((name == null) || (value == null)) {
525                            throw new IllegalArgumentException();
526                    }
527    
528                    setParameter(name, new String[] {value}, append);
529            }
530    
531            @Override
532            public void setParameter(String name, String[] values) {
533                    setParameter(name, values, PropsValues.PORTLET_URL_APPEND_PARAMETERS);
534            }
535    
536            @Override
537            public void setParameter(String name, String[] values, boolean append) {
538                    if ((name == null) || (values == null)) {
539                            throw new IllegalArgumentException();
540                    }
541    
542                    for (String value : values) {
543                            if (value == null) {
544                                    throw new IllegalArgumentException();
545                            }
546                    }
547    
548                    if (!append) {
549                            _params.put(name, values);
550                    }
551                    else {
552                            String[] oldValues = _params.get(name);
553    
554                            if (oldValues == null) {
555                                    _params.put(name, values);
556                            }
557                            else {
558                                    String[] newValues = ArrayUtil.append(oldValues, values);
559    
560                                    _params.put(name, newValues);
561                            }
562                    }
563    
564                    clearCache();
565            }
566    
567            @Override
568            public void setParameters(Map<String, String[]> params) {
569                    if (params == null) {
570                            throw new IllegalArgumentException();
571                    }
572                    else {
573                            Map<String, String[]> newParams = new LinkedHashMap<>();
574    
575                            for (Map.Entry<String, String[]> entry : params.entrySet()) {
576                                    try {
577                                            String key = entry.getKey();
578                                            String[] value = entry.getValue();
579    
580                                            if (key == null) {
581                                                    throw new IllegalArgumentException();
582                                            }
583                                            else if (value == null) {
584                                                    throw new IllegalArgumentException();
585                                            }
586    
587                                            newParams.put(key, value);
588                                    }
589                                    catch (ClassCastException cce) {
590                                            throw new IllegalArgumentException(cce);
591                                    }
592                            }
593    
594                            _params = newParams;
595                    }
596    
597                    clearCache();
598            }
599    
600            @Override
601            public void setPlid(long plid) {
602                    _plid = plid;
603    
604                    clearCache();
605            }
606    
607            @Override
608            public void setPortletId(String portletId) {
609                    _portletId = portletId;
610    
611                    clearCache();
612            }
613    
614            @Override
615            public void setPortletMode(PortletMode portletMode)
616                    throws PortletModeException {
617    
618                    if (_portletRequest != null) {
619                            Portlet portlet = getPortlet();
620    
621                            if ((portlet != null) &&
622                                    !portlet.hasPortletMode(
623                                            _portletRequest.getResponseContentType(), portletMode)) {
624    
625                                    throw new PortletModeException(
626                                            portletMode.toString(), portletMode);
627                            }
628                    }
629    
630                    _portletModeString = portletMode.toString();
631    
632                    clearCache();
633            }
634    
635            public void setPortletMode(String portletMode) throws PortletModeException {
636                    setPortletMode(PortletModeFactory.getPortletMode(portletMode));
637            }
638    
639            @Override
640            public void setProperty(String key, String value) {
641                    if (key == null) {
642                            throw new IllegalArgumentException();
643                    }
644            }
645    
646            public void setRefererGroupId(long refererGroupId) {
647                    _refererGroupId = refererGroupId;
648    
649                    clearCache();
650            }
651    
652            @Override
653            public void setRefererPlid(long refererPlid) {
654                    _refererPlid = refererPlid;
655    
656                    clearCache();
657            }
658    
659            @Override
660            public void setRemovedParameterNames(Set<String> removedParameterNames) {
661                    _removedParameterNames = removedParameterNames;
662    
663                    clearCache();
664            }
665    
666            @Override
667            public void setResourceID(String resourceID) {
668                    _resourceID = resourceID;
669            }
670    
671            @Override
672            public void setSecure(boolean secure) {
673                    _secure = secure;
674    
675                    clearCache();
676            }
677    
678            public void setWindowState(String windowState) throws WindowStateException {
679                    setWindowState(WindowStateFactory.getWindowState(windowState));
680            }
681    
682            @Override
683            public void setWindowState(WindowState windowState)
684                    throws WindowStateException {
685    
686                    if (_portletRequest != null) {
687                            if (!_portletRequest.isWindowStateAllowed(windowState)) {
688                                    throw new WindowStateException(
689                                            windowState.toString(), windowState);
690                            }
691                    }
692    
693                    if (LiferayWindowState.isWindowStatePreserved(
694                                    getWindowState(), windowState)) {
695    
696                            _windowStateString = windowState.toString();
697                    }
698    
699                    clearCache();
700            }
701    
702            public void setWindowStateRestoreCurrentView(
703                    boolean windowStateRestoreCurrentView) {
704    
705                    _windowStateRestoreCurrentView = windowStateRestoreCurrentView;
706            }
707    
708            @Override
709            public String toString() {
710                    if (_toString != null) {
711                            return _toString;
712                    }
713    
714                    _toString = DoPrivilegedUtil.wrap(new ToStringPrivilegedAction());
715    
716                    return _toString;
717            }
718    
719            @Override
720            public void write(Writer writer) throws IOException {
721                    write(writer, _escapeXml);
722            }
723    
724            @Override
725            public void write(Writer writer, boolean escapeXml) throws IOException {
726                    String toString = toString();
727    
728                    if (escapeXml && !_escapeXml) {
729                            toString = HtmlUtil.escape(toString);
730                    }
731    
732                    writer.write(toString);
733            }
734    
735            protected PortletURLImpl(
736                    HttpServletRequest request, String portletId,
737                    PortletRequest portletRequest, long plid, String lifecycle) {
738    
739                    _request = request;
740                    _portletId = portletId;
741                    _portletRequest = portletRequest;
742                    _plid = plid;
743                    _lifecycle = lifecycle;
744                    _parametersIncludedInPath = new LinkedHashSet<>();
745                    _params = new LinkedHashMap<>();
746                    _removePublicRenderParameters = new LinkedHashMap<>();
747                    _secure = PortalUtil.isSecure(request);
748                    _wsrp = ParamUtil.getBoolean(request, "wsrp");
749    
750                    Portlet portlet = getPortlet();
751    
752                    if (portlet != null) {
753                            Set<String> autopropagatedParameters =
754                                    portlet.getAutopropagatedParameters();
755    
756                            for (String autopropagatedParameter : autopropagatedParameters) {
757                                    if (PortalUtil.isReservedParameter(autopropagatedParameter)) {
758                                            continue;
759                                    }
760    
761                                    String value = request.getParameter(autopropagatedParameter);
762    
763                                    if (value != null) {
764                                            setParameter(autopropagatedParameter, value);
765                                    }
766                            }
767    
768                            PortletApp portletApp = portlet.getPortletApp();
769    
770                            _escapeXml = MapUtil.getBoolean(
771                                    portletApp.getContainerRuntimeOptions(),
772                                    LiferayPortletConfig.RUNTIME_OPTION_ESCAPE_XML,
773                                    PropsValues.PORTLET_URL_ESCAPE_XML);
774                    }
775    
776                    Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
777    
778                    if ((layout != null) && (layout.getPlid() == _plid) &&
779                            (layout instanceof VirtualLayout)) {
780    
781                            _layout = layout;
782                    }
783            }
784    
785            protected void addPortalAuthToken(StringBundler sb, Key key) {
786                    if (!PropsValues.AUTH_TOKEN_CHECK_ENABLED ||
787                            !_lifecycle.equals(PortletRequest.ACTION_PHASE)) {
788    
789                            return;
790                    }
791    
792                    Portlet portlet = getPortlet();
793    
794                    if (portlet == null) {
795                            return;
796                    }
797    
798                    String strutsAction = getParameter("struts_action");
799    
800                    if (AuthTokenWhitelistUtil.isPortletCSRFWhitelisted(
801                                    portlet.getCompanyId(), _portletId, strutsAction)) {
802    
803                            return;
804                    }
805    
806                    sb.append("p_auth");
807                    sb.append(StringPool.EQUAL);
808                    sb.append(processValue(key, AuthTokenUtil.getToken(_request)));
809                    sb.append(StringPool.AMPERSAND);
810            }
811    
812            protected void addPortletAuthToken(StringBundler sb, Key key) {
813                    if (!PropsValues.PORTLET_ADD_DEFAULT_RESOURCE_CHECK_ENABLED) {
814                            return;
815                    }
816    
817                    Portlet portlet = getPortlet();
818    
819                    if (portlet == null) {
820                            return;
821                    }
822    
823                    if (!portlet.isAddDefaultResource()) {
824                            return;
825                    }
826    
827                    String strutsAction = getParameter("struts_action");
828    
829                    if (AuthTokenWhitelistUtil.isPortletInvocationWhitelisted(
830                                    portlet.getCompanyId(), _portletId, strutsAction)) {
831    
832                            return;
833                    }
834    
835                    try {
836                            LayoutTypePortlet targetLayoutTypePortlet =
837                                    (LayoutTypePortlet)getLayout().getLayoutType();
838    
839                            if (targetLayoutTypePortlet.hasPortletId(_portletId)) {
840                                    return;
841                            }
842                    }
843                    catch (Exception e) {
844                            if (_log.isDebugEnabled()) {
845                                    _log.debug(e.getMessage(), e);
846                            }
847                    }
848    
849                    String controlPanelMenuPortletId = PortletProviderUtil.getPortletId(
850                            PortalProductMenuApplicationType.ProductMenu.CLASS_NAME,
851                            PortletProvider.Action.VIEW);
852    
853                    if (_portletId.equals(controlPanelMenuPortletId)) {
854                            return;
855                    }
856    
857                    sb.append("p_p_auth");
858                    sb.append(StringPool.EQUAL);
859                    sb.append(
860                            processValue(
861                                    key, AuthTokenUtil.getToken(_request, _plid, _portletId)));
862                    sb.append(StringPool.AMPERSAND);
863            }
864    
865            protected void clearCache() {
866                    _reservedParameters = null;
867                    _toString = null;
868            }
869    
870            protected String generateToString() {
871                    StringBundler sb = new StringBundler(64);
872    
873                    ThemeDisplay themeDisplay = (ThemeDisplay)_request.getAttribute(
874                            WebKeys.THEME_DISPLAY);
875    
876                    if (themeDisplay == null) {
877                            if (_log.isWarnEnabled()) {
878                                    _log.warn(
879                                            "Unable to generate string because theme display is null");
880                            }
881    
882                            return StringPool.BLANK;
883                    }
884    
885                    String portalURL = null;
886    
887                    if (themeDisplay.isFacebook()) {
888                            portalURL =
889                                    FacebookUtil.FACEBOOK_APPS_URL +
890                                            themeDisplay.getFacebookCanvasPageURL();
891                    }
892                    else {
893                            portalURL = PortalUtil.getPortalURL(_request, _secure);
894                    }
895    
896                    try {
897                            if (_layoutFriendlyURL == null) {
898                                    Layout layout = getLayout();
899    
900                                    if (layout != null) {
901                                            _layoutFriendlyURL = GetterUtil.getString(
902                                                    PortalUtil.getLayoutFriendlyURL(layout, themeDisplay));
903    
904                                            if (_secure) {
905                                                    _layoutFriendlyURL = HttpUtil.protocolize(
906                                                            _layoutFriendlyURL,
907                                                            PropsValues.WEB_SERVER_HTTPS_PORT, true);
908                                            }
909                                    }
910                            }
911                    }
912                    catch (Exception e) {
913                            _log.error(e);
914                    }
915    
916                    Key key = null;
917    
918                    try {
919                            if (_encrypt) {
920                                    Company company = PortalUtil.getCompany(_request);
921    
922                                    key = company.getKeyObj();
923                            }
924                    }
925                    catch (Exception e) {
926                            _log.error(e);
927                    }
928    
929                    if (Validator.isNull(_layoutFriendlyURL)) {
930                            sb.append(portalURL);
931                            sb.append(themeDisplay.getPathMain());
932                            sb.append("/portal/layout?");
933    
934                            addPortalAuthToken(sb, key);
935    
936                            sb.append("p_l_id");
937                            sb.append(StringPool.EQUAL);
938                            sb.append(processValue(key, _plid));
939                            sb.append(StringPool.AMPERSAND);
940                    }
941                    else {
942                            if (themeDisplay.isFacebook()) {
943                                    sb.append(portalURL);
944                            }
945                            else {
946    
947                                    // A virtual host URL will contain the complete path. Do not
948                                    // append the portal URL if the virtual host URL starts with
949                                    // "http://" or "https://".
950    
951                                    if (!_layoutFriendlyURL.startsWith(Http.HTTP_WITH_SLASH) &&
952                                            !_layoutFriendlyURL.startsWith(Http.HTTPS_WITH_SLASH)) {
953    
954                                            sb.append(portalURL);
955                                    }
956    
957                                    sb.append(_layoutFriendlyURL);
958                            }
959    
960                            String friendlyURLPath = getPortletFriendlyURLPath();
961    
962                            if (Validator.isNotNull(friendlyURLPath)) {
963                                    if (themeDisplay.isFacebook()) {
964                                            int pos = friendlyURLPath.indexOf(CharPool.SLASH, 1);
965    
966                                            if (pos != -1) {
967                                                    sb.append(friendlyURLPath.substring(pos));
968                                            }
969                                            else {
970                                                    sb.append(friendlyURLPath);
971                                            }
972                                    }
973                                    else {
974                                            sb.append("/-");
975                                            sb.append(friendlyURLPath);
976                                    }
977                            }
978    
979                            sb.append(StringPool.QUESTION);
980    
981                            addPortalAuthToken(sb, key);
982                    }
983    
984                    addPortletAuthToken(sb, key);
985    
986                    for (Map.Entry<String, String> entry :
987                                    getReservedParameterMap().entrySet()) {
988    
989                            String name = entry.getKey();
990    
991                            if (!isParameterIncludedInPath(name)) {
992                                    sb.append(HttpUtil.encodeURL(name));
993                                    sb.append(StringPool.EQUAL);
994                                    sb.append(processValue(key, entry.getValue()));
995                                    sb.append(StringPool.AMPERSAND);
996                            }
997                    }
998    
999                    if (_doAsUserId > 0) {
1000                            try {
1001                                    Company company = PortalUtil.getCompany(_request);
1002    
1003                                    sb.append("doAsUserId");
1004                                    sb.append(StringPool.EQUAL);
1005                                    sb.append(processValue(company.getKeyObj(), _doAsUserId));
1006                                    sb.append(StringPool.AMPERSAND);
1007                            }
1008                            catch (Exception e) {
1009                                    _log.error(e);
1010                            }
1011                    }
1012                    else {
1013                            String doAsUserId = themeDisplay.getDoAsUserId();
1014    
1015                            if (Validator.isNotNull(doAsUserId)) {
1016                                    sb.append("doAsUserId");
1017                                    sb.append(StringPool.EQUAL);
1018                                    sb.append(processValue(key, doAsUserId));
1019                                    sb.append(StringPool.AMPERSAND);
1020                            }
1021                    }
1022    
1023                    String doAsUserLanguageId = _doAsUserLanguageId;
1024    
1025                    if (Validator.isNull(doAsUserLanguageId)) {
1026                            doAsUserLanguageId = themeDisplay.getDoAsUserLanguageId();
1027                    }
1028    
1029                    if (Validator.isNotNull(doAsUserLanguageId)) {
1030                            sb.append("doAsUserLanguageId");
1031                            sb.append(StringPool.EQUAL);
1032                            sb.append(processValue(key, doAsUserLanguageId));
1033                            sb.append(StringPool.AMPERSAND);
1034                    }
1035    
1036                    long doAsGroupId = _doAsGroupId;
1037    
1038                    if (doAsGroupId <= 0) {
1039                            doAsGroupId = themeDisplay.getDoAsGroupId();
1040                    }
1041    
1042                    if (doAsGroupId > 0) {
1043                            sb.append("doAsGroupId");
1044                            sb.append(StringPool.EQUAL);
1045                            sb.append(processValue(key, doAsGroupId));
1046                            sb.append(StringPool.AMPERSAND);
1047                    }
1048    
1049                    long refererGroupId = _refererGroupId;
1050    
1051                    if (refererGroupId <= 0) {
1052                            refererGroupId = themeDisplay.getRefererGroupId();
1053                    }
1054    
1055                    if (refererGroupId > 0) {
1056                            sb.append("refererGroupId");
1057                            sb.append(StringPool.EQUAL);
1058                            sb.append(processValue(key, refererGroupId));
1059                            sb.append(StringPool.AMPERSAND);
1060                    }
1061    
1062                    long refererPlid = _refererPlid;
1063    
1064                    if (refererPlid <= 0) {
1065                            refererPlid = themeDisplay.getRefererPlid();
1066                    }
1067    
1068                    if (refererPlid > 0) {
1069                            sb.append("refererPlid");
1070                            sb.append(StringPool.EQUAL);
1071                            sb.append(processValue(key, refererPlid));
1072                            sb.append(StringPool.AMPERSAND);
1073                    }
1074    
1075                    for (Map.Entry<String, String[]> entry :
1076                                    _removePublicRenderParameters.entrySet()) {
1077    
1078                            String lastString = sb.stringAt(sb.index() - 1);
1079    
1080                            if (lastString.charAt(lastString.length() - 1) !=
1081                                            CharPool.AMPERSAND) {
1082    
1083                                    sb.append(StringPool.AMPERSAND);
1084                            }
1085    
1086                            sb.append(HttpUtil.encodeURL(entry.getKey()));
1087                            sb.append(StringPool.EQUAL);
1088                            sb.append(processValue(key, entry.getValue()[0]));
1089                            sb.append(StringPool.AMPERSAND);
1090                    }
1091    
1092                    if (_copyCurrentRenderParameters) {
1093                            mergeRenderParameters();
1094                    }
1095    
1096                    int previousSbIndex = sb.index();
1097    
1098                    for (Map.Entry<String, String[]> entry : _params.entrySet()) {
1099                            String name = entry.getKey();
1100                            String[] values = entry.getValue();
1101    
1102                            if (isParameterIncludedInPath(name)) {
1103                                    continue;
1104                            }
1105    
1106                            String publicRenderParameterName = getPublicRenderParameterName(
1107                                    name);
1108    
1109                            if (Validator.isNotNull(publicRenderParameterName)) {
1110                                    name = publicRenderParameterName;
1111                            }
1112    
1113                            name = HttpUtil.encodeURL(prependNamespace(name));
1114    
1115                            for (String value : values) {
1116                                    sb.append(name);
1117                                    sb.append(StringPool.EQUAL);
1118                                    sb.append(processValue(key, value));
1119                                    sb.append(StringPool.AMPERSAND);
1120                            }
1121                    }
1122    
1123                    if (sb.index() > previousSbIndex) {
1124                            sb.setIndex(sb.index() - 1);
1125                    }
1126    
1127                    if (_encrypt) {
1128                            sb.append(StringPool.AMPERSAND);
1129                            sb.append(WebKeys.ENCRYPT);
1130                            sb.append("=1");
1131                    }
1132    
1133                    if (PropsValues.PORTLET_URL_ANCHOR_ENABLE) {
1134                            if (_anchor && (_windowStateString != null) &&
1135                                    !_windowStateString.equals(WindowState.MAXIMIZED.toString()) &&
1136                                    !_windowStateString.equals(
1137                                            LiferayWindowState.EXCLUSIVE.toString()) &&
1138                                    !_windowStateString.equals(
1139                                            LiferayWindowState.POP_UP.toString())) {
1140    
1141                                    String lastString = sb.stringAt(sb.index() - 1);
1142    
1143                                    if (lastString.charAt(lastString.length() - 1) !=
1144                                                    CharPool.AMPERSAND) {
1145    
1146                                            sb.append(StringPool.AMPERSAND);
1147                                    }
1148    
1149                                    sb.append("#p_");
1150                                    sb.append(HttpUtil.encodeURL(_portletId));
1151                            }
1152                    }
1153    
1154                    String result = sb.toString();
1155    
1156                    if (result.endsWith(StringPool.AMPERSAND) ||
1157                            result.endsWith(StringPool.QUESTION)) {
1158    
1159                            result = result.substring(0, result.length() - 1);
1160                    }
1161    
1162                    if (themeDisplay.isFacebook()) {
1163    
1164                            // Facebook requires the path portion of the URL to end with a slash
1165    
1166                            int pos = result.indexOf(CharPool.QUESTION);
1167    
1168                            if (pos == -1) {
1169                                    if (!result.endsWith(StringPool.SLASH)) {
1170                                            result += StringPool.SLASH;
1171                                    }
1172                            }
1173                            else {
1174                                    String path = result.substring(0, pos);
1175    
1176                                    if (!result.endsWith(StringPool.SLASH)) {
1177                                            result = path + StringPool.SLASH + result.substring(pos);
1178                                    }
1179                            }
1180                    }
1181                    else if (!CookieKeys.hasSessionId(_request)) {
1182                            result = PortalUtil.getURLWithSessionId(
1183                                    result, _request.getSession().getId());
1184                    }
1185    
1186                    if (_escapeXml) {
1187                            result = HtmlUtil.escape(result);
1188                    }
1189    
1190                    if (result.length() > Http.URL_MAXIMUM_LENGTH) {
1191                            result = HttpUtil.shortenURL(result, 2);
1192                    }
1193    
1194                    return result;
1195            }
1196    
1197            protected String generateWSRPToString() {
1198                    StringBundler sb = new StringBundler("wsrp_rewrite?");
1199    
1200                    sb.append("wsrp-urlType");
1201                    sb.append(StringPool.EQUAL);
1202    
1203                    if (_lifecycle.equals(PortletRequest.ACTION_PHASE)) {
1204                            sb.append(HttpUtil.encodeURL("blockingAction"));
1205                    }
1206                    else if (_lifecycle.equals(PortletRequest.RENDER_PHASE)) {
1207                            sb.append(HttpUtil.encodeURL("render"));
1208                    }
1209                    else if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
1210                            sb.append(HttpUtil.encodeURL("resource"));
1211                    }
1212    
1213                    sb.append(StringPool.AMPERSAND);
1214    
1215                    if (_windowStateString != null) {
1216                            sb.append("wsrp-windowState");
1217                            sb.append(StringPool.EQUAL);
1218                            sb.append(HttpUtil.encodeURL("wsrp:" + _windowStateString));
1219                            sb.append(StringPool.AMPERSAND);
1220                    }
1221    
1222                    if (_portletModeString != null) {
1223                            sb.append("wsrp-mode");
1224                            sb.append(StringPool.EQUAL);
1225                            sb.append(HttpUtil.encodeURL("wsrp:" + _portletModeString));
1226                            sb.append(StringPool.AMPERSAND);
1227                    }
1228    
1229                    if (_resourceID != null) {
1230                            sb.append("wsrp-resourceID");
1231                            sb.append(StringPool.EQUAL);
1232                            sb.append(HttpUtil.encodeURL(_resourceID));
1233                            sb.append(StringPool.AMPERSAND);
1234                    }
1235    
1236                    if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
1237                            sb.append("wsrp-resourceCacheability");
1238                            sb.append(StringPool.EQUAL);
1239                            sb.append(HttpUtil.encodeURL(_cacheability));
1240                            sb.append(StringPool.AMPERSAND);
1241                    }
1242    
1243                    if (PropsValues.PORTLET_URL_ANCHOR_ENABLE) {
1244                            if (_anchor && (_windowStateString != null) &&
1245                                    !_windowStateString.equals(WindowState.MAXIMIZED.toString()) &&
1246                                    !_windowStateString.equals(
1247                                            LiferayWindowState.EXCLUSIVE.toString()) &&
1248                                    !_windowStateString.equals(
1249                                            LiferayWindowState.POP_UP.toString())) {
1250    
1251                                    sb.append("wsrp-fragmentID");
1252                                    sb.append(StringPool.EQUAL);
1253                                    sb.append("#p_");
1254                                    sb.append(HttpUtil.encodeURL(_portletId));
1255                                    sb.append(StringPool.AMPERSAND);
1256                            }
1257                    }
1258    
1259                    if (_copyCurrentRenderParameters) {
1260                            mergeRenderParameters();
1261                    }
1262    
1263                    StringBundler parameterSb = new StringBundler();
1264    
1265                    int previousSbIndex = sb.index();
1266    
1267                    for (Map.Entry<String, String[]> entry : _params.entrySet()) {
1268                            String name = entry.getKey();
1269                            String[] values = entry.getValue();
1270    
1271                            if (isParameterIncludedInPath(name)) {
1272                                    continue;
1273                            }
1274    
1275                            String publicRenderParameterName = getPublicRenderParameterName(
1276                                    name);
1277    
1278                            if (Validator.isNotNull(publicRenderParameterName)) {
1279                                    name = publicRenderParameterName;
1280                            }
1281    
1282                            name = HttpUtil.encodeURL(prependNamespace(name));
1283    
1284                            for (String value : values) {
1285                                    parameterSb.append(name);
1286                                    parameterSb.append(StringPool.EQUAL);
1287                                    parameterSb.append(HttpUtil.encodeURL(value));
1288                                    parameterSb.append(StringPool.AMPERSAND);
1289                            }
1290                    }
1291    
1292                    if (sb.index() > previousSbIndex) {
1293                            sb.setIndex(sb.index() - 1);
1294                    }
1295    
1296                    sb.append("wsrp-navigationalState");
1297                    sb.append(StringPool.EQUAL);
1298    
1299                    byte[] parameterBytes = null;
1300    
1301                    try {
1302                            String parameterString = parameterSb.toString();
1303    
1304                            parameterBytes = parameterString.getBytes(StringPool.UTF8);
1305                    }
1306                    catch (UnsupportedEncodingException uee) {
1307                            if (_log.isWarnEnabled()) {
1308                                    _log.warn(uee, uee);
1309                            }
1310                    }
1311    
1312                    String navigationalState = Base64.toURLSafe(
1313                            Base64.encode(parameterBytes));
1314    
1315                    sb.append(navigationalState);
1316    
1317                    sb.append("/wsrp_rewrite");
1318    
1319                    return sb.toString();
1320            }
1321    
1322            protected String getPublicRenderParameterName(String name) {
1323                    Portlet portlet = getPortlet();
1324    
1325                    String publicRenderParameterName = null;
1326    
1327                    if (portlet != null) {
1328                            PublicRenderParameter publicRenderParameter =
1329                                    portlet.getPublicRenderParameter(name);
1330    
1331                            if (publicRenderParameter != null) {
1332                                    QName qName = publicRenderParameter.getQName();
1333    
1334                                    publicRenderParameterName =
1335                                            PortletQNameUtil.getPublicRenderParameterName(qName);
1336                            }
1337                    }
1338    
1339                    return publicRenderParameterName;
1340            }
1341    
1342            protected boolean isBlankValue(String[] value) {
1343                    if ((value != null) && (value.length == 1) &&
1344                            value[0].equals(StringPool.BLANK)) {
1345    
1346                            return true;
1347                    }
1348                    else {
1349                            return false;
1350                    }
1351            }
1352    
1353            protected void mergeRenderParameters() {
1354                    String namespace = getNamespace();
1355    
1356                    Layout layout = getLayout();
1357    
1358                    Map<String, String[]> renderParameters = RenderParametersPool.get(
1359                            _request, layout.getPlid(), getPortlet().getPortletId());
1360    
1361                    for (Map.Entry<String, String[]> entry : renderParameters.entrySet()) {
1362                            String name = entry.getKey();
1363    
1364                            if (name.contains(namespace)) {
1365                                    name = name.substring(namespace.length());
1366                            }
1367    
1368                            if (!_lifecycle.equals(PortletRequest.RESOURCE_PHASE) &&
1369                                    (_removedParameterNames != null) &&
1370                                    _removedParameterNames.contains(name)) {
1371    
1372                                    continue;
1373                            }
1374    
1375                            String[] oldValues = entry.getValue();
1376                            String[] newValues = _params.get(name);
1377    
1378                            if (newValues == null) {
1379                                    _params.put(name, oldValues);
1380                            }
1381                            else if (isBlankValue(newValues)) {
1382                                    _params.remove(name);
1383                            }
1384                            else {
1385                                    newValues = ArrayUtil.append(newValues, oldValues);
1386    
1387                                    _params.put(name, newValues);
1388                            }
1389                    }
1390            }
1391    
1392            protected String prependNamespace(String name) {
1393                    String namespace = getNamespace();
1394    
1395                    if (!PortalUtil.isReservedParameter(name) &&
1396                            !name.startsWith(PortletQName.PUBLIC_RENDER_PARAMETER_NAMESPACE) &&
1397                            !name.startsWith(namespace)) {
1398    
1399                            return namespace.concat(name);
1400                    }
1401                    else {
1402                            return name;
1403                    }
1404            }
1405    
1406            protected String processValue(Key key, int value) {
1407                    return processValue(key, String.valueOf(value));
1408            }
1409    
1410            protected String processValue(Key key, long value) {
1411                    return processValue(key, String.valueOf(value));
1412            }
1413    
1414            protected String processValue(Key key, String value) {
1415                    if (key == null) {
1416                            return HttpUtil.encodeURL(value);
1417                    }
1418    
1419                    try {
1420                            return HttpUtil.encodeURL(Encryptor.encrypt(key, value));
1421                    }
1422                    catch (EncryptorException ee) {
1423                            return value;
1424                    }
1425            }
1426    
1427            private static final Log _log = LogFactoryUtil.getLog(PortletURLImpl.class);
1428    
1429            private boolean _anchor = true;
1430            private String _cacheability = ResourceURL.PAGE;
1431            private boolean _copyCurrentRenderParameters;
1432            private long _doAsGroupId;
1433            private long _doAsUserId;
1434            private String _doAsUserLanguageId;
1435            private boolean _encrypt;
1436            private boolean _escapeXml = PropsValues.PORTLET_URL_ESCAPE_XML;
1437            private Layout _layout;
1438            private String _layoutFriendlyURL;
1439            private String _lifecycle;
1440            private String _namespace;
1441            private final Set<String> _parametersIncludedInPath;
1442            private Map<String, String[]> _params;
1443            private long _plid;
1444            private Portlet _portlet;
1445            private String _portletId;
1446            private String _portletModeString;
1447            private final PortletRequest _portletRequest;
1448            private long _refererGroupId;
1449            private long _refererPlid;
1450            private Set<String> _removedParameterNames;
1451            private final Map<String, String[]> _removePublicRenderParameters;
1452            private final HttpServletRequest _request;
1453            private Map<String, String> _reservedParameters;
1454            private String _resourceID;
1455            private boolean _secure;
1456            private String _toString;
1457            private boolean _windowStateRestoreCurrentView;
1458            private String _windowStateString;
1459            private final boolean _wsrp;
1460    
1461            private class ToStringPrivilegedAction implements PrivilegedAction<String> {
1462    
1463                    @Override
1464                    public String run() {
1465                            if (_wsrp) {
1466                                    return generateWSRPToString();
1467                            }
1468    
1469                            return generateToString();
1470                    }
1471    
1472            }
1473    
1474    }