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.StatusConstants;
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 String className = BlogsEntry.class.getName();
108 long classPK = entry.getEntryId();
109
110 MBMessageDisplay messageDisplay =
111 MBMessageLocalServiceUtil.getDiscussionMessageDisplay(
112 userId, className, classPK, StatusConstants.APPROVED);
113
114 MBThread thread = messageDisplay.getThread();
115
116 long threadId = thread.getThreadId();
117 long parentMessageId = thread.getRootMessageId();
118 String body =
119 "[...] " + getExcerpt() + " [...] [url=" + _sourceUri + "]" +
120 LanguageUtil.get(LocaleUtil.getDefault(), "read-more") +
121 "[/url]";
122
123 List<MBMessage> messages =
124 MBMessageLocalServiceUtil.getThreadMessages(
125 threadId, StatusConstants.APPROVED);
126
127 for (MBMessage message : messages) {
128 if (message.getBody().equals(body)) {
129 return XmlRpcUtil.createFault(
130 PINGBACK_ALREADY_REGISTERED,
131 "Pingback previously registered");
132 }
133 }
134
135 MBMessageLocalServiceUtil.addDiscussionMessage(
136 userId, StringPool.BLANK, className, classPK, threadId,
137 parentMessageId, StringPool.BLANK, body, new ServiceContext());
138
139 return XmlRpcUtil.createSuccess("Pingback accepted");
140 }
141 catch (Exception e) {
142 if (_log.isDebugEnabled()) {
143 _log.debug(e, e);
144 }
145
146 return XmlRpcUtil.createFault(
147 TARGET_URI_INVALID, "Error parsing target URI");
148 }
149 }
150
151 public String getMethodName() {
152 return "pingback.ping";
153 }
154
155 public String getToken() {
156 return "pingback";
157 }
158
159 public boolean setArguments(Object[] arguments) {
160 try {
161 _sourceUri = (String)arguments[0];
162 _targetUri = (String)arguments[1];
163
164 return true;
165 }
166 catch (Exception e) {
167 return false;
168 }
169 }
170
171 protected BlogsEntry getBlogsEntry(long companyId) throws Exception {
172 BlogsEntry entry = null;
173
174 URL url = new URL(_targetUri);
175
176 String friendlyURL = url.getPath();
177
178 int end = friendlyURL.indexOf(Portal.FRIENDLY_URL_SEPARATOR);
179
180 if (end != -1) {
181 friendlyURL = friendlyURL.substring(0, end);
182 }
183
184 long plid = PortalUtil.getPlidFromFriendlyURL(companyId, friendlyURL);
185 long groupId = PortalUtil.getScopeGroupId(plid);
186
187 Map<String, String[]> params = new HashMap<String, String[]>();
188
189 FriendlyURLMapperThreadLocal.setPRPIdentifiers(
190 new HashMap<String, String>());
191
192 Portlet portlet =
193 PortletLocalServiceUtil.getPortletById(PortletKeys.BLOGS);
194
195 FriendlyURLMapper friendlyURLMapper =
196 portlet.getFriendlyURLMapperInstance();
197
198 friendlyURL = url.getPath();
199
200 end = friendlyURL.indexOf(Portal.FRIENDLY_URL_SEPARATOR);
201
202 if (end != -1) {
203 friendlyURL = friendlyURL.substring(
204 end + Portal.FRIENDLY_URL_SEPARATOR.length() - 1);
205 }
206
207 friendlyURLMapper.populateParams(friendlyURL, params);
208
209 String param = getParam(params, "entryId");
210
211 if (Validator.isNotNull(param)) {
212 long entryId = GetterUtil.getLong(param);
213
214 entry = BlogsEntryLocalServiceUtil.getEntry(entryId);
215 }
216 else {
217 String urlTitle = getParam(params, "urlTitle");
218
219 entry = BlogsEntryLocalServiceUtil.getEntry(groupId, urlTitle);
220 }
221
222 return entry;
223 }
224
225 protected String getExcerpt() throws IOException {
226 String html = HttpUtil.URLtoString(_sourceUri);
227
228 Source source = new Source(html);
229
230 source.fullSequentialParse();
231
232 List<Element> elements = source.getAllElements("a");
233
234 for (Element element : elements) {
235 String href = GetterUtil.getString(
236 element.getAttributeValue("href"));
237
238 if (href.equals(_targetUri)) {
239 element = element.getParentElement();
240
241 TextExtractor textExtractor = new TextExtractor(element);
242
243 String body = textExtractor.toString();
244
245 if (body.length() < PropsValues.BLOGS_LINKBACK_EXCERPT_LENGTH) {
246 element = element.getParentElement();
247
248 if (element != null) {
249 textExtractor = new TextExtractor(element);
250
251 body = textExtractor.toString();
252 }
253 }
254
255 return StringUtil.shorten(
256 body, PropsValues.BLOGS_LINKBACK_EXCERPT_LENGTH);
257 }
258 }
259
260 return StringPool.BLANK;
261 }
262
263 protected String getParam(Map<String, String[]> params, String name) {
264 String[] paramArray = params.get(name);
265
266 if (paramArray == null) {
267 String namespace = PortalUtil.getPortletNamespace(
268 PortletKeys.BLOGS);
269
270 paramArray = params.get(namespace + name);
271 }
272
273 if ((paramArray != null) && (paramArray.length > 0)) {
274 return paramArray[0];
275 }
276 else {
277 return null;
278 }
279 }
280
281 protected Response validateSource() {
282 Source source = null;
283
284 try {
285 String html = HttpUtil.URLtoString(_sourceUri);
286
287 source = new Source(html);
288 }
289 catch (Exception e) {
290 return XmlRpcUtil.createFault(
291 SOURCE_URI_DOES_NOT_EXIST, "Error accessing source URI");
292 }
293
294 List<StartTag> startTags = source.getAllStartTags("a");
295
296 for (StartTag startTag : startTags) {
297 String href = GetterUtil.getString(
298 startTag.getAttributeValue("href"));
299
300 if (href.equals(_targetUri)) {
301 return null;
302 }
303 }
304
305 return XmlRpcUtil.createFault(
306 SOURCE_URI_INVALID, "Could not find target URI in source");
307 }
308
309 private static Log _log = LogFactoryUtil.getLog(PingbackMethodImpl.class);
310
311 private String _sourceUri;
312 private String _targetUri;
313
314 }