001
014
015 package com.liferay.portlet.messageboards.util;
016
017 import com.liferay.portal.kernel.dao.shard.ShardCallable;
018 import com.liferay.portal.kernel.exception.PortalException;
019 import com.liferay.portal.kernel.exception.SystemException;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.portlet.LiferayWindowState;
023 import com.liferay.portal.kernel.sanitizer.Sanitizer;
024 import com.liferay.portal.kernel.sanitizer.SanitizerUtil;
025 import com.liferay.portal.kernel.search.Document;
026 import com.liferay.portal.kernel.search.Field;
027 import com.liferay.portal.kernel.search.Hits;
028 import com.liferay.portal.kernel.transaction.TransactionCommitCallbackRegistryUtil;
029 import com.liferay.portal.kernel.util.ArrayUtil;
030 import com.liferay.portal.kernel.util.CharPool;
031 import com.liferay.portal.kernel.util.ContentTypes;
032 import com.liferay.portal.kernel.util.GetterUtil;
033 import com.liferay.portal.kernel.util.Http;
034 import com.liferay.portal.kernel.util.LocaleUtil;
035 import com.liferay.portal.kernel.util.LocalizationUtil;
036 import com.liferay.portal.kernel.util.ParamUtil;
037 import com.liferay.portal.kernel.util.PropsUtil;
038 import com.liferay.portal.kernel.util.StringBundler;
039 import com.liferay.portal.kernel.util.StringPool;
040 import com.liferay.portal.kernel.util.StringUtil;
041 import com.liferay.portal.kernel.util.Validator;
042 import com.liferay.portal.kernel.workflow.WorkflowConstants;
043 import com.liferay.portal.model.Group;
044 import com.liferay.portal.model.Organization;
045 import com.liferay.portal.model.Role;
046 import com.liferay.portal.model.Subscription;
047 import com.liferay.portal.model.UserGroup;
048 import com.liferay.portal.security.permission.ActionKeys;
049 import com.liferay.portal.security.permission.PermissionChecker;
050 import com.liferay.portal.service.GroupLocalServiceUtil;
051 import com.liferay.portal.service.OrganizationLocalServiceUtil;
052 import com.liferay.portal.service.RoleLocalServiceUtil;
053 import com.liferay.portal.service.SubscriptionLocalServiceUtil;
054 import com.liferay.portal.service.UserGroupLocalServiceUtil;
055 import com.liferay.portal.service.UserGroupRoleLocalServiceUtil;
056 import com.liferay.portal.service.UserLocalServiceUtil;
057 import com.liferay.portal.theme.ThemeDisplay;
058 import com.liferay.portal.util.PortalUtil;
059 import com.liferay.portal.util.PropsValues;
060 import com.liferay.portal.util.WebKeys;
061 import com.liferay.portlet.documentlibrary.model.DLFileEntry;
062 import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
063 import com.liferay.portlet.messageboards.model.MBBan;
064 import com.liferay.portlet.messageboards.model.MBCategory;
065 import com.liferay.portlet.messageboards.model.MBCategoryConstants;
066 import com.liferay.portlet.messageboards.model.MBMessage;
067 import com.liferay.portlet.messageboards.model.MBMessageConstants;
068 import com.liferay.portlet.messageboards.model.MBStatsUser;
069 import com.liferay.portlet.messageboards.model.MBThread;
070 import com.liferay.portlet.messageboards.service.MBCategoryLocalServiceUtil;
071 import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
072 import com.liferay.portlet.messageboards.service.MBThreadLocalServiceUtil;
073 import com.liferay.portlet.messageboards.service.permission.MBMessagePermission;
074 import com.liferay.util.ContentUtil;
075 import com.liferay.util.mail.JavaMailUtil;
076
077 import java.io.InputStream;
078
079 import java.util.ArrayList;
080 import java.util.Calendar;
081 import java.util.Collections;
082 import java.util.Date;
083 import java.util.HashMap;
084 import java.util.HashSet;
085 import java.util.List;
086 import java.util.Map;
087 import java.util.Set;
088 import java.util.concurrent.Callable;
089
090 import javax.mail.BodyPart;
091 import javax.mail.Message;
092 import javax.mail.Part;
093 import javax.mail.internet.MimeMessage;
094 import javax.mail.internet.MimeMultipart;
095
096 import javax.portlet.PortletPreferences;
097 import javax.portlet.PortletRequest;
098 import javax.portlet.PortletURL;
099 import javax.portlet.RenderResponse;
100
101 import javax.servlet.http.HttpServletRequest;
102
103
106 public class MBUtil {
107
108 public static final String BB_CODE_EDITOR_WYSIWYG_IMPL_KEY =
109 "editor.wysiwyg.portal-web.docroot.html.portlet.message_boards." +
110 "edit_message.bb_code.jsp";
111
112 public static final String MESSAGE_POP_PORTLET_PREFIX = "mb_message.";
113
114 public static void addPortletBreadcrumbEntries(
115 long categoryId, HttpServletRequest request,
116 RenderResponse renderResponse)
117 throws Exception {
118
119 if ((categoryId == MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) ||
120 (categoryId == MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
121
122 return;
123 }
124
125 MBCategory category = MBCategoryLocalServiceUtil.getCategory(
126 categoryId);
127
128 addPortletBreadcrumbEntries(category, request, renderResponse);
129 }
130
131 public static void addPortletBreadcrumbEntries(
132 MBCategory category, HttpServletRequest request,
133 RenderResponse renderResponse)
134 throws Exception {
135
136 String strutsAction = ParamUtil.getString(request, "struts_action");
137
138 PortletURL portletURL = renderResponse.createRenderURL();
139
140 if (strutsAction.equals("/message_boards/select_category") ||
141 strutsAction.equals("/message_boards_admin/select_category")) {
142
143 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
144 WebKeys.THEME_DISPLAY);
145
146 portletURL.setParameter(
147 "struts_action", "/message_boards/select_category");
148 portletURL.setWindowState(LiferayWindowState.POP_UP);
149
150 PortalUtil.addPortletBreadcrumbEntry(
151 request, themeDisplay.translate("categories"),
152 portletURL.toString());
153 }
154 else {
155 portletURL.setParameter("struts_action", "/message_boards/view");
156 }
157
158 List<MBCategory> ancestorCategories = category.getAncestors();
159
160 Collections.reverse(ancestorCategories);
161
162 for (MBCategory curCategory : ancestorCategories) {
163 portletURL.setParameter(
164 "mbCategoryId", String.valueOf(curCategory.getCategoryId()));
165
166 PortalUtil.addPortletBreadcrumbEntry(
167 request, curCategory.getName(), portletURL.toString());
168 }
169
170 portletURL.setParameter(
171 "mbCategoryId", String.valueOf(category.getCategoryId()));
172
173 PortalUtil.addPortletBreadcrumbEntry(
174 request, category.getName(), portletURL.toString());
175 }
176
177 public static void addPortletBreadcrumbEntries(
178 MBMessage message, HttpServletRequest request,
179 RenderResponse renderResponse)
180 throws Exception {
181
182 if (message.getCategoryId() ==
183 MBCategoryConstants.DISCUSSION_CATEGORY_ID) {
184
185 return;
186 }
187
188 if (message.getCategoryId() !=
189 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
190
191 addPortletBreadcrumbEntries(
192 message.getCategory(), request, renderResponse);
193 }
194
195 PortletURL portletURL = renderResponse.createRenderURL();
196
197 portletURL.setParameter(
198 "struts_action", "/message_boards/view_message");
199 portletURL.setParameter(
200 "messageId", String.valueOf(message.getMessageId()));
201
202 PortalUtil.addPortletBreadcrumbEntry(
203 request, message.getSubject(), portletURL.toString());
204 }
205
206 public static void collectMultipartContent(
207 MimeMultipart multipart, MBMailMessage collector)
208 throws Exception {
209
210 for (int i = 0; i < multipart.getCount(); i++) {
211 BodyPart part = multipart.getBodyPart(i);
212
213 collectPartContent(part, collector);
214 }
215 }
216
217 public static void collectPartContent(
218 Part part, MBMailMessage mbMailMessage)
219 throws Exception {
220
221 Object partContent = part.getContent();
222
223 String contentType = StringUtil.toLowerCase(part.getContentType());
224
225 if ((part.getDisposition() != null) &&
226 StringUtil.equalsIgnoreCase(
227 part.getDisposition(), MimeMessage.ATTACHMENT)) {
228
229 if (_log.isDebugEnabled()) {
230 _log.debug("Processing attachment");
231 }
232
233 byte[] bytes = null;
234
235 if (partContent instanceof String) {
236 bytes = ((String)partContent).getBytes();
237 }
238 else if (partContent instanceof InputStream) {
239 bytes = JavaMailUtil.getBytes(part);
240 }
241
242 mbMailMessage.addBytes(part.getFileName(), bytes);
243 }
244 else {
245 if (partContent instanceof MimeMultipart) {
246 MimeMultipart mimeMultipart = (MimeMultipart)partContent;
247
248 collectMultipartContent(mimeMultipart, mbMailMessage);
249 }
250 else if (partContent instanceof String) {
251 Map<String, Object> options = new HashMap<String, Object>();
252
253 options.put("emailPartToMBMessageBody", Boolean.TRUE);
254
255 String messageBody = SanitizerUtil.sanitize(
256 0, 0, 0, MBMessage.class.getName(), 0, contentType,
257 Sanitizer.MODE_ALL, (String)partContent, options);
258
259 if (contentType.startsWith(ContentTypes.TEXT_HTML)) {
260 mbMailMessage.setHtmlBody(messageBody);
261 }
262 else {
263 mbMailMessage.setPlainBody(messageBody);
264 }
265 }
266 }
267 }
268
269 public static String getAbsolutePath(
270 PortletRequest portletRequest, long mbCategoryId)
271 throws PortalException, SystemException {
272
273 ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
274 WebKeys.THEME_DISPLAY);
275
276 if (mbCategoryId == MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
277 return themeDisplay.translate("home");
278 }
279
280 MBCategory mbCategory = MBCategoryLocalServiceUtil.fetchMBCategory(
281 mbCategoryId);
282
283 List<MBCategory> categories = mbCategory.getAncestors();
284
285 Collections.reverse(categories);
286
287 StringBundler sb = new StringBundler((categories.size() * 3) + 5);
288
289 sb.append(themeDisplay.translate("home"));
290 sb.append(StringPool.SPACE);
291
292 for (MBCategory curCategory : categories) {
293 sb.append(StringPool.RAQUO);
294 sb.append(StringPool.SPACE);
295 sb.append(curCategory.getName());
296 }
297
298 sb.append(StringPool.RAQUO);
299 sb.append(StringPool.SPACE);
300 sb.append(mbCategory.getName());
301
302 return sb.toString();
303 }
304
305 public static long getCategoryId(
306 HttpServletRequest request, MBCategory category) {
307
308 long categoryId = MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID;
309
310 if (category != null) {
311 categoryId = category.getCategoryId();
312 }
313
314 categoryId = ParamUtil.getLong(request, "mbCategoryId", categoryId);
315
316 return categoryId;
317 }
318
319 public static long getCategoryId(
320 HttpServletRequest request, MBMessage message) {
321
322 long categoryId = MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID;
323
324 if (message != null) {
325 categoryId = message.getCategoryId();
326 }
327
328 categoryId = ParamUtil.getLong(request, "mbCategoryId", categoryId);
329
330 return categoryId;
331 }
332
333 public static Set<Long> getCategorySubscriptionClassPKs(long userId)
334 throws SystemException {
335
336 List<Subscription> subscriptions =
337 SubscriptionLocalServiceUtil.getUserSubscriptions(
338 userId, MBCategory.class.getName());
339
340 Set<Long> classPKs = new HashSet<Long>(subscriptions.size());
341
342 for (Subscription subscription : subscriptions) {
343 classPKs.add(subscription.getClassPK());
344 }
345
346 return classPKs;
347 }
348
349 public static String getEmailFromAddress(
350 PortletPreferences preferences, long companyId)
351 throws SystemException {
352
353 return PortalUtil.getEmailFromAddress(
354 preferences, companyId,
355 PropsValues.MESSAGE_BOARDS_EMAIL_FROM_ADDRESS);
356 }
357
358 public static String getEmailFromName(
359 PortletPreferences preferences, long companyId)
360 throws SystemException {
361
362 return PortalUtil.getEmailFromName(
363 preferences, companyId, PropsValues.MESSAGE_BOARDS_EMAIL_FROM_NAME);
364 }
365
366 public static boolean getEmailHtmlFormat(PortletPreferences preferences) {
367 String emailHtmlFormat = preferences.getValue(
368 "emailHtmlFormat", StringPool.BLANK);
369
370 if (Validator.isNotNull(emailHtmlFormat)) {
371 return GetterUtil.getBoolean(emailHtmlFormat);
372 }
373 else {
374 return PropsValues.MESSAGE_BOARDS_EMAIL_HTML_FORMAT;
375 }
376 }
377
378 public static String getEmailMessageAddedBody(
379 PortletPreferences preferences) {
380
381 String emailMessageAddedBody = preferences.getValue(
382 "emailMessageAddedBody", StringPool.BLANK);
383
384 if (Validator.isNotNull(emailMessageAddedBody)) {
385 return emailMessageAddedBody;
386 }
387 else {
388 return ContentUtil.get(
389 PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_ADDED_BODY);
390 }
391 }
392
393 public static boolean getEmailMessageAddedEnabled(
394 PortletPreferences preferences) {
395
396 String emailMessageAddedEnabled = preferences.getValue(
397 "emailMessageAddedEnabled", StringPool.BLANK);
398
399 if (Validator.isNotNull(emailMessageAddedEnabled)) {
400 return GetterUtil.getBoolean(emailMessageAddedEnabled);
401 }
402 else {
403 return PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_ADDED_ENABLED;
404 }
405 }
406
407 public static String getEmailMessageAddedSignature(
408 PortletPreferences preferences) {
409
410 String emailMessageAddedSignature = preferences.getValue(
411 "emailMessageAddedSignature", StringPool.BLANK);
412
413 if (Validator.isNotNull(emailMessageAddedSignature)) {
414 return emailMessageAddedSignature;
415 }
416 else {
417 return ContentUtil.get(
418 PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_ADDED_SIGNATURE);
419 }
420 }
421
422 public static String getEmailMessageAddedSubject(
423 PortletPreferences preferences) {
424
425 String emailMessageAddedSubject = preferences.getValue(
426 "emailMessageAddedSubject", StringPool.BLANK);
427
428 if (Validator.isNotNull(emailMessageAddedSubject)) {
429 return emailMessageAddedSubject;
430 }
431 else {
432 return ContentUtil.get(
433 PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_ADDED_SUBJECT);
434 }
435 }
436
437 public static String getEmailMessageUpdatedBody(
438 PortletPreferences preferences) {
439
440 String emailMessageUpdatedBody = preferences.getValue(
441 "emailMessageUpdatedBody", StringPool.BLANK);
442
443 if (Validator.isNotNull(emailMessageUpdatedBody)) {
444 return emailMessageUpdatedBody;
445 }
446 else {
447 return ContentUtil.get(
448 PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_UPDATED_BODY);
449 }
450 }
451
452 public static boolean getEmailMessageUpdatedEnabled(
453 PortletPreferences preferences) {
454
455 String emailMessageUpdatedEnabled = preferences.getValue(
456 "emailMessageUpdatedEnabled", StringPool.BLANK);
457
458 if (Validator.isNotNull(emailMessageUpdatedEnabled)) {
459 return GetterUtil.getBoolean(emailMessageUpdatedEnabled);
460 }
461 else {
462 return PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_UPDATED_ENABLED;
463 }
464 }
465
466 public static String getEmailMessageUpdatedSignature(
467 PortletPreferences preferences) {
468
469 String emailMessageUpdatedSignature = preferences.getValue(
470 "emailMessageUpdatedSignature", StringPool.BLANK);
471
472 if (Validator.isNotNull(emailMessageUpdatedSignature)) {
473 return emailMessageUpdatedSignature;
474 }
475 else {
476 return ContentUtil.get(
477 PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_UPDATED_SIGNATURE);
478 }
479 }
480
481 public static String getEmailMessageUpdatedSubject(
482 PortletPreferences preferences) {
483
484 String emailMessageUpdatedSubject = preferences.getValue(
485 "emailMessageUpdatedSubject", StringPool.BLANK);
486
487 if (Validator.isNotNull(emailMessageUpdatedSubject)) {
488 return emailMessageUpdatedSubject;
489 }
490 else {
491 return ContentUtil.get(
492 PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_UPDATED_SUBJECT);
493 }
494 }
495
496 public static List<Object> getEntries(Hits hits) {
497 List<Object> entries = new ArrayList<Object>();
498
499 for (Document document : hits.getDocs()) {
500 long categoryId = GetterUtil.getLong(
501 document.get(Field.CATEGORY_ID));
502
503 try {
504 MBCategoryLocalServiceUtil.getCategory(categoryId);
505 }
506 catch (Exception e) {
507 if (_log.isWarnEnabled()) {
508 _log.warn(
509 "Message boards search index is stale and contains " +
510 "category " + categoryId);
511 }
512
513 continue;
514 }
515
516 long threadId = GetterUtil.getLong(document.get("threadId"));
517
518 try {
519 MBThreadLocalServiceUtil.getThread(threadId);
520 }
521 catch (Exception e) {
522 if (_log.isWarnEnabled()) {
523 _log.warn(
524 "Message boards search index is stale and contains " +
525 "thread " + threadId);
526 }
527
528 continue;
529 }
530
531 String entryClassName = document.get(Field.ENTRY_CLASS_NAME);
532 long entryClassPK = GetterUtil.getLong(
533 document.get(Field.ENTRY_CLASS_PK));
534
535 Object obj = null;
536
537 try {
538 if (entryClassName.equals(DLFileEntry.class.getName())) {
539 long classPK = GetterUtil.getLong(
540 document.get(Field.CLASS_PK));
541
542 MBMessageLocalServiceUtil.getMessage(classPK);
543
544 obj = DLFileEntryLocalServiceUtil.getDLFileEntry(
545 entryClassPK);
546 }
547 else if (entryClassName.equals(MBMessage.class.getName())) {
548 obj = MBMessageLocalServiceUtil.getMessage(entryClassPK);
549 }
550
551 entries.add(obj);
552 }
553 catch (Exception e) {
554 if (_log.isWarnEnabled()) {
555 _log.warn(
556 "Message boards search index is stale and contains " +
557 "entry {className=" + entryClassName + ", " +
558 "classPK=" + entryClassPK + "}");
559 }
560
561 continue;
562 }
563 }
564
565 return entries;
566 }
567
568 public static String getMessageFormat(PortletPreferences preferences) {
569 String messageFormat = preferences.getValue(
570 "messageFormat", MBMessageConstants.DEFAULT_FORMAT);
571
572 if (isValidMessageFormat(messageFormat)) {
573 return messageFormat;
574 }
575
576 return "html";
577 }
578
579 public static long getMessageId(String mailId) {
580 int x = mailId.indexOf(CharPool.LESS_THAN) + 1;
581 int y = mailId.indexOf(CharPool.AT);
582
583 long messageId = 0;
584
585 if ((x > 0 ) && (y != -1)) {
586 String temp = mailId.substring(x, y);
587
588 int z = temp.lastIndexOf(CharPool.PERIOD);
589
590 if (z != -1) {
591 messageId = GetterUtil.getLong(temp.substring(z + 1));
592 }
593 }
594
595 return messageId;
596 }
597
598 public static long getParentMessageId(Message message) throws Exception {
599 long parentMessageId = -1;
600
601 String parentHeader = getParentMessageIdString(message);
602
603 if (parentHeader != null) {
604 if (_log.isDebugEnabled()) {
605 _log.debug("Parent header " + parentHeader);
606 }
607
608 parentMessageId = getMessageId(parentHeader);
609
610 if (_log.isDebugEnabled()) {
611 _log.debug("Previous message id " + parentMessageId);
612 }
613 }
614
615 return parentMessageId;
616 }
617
618 public static String getParentMessageIdString(Message message)
619 throws Exception {
620
621
622
623
624
625
626 String parentHeader = null;
627
628 String[] references = message.getHeader("References");
629
630 if (ArrayUtil.isNotEmpty(references)) {
631 String reference = references[0];
632
633 int x = reference.lastIndexOf("<mb.");
634
635 if (x > -1) {
636 int y = reference.indexOf(">", x);
637
638 parentHeader = reference.substring(x, y);
639 }
640 }
641
642 if (parentHeader == null) {
643 String[] inReplyToHeaders = message.getHeader("In-Reply-To");
644
645 if (ArrayUtil.isNotEmpty(inReplyToHeaders)) {
646 parentHeader = inReplyToHeaders[0];
647 }
648 }
649
650 if (Validator.isNull(parentHeader) ||
651 !parentHeader.startsWith(MESSAGE_POP_PORTLET_PREFIX, 1)) {
652
653 parentHeader = _getParentMessageIdFromSubject(message);
654 }
655
656 return parentHeader;
657 }
658
659 public static String getReplyToAddress(
660 long categoryId, long messageId, String mx,
661 String defaultMailingListAddress) {
662
663 if (PropsValues.POP_SERVER_SUBDOMAIN.length() <= 0) {
664 return defaultMailingListAddress;
665 }
666
667 StringBundler sb = new StringBundler(8);
668
669 sb.append(MESSAGE_POP_PORTLET_PREFIX);
670 sb.append(categoryId);
671 sb.append(StringPool.PERIOD);
672 sb.append(messageId);
673 sb.append(StringPool.AT);
674 sb.append(PropsValues.POP_SERVER_SUBDOMAIN);
675 sb.append(StringPool.PERIOD);
676 sb.append(mx);
677
678 return sb.toString();
679 }
680
681 public static String getSubjectWithoutMessageId(Message message)
682 throws Exception {
683
684 String subject = message.getSubject();
685
686 String parentMessageId = _getParentMessageIdFromSubject(message);
687
688 if (Validator.isNotNull(parentMessageId)) {
689 int pos = subject.indexOf(parentMessageId);
690
691 if (pos != -1) {
692 subject = subject.substring(0, pos);
693 }
694 }
695
696 return subject;
697 }
698
699 public static String[] getThreadPriority(
700 PortletPreferences preferences, String languageId, double value,
701 ThemeDisplay themeDisplay)
702 throws Exception {
703
704 String[] priorities = LocalizationUtil.getPreferencesValues(
705 preferences, "priorities", languageId);
706
707 String[] priorityPair = _findThreadPriority(
708 value, themeDisplay, priorities);
709
710 if (priorityPair == null) {
711 String defaultLanguageId = LocaleUtil.toLanguageId(
712 LocaleUtil.getSiteDefault());
713
714 priorities = LocalizationUtil.getPreferencesValues(
715 preferences, "priorities", defaultLanguageId);
716
717 priorityPair = _findThreadPriority(value, themeDisplay, priorities);
718 }
719
720 return priorityPair;
721 }
722
723 public static Set<Long> getThreadSubscriptionClassPKs(long userId)
724 throws SystemException {
725
726 List<Subscription> subscriptions =
727 SubscriptionLocalServiceUtil.getUserSubscriptions(
728 userId, MBThread.class.getName());
729
730 Set<Long> classPKs = new HashSet<Long>(subscriptions.size());
731
732 for (Subscription subscription : subscriptions) {
733 classPKs.add(subscription.getClassPK());
734 }
735
736 return classPKs;
737 }
738
739 public static Date getUnbanDate(MBBan ban, int expireInterval) {
740 Date banDate = ban.getCreateDate();
741
742 Calendar cal = Calendar.getInstance();
743
744 cal.setTime(banDate);
745
746 cal.add(Calendar.DATE, expireInterval);
747
748 return cal.getTime();
749 }
750
751 public static String getUserRank(
752 PortletPreferences preferences, String languageId, int posts)
753 throws Exception {
754
755 String rank = StringPool.BLANK;
756
757 String[] ranks = LocalizationUtil.getPreferencesValues(
758 preferences, "ranks", languageId);
759
760 for (int i = 0; i < ranks.length; i++) {
761 String[] kvp = StringUtil.split(ranks[i], CharPool.EQUAL);
762
763 String kvpName = kvp[0];
764 int kvpPosts = GetterUtil.getInteger(kvp[1]);
765
766 if (posts >= kvpPosts) {
767 rank = kvpName;
768 }
769 else {
770 break;
771 }
772 }
773
774 return rank;
775 }
776
777 public static String[] getUserRank(
778 PortletPreferences preferences, String languageId,
779 MBStatsUser statsUser)
780 throws Exception {
781
782 String[] rank = {StringPool.BLANK, StringPool.BLANK};
783
784 int maxPosts = 0;
785
786 Group group = GroupLocalServiceUtil.getGroup(statsUser.getGroupId());
787
788 long companyId = group.getCompanyId();
789
790 String[] ranks = LocalizationUtil.getPreferencesValues(
791 preferences, "ranks", languageId);
792
793 for (int i = 0; i < ranks.length; i++) {
794 String[] kvp = StringUtil.split(ranks[i], CharPool.EQUAL);
795
796 String curRank = kvp[0];
797 String curRankValue = kvp[1];
798
799 String[] curRankValueKvp = StringUtil.split(
800 curRankValue, CharPool.COLON);
801
802 if (curRankValueKvp.length <= 1) {
803 int posts = GetterUtil.getInteger(curRankValue);
804
805 if ((posts <= statsUser.getMessageCount()) &&
806 (posts >= maxPosts)) {
807
808 rank[0] = curRank;
809 maxPosts = posts;
810 }
811 }
812 else {
813 String entityType = curRankValueKvp[0];
814 String entityValue = curRankValueKvp[1];
815
816 try {
817 if (_isEntityRank(
818 companyId, statsUser, entityType, entityValue)) {
819
820 rank[1] = curRank;
821
822 break;
823 }
824 }
825 catch (Exception e) {
826 if (_log.isWarnEnabled()) {
827 _log.warn(e);
828 }
829 }
830 }
831 }
832
833 return rank;
834 }
835
836 public static boolean hasMailIdHeader(Message message) throws Exception {
837 String[] messageIds = message.getHeader("Message-ID");
838
839 if (messageIds == null) {
840 return false;
841 }
842
843 for (String messageId : messageIds) {
844 if (Validator.isNotNull(PropsValues.POP_SERVER_SUBDOMAIN) &&
845 messageId.contains(PropsValues.POP_SERVER_SUBDOMAIN)) {
846
847 return true;
848 }
849 }
850
851 return false;
852 }
853
854 public static boolean isAllowAnonymousPosting(
855 PortletPreferences preferences) {
856
857 return GetterUtil.getBoolean(
858 preferences.getValue("allowAnonymousPosting", null),
859 PropsValues.MESSAGE_BOARDS_ANONYMOUS_POSTING_ENABLED);
860 }
861
862 public static boolean isValidMessageFormat(String messageFormat) {
863 String editorImpl = PropsUtil.get(BB_CODE_EDITOR_WYSIWYG_IMPL_KEY);
864
865 if (messageFormat.equals("bbcode") &&
866 !(editorImpl.equals("bbcode") ||
867 editorImpl.equals("ckeditor_bbcode"))) {
868
869 return false;
870 }
871
872 return true;
873 }
874
875 public static boolean isViewableMessage(
876 ThemeDisplay themeDisplay, MBMessage message)
877 throws Exception {
878
879 return isViewableMessage(themeDisplay, message, message);
880 }
881
882 public static boolean isViewableMessage(
883 ThemeDisplay themeDisplay, MBMessage message,
884 MBMessage parentMessage)
885 throws Exception {
886
887 PermissionChecker permissionChecker =
888 themeDisplay.getPermissionChecker();
889
890 if (!MBMessagePermission.contains(
891 permissionChecker, parentMessage, ActionKeys.VIEW)) {
892
893 return false;
894 }
895
896 if ((message.getMessageId() != parentMessage.getMessageId()) &&
897 !MBMessagePermission.contains(
898 permissionChecker, message, ActionKeys.VIEW)) {
899
900 return false;
901 }
902
903 if (!message.isApproved() &&
904 !Validator.equals(message.getUserId(), themeDisplay.getUserId()) &&
905 !permissionChecker.isGroupAdmin(themeDisplay.getScopeGroupId())) {
906
907 return false;
908 }
909
910 return true;
911 }
912
913 public static String replaceMessageBodyPaths(
914 ThemeDisplay themeDisplay, String messageBody) {
915
916 return StringUtil.replace(
917 messageBody,
918 new String[] {
919 "@theme_images_path@", "href=\"/", "src=\"/"
920 },
921 new String[] {
922 themeDisplay.getPathThemeImages(),
923 "href=\"" + themeDisplay.getURLPortal() + "/",
924 "src=\"" + themeDisplay.getURLPortal() + "/"
925 });
926 }
927
928 public static void updateCategoryMessageCount(
929 long companyId, final long categoryId) {
930
931 Callable<Void> callable = new ShardCallable<Void>(companyId) {
932
933 @Override
934 protected Void doCall() throws Exception {
935 MBCategory category =
936 MBCategoryLocalServiceUtil.fetchMBCategory(categoryId);
937
938 if (category == null) {
939 return null;
940 }
941
942 int messageCount = _getMessageCount(category);
943
944 category.setMessageCount(messageCount);
945
946 MBCategoryLocalServiceUtil.updateMBCategory(category);
947
948 return null;
949 }
950
951 };
952
953 TransactionCommitCallbackRegistryUtil.registerCallback(callable);
954 }
955
956 public static void updateCategoryStatistics(
957 long companyId, final long categoryId) {
958
959 Callable<Void> callable = new ShardCallable<Void>(companyId) {
960
961 @Override
962 protected Void doCall() throws Exception {
963 MBCategory category =
964 MBCategoryLocalServiceUtil.fetchMBCategory(categoryId);
965
966 if (category == null) {
967 return null;
968 }
969
970 int messageCount = _getMessageCount(category);
971
972 int threadCount =
973 MBThreadLocalServiceUtil.getCategoryThreadsCount(
974 category.getGroupId(), category.getCategoryId(),
975 WorkflowConstants.STATUS_APPROVED);
976
977 category.setMessageCount(messageCount);
978 category.setThreadCount(threadCount);
979
980 MBCategoryLocalServiceUtil.updateMBCategory(category);
981
982 return null;
983 }
984
985 };
986
987 TransactionCommitCallbackRegistryUtil.registerCallback(callable);
988 }
989
990 public static void updateCategoryThreadCount(
991 long companyId, final long categoryId) {
992
993 Callable<Void> callable = new ShardCallable<Void>(companyId) {
994
995 @Override
996 protected Void doCall() throws Exception {
997 MBCategory category =
998 MBCategoryLocalServiceUtil.fetchMBCategory(categoryId);
999
1000 if (category == null) {
1001 return null;
1002 }
1003
1004 int threadCount =
1005 MBThreadLocalServiceUtil.getCategoryThreadsCount(
1006 category.getGroupId(), category.getCategoryId(),
1007 WorkflowConstants.STATUS_APPROVED);
1008
1009 category.setThreadCount(threadCount);
1010
1011 MBCategoryLocalServiceUtil.updateMBCategory(category);
1012
1013 return null;
1014 }
1015
1016 };
1017
1018 TransactionCommitCallbackRegistryUtil.registerCallback(callable);
1019 }
1020
1021 public static void updateThreadMessageCount(
1022 long companyId, final long threadId) {
1023
1024 Callable<Void> callable = new ShardCallable<Void>(companyId) {
1025
1026 @Override
1027 protected Void doCall() throws Exception {
1028 MBThread thread = MBThreadLocalServiceUtil.fetchThread(
1029 threadId);
1030
1031 if (thread == null) {
1032 return null;
1033 }
1034
1035 int messageCount =
1036 MBMessageLocalServiceUtil.getThreadMessagesCount(
1037 threadId, WorkflowConstants.STATUS_APPROVED);
1038
1039 thread.setMessageCount(messageCount);
1040
1041 MBThreadLocalServiceUtil.updateMBThread(thread);
1042
1043 return null;
1044 }
1045
1046 };
1047
1048 TransactionCommitCallbackRegistryUtil.registerCallback(callable);
1049 }
1050
1051 private static String[] _findThreadPriority(
1052 double value, ThemeDisplay themeDisplay, String[] priorities) {
1053
1054 for (int i = 0; i < priorities.length; i++) {
1055 String[] priority = StringUtil.split(priorities[i]);
1056
1057 try {
1058 String priorityName = priority[0];
1059 String priorityImage = priority[1];
1060 double priorityValue = GetterUtil.getDouble(priority[2]);
1061
1062 if (value == priorityValue) {
1063 if (!priorityImage.startsWith(Http.HTTP)) {
1064 priorityImage =
1065 themeDisplay.getPathThemeImages() + priorityImage;
1066 }
1067
1068 return new String[] {priorityName, priorityImage};
1069 }
1070 }
1071 catch (Exception e) {
1072 _log.error("Unable to determine thread priority", e);
1073 }
1074 }
1075
1076 return null;
1077 }
1078
1079 private static int _getMessageCount(MBCategory category)
1080 throws SystemException {
1081
1082 return MBMessageLocalServiceUtil.getCategoryMessagesCount(
1083 category.getGroupId(), category.getCategoryId(),
1084 WorkflowConstants.STATUS_APPROVED);
1085 }
1086
1087 private static String _getParentMessageIdFromSubject(Message message)
1088 throws Exception {
1089
1090 if (message.getSubject() == null) {
1091 return null;
1092 }
1093
1094 String parentMessageId = null;
1095
1096 String subject = StringUtil.reverse(message.getSubject());
1097
1098 int pos = subject.indexOf(CharPool.LESS_THAN);
1099
1100 if (pos != -1) {
1101 parentMessageId = StringUtil.reverse(subject.substring(0, pos + 1));
1102 }
1103
1104 return parentMessageId;
1105 }
1106
1107 private static boolean _isEntityRank(
1108 long companyId, MBStatsUser statsUser, String entityType,
1109 String entityValue)
1110 throws Exception {
1111
1112 long groupId = statsUser.getGroupId();
1113 long userId = statsUser.getUserId();
1114
1115 if (entityType.equals("organization-role") ||
1116 entityType.equals("site-role")) {
1117
1118 Role role = RoleLocalServiceUtil.getRole(companyId, entityValue);
1119
1120 if (UserGroupRoleLocalServiceUtil.hasUserGroupRole(
1121 userId, groupId, role.getRoleId(), true)) {
1122
1123 return true;
1124 }
1125 }
1126 else if (entityType.equals("organization")) {
1127 Organization organization =
1128 OrganizationLocalServiceUtil.getOrganization(
1129 companyId, entityValue);
1130
1131 if (OrganizationLocalServiceUtil.hasUserOrganization(
1132 userId, organization.getOrganizationId(), false, false)) {
1133
1134 return true;
1135 }
1136 }
1137 else if (entityType.equals("regular-role")) {
1138 if (RoleLocalServiceUtil.hasUserRole(
1139 userId, companyId, entityValue, true)) {
1140
1141 return true;
1142 }
1143 }
1144 else if (entityType.equals("user-group")) {
1145 UserGroup userGroup = UserGroupLocalServiceUtil.getUserGroup(
1146 companyId, entityValue);
1147
1148 if (UserLocalServiceUtil.hasUserGroupUser(
1149 userGroup.getUserGroupId(), userId)) {
1150
1151 return true;
1152 }
1153 }
1154
1155 return false;
1156 }
1157
1158 private static Log _log = LogFactoryUtil.getLog(MBUtil.class);
1159
1160 }