1
14
15 package com.liferay.portlet.blogs.util;
16
17 import com.liferay.portal.kernel.language.LanguageUtil;
18 import com.liferay.portal.kernel.log.Log;
19 import com.liferay.portal.kernel.log.LogFactoryUtil;
20 import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
21 import com.liferay.portal.kernel.portlet.FriendlyURLMapperThreadLocal;
22 import com.liferay.portal.kernel.util.GetterUtil;
23 import com.liferay.portal.kernel.util.HttpUtil;
24 import com.liferay.portal.kernel.util.LocaleUtil;
25 import com.liferay.portal.kernel.util.StringPool;
26 import com.liferay.portal.kernel.util.StringUtil;
27 import com.liferay.portal.kernel.util.Validator;
28 import com.liferay.portal.kernel.workflow.WorkflowConstants;
29 import com.liferay.portal.kernel.xmlrpc.Method;
30 import com.liferay.portal.kernel.xmlrpc.Response;
31 import com.liferay.portal.kernel.xmlrpc.XmlRpcConstants;
32 import com.liferay.portal.kernel.xmlrpc.XmlRpcUtil;
33 import com.liferay.portal.model.Portlet;
34 import com.liferay.portal.service.PortletLocalServiceUtil;
35 import com.liferay.portal.service.ServiceContext;
36 import com.liferay.portal.service.UserLocalServiceUtil;
37 import com.liferay.portal.util.Portal;
38 import com.liferay.portal.util.PortalUtil;
39 import com.liferay.portal.util.PortletKeys;
40 import com.liferay.portal.util.PropsValues;
41 import com.liferay.portlet.blogs.model.BlogsEntry;
42 import com.liferay.portlet.blogs.service.BlogsEntryLocalServiceUtil;
43 import com.liferay.portlet.messageboards.model.MBMessage;
44 import com.liferay.portlet.messageboards.model.MBMessageDisplay;
45 import com.liferay.portlet.messageboards.model.MBThread;
46 import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
47
48 import java.io.IOException;
49
50 import java.net.URL;
51
52 import java.util.HashMap;
53 import java.util.List;
54 import java.util.Map;
55
56 import net.htmlparser.jericho.Element;
57 import net.htmlparser.jericho.Source;
58 import net.htmlparser.jericho.StartTag;
59 import net.htmlparser.jericho.TextExtractor;
60
61
66 public class PingbackMethodImpl implements Method {
67
68 public static int ACCESS_DENIED = 49;
69
70 public static int GENERIC_FAULT = 0;
71
72 public static int PINGBACK_ALREADY_REGISTERED = 48;
73
74 public static int SERVER_ERROR = 50;
75
76 public static int SOURCE_URI_DOES_NOT_EXIST = 16;
77
78 public static int SOURCE_URI_INVALID = 17;
79
80 public static int TARGET_URI_DOES_NOT_EXIST = 32;
81
82 public static int TARGET_URI_INVALID = 33;
83
84 public Response execute(long companyId) {
85 if (!PropsValues.BLOGS_PINGBACK_ENABLED) {
86 return XmlRpcUtil.createFault(
87 XmlRpcConstants.REQUESTED_METHOD_NOT_FOUND,
88 "Pingbacks are disabled");
89 }
90
91 Response response = validateSource();
92
93 if (response != null) {
94 return response;
95 }
96
97 try {
98 BlogsEntry entry = getBlogsEntry(companyId);
99
100 if (!entry.isAllowPingbacks()) {
101 return XmlRpcUtil.createFault(
102 XmlRpcConstants.REQUESTED_METHOD_NOT_FOUND,
103 "Pingbacks are disabled");
104 }
105
106 long userId = UserLocalServiceUtil.getDefaultUserId(companyId);
107 long groupId = entry.getGroupId();
108 String className = BlogsEntry.class.getName();
109 long classPK = entry.getEntryId();
110
111 MBMessageDisplay messageDisplay =
112 MBMessageLocalServiceUtil.getDiscussionMessageDisplay(
113 userId, groupId, className, classPK,
114 WorkflowConstants.STATUS_APPROVED);
115
116 MBThread thread = messageDisplay.getThread();
117
118 long threadId = thread.getThreadId();
119 long parentMessageId = thread.getRootMessageId();
120 String body =
121 "[...] " + getExcerpt() + " [...] [url=" + _sourceUri + "]" +
122 LanguageUtil.get(LocaleUtil.getDefault(), "read-more") +
123 "[/url]";
124
125 List<MBMessage> messages =
126 MBMessageLocalServiceUtil.getThreadMessages(
127 threadId, WorkflowConstants.STATUS_APPROVED);
128
129 for (MBMessage message : messages) {
130 if (message.getBody().equals(body)) {
131 return XmlRpcUtil.createFault(
132 PINGBACK_ALREADY_REGISTERED,
133 "Pingback previously registered");
134 }
135 }
136
137 ServiceContext serviceContext = new ServiceContext();
138
139 MBMessageLocalServiceUtil.addDiscussionMessage(
140 null, userId, StringPool.BLANK, groupId, className, classPK,
141 threadId, parentMessageId, StringPool.BLANK, body,
142 serviceContext);
143
144 return XmlRpcUtil.createSuccess("Pingback accepted");
145 }
146 catch (Exception e) {
147 if (_log.isDebugEnabled()) {
148 _log.debug(e, e);
149 }
150
151 return XmlRpcUtil.createFault(
152 TARGET_URI_INVALID, "Error parsing target URI");
153 }
154 }
155
156 public String getMethodName() {
157 return "pingback.ping";
158 }
159
160 public String getToken() {
161 return "pingback";
162 }
163
164 public boolean setArguments(Object[] arguments) {
165 try {
166 _sourceUri = (String)arguments[0];
167 _targetUri = (String)arguments[1];
168
169 return true;
170 }
171 catch (Exception e) {
172 return false;
173 }
174 }
175
176 protected BlogsEntry getBlogsEntry(long companyId) throws Exception {
177 BlogsEntry entry = null;
178
179 URL url = new URL(_targetUri);
180
181 String friendlyURL = url.getPath();
182
183 int end = friendlyURL.indexOf(Portal.FRIENDLY_URL_SEPARATOR);
184
185 if (end != -1) {
186 friendlyURL = friendlyURL.substring(0, end);
187 }
188
189 long plid = PortalUtil.getPlidFromFriendlyURL(companyId, friendlyURL);
190 long groupId = PortalUtil.getScopeGroupId(plid);
191
192 Map<String, String[]> params = new HashMap<String, String[]>();
193
194 FriendlyURLMapperThreadLocal.setPRPIdentifiers(
195 new HashMap<String, String>());
196
197 Portlet portlet =
198 PortletLocalServiceUtil.getPortletById(PortletKeys.BLOGS);
199
200 FriendlyURLMapper friendlyURLMapper =
201 portlet.getFriendlyURLMapperInstance();
202
203 friendlyURL = url.getPath();
204
205 end = friendlyURL.indexOf(Portal.FRIENDLY_URL_SEPARATOR);
206
207 if (end != -1) {
208 friendlyURL = friendlyURL.substring(
209 end + Portal.FRIENDLY_URL_SEPARATOR.length() - 1);
210 }
211
212 Map<String, Object> requestContext = new HashMap<String, Object>();
213
214 friendlyURLMapper.populateParams(friendlyURL, params, requestContext);
215
216 String param = getParam(params, "entryId");
217
218 if (Validator.isNotNull(param)) {
219 long entryId = GetterUtil.getLong(param);
220
221 entry = BlogsEntryLocalServiceUtil.getEntry(entryId);
222 }
223 else {
224 String urlTitle = getParam(params, "urlTitle");
225
226 entry = BlogsEntryLocalServiceUtil.getEntry(groupId, urlTitle);
227 }
228
229 return entry;
230 }
231
232 protected String getExcerpt() throws IOException {
233 String html = HttpUtil.URLtoString(_sourceUri);
234
235 Source source = new Source(html);
236
237 source.fullSequentialParse();
238
239 List<Element> elements = source.getAllElements("a");
240
241 for (Element element : elements) {
242 String href = GetterUtil.getString(
243 element.getAttributeValue("href"));
244
245 if (href.equals(_targetUri)) {
246 element = element.getParentElement();
247
248 TextExtractor textExtractor = new TextExtractor(element);
249
250 String body = textExtractor.toString();
251
252 if (body.length() < PropsValues.BLOGS_LINKBACK_EXCERPT_LENGTH) {
253 element = element.getParentElement();
254
255 if (element != null) {
256 textExtractor = new TextExtractor(element);
257
258 body = textExtractor.toString();
259 }
260 }
261
262 return StringUtil.shorten(
263 body, PropsValues.BLOGS_LINKBACK_EXCERPT_LENGTH);
264 }
265 }
266
267 return StringPool.BLANK;
268 }
269
270 protected String getParam(Map<String, String[]> params, String name) {
271 String[] paramArray = params.get(name);
272
273 if (paramArray == null) {
274 String namespace = PortalUtil.getPortletNamespace(
275 PortletKeys.BLOGS);
276
277 paramArray = params.get(namespace + name);
278 }
279
280 if ((paramArray != null) && (paramArray.length > 0)) {
281 return paramArray[0];
282 }
283 else {
284 return null;
285 }
286 }
287
288 protected Response validateSource() {
289 Source source = null;
290
291 try {
292 String html = HttpUtil.URLtoString(_sourceUri);
293
294 source = new Source(html);
295 }
296 catch (Exception e) {
297 return XmlRpcUtil.createFault(
298 SOURCE_URI_DOES_NOT_EXIST, "Error accessing source URI");
299 }
300
301 List<StartTag> startTags = source.getAllStartTags("a");
302
303 for (StartTag startTag : startTags) {
304 String href = GetterUtil.getString(
305 startTag.getAttributeValue("href"));
306
307 if (href.equals(_targetUri)) {
308 return null;
309 }
310 }
311
312 return XmlRpcUtil.createFault(
313 SOURCE_URI_INVALID, "Could not find target URI in source");
314 }
315
316 private static Log _log = LogFactoryUtil.getLog(PingbackMethodImpl.class);
317
318 private String _sourceUri;
319 private String _targetUri;
320
321 }