001
014
015 package com.liferay.portlet.blogs.util;
016
017 import com.liferay.portal.kernel.language.LanguageUtil;
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.FriendlyURLMapperThreadLocal;
022 import com.liferay.portal.kernel.util.GetterUtil;
023 import com.liferay.portal.kernel.util.HttpUtil;
024 import com.liferay.portal.kernel.util.LocaleUtil;
025 import com.liferay.portal.kernel.util.StringPool;
026 import com.liferay.portal.kernel.util.StringUtil;
027 import com.liferay.portal.kernel.util.Validator;
028 import com.liferay.portal.kernel.workflow.WorkflowConstants;
029 import com.liferay.portal.kernel.xmlrpc.Method;
030 import com.liferay.portal.kernel.xmlrpc.Response;
031 import com.liferay.portal.kernel.xmlrpc.XmlRpcConstants;
032 import com.liferay.portal.kernel.xmlrpc.XmlRpcUtil;
033 import com.liferay.portal.model.Portlet;
034 import com.liferay.portal.service.PortletLocalServiceUtil;
035 import com.liferay.portal.service.ServiceContext;
036 import com.liferay.portal.service.UserLocalServiceUtil;
037 import com.liferay.portal.util.Portal;
038 import com.liferay.portal.util.PortalUtil;
039 import com.liferay.portal.util.PortletKeys;
040 import com.liferay.portal.util.PropsValues;
041 import com.liferay.portlet.blogs.model.BlogsEntry;
042 import com.liferay.portlet.blogs.service.BlogsEntryLocalServiceUtil;
043 import com.liferay.portlet.messageboards.model.MBMessage;
044 import com.liferay.portlet.messageboards.model.MBMessageDisplay;
045 import com.liferay.portlet.messageboards.model.MBThread;
046 import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
047
048 import java.io.IOException;
049
050 import java.net.URL;
051
052 import java.util.HashMap;
053 import java.util.List;
054 import java.util.Map;
055
056 import net.htmlparser.jericho.Element;
057 import net.htmlparser.jericho.Source;
058 import net.htmlparser.jericho.StartTag;
059 import net.htmlparser.jericho.TextExtractor;
060
061
064 public class PingbackMethodImpl implements Method {
065
066 public static int ACCESS_DENIED = 49;
067
068 public static int GENERIC_FAULT = 0;
069
070 public static int PINGBACK_ALREADY_REGISTERED = 48;
071
072 public static int SERVER_ERROR = 50;
073
074 public static int SOURCE_URI_DOES_NOT_EXIST = 16;
075
076 public static int SOURCE_URI_INVALID = 17;
077
078 public static int TARGET_URI_DOES_NOT_EXIST = 32;
079
080 public static int TARGET_URI_INVALID = 33;
081
082 public Response execute(long companyId) {
083 if (!PropsValues.BLOGS_PINGBACK_ENABLED) {
084 return XmlRpcUtil.createFault(
085 XmlRpcConstants.REQUESTED_METHOD_NOT_FOUND,
086 "Pingbacks are disabled");
087 }
088
089 Response response = validateSource();
090
091 if (response != null) {
092 return response;
093 }
094
095 try {
096 BlogsEntry entry = getBlogsEntry(companyId);
097
098 if (!entry.isAllowPingbacks()) {
099 return XmlRpcUtil.createFault(
100 XmlRpcConstants.REQUESTED_METHOD_NOT_FOUND,
101 "Pingbacks are disabled");
102 }
103
104 long userId = UserLocalServiceUtil.getDefaultUserId(companyId);
105 long groupId = entry.getGroupId();
106 String className = BlogsEntry.class.getName();
107 long classPK = entry.getEntryId();
108
109 MBMessageDisplay messageDisplay =
110 MBMessageLocalServiceUtil.getDiscussionMessageDisplay(
111 userId, groupId, className, classPK,
112 WorkflowConstants.STATUS_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, WorkflowConstants.STATUS_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, groupId, className, classPK,
137 threadId, parentMessageId, StringPool.BLANK, body,
138 new ServiceContext());
139
140 return XmlRpcUtil.createSuccess("Pingback accepted");
141 }
142 catch (Exception e) {
143 if (_log.isDebugEnabled()) {
144 _log.debug(e, e);
145 }
146
147 return XmlRpcUtil.createFault(
148 TARGET_URI_INVALID, "Error parsing target URI");
149 }
150 }
151
152 public String getMethodName() {
153 return "pingback.ping";
154 }
155
156 public String getToken() {
157 return "pingback";
158 }
159
160 public boolean setArguments(Object[] arguments) {
161 try {
162 _sourceUri = (String)arguments[0];
163 _targetUri = (String)arguments[1];
164
165 return true;
166 }
167 catch (Exception e) {
168 return false;
169 }
170 }
171
172 protected BlogsEntry getBlogsEntry(long companyId) throws Exception {
173 BlogsEntry entry = null;
174
175 URL url = new URL(_targetUri);
176
177 String friendlyURL = url.getPath();
178
179 int end = friendlyURL.indexOf(Portal.FRIENDLY_URL_SEPARATOR);
180
181 if (end != -1) {
182 friendlyURL = friendlyURL.substring(0, end);
183 }
184
185 long plid = PortalUtil.getPlidFromFriendlyURL(companyId, friendlyURL);
186 long groupId = PortalUtil.getScopeGroupId(plid);
187
188 Map<String, String[]> params = new HashMap<String, String[]>();
189
190 FriendlyURLMapperThreadLocal.setPRPIdentifiers(
191 new HashMap<String, String>());
192
193 Portlet portlet =
194 PortletLocalServiceUtil.getPortletById(PortletKeys.BLOGS);
195
196 FriendlyURLMapper friendlyURLMapper =
197 portlet.getFriendlyURLMapperInstance();
198
199 friendlyURL = url.getPath();
200
201 end = friendlyURL.indexOf(Portal.FRIENDLY_URL_SEPARATOR);
202
203 if (end != -1) {
204 friendlyURL = friendlyURL.substring(
205 end + Portal.FRIENDLY_URL_SEPARATOR.length() - 1);
206 }
207
208 Map<String, Object> requestContext = new HashMap<String, Object>();
209
210 friendlyURLMapper.populateParams(friendlyURL, params, requestContext);
211
212 String param = getParam(params, "entryId");
213
214 if (Validator.isNotNull(param)) {
215 long entryId = GetterUtil.getLong(param);
216
217 entry = BlogsEntryLocalServiceUtil.getEntry(entryId);
218 }
219 else {
220 String urlTitle = getParam(params, "urlTitle");
221
222 entry = BlogsEntryLocalServiceUtil.getEntry(groupId, urlTitle);
223 }
224
225 return entry;
226 }
227
228 protected String getExcerpt() throws IOException {
229 String html = HttpUtil.URLtoString(_sourceUri);
230
231 Source source = new Source(html);
232
233 source.fullSequentialParse();
234
235 List<Element> elements = source.getAllElements("a");
236
237 for (Element element : elements) {
238 String href = GetterUtil.getString(
239 element.getAttributeValue("href"));
240
241 if (href.equals(_targetUri)) {
242 element = element.getParentElement();
243
244 TextExtractor textExtractor = new TextExtractor(element);
245
246 String body = textExtractor.toString();
247
248 if (body.length() < PropsValues.BLOGS_LINKBACK_EXCERPT_LENGTH) {
249 element = element.getParentElement();
250
251 if (element != null) {
252 textExtractor = new TextExtractor(element);
253
254 body = textExtractor.toString();
255 }
256 }
257
258 return StringUtil.shorten(
259 body, PropsValues.BLOGS_LINKBACK_EXCERPT_LENGTH);
260 }
261 }
262
263 return StringPool.BLANK;
264 }
265
266 protected String getParam(Map<String, String[]> params, String name) {
267 String[] paramArray = params.get(name);
268
269 if (paramArray == null) {
270 String namespace = PortalUtil.getPortletNamespace(
271 PortletKeys.BLOGS);
272
273 paramArray = params.get(namespace + name);
274 }
275
276 if ((paramArray != null) && (paramArray.length > 0)) {
277 return paramArray[0];
278 }
279 else {
280 return null;
281 }
282 }
283
284 protected Response validateSource() {
285 Source source = null;
286
287 try {
288 String html = HttpUtil.URLtoString(_sourceUri);
289
290 source = new Source(html);
291 }
292 catch (Exception e) {
293 return XmlRpcUtil.createFault(
294 SOURCE_URI_DOES_NOT_EXIST, "Error accessing source URI");
295 }
296
297 List<StartTag> startTags = source.getAllStartTags("a");
298
299 for (StartTag startTag : startTags) {
300 String href = GetterUtil.getString(
301 startTag.getAttributeValue("href"));
302
303 if (href.equals(_targetUri)) {
304 return null;
305 }
306 }
307
308 return XmlRpcUtil.createFault(
309 SOURCE_URI_INVALID, "Could not find target URI in source");
310 }
311
312 private static Log _log = LogFactoryUtil.getLog(PingbackMethodImpl.class);
313
314 private String _sourceUri;
315 private String _targetUri;
316
317 }