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