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