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 long getCategoryId(String messageIdString) {
339 String[] parts = _getMessageIdStringParts(messageIdString);
340
341 return GetterUtil.getLong(parts[0]);
342 }
343
344 public static Set<Long> getCategorySubscriptionClassPKs(long userId)
345 throws SystemException {
346
347 List<Subscription> subscriptions =
348 SubscriptionLocalServiceUtil.getUserSubscriptions(
349 userId, MBCategory.class.getName());
350
351 Set<Long> classPKs = new HashSet<Long>(subscriptions.size());
352
353 for (Subscription subscription : subscriptions) {
354 classPKs.add(subscription.getClassPK());
355 }
356
357 return classPKs;
358 }
359
360 public static String getEmailFromAddress(
361 PortletPreferences preferences, long companyId)
362 throws SystemException {
363
364 return PortalUtil.getEmailFromAddress(
365 preferences, companyId,
366 PropsValues.MESSAGE_BOARDS_EMAIL_FROM_ADDRESS);
367 }
368
369 public static String getEmailFromName(
370 PortletPreferences preferences, long companyId)
371 throws SystemException {
372
373 return PortalUtil.getEmailFromName(
374 preferences, companyId, PropsValues.MESSAGE_BOARDS_EMAIL_FROM_NAME);
375 }
376
377 public static boolean getEmailHtmlFormat(PortletPreferences preferences) {
378 String emailHtmlFormat = preferences.getValue(
379 "emailHtmlFormat", StringPool.BLANK);
380
381 if (Validator.isNotNull(emailHtmlFormat)) {
382 return GetterUtil.getBoolean(emailHtmlFormat);
383 }
384 else {
385 return PropsValues.MESSAGE_BOARDS_EMAIL_HTML_FORMAT;
386 }
387 }
388
389 public static String getEmailMessageAddedBody(
390 PortletPreferences preferences) {
391
392 String emailMessageAddedBody = preferences.getValue(
393 "emailMessageAddedBody", StringPool.BLANK);
394
395 if (Validator.isNotNull(emailMessageAddedBody)) {
396 return emailMessageAddedBody;
397 }
398 else {
399 return ContentUtil.get(
400 PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_ADDED_BODY);
401 }
402 }
403
404 public static boolean getEmailMessageAddedEnabled(
405 PortletPreferences preferences) {
406
407 String emailMessageAddedEnabled = preferences.getValue(
408 "emailMessageAddedEnabled", StringPool.BLANK);
409
410 if (Validator.isNotNull(emailMessageAddedEnabled)) {
411 return GetterUtil.getBoolean(emailMessageAddedEnabled);
412 }
413 else {
414 return PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_ADDED_ENABLED;
415 }
416 }
417
418 public static String getEmailMessageAddedSignature(
419 PortletPreferences preferences) {
420
421 String emailMessageAddedSignature = preferences.getValue(
422 "emailMessageAddedSignature", StringPool.BLANK);
423
424 if (Validator.isNotNull(emailMessageAddedSignature)) {
425 return emailMessageAddedSignature;
426 }
427 else {
428 return ContentUtil.get(
429 PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_ADDED_SIGNATURE);
430 }
431 }
432
433 public static String getEmailMessageAddedSubject(
434 PortletPreferences preferences) {
435
436 String emailMessageAddedSubject = preferences.getValue(
437 "emailMessageAddedSubject", StringPool.BLANK);
438
439 if (Validator.isNotNull(emailMessageAddedSubject)) {
440 return emailMessageAddedSubject;
441 }
442 else {
443 return ContentUtil.get(
444 PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_ADDED_SUBJECT);
445 }
446 }
447
448 public static String getEmailMessageUpdatedBody(
449 PortletPreferences preferences) {
450
451 String emailMessageUpdatedBody = preferences.getValue(
452 "emailMessageUpdatedBody", StringPool.BLANK);
453
454 if (Validator.isNotNull(emailMessageUpdatedBody)) {
455 return emailMessageUpdatedBody;
456 }
457 else {
458 return ContentUtil.get(
459 PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_UPDATED_BODY);
460 }
461 }
462
463 public static boolean getEmailMessageUpdatedEnabled(
464 PortletPreferences preferences) {
465
466 String emailMessageUpdatedEnabled = preferences.getValue(
467 "emailMessageUpdatedEnabled", StringPool.BLANK);
468
469 if (Validator.isNotNull(emailMessageUpdatedEnabled)) {
470 return GetterUtil.getBoolean(emailMessageUpdatedEnabled);
471 }
472 else {
473 return PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_UPDATED_ENABLED;
474 }
475 }
476
477 public static String getEmailMessageUpdatedSignature(
478 PortletPreferences preferences) {
479
480 String emailMessageUpdatedSignature = preferences.getValue(
481 "emailMessageUpdatedSignature", StringPool.BLANK);
482
483 if (Validator.isNotNull(emailMessageUpdatedSignature)) {
484 return emailMessageUpdatedSignature;
485 }
486 else {
487 return ContentUtil.get(
488 PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_UPDATED_SIGNATURE);
489 }
490 }
491
492 public static String getEmailMessageUpdatedSubject(
493 PortletPreferences preferences) {
494
495 String emailMessageUpdatedSubject = preferences.getValue(
496 "emailMessageUpdatedSubject", StringPool.BLANK);
497
498 if (Validator.isNotNull(emailMessageUpdatedSubject)) {
499 return emailMessageUpdatedSubject;
500 }
501 else {
502 return ContentUtil.get(
503 PropsValues.MESSAGE_BOARDS_EMAIL_MESSAGE_UPDATED_SUBJECT);
504 }
505 }
506
507 public static List<Object> getEntries(Hits hits) {
508 List<Object> entries = new ArrayList<Object>();
509
510 for (Document document : hits.getDocs()) {
511 long categoryId = GetterUtil.getLong(
512 document.get(Field.CATEGORY_ID));
513
514 try {
515 MBCategoryLocalServiceUtil.getCategory(categoryId);
516 }
517 catch (Exception e) {
518 if (_log.isWarnEnabled()) {
519 _log.warn(
520 "Message boards search index is stale and contains " +
521 "category " + categoryId);
522 }
523
524 continue;
525 }
526
527 long threadId = GetterUtil.getLong(document.get("threadId"));
528
529 try {
530 MBThreadLocalServiceUtil.getThread(threadId);
531 }
532 catch (Exception e) {
533 if (_log.isWarnEnabled()) {
534 _log.warn(
535 "Message boards search index is stale and contains " +
536 "thread " + threadId);
537 }
538
539 continue;
540 }
541
542 String entryClassName = document.get(Field.ENTRY_CLASS_NAME);
543 long entryClassPK = GetterUtil.getLong(
544 document.get(Field.ENTRY_CLASS_PK));
545
546 Object obj = null;
547
548 try {
549 if (entryClassName.equals(DLFileEntry.class.getName())) {
550 long classPK = GetterUtil.getLong(
551 document.get(Field.CLASS_PK));
552
553 MBMessageLocalServiceUtil.getMessage(classPK);
554
555 obj = DLFileEntryLocalServiceUtil.getDLFileEntry(
556 entryClassPK);
557 }
558 else if (entryClassName.equals(MBMessage.class.getName())) {
559 obj = MBMessageLocalServiceUtil.getMessage(entryClassPK);
560 }
561
562 entries.add(obj);
563 }
564 catch (Exception e) {
565 if (_log.isWarnEnabled()) {
566 _log.warn(
567 "Message boards search index is stale and contains " +
568 "entry {className=" + entryClassName + ", " +
569 "classPK=" + entryClassPK + "}");
570 }
571
572 continue;
573 }
574 }
575
576 return entries;
577 }
578
579 public static String getMessageFormat(PortletPreferences preferences) {
580 String messageFormat = preferences.getValue(
581 "messageFormat", MBMessageConstants.DEFAULT_FORMAT);
582
583 if (isValidMessageFormat(messageFormat)) {
584 return messageFormat;
585 }
586
587 return "html";
588 }
589
590 public static long getMessageId(String messageIdString) {
591 String[] parts = _getMessageIdStringParts(messageIdString);
592
593 return GetterUtil.getLong(parts[1]);
594 }
595
596 public static int getMessageIdStringOffset() {
597 if (PropsValues.POP_SERVER_SUBDOMAIN.length() == 0) {
598 return 1;
599 }
600
601 return 0;
602 }
603
604 public static long getParentMessageId(Message message) throws Exception {
605 long parentMessageId = -1;
606
607 String parentMessageIdString = getParentMessageIdString(message);
608
609 if (parentMessageIdString != null) {
610 if (_log.isDebugEnabled()) {
611 _log.debug("Parent header " + parentMessageIdString);
612 }
613
614 parentMessageId = getMessageId(parentMessageIdString);
615
616 if (_log.isDebugEnabled()) {
617 _log.debug("Parent message id " + parentMessageId);
618 }
619 }
620
621 return parentMessageId;
622 }
623
624 public static String getParentMessageIdString(Message message)
625 throws Exception {
626
627
628
629
630
631
632 String parentHeader = null;
633
634 String[] references = message.getHeader("References");
635
636 if (ArrayUtil.isNotEmpty(references)) {
637 String reference = references[0];
638
639 int x = reference.lastIndexOf(
640 StringPool.LESS_THAN + MESSAGE_POP_PORTLET_PREFIX);
641
642 if (x > -1) {
643 int y = reference.indexOf(StringPool.GREATER_THAN, x);
644
645 parentHeader = reference.substring(x, y + 1);
646 }
647 }
648
649 if (parentHeader == null) {
650 String[] inReplyToHeaders = message.getHeader("In-Reply-To");
651
652 if (ArrayUtil.isNotEmpty(inReplyToHeaders)) {
653 parentHeader = inReplyToHeaders[0];
654 }
655 }
656
657 if (Validator.isNull(parentHeader) ||
658 !parentHeader.startsWith(MESSAGE_POP_PORTLET_PREFIX, 1)) {
659
660 parentHeader = _getParentMessageIdFromSubject(message);
661 }
662
663 return parentHeader;
664 }
665
666 public static String getReplyToAddress(
667 long categoryId, long messageId, String mx,
668 String defaultMailingListAddress) {
669
670 if (PropsValues.POP_SERVER_SUBDOMAIN.length() <= 0) {
671 return defaultMailingListAddress;
672 }
673
674 StringBundler sb = new StringBundler(8);
675
676 sb.append(MESSAGE_POP_PORTLET_PREFIX);
677 sb.append(categoryId);
678 sb.append(StringPool.PERIOD);
679 sb.append(messageId);
680 sb.append(StringPool.AT);
681 sb.append(PropsValues.POP_SERVER_SUBDOMAIN);
682 sb.append(StringPool.PERIOD);
683 sb.append(mx);
684
685 return sb.toString();
686 }
687
688 public static String getSubjectForEmail(MBMessage message)
689 throws Exception {
690
691 String subject = message.getSubject();
692
693 if (subject.startsWith("RE:")) {
694 return subject;
695 }
696 else {
697 return "RE: " + message.getSubject();
698 }
699 }
700
701 public static String getSubjectWithoutMessageId(Message message)
702 throws Exception {
703
704 String subject = message.getSubject();
705
706 String parentMessageId = _getParentMessageIdFromSubject(message);
707
708 if (Validator.isNotNull(parentMessageId)) {
709 int pos = subject.indexOf(parentMessageId);
710
711 if (pos != -1) {
712 subject = subject.substring(0, pos);
713 }
714 }
715
716 return subject;
717 }
718
719 public static String[] getThreadPriority(
720 PortletPreferences preferences, String languageId, double value,
721 ThemeDisplay themeDisplay)
722 throws Exception {
723
724 String[] priorities = LocalizationUtil.getPreferencesValues(
725 preferences, "priorities", languageId);
726
727 String[] priorityPair = _findThreadPriority(
728 value, themeDisplay, priorities);
729
730 if (priorityPair == null) {
731 String defaultLanguageId = LocaleUtil.toLanguageId(
732 LocaleUtil.getSiteDefault());
733
734 priorities = LocalizationUtil.getPreferencesValues(
735 preferences, "priorities", defaultLanguageId);
736
737 priorityPair = _findThreadPriority(value, themeDisplay, priorities);
738 }
739
740 return priorityPair;
741 }
742
743 public static Set<Long> getThreadSubscriptionClassPKs(long userId)
744 throws SystemException {
745
746 List<Subscription> subscriptions =
747 SubscriptionLocalServiceUtil.getUserSubscriptions(
748 userId, MBThread.class.getName());
749
750 Set<Long> classPKs = new HashSet<Long>(subscriptions.size());
751
752 for (Subscription subscription : subscriptions) {
753 classPKs.add(subscription.getClassPK());
754 }
755
756 return classPKs;
757 }
758
759 public static Date getUnbanDate(MBBan ban, int expireInterval) {
760 Date banDate = ban.getCreateDate();
761
762 Calendar cal = Calendar.getInstance();
763
764 cal.setTime(banDate);
765
766 cal.add(Calendar.DATE, expireInterval);
767
768 return cal.getTime();
769 }
770
771 public static String getUserRank(
772 PortletPreferences preferences, String languageId, int posts)
773 throws Exception {
774
775 String rank = StringPool.BLANK;
776
777 String[] ranks = LocalizationUtil.getPreferencesValues(
778 preferences, "ranks", languageId);
779
780 for (int i = 0; i < ranks.length; i++) {
781 String[] kvp = StringUtil.split(ranks[i], CharPool.EQUAL);
782
783 String kvpName = kvp[0];
784 int kvpPosts = GetterUtil.getInteger(kvp[1]);
785
786 if (posts >= kvpPosts) {
787 rank = kvpName;
788 }
789 else {
790 break;
791 }
792 }
793
794 return rank;
795 }
796
797 public static String[] getUserRank(
798 PortletPreferences preferences, String languageId,
799 MBStatsUser statsUser)
800 throws Exception {
801
802 String[] rank = {StringPool.BLANK, StringPool.BLANK};
803
804 int maxPosts = 0;
805
806 Group group = GroupLocalServiceUtil.getGroup(statsUser.getGroupId());
807
808 long companyId = group.getCompanyId();
809
810 String[] ranks = LocalizationUtil.getPreferencesValues(
811 preferences, "ranks", languageId);
812
813 for (int i = 0; i < ranks.length; i++) {
814 String[] kvp = StringUtil.split(ranks[i], CharPool.EQUAL);
815
816 String curRank = kvp[0];
817 String curRankValue = kvp[1];
818
819 String[] curRankValueKvp = StringUtil.split(
820 curRankValue, CharPool.COLON);
821
822 if (curRankValueKvp.length <= 1) {
823 int posts = GetterUtil.getInteger(curRankValue);
824
825 if ((posts <= statsUser.getMessageCount()) &&
826 (posts >= maxPosts)) {
827
828 rank[0] = curRank;
829 maxPosts = posts;
830 }
831 }
832 else {
833 String entityType = curRankValueKvp[0];
834 String entityValue = curRankValueKvp[1];
835
836 try {
837 if (_isEntityRank(
838 companyId, statsUser, entityType, entityValue)) {
839
840 rank[1] = curRank;
841
842 break;
843 }
844 }
845 catch (Exception e) {
846 if (_log.isWarnEnabled()) {
847 _log.warn(e);
848 }
849 }
850 }
851 }
852
853 return rank;
854 }
855
856 public static boolean hasMailIdHeader(Message message) throws Exception {
857 String[] messageIds = message.getHeader("Message-ID");
858
859 if (messageIds == null) {
860 return false;
861 }
862
863 for (String messageId : messageIds) {
864 if (Validator.isNotNull(PropsValues.POP_SERVER_SUBDOMAIN) &&
865 messageId.contains(PropsValues.POP_SERVER_SUBDOMAIN)) {
866
867 return true;
868 }
869 }
870
871 return false;
872 }
873
874 public static boolean isAllowAnonymousPosting(
875 PortletPreferences preferences) {
876
877 return GetterUtil.getBoolean(
878 preferences.getValue("allowAnonymousPosting", null),
879 PropsValues.MESSAGE_BOARDS_ANONYMOUS_POSTING_ENABLED);
880 }
881
882 public static boolean isValidMessageFormat(String messageFormat) {
883 String editorImpl = PropsUtil.get(BB_CODE_EDITOR_WYSIWYG_IMPL_KEY);
884
885 if (messageFormat.equals("bbcode") &&
886 !(editorImpl.equals("bbcode") ||
887 editorImpl.equals("ckeditor_bbcode"))) {
888
889 return false;
890 }
891
892 return true;
893 }
894
895 public static boolean isViewableMessage(
896 ThemeDisplay themeDisplay, MBMessage message)
897 throws Exception {
898
899 return isViewableMessage(themeDisplay, message, message);
900 }
901
902 public static boolean isViewableMessage(
903 ThemeDisplay themeDisplay, MBMessage message,
904 MBMessage parentMessage)
905 throws Exception {
906
907 PermissionChecker permissionChecker =
908 themeDisplay.getPermissionChecker();
909
910 if (!MBMessagePermission.contains(
911 permissionChecker, parentMessage, ActionKeys.VIEW)) {
912
913 return false;
914 }
915
916 if ((message.getMessageId() != parentMessage.getMessageId()) &&
917 !MBMessagePermission.contains(
918 permissionChecker, message, ActionKeys.VIEW)) {
919
920 return false;
921 }
922
923 if (!message.isApproved() &&
924 !Validator.equals(message.getUserId(), themeDisplay.getUserId()) &&
925 !permissionChecker.isGroupAdmin(themeDisplay.getScopeGroupId())) {
926
927 return false;
928 }
929
930 return true;
931 }
932
933 public static void propagatePermissions(
934 long companyId, long groupId, long parentMessageId,
935 ServiceContext serviceContext)
936 throws PortalException, SystemException {
937
938 MBMessage parentMessage = MBMessageLocalServiceUtil.getMBMessage(
939 parentMessageId);
940
941 Role defaultGroupRole = RoleLocalServiceUtil.getDefaultGroupRole(
942 groupId);
943 Role guestRole = RoleLocalServiceUtil.getRole(
944 companyId, RoleConstants.GUEST);
945
946 long[] roleIds = {defaultGroupRole.getRoleId(), guestRole.getRoleId()};
947
948 List<String> actionIds = ResourceActionsUtil.getModelResourceActions(
949 MBMessage.class.getName());
950
951 Map<Long, Set<String>> roleIdsToActionIds =
952 ResourcePermissionLocalServiceUtil.
953 getAvailableResourcePermissionActionIds(
954 companyId, MBMessage.class.getName(),
955 ResourceConstants.SCOPE_INDIVIDUAL,
956 String.valueOf(parentMessage.getMessageId()), roleIds,
957 actionIds);
958
959 Set<String> defaultGroupActionIds = roleIdsToActionIds.get(
960 defaultGroupRole.getRoleId());
961
962 if (defaultGroupActionIds == null) {
963 serviceContext.setGroupPermissions(new String[]{});
964 }
965 else {
966 serviceContext.setGroupPermissions(
967 defaultGroupActionIds.toArray(
968 new String[defaultGroupActionIds.size()]));
969 }
970
971 Set<String> guestActionIds = roleIdsToActionIds.get(
972 guestRole.getRoleId());
973
974 if (guestActionIds == null) {
975 serviceContext.setGuestPermissions(new String[]{});
976 }
977 else {
978 serviceContext.setGuestPermissions(
979 guestActionIds.toArray(new String[guestActionIds.size()]));
980 }
981 }
982
983 public static String replaceMessageBodyPaths(
984 ThemeDisplay themeDisplay, String messageBody) {
985
986 return StringUtil.replace(
987 messageBody,
988 new String[] {
989 "@theme_images_path@", "href=\"/", "src=\"/"
990 },
991 new String[] {
992 themeDisplay.getPathThemeImages(),
993 "href=\"" + themeDisplay.getURLPortal() + "/",
994 "src=\"" + themeDisplay.getURLPortal() + "/"
995 });
996 }
997
998 public static void updateCategoryMessageCount(
999 long companyId, final long categoryId) {
1000
1001 Callable<Void> callable = new ShardCallable<Void>(companyId) {
1002
1003 @Override
1004 protected Void doCall() throws Exception {
1005 MBCategory category =
1006 MBCategoryLocalServiceUtil.fetchMBCategory(categoryId);
1007
1008 if (category == null) {
1009 return null;
1010 }
1011
1012 int messageCount = _getMessageCount(category);
1013
1014 category.setMessageCount(messageCount);
1015
1016 MBCategoryLocalServiceUtil.updateMBCategory(category);
1017
1018 return null;
1019 }
1020
1021 };
1022
1023 TransactionCommitCallbackRegistryUtil.registerCallback(callable);
1024 }
1025
1026 public static void updateCategoryStatistics(
1027 long companyId, final long categoryId) {
1028
1029 Callable<Void> callable = new ShardCallable<Void>(companyId) {
1030
1031 @Override
1032 protected Void doCall() throws Exception {
1033 MBCategory category =
1034 MBCategoryLocalServiceUtil.fetchMBCategory(categoryId);
1035
1036 if (category == null) {
1037 return null;
1038 }
1039
1040 int messageCount = _getMessageCount(category);
1041
1042 int threadCount =
1043 MBThreadLocalServiceUtil.getCategoryThreadsCount(
1044 category.getGroupId(), category.getCategoryId(),
1045 WorkflowConstants.STATUS_APPROVED);
1046
1047 category.setMessageCount(messageCount);
1048 category.setThreadCount(threadCount);
1049
1050 MBCategoryLocalServiceUtil.updateMBCategory(category);
1051
1052 return null;
1053 }
1054
1055 };
1056
1057 TransactionCommitCallbackRegistryUtil.registerCallback(callable);
1058 }
1059
1060 public static void updateCategoryThreadCount(
1061 long companyId, final long categoryId) {
1062
1063 Callable<Void> callable = new ShardCallable<Void>(companyId) {
1064
1065 @Override
1066 protected Void doCall() throws Exception {
1067 MBCategory category =
1068 MBCategoryLocalServiceUtil.fetchMBCategory(categoryId);
1069
1070 if (category == null) {
1071 return null;
1072 }
1073
1074 int threadCount =
1075 MBThreadLocalServiceUtil.getCategoryThreadsCount(
1076 category.getGroupId(), category.getCategoryId(),
1077 WorkflowConstants.STATUS_APPROVED);
1078
1079 category.setThreadCount(threadCount);
1080
1081 MBCategoryLocalServiceUtil.updateMBCategory(category);
1082
1083 return null;
1084 }
1085
1086 };
1087
1088 TransactionCommitCallbackRegistryUtil.registerCallback(callable);
1089 }
1090
1091 public static void updateThreadMessageCount(
1092 long companyId, final long threadId) {
1093
1094 Callable<Void> callable = new ShardCallable<Void>(companyId) {
1095
1096 @Override
1097 protected Void doCall() throws Exception {
1098 MBThread thread = MBThreadLocalServiceUtil.fetchThread(
1099 threadId);
1100
1101 if (thread == null) {
1102 return null;
1103 }
1104
1105 int messageCount =
1106 MBMessageLocalServiceUtil.getThreadMessagesCount(
1107 threadId, WorkflowConstants.STATUS_APPROVED);
1108
1109 thread.setMessageCount(messageCount);
1110
1111 MBThreadLocalServiceUtil.updateMBThread(thread);
1112
1113 return null;
1114 }
1115
1116 };
1117
1118 TransactionCommitCallbackRegistryUtil.registerCallback(callable);
1119 }
1120
1121 private static String[] _findThreadPriority(
1122 double value, ThemeDisplay themeDisplay, String[] priorities) {
1123
1124 for (int i = 0; i < priorities.length; i++) {
1125 String[] priority = StringUtil.split(priorities[i]);
1126
1127 try {
1128 String priorityName = priority[0];
1129 String priorityImage = priority[1];
1130 double priorityValue = GetterUtil.getDouble(priority[2]);
1131
1132 if (value == priorityValue) {
1133 if (!priorityImage.startsWith(Http.HTTP)) {
1134 priorityImage =
1135 themeDisplay.getPathThemeImages() + priorityImage;
1136 }
1137
1138 return new String[] {priorityName, priorityImage};
1139 }
1140 }
1141 catch (Exception e) {
1142 _log.error("Unable to determine thread priority", e);
1143 }
1144 }
1145
1146 return null;
1147 }
1148
1149 private static int _getMessageCount(MBCategory category)
1150 throws SystemException {
1151
1152 return MBMessageLocalServiceUtil.getCategoryMessagesCount(
1153 category.getGroupId(), category.getCategoryId(),
1154 WorkflowConstants.STATUS_APPROVED);
1155 }
1156
1157 private static String[] _getMessageIdStringParts(String messageIdString) {
1158 int pos = messageIdString.indexOf(CharPool.AT);
1159
1160 return StringUtil.split(
1161 messageIdString.substring(
1162 MBUtil.MESSAGE_POP_PORTLET_PREFIX.length() +
1163 getMessageIdStringOffset(),
1164 pos),
1165 CharPool.PERIOD);
1166 }
1167
1168 private static String _getParentMessageIdFromSubject(Message message)
1169 throws Exception {
1170
1171 if (message.getSubject() == null) {
1172 return null;
1173 }
1174
1175 String parentMessageId = null;
1176
1177 String subject = StringUtil.reverse(message.getSubject());
1178
1179 int pos = subject.indexOf(CharPool.LESS_THAN);
1180
1181 if (pos != -1) {
1182 parentMessageId = StringUtil.reverse(subject.substring(0, pos + 1));
1183 }
1184
1185 return parentMessageId;
1186 }
1187
1188 private static boolean _isEntityRank(
1189 long companyId, MBStatsUser statsUser, String entityType,
1190 String entityValue)
1191 throws Exception {
1192
1193 long groupId = statsUser.getGroupId();
1194 long userId = statsUser.getUserId();
1195
1196 if (entityType.equals("organization-role") ||
1197 entityType.equals("site-role")) {
1198
1199 Role role = RoleLocalServiceUtil.getRole(companyId, entityValue);
1200
1201 if (UserGroupRoleLocalServiceUtil.hasUserGroupRole(
1202 userId, groupId, role.getRoleId(), true)) {
1203
1204 return true;
1205 }
1206 }
1207 else if (entityType.equals("organization")) {
1208 Organization organization =
1209 OrganizationLocalServiceUtil.getOrganization(
1210 companyId, entityValue);
1211
1212 if (OrganizationLocalServiceUtil.hasUserOrganization(
1213 userId, organization.getOrganizationId(), false, false)) {
1214
1215 return true;
1216 }
1217 }
1218 else if (entityType.equals("regular-role")) {
1219 if (RoleLocalServiceUtil.hasUserRole(
1220 userId, companyId, entityValue, true)) {
1221
1222 return true;
1223 }
1224 }
1225 else if (entityType.equals("user-group")) {
1226 UserGroup userGroup = UserGroupLocalServiceUtil.getUserGroup(
1227 companyId, entityValue);
1228
1229 if (UserLocalServiceUtil.hasUserGroupUser(
1230 userGroup.getUserGroupId(), userId)) {
1231
1232 return true;
1233 }
1234 }
1235
1236 return false;
1237 }
1238
1239 private static Log _log = LogFactoryUtil.getLog(MBUtil.class);
1240
1241 }