001
014
015 package com.liferay.portlet.wiki.util;
016
017 import com.liferay.portal.kernel.configuration.Filter;
018 import com.liferay.portal.kernel.exception.PortalException;
019 import com.liferay.portal.kernel.exception.SystemException;
020 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
021 import com.liferay.portal.kernel.portlet.LiferayPortletURL;
022 import com.liferay.portal.kernel.util.CharPool;
023 import com.liferay.portal.kernel.util.DiffHtmlUtil;
024 import com.liferay.portal.kernel.util.GetterUtil;
025 import com.liferay.portal.kernel.util.HttpUtil;
026 import com.liferay.portal.kernel.util.InstancePool;
027 import com.liferay.portal.kernel.util.ListUtil;
028 import com.liferay.portal.kernel.util.PropsKeys;
029 import com.liferay.portal.kernel.util.StringBundler;
030 import com.liferay.portal.kernel.util.StringPool;
031 import com.liferay.portal.kernel.util.StringUtil;
032 import com.liferay.portal.kernel.util.Validator;
033 import com.liferay.portal.security.permission.ActionKeys;
034 import com.liferay.portal.security.permission.PermissionChecker;
035 import com.liferay.portal.theme.ThemeDisplay;
036 import com.liferay.portal.util.ContentUtil;
037 import com.liferay.portal.util.PropsUtil;
038 import com.liferay.portal.util.PropsValues;
039 import com.liferay.portal.util.WebKeys;
040 import com.liferay.portlet.wiki.PageContentException;
041 import com.liferay.portlet.wiki.WikiFormatException;
042 import com.liferay.portlet.wiki.engines.WikiEngine;
043 import com.liferay.portlet.wiki.model.WikiNode;
044 import com.liferay.portlet.wiki.model.WikiPage;
045 import com.liferay.portlet.wiki.service.WikiNodeLocalServiceUtil;
046 import com.liferay.portlet.wiki.service.permission.WikiNodePermission;
047
048 import java.io.IOException;
049
050 import java.util.ArrayList;
051 import java.util.Arrays;
052 import java.util.Collections;
053 import java.util.HashMap;
054 import java.util.Iterator;
055 import java.util.List;
056 import java.util.Map;
057 import java.util.regex.Matcher;
058 import java.util.regex.Pattern;
059
060 import javax.portlet.PortletPreferences;
061 import javax.portlet.PortletRequest;
062 import javax.portlet.PortletURL;
063
064
068 public class WikiUtil {
069
070 public static final String POP_PORTLET_PREFIX = "wiki.";
071
072 public static String convert(
073 WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
074 String attachmentURLPrefix)
075 throws PageContentException, WikiFormatException {
076
077 return _instance._convert(
078 page, viewPageURL, editPageURL, attachmentURLPrefix);
079 }
080
081 public static String decodeJSPWikiName(String jspWikiName) {
082 return StringUtil.replace(
083 jspWikiName, _JSP_WIKI_NAME_2, _JSP_WIKI_NAME_1);
084 }
085
086 public static String diffHtml (
087 WikiPage sourcePage, WikiPage targetPage, PortletURL viewPageURL,
088 PortletURL editPageURL, String attachmentURLPrefix)
089 throws Exception {
090
091 String sourceContent = StringPool.BLANK;
092 String targetContent = StringPool.BLANK;
093
094 if (sourcePage != null) {
095 sourceContent = WikiUtil.convert(
096 sourcePage, viewPageURL, editPageURL,attachmentURLPrefix);
097 }
098
099 if (targetPage != null) {
100 targetContent = WikiUtil.convert(
101 targetPage, viewPageURL, editPageURL, attachmentURLPrefix);
102 }
103
104 return DiffHtmlUtil.diff(
105 new UnsyncStringReader(sourceContent),
106 new UnsyncStringReader(targetContent));
107 }
108
109 public static String encodeJSPWikiContent(String content) {
110 String newContent = content;
111
112 Matcher matcher = _wikiLinkPattern.matcher(content);
113
114 while (matcher.find()) {
115 String link = matcher.group();
116 String linkValues = matcher.group(1);
117
118 int index = linkValues.indexOf(CharPool.PIPE);
119
120 String name = linkValues;
121
122 if (index != -1) {
123 name = linkValues.substring(0, index);
124 }
125
126 String newLink =
127 "[[" + encodeJSPWikiName(name) + "|" + name + "]]";
128
129 newContent = StringUtil.replace(newContent, link, newLink);
130 }
131
132 return newContent;
133 }
134
135 public static String encodeJSPWikiName(String name) {
136 if (name == null) {
137 return StringPool.BLANK;
138 }
139
140 return StringUtil.replace(name, _JSP_WIKI_NAME_1, _JSP_WIKI_NAME_2);
141 }
142
143 public static String getEditPage(String format) {
144 return _instance._getEditPage(format);
145 }
146
147 public static String getEmailFromAddress(PortletPreferences preferences) {
148 String emailFromAddress = PropsUtil.get(
149 PropsKeys.WIKI_EMAIL_FROM_ADDRESS);
150
151 return preferences.getValue("email-from-address", emailFromAddress);
152 }
153
154 public static String getEmailFromName(PortletPreferences preferences) {
155 String emailFromName = PropsUtil.get(PropsKeys.WIKI_EMAIL_FROM_NAME);
156
157 return preferences.getValue("email-from-name", emailFromName);
158 }
159
160 public static boolean getEmailPageAddedEnabled(
161 PortletPreferences preferences) {
162
163 String emailPageAddedEnabled = preferences.getValue(
164 "email-page-added-enabled", StringPool.BLANK);
165
166 if (Validator.isNotNull(emailPageAddedEnabled)) {
167 return GetterUtil.getBoolean(emailPageAddedEnabled);
168 }
169 else {
170 return GetterUtil.getBoolean(PropsUtil.get(
171 PropsKeys.WIKI_EMAIL_PAGE_ADDED_ENABLED));
172 }
173 }
174
175 public static String getEmailPageAddedBody(PortletPreferences preferences) {
176 String emailPageAddedBody = preferences.getValue(
177 "email-page-added-body", StringPool.BLANK);
178
179 if (Validator.isNotNull(emailPageAddedBody)) {
180 return emailPageAddedBody;
181 }
182 else {
183 return ContentUtil.get(PropsUtil.get(
184 PropsKeys.WIKI_EMAIL_PAGE_ADDED_BODY));
185 }
186 }
187
188 public static String getEmailPageAddedSignature(
189 PortletPreferences preferences) {
190
191 String emailPageAddedSignature = preferences.getValue(
192 "email-page-added-signature", StringPool.BLANK);
193
194 if (Validator.isNotNull(emailPageAddedSignature)) {
195 return emailPageAddedSignature;
196 }
197 else {
198 return ContentUtil.get(PropsUtil.get(
199 PropsKeys.WIKI_EMAIL_PAGE_ADDED_SIGNATURE));
200 }
201 }
202
203 public static String getEmailPageAddedSubjectPrefix(
204 PortletPreferences preferences) {
205
206 String emailPageAddedSubjectPrefix = preferences.getValue(
207 "email-page-added-subject-prefix", StringPool.BLANK);
208
209 if (Validator.isNotNull(emailPageAddedSubjectPrefix)) {
210 return emailPageAddedSubjectPrefix;
211 }
212 else {
213 return ContentUtil.get(PropsUtil.get(
214 PropsKeys.WIKI_EMAIL_PAGE_ADDED_SUBJECT_PREFIX));
215 }
216 }
217
218 public static boolean getEmailPageUpdatedEnabled(
219 PortletPreferences preferences) {
220
221 String emailPageUpdatedEnabled = preferences.getValue(
222 "email-page-updated-enabled", StringPool.BLANK);
223
224 if (Validator.isNotNull(emailPageUpdatedEnabled)) {
225 return GetterUtil.getBoolean(emailPageUpdatedEnabled);
226 }
227 else {
228 return GetterUtil.getBoolean(PropsUtil.get(
229 PropsKeys.WIKI_EMAIL_PAGE_UPDATED_ENABLED));
230 }
231 }
232
233 public static String getEmailPageUpdatedBody(
234 PortletPreferences preferences) {
235
236 String emailPageUpdatedBody = preferences.getValue(
237 "email-page-updated-body", StringPool.BLANK);
238
239 if (Validator.isNotNull(emailPageUpdatedBody)) {
240 return emailPageUpdatedBody;
241 }
242 else {
243 return ContentUtil.get(PropsUtil.get(
244 PropsKeys.WIKI_EMAIL_PAGE_UPDATED_BODY));
245 }
246 }
247
248 public static String getEmailPageUpdatedSignature(
249 PortletPreferences preferences) {
250
251 String emailPageUpdatedSignature = preferences.getValue(
252 "email-page-updated-signature", StringPool.BLANK);
253
254 if (Validator.isNotNull(emailPageUpdatedSignature)) {
255 return emailPageUpdatedSignature;
256 }
257 else {
258 return ContentUtil.get(PropsUtil.get(
259 PropsKeys.WIKI_EMAIL_PAGE_UPDATED_SIGNATURE));
260 }
261 }
262
263 public static String getEmailPageUpdatedSubjectPrefix(
264 PortletPreferences preferences) {
265
266 String emailPageUpdatedSubject = preferences.getValue(
267 "email-page-updated-subject-prefix", StringPool.BLANK);
268
269 if (Validator.isNotNull(emailPageUpdatedSubject)) {
270 return emailPageUpdatedSubject;
271 }
272 else {
273 return ContentUtil.get(PropsUtil.get(
274 PropsKeys.WIKI_EMAIL_PAGE_UPDATED_SUBJECT_PREFIX));
275 }
276 }
277
278 public static WikiNode getFirstNode(PortletRequest portletRequest)
279 throws PortalException, SystemException {
280
281 ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
282 WebKeys.THEME_DISPLAY);
283 long groupId = themeDisplay.getScopeGroupId();
284 PermissionChecker permissionChecker =
285 themeDisplay.getPermissionChecker();
286
287 List<WikiNode> nodes = WikiNodeLocalServiceUtil.getNodes(groupId);
288
289 PortletPreferences preferences = portletRequest.getPreferences();
290 String[] visibleNodeNames =
291 StringUtil.split(preferences.getValue("visible-nodes", null));
292 nodes = orderNodes(nodes, visibleNodeNames);
293
294 String[] hiddenNodes = StringUtil.split(
295 preferences.getValue("hidden-nodes", StringPool.BLANK));
296 Arrays.sort(hiddenNodes);
297
298 for(WikiNode node : nodes) {
299 if ((Arrays.binarySearch(hiddenNodes, node.getName()) < 0) &&
300 (WikiNodePermission.contains(permissionChecker, node,
301 ActionKeys.VIEW))) {
302 return node;
303 }
304 }
305 return null;
306 }
307
308 public static String getHelpPage(String format) {
309 return _instance._getHelpPage(format);
310 }
311
312 public static String getHelpURL(String format) {
313 return _instance._getHelpURL(format);
314 }
315
316 public static Map<String, Boolean> getLinks(WikiPage page)
317 throws PageContentException {
318
319 return _instance._getLinks(page);
320 }
321
322 public static String getMailId(String mx, long nodeId, long pageId) {
323 StringBundler sb = new StringBundler(10);
324
325 sb.append(StringPool.LESS_THAN);
326 sb.append(POP_PORTLET_PREFIX);
327 sb.append(nodeId);
328 sb.append(StringPool.PERIOD);
329 sb.append(pageId);
330 sb.append(StringPool.AT);
331 sb.append(PropsValues.POP_SERVER_SUBDOMAIN);
332 sb.append(StringPool.PERIOD);
333 sb.append(mx);
334 sb.append(StringPool.GREATER_THAN);
335
336 return sb.toString();
337 }
338
339 public static List<String> getNodeNames(List<WikiNode> nodes) {
340 List<String> nodeNames = new ArrayList<String>(nodes.size());
341
342 for (WikiNode node : nodes) {
343 nodeNames.add(node.getName());
344 }
345
346 return nodeNames;
347 }
348
349 public static List<WikiNode> getNodes(
350 List<WikiNode> nodes, String[] hiddenNodes,
351 PermissionChecker permissionChecker) {
352
353 nodes = ListUtil.copy(nodes);
354
355 Arrays.sort(hiddenNodes);
356
357 Iterator<WikiNode> itr = nodes.iterator();
358
359 while (itr.hasNext()) {
360 WikiNode node = itr.next();
361
362 if (!(Arrays.binarySearch(hiddenNodes, node.getName()) < 0) ||
363 !WikiNodePermission.contains(
364 permissionChecker, node, ActionKeys.VIEW)) {
365
366 itr.remove();
367 }
368 }
369
370 return nodes;
371 }
372
373 public static List<WikiNode> orderNodes(
374 List<WikiNode> nodes, String[] visibleNodeNames) {
375
376 if ((visibleNodeNames == null) || (visibleNodeNames.length == 0)) {
377 return nodes;
378 }
379
380 nodes = ListUtil.copy(nodes);
381
382 List<WikiNode> orderedNodes = new ArrayList<WikiNode>(nodes.size());
383
384 for (String visibleNodeName : visibleNodeNames) {
385 for (WikiNode node : nodes) {
386 if (node.getName().equals(visibleNodeName)) {
387 orderedNodes.add(node);
388
389 nodes.remove(node);
390
391 break;
392 }
393 }
394 }
395
396 orderedNodes.addAll(nodes);
397
398 return orderedNodes;
399 }
400
401 public static String processContent(String content) {
402 content = content.replaceAll("</p>", "</p>\n");
403 content = content.replaceAll("</br>", "</br>\n");
404 content = content.replaceAll("</div>", "</div>\n");
405
406 return content;
407 }
408
409 public static boolean validate(
410 long nodeId, String content, String format)
411 throws WikiFormatException {
412
413 return _instance._validate(nodeId, content, format);
414 }
415
416 private static String _decodeJSPWikiContent(String jspWikiContent) {
417 return StringUtil.replace(
418 jspWikiContent, _JSP_WIKI_NAME_2, _JSP_WIKI_NAME_1);
419 }
420
421 private String _convert(
422 WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
423 String attachmentURLPrefix)
424 throws PageContentException, WikiFormatException {
425
426 LiferayPortletURL liferayViewPageURL = (LiferayPortletURL)viewPageURL;
427 LiferayPortletURL liferayEditPageURL = (LiferayPortletURL)editPageURL;
428
429 WikiEngine engine = _getEngine(page.getFormat());
430
431 String content = engine.convert(page, editPageURL);
432
433 String editPageURLString = StringPool.BLANK;
434
435 if (editPageURL != null) {
436 liferayEditPageURL.setParameter("title", "__REPLACEMENT__", false);
437
438 editPageURLString = editPageURL.toString();
439
440 editPageURLString = StringUtil.replace(
441 editPageURLString, "__REPLACEMENT__", "$1");
442 }
443
444 Matcher matcher = _editPageURLPattern.matcher(content);
445
446 content = matcher.replaceAll(editPageURLString);
447
448 String viewPageURLString = StringPool.BLANK;
449
450 if (viewPageURL != null) {
451 liferayViewPageURL.setParameter("title", "__REPLACEMENT__", false);
452
453 viewPageURLString = viewPageURL.toString();
454
455 viewPageURLString = StringUtil.replace(
456 viewPageURLString, "__REPLACEMENT__", "$1");
457 }
458
459 matcher = _viewPageURLPattern.matcher(content);
460
461 content = matcher.replaceAll(viewPageURLString);
462
463 content = _replaceAttachments(
464 content, page.getTitle(), attachmentURLPrefix);
465
466 content = _decodeJSPWikiContent(content);
467
468 return content;
469 }
470
471 private String _getEditPage(String format) {
472 return PropsUtil.get(
473 PropsKeys.WIKI_FORMATS_EDIT_PAGE, new Filter(format));
474 }
475
476 private WikiEngine _getEngine(String format) throws WikiFormatException {
477 WikiEngine engine = _engines.get(format);
478
479 if (engine == null) {
480 try {
481 String engineClass = PropsUtil.get(
482 PropsKeys.WIKI_FORMATS_ENGINE, new Filter(format));
483
484 if (engineClass != null) {
485 if (!InstancePool.contains(engineClass)) {
486 engine = (WikiEngine)InstancePool.get(engineClass);
487
488 engine.setMainConfiguration(
489 _readConfigurationFile(
490 PropsKeys.WIKI_FORMATS_CONFIGURATION_MAIN,
491 format));
492
493 engine.setInterWikiConfiguration(
494 _readConfigurationFile(
495 PropsKeys.WIKI_FORMATS_CONFIGURATION_INTERWIKI,
496 format));
497 }
498 else {
499 engine = (WikiEngine)InstancePool.get(engineClass);
500 }
501
502 _engines.put(format, engine);
503 }
504 }
505 catch (Exception e) {
506 throw new WikiFormatException(e);
507 }
508
509 if (engine == null) {
510 throw new WikiFormatException(format);
511 }
512 }
513
514 return engine;
515 }
516
517 private String _getHelpPage(String format) {
518 return PropsUtil.get(
519 PropsKeys.WIKI_FORMATS_HELP_PAGE, new Filter(format));
520 }
521
522 private String _getHelpURL(String format) {
523 return PropsUtil.get(
524 PropsKeys.WIKI_FORMATS_HELP_URL, new Filter(format));
525 }
526
527 private Map<String, Boolean> _getLinks(WikiPage page)
528 throws PageContentException {
529
530 try {
531 return _getEngine(page.getFormat()).getOutgoingLinks(page);
532 }
533 catch (WikiFormatException wfe) {
534 return Collections.EMPTY_MAP;
535 }
536 }
537
538 private String _readConfigurationFile(String propertyName, String format)
539 throws IOException {
540
541 ClassLoader classLoader = getClass().getClassLoader();
542
543 String configurationFile = PropsUtil.get(
544 propertyName, new Filter(format));
545
546 if (Validator.isNotNull(configurationFile)) {
547 return HttpUtil.URLtoString(
548 classLoader.getResource(configurationFile));
549 }
550 else {
551 return StringPool.BLANK;
552 }
553 }
554
555 private String _replaceAttachments(
556 String content, String title, String attachmentURLPrefix) {
557
558 content = StringUtil.replace(content, "[$WIKI_PAGE_NAME$]", title);
559
560 content = StringUtil.replace(
561 content, "[$ATTACHMENT_URL_PREFIX$]", attachmentURLPrefix);
562
563 return content;
564 }
565
566 private boolean _validate(long nodeId, String content, String format)
567 throws WikiFormatException {
568
569 return _getEngine(format).validate(nodeId, content);
570 }
571
572 private static final String[] _JSP_WIKI_NAME_1 = {
573 StringPool.APOSTROPHE, StringPool.AT, StringPool.CARET,
574 StringPool.EXCLAMATION, StringPool.INVERTED_EXCLAMATION,
575 StringPool.INVERTED_QUESTION, StringPool.GRAVE_ACCENT,
576 StringPool.QUESTION, StringPool.SLASH, StringPool.STAR
577 };
578
579 private static final String[] _JSP_WIKI_NAME_2 = {
580 "__APO__", "__AT__", "__CAR__", "__EXM__", "__INE__", "__INQ__",
581 "__GRA__", "__QUE__", "__SLA__", "__STA__"
582 };
583
584 private static WikiUtil _instance = new WikiUtil();
585
586 private static Pattern _editPageURLPattern = Pattern.compile(
587 "\\[\\$BEGIN_PAGE_TITLE_EDIT\\$\\](.*?)\\[\\$END_PAGE_TITLE_EDIT\\$\\]");
588 private static Pattern _viewPageURLPattern = Pattern.compile(
589 "\\[\\$BEGIN_PAGE_TITLE\\$\\](.*?)\\[\\$END_PAGE_TITLE\\$\\]");
590 private static Pattern _wikiLinkPattern = Pattern.compile(
591 "[\\[]{2,2}(.+?)[\\]]{2,2}");
592
593 private Map<String, WikiEngine> _engines =
594 new HashMap<String, WikiEngine>();
595
596 }