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.blogs.action;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.servlet.ServletResponseUtil;
020    import com.liferay.portal.kernel.util.ContentTypes;
021    import com.liferay.portal.kernel.util.GetterUtil;
022    import com.liferay.portal.kernel.util.HttpUtil;
023    import com.liferay.portal.kernel.util.ParamUtil;
024    import com.liferay.portal.kernel.util.StringBundler;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.Validator;
027    import com.liferay.portal.security.auth.PrincipalException;
028    import com.liferay.portal.service.ServiceContextFunction;
029    import com.liferay.portal.struts.ActionConstants;
030    import com.liferay.portal.struts.PortletAction;
031    import com.liferay.portal.theme.ThemeDisplay;
032    import com.liferay.portal.util.PortalUtil;
033    import com.liferay.portal.util.WebKeys;
034    import com.liferay.portlet.blogs.NoSuchEntryException;
035    import com.liferay.portlet.blogs.TrackbackValidationException;
036    import com.liferay.portlet.blogs.model.BlogsEntry;
037    import com.liferay.portlet.blogs.trackback.Trackback;
038    import com.liferay.portlet.blogs.trackback.TrackbackImpl;
039    
040    import javax.portlet.ActionRequest;
041    import javax.portlet.ActionResponse;
042    import javax.portlet.PortletConfig;
043    import javax.portlet.PortletPreferences;
044    
045    import javax.servlet.http.HttpServletRequest;
046    import javax.servlet.http.HttpServletResponse;
047    
048    import org.apache.struts.action.ActionForm;
049    import org.apache.struts.action.ActionMapping;
050    
051    /**
052     * @author Alexander Chow
053     */
054    public class TrackbackAction extends PortletAction {
055    
056            public TrackbackAction() {
057                    _trackback = new TrackbackImpl();
058            }
059    
060            @Override
061            public void processAction(
062                            ActionMapping actionMapping, ActionForm actionForm,
063                            PortletConfig portletConfig, ActionRequest actionRequest,
064                            ActionResponse actionResponse)
065                    throws Exception {
066    
067                    try {
068                            addTrackback(actionRequest, actionResponse);
069                    }
070                    catch (NoSuchEntryException nsee) {
071                            if (_log.isWarnEnabled()) {
072                                    _log.warn(nsee, nsee);
073                            }
074                    }
075                    catch (Exception e) {
076                            _log.error(e, e);
077                    }
078    
079                    setForward(actionRequest, ActionConstants.COMMON_NULL);
080            }
081    
082            protected TrackbackAction(Trackback trackback) {
083                    _trackback = trackback;
084            }
085    
086            protected void addTrackback(
087                            ActionRequest actionRequest, ActionResponse actionResponse)
088                    throws Exception {
089    
090                    try {
091                            BlogsEntry entry = getBlogsEntry(actionRequest);
092    
093                            validate(entry);
094    
095                            ThemeDisplay themeDisplay =
096                                    (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
097    
098                            HttpServletRequest request = PortalUtil.getHttpServletRequest(
099                                    actionRequest);
100    
101                            HttpServletRequest originalRequest =
102                                    PortalUtil.getOriginalServletRequest(request);
103    
104                            String excerpt = ParamUtil.getString(originalRequest, "excerpt");
105                            String url = ParamUtil.getString(originalRequest, "url");
106                            String blogName = ParamUtil.getString(originalRequest, "blog_name");
107                            String title = ParamUtil.getString(originalRequest, "title");
108    
109                            validate(actionRequest, request.getRemoteAddr(), url);
110    
111                            _trackback.addTrackback(
112                                    entry, themeDisplay, excerpt, url, blogName, title,
113                                    new ServiceContextFunction(actionRequest));
114                    }
115                    catch (TrackbackValidationException tve) {
116                            sendError(actionRequest, actionResponse, tve.getMessage());
117    
118                            return;
119                    }
120    
121                    sendSuccess(actionRequest, actionResponse);
122            }
123    
124            protected BlogsEntry getBlogsEntry(ActionRequest actionRequest)
125                    throws Exception {
126    
127                    try {
128                            ActionUtil.getEntry(actionRequest);
129                    }
130                    catch (PrincipalException pe) {
131                            throw new TrackbackValidationException(
132                                    "Blog entry must have guest view permissions to enable " +
133                                            "trackbacks");
134                    }
135    
136                    return (BlogsEntry)actionRequest.getAttribute(WebKeys.BLOGS_ENTRY);
137            }
138    
139            @Override
140            protected boolean isCheckMethodOnProcessAction() {
141                    return _CHECK_METHOD_ON_PROCESS_ACTION;
142            }
143    
144            protected boolean isCommentsEnabled(ActionRequest actionRequest)
145                    throws Exception {
146    
147                    PortletPreferences portletPreferences = getStrictPortletSetup(
148                            actionRequest);
149    
150                    if (portletPreferences == null) {
151                            portletPreferences = actionRequest.getPreferences();
152                    }
153    
154                    return GetterUtil.getBoolean(
155                            portletPreferences.getValue("enableComments", null), true);
156            }
157    
158            protected void sendError(
159                            ActionRequest actionRequest, ActionResponse actionResponse,
160                            String msg)
161                    throws Exception {
162    
163                    sendResponse(actionRequest, actionResponse, msg, false);
164            }
165    
166            protected void sendResponse(
167                            ActionRequest actionRequest, ActionResponse actionResponse,
168                            String msg, boolean success)
169                    throws Exception {
170    
171                    StringBundler sb = new StringBundler(7);
172    
173                    sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
174                    sb.append("<response>");
175    
176                    if (success) {
177                            sb.append("<error>0</error>");
178                    }
179                    else {
180                            sb.append("<error>1</error>");
181                            sb.append("<message>");
182                            sb.append(msg);
183                            sb.append("</message>");
184                    }
185    
186                    sb.append("</response>");
187    
188                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
189                            actionRequest);
190                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
191                            actionResponse);
192    
193                    ServletResponseUtil.sendFile(
194                            request, response, null, sb.toString().getBytes(StringPool.UTF8),
195                            ContentTypes.TEXT_XML_UTF8);
196            }
197    
198            protected void sendSuccess(
199                            ActionRequest actionRequest, ActionResponse actionResponse)
200                    throws Exception {
201    
202                    sendResponse(actionRequest, actionResponse, null, true);
203            }
204    
205            protected void validate(
206                            ActionRequest actionRequest, String remoteIP, String url)
207                    throws Exception {
208    
209                    if (!isCommentsEnabled(actionRequest)) {
210                            throw new TrackbackValidationException("Comments are disabled");
211                    }
212    
213                    if (Validator.isNull(url)) {
214                            throw new TrackbackValidationException(
215                                    "Trackback requires a valid permanent URL");
216                    }
217    
218                    String trackbackIP = HttpUtil.getIpAddress(url);
219    
220                    if (!remoteIP.equals(trackbackIP)) {
221                            throw new TrackbackValidationException(
222                                    "Remote IP does not match the trackback URL's IP");
223                    }
224            }
225    
226            protected void validate(BlogsEntry entry)
227                    throws TrackbackValidationException {
228    
229                    if (!entry.isAllowTrackbacks()) {
230                            throw new TrackbackValidationException(
231                                    "Trackbacks are not enabled");
232                    }
233            }
234    
235            private static final boolean _CHECK_METHOD_ON_PROCESS_ACTION = false;
236    
237            private static final Log _log = LogFactoryUtil.getLog(
238                    TrackbackAction.class);
239    
240            private final Trackback _trackback;
241    
242    }