/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.akismet.util;
import com.liferay.akismet.model.AkismetData;
import com.liferay.akismet.service.AkismetDataLocalServiceUtil;
import com.liferay.message.boards.kernel.model.MBMessage;
import com.liferay.portal.kernel.dao.orm.DynamicQuery;
import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
import com.liferay.portal.kernel.dao.orm.OrderFactoryUtil;
import com.liferay.portal.kernel.dao.orm.Property;
import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.Company;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.service.CompanyLocalServiceUtil;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.service.UserLocalServiceUtil;
import com.liferay.portal.kernel.servlet.HttpHeaders;
import com.liferay.portal.kernel.util.Http;
import com.liferay.portal.kernel.util.HttpUtil;
import com.liferay.portal.kernel.util.PortalUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Time;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.workflow.WorkflowConstants;
import com.liferay.wiki.model.WikiPage;
import com.liferay.wiki.service.WikiPageLocalServiceUtil;
import com.liferay.wiki.util.comparator.PageVersionComparator;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Amos Fong
* @author Peter Shin
*/
public class AkismetUtil {
public static Date getReportableTime(long companyId) {
int reportableTime = PrefsPortletPropsUtil.getInteger(
companyId, PortletPropsKeys.AKISMET_REPORTABLE_TIME);
return new Date(
System.currentTimeMillis() - (reportableTime * Time.DAY));
}
public static Date getRetainSpamTime() {
return new Date(
System.currentTimeMillis() -
(PortletPropsValues.AKISMET_RETAIN_SPAM_TIME * Time.DAY));
}
public static WikiPage getWikiPage(
long nodeId, String title, double version, boolean previous) {
DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
WikiPage.class);
Property summaryProperty = PropertyFactoryUtil.forName("summary");
dynamicQuery.add(
summaryProperty.ne(AkismetConstants.WIKI_PAGE_MARKED_AS_SPAM));
dynamicQuery.add(
summaryProperty.ne(AkismetConstants.WIKI_PAGE_PENDING_APPROVAL));
Property nodeIdProperty = PropertyFactoryUtil.forName("nodeId");
dynamicQuery.add(nodeIdProperty.eq(nodeId));
Property titleProperty = PropertyFactoryUtil.forName("title");
dynamicQuery.add(titleProperty.eq(title));
Property statusProperty = PropertyFactoryUtil.forName("status");
dynamicQuery.add(statusProperty.eq(WorkflowConstants.STATUS_APPROVED));
Property versionProperty = PropertyFactoryUtil.forName("version");
if (previous) {
dynamicQuery.add(versionProperty.lt(version));
}
else {
dynamicQuery.add(versionProperty.ge(version));
}
OrderFactoryUtil.addOrderByComparator(
dynamicQuery, new PageVersionComparator());
List<WikiPage> wikiPages = WikiPageLocalServiceUtil.dynamicQuery(
dynamicQuery, 0, 1);
if (wikiPages.isEmpty()) {
return null;
}
return wikiPages.get(0);
}
public static boolean hasRequiredInfo(ServiceContext serviceContext) {
Map<String, String> headers = serviceContext.getHeaders();
if (headers == null) {
return false;
}
String userAgent = headers.get(
StringUtil.toLowerCase(HttpHeaders.USER_AGENT));
if (Validator.isNull(userAgent)) {
return false;
}
String userIP = serviceContext.getRemoteAddr();
if (Validator.isNull(userIP)) {
return false;
}
return true;
}
public static boolean isDiscussionsEnabled(long companyId) {
String apiKey = PrefsPortletPropsUtil.getString(
companyId, PortletPropsKeys.AKISMET_API_KEY);
if (Validator.isNull(apiKey)) {
return false;
}
return PrefsPortletPropsUtil.getBoolean(
companyId, PortletPropsKeys.AKISMET_DISCUSSIONS_CHECK_ENABLED);
}
public static boolean isMessageBoardsEnabled(long companyId) {
String apiKey = PrefsPortletPropsUtil.getString(
companyId, PortletPropsKeys.AKISMET_API_KEY);
if (Validator.isNull(apiKey)) {
return false;
}
return PrefsPortletPropsUtil.getBoolean(
companyId, PortletPropsKeys.AKISMET_MESSAGE_BOARDS_CHECK_ENABLED);
}
public static boolean isSpam(
long userId, String content, AkismetData akismetData)
throws PortalException {
User user = UserLocalServiceUtil.getUser(userId);
StringBundler sb = new StringBundler(5);
sb.append(Http.HTTP_WITH_SLASH);
sb.append(
PrefsPortletPropsUtil.getString(
user.getCompanyId(), PortletPropsKeys.AKISMET_API_KEY));
sb.append(StringPool.PERIOD);
sb.append(AkismetConstants.URL_REST);
sb.append(AkismetConstants.PATH_CHECK_SPAM);
String location = sb.toString();
String response = _sendRequest(
location, user.getCompanyId(), akismetData.getUserIP(),
akismetData.getUserAgent(), akismetData.getReferrer(),
akismetData.getPermalink(), akismetData.getType(),
user.getFullName(), user.getEmailAddress(), content);
if (Validator.isNull(response) || response.equals("invalid")) {
_log.error("There was an issue with Akismet comment validation");
return false;
}
else if (response.equals("true")) {
if (_log.isDebugEnabled()) {
_log.debug("Spam detected: " + akismetData.getPermalink());
}
return true;
}
if (_log.isDebugEnabled()) {
_log.debug("Passed: " + akismetData.getPermalink());
}
return false;
}
public static boolean isWikiEnabled(long companyId) {
String apiKey = PrefsPortletPropsUtil.getString(
companyId, PortletPropsKeys.AKISMET_API_KEY);
if (Validator.isNull(apiKey)) {
return false;
}
return PrefsPortletPropsUtil.getBoolean(
companyId, PortletPropsKeys.AKISMET_WIKI_CHECK_ENABLED);
}
public static void submitHam(
long companyId, String ipAddress, String userAgent, String referrer,
String permalink, String commentType, String userName,
String emailAddress, String content)
throws PortalException {
if (_log.isDebugEnabled()) {
_log.debug("Submitting message as ham: " + permalink);
}
StringBundler sb = new StringBundler(5);
sb.append(Http.HTTP_WITH_SLASH);
sb.append(
PrefsPortletPropsUtil.getString(
companyId, PortletPropsKeys.AKISMET_API_KEY));
sb.append(StringPool.PERIOD);
sb.append(AkismetConstants.URL_REST);
sb.append(AkismetConstants.PATH_SUBMIT_HAM);
String location = sb.toString();
String response = _sendRequest(
location, companyId, ipAddress, userAgent, referrer, permalink,
commentType, userName, emailAddress, content);
if (Validator.isNull(response)) {
_log.error("There was an issue submitting message as ham");
}
}
public static void submitHam(MBMessage mbMessage) throws PortalException {
AkismetData akismetData = AkismetDataLocalServiceUtil.fetchAkismetData(
MBMessage.class.getName(), mbMessage.getMessageId());
if (akismetData == null) {
return;
}
User user = UserLocalServiceUtil.getUser(mbMessage.getUserId());
String content = mbMessage.getSubject() + "\n\n" + mbMessage.getBody();
submitHam(
mbMessage.getCompanyId(), akismetData.getUserIP(),
akismetData.getUserAgent(), akismetData.getReferrer(),
akismetData.getPermalink(), akismetData.getType(),
user.getFullName(), user.getEmailAddress(), content);
}
public static void submitHam(WikiPage wikiPage) throws PortalException {
AkismetData akismetData = AkismetDataLocalServiceUtil.fetchAkismetData(
WikiPage.class.getName(), wikiPage.getPageId());
if (akismetData == null) {
return;
}
User user = UserLocalServiceUtil.getUser(wikiPage.getUserId());
String content = wikiPage.getTitle() + "\n\n" + wikiPage.getContent();
submitHam(
wikiPage.getCompanyId(), akismetData.getUserIP(),
akismetData.getUserAgent(), akismetData.getReferrer(),
akismetData.getPermalink(), akismetData.getType(),
user.getFullName(), user.getEmailAddress(), content);
}
public static void submitSpam(
long companyId, String ipAddress, String userAgent, String referrer,
String permalink, String commentType, String userName,
String emailAddress, String content)
throws PortalException {
if (_log.isDebugEnabled()) {
_log.debug("Submitting message as spam: " + permalink);
}
StringBundler sb = new StringBundler(5);
sb.append(Http.HTTP_WITH_SLASH);
sb.append(
PrefsPortletPropsUtil.getString(
companyId, PortletPropsKeys.AKISMET_API_KEY));
sb.append(StringPool.PERIOD);
sb.append(AkismetConstants.URL_REST);
sb.append(AkismetConstants.PATH_SUBMIT_SPAM);
String location = sb.toString();
String response = _sendRequest(
location, companyId, ipAddress, userAgent, referrer, permalink,
commentType, userName, emailAddress, content);
if (Validator.isNull(response)) {
_log.error("There was an issue submitting message as spam");
}
}
public static void submitSpam(MBMessage mbMessage) throws PortalException {
AkismetData akismetData = AkismetDataLocalServiceUtil.fetchAkismetData(
MBMessage.class.getName(), mbMessage.getMessageId());
if (akismetData == null) {
return;
}
User user = UserLocalServiceUtil.getUser(mbMessage.getUserId());
String content = mbMessage.getSubject() + "\n\n" + mbMessage.getBody();
submitSpam(
mbMessage.getCompanyId(), akismetData.getUserIP(),
akismetData.getUserAgent(), akismetData.getReferrer(),
akismetData.getPermalink(), akismetData.getType(),
user.getFullName(), user.getEmailAddress(), content);
}
public static void submitSpam(WikiPage wikiPage) throws PortalException {
AkismetData akismetData = AkismetDataLocalServiceUtil.fetchAkismetData(
WikiPage.class.getName(), wikiPage.getPageId());
if (akismetData == null) {
return;
}
User user = UserLocalServiceUtil.getUser(wikiPage.getUserId());
String content = wikiPage.getTitle() + "\n\n" + wikiPage.getContent();
submitSpam(
wikiPage.getCompanyId(), akismetData.getUserIP(),
akismetData.getUserAgent(), akismetData.getReferrer(),
akismetData.getPermalink(), akismetData.getType(),
user.getFullName(), user.getEmailAddress(), content);
}
public static boolean verifyApiKey(long companyId, String apiKey)
throws PortalException {
String location =
Http.HTTP_WITH_SLASH + AkismetConstants.URL_REST +
AkismetConstants.PATH_VERIFY;
Map<String, String> parts = new HashMap<>();
parts.put("blog", _getPortalURL(companyId));
parts.put("key", apiKey);
String response = _sendRequest(location, parts);
if (response.equals("valid")) {
return true;
}
else {
return false;
}
}
private static String _getPortalURL(long companyId) throws PortalException {
Company company = CompanyLocalServiceUtil.getCompany(companyId);
return PortalUtil.getPortalURL(
company.getVirtualHostname(), PortalUtil.getPortalPort(false),
false);
}
private static String _sendRequest(
String location, long companyId, String ipAddress, String userAgent,
String referrer, String permalink, String commentType,
String userName, String emailAddress, String content)
throws PortalException {
Map<String, String> parts = new HashMap<>();
parts.put("blog", _getPortalURL(companyId));
parts.put("comment_author", userName);
parts.put("comment_author_email", emailAddress);
parts.put("comment_content", content);
parts.put("comment_type", commentType);
parts.put("permalink", permalink);
parts.put("referrer", referrer);
parts.put("user_agent", userAgent);
parts.put("user_ip", ipAddress);
return _sendRequest(location, parts);
}
private static String _sendRequest(
String location, Map<String, String> parts) {
Http.Options options = new Http.Options();
options.addHeader(HttpHeaders.USER_AGENT, "Akismet/2.5.3");
options.setLocation(location);
options.setParts(parts);
options.setPost(true);
try {
return HttpUtil.URLtoString(options);
}
catch (IOException ioe) {
_log.error(ioe, ioe);
}
return StringPool.BLANK;
}
private static Log _log = LogFactoryUtil.getLog(AkismetUtil.class);
}