1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   * SOFTWARE.
18   */
19  
20  package com.liferay.portlet.wiki.util;
21  
22  import com.liferay.portal.PortalException;
23  import com.liferay.portal.SystemException;
24  import com.liferay.portal.kernel.configuration.Filter;
25  import com.liferay.portal.kernel.portlet.LiferayPortletURL;
26  import com.liferay.portal.kernel.util.ArrayUtil;
27  import com.liferay.portal.kernel.util.GetterUtil;
28  import com.liferay.portal.kernel.util.HttpUtil;
29  import com.liferay.portal.kernel.util.InstancePool;
30  import com.liferay.portal.kernel.util.ListUtil;
31  import com.liferay.portal.kernel.util.StringPool;
32  import com.liferay.portal.kernel.util.StringUtil;
33  import com.liferay.portal.kernel.util.Validator;
34  import com.liferay.portal.security.permission.ActionKeys;
35  import com.liferay.portal.security.permission.PermissionChecker;
36  import com.liferay.portal.theme.ThemeDisplay;
37  import com.liferay.portal.util.ContentUtil;
38  import com.liferay.portal.util.PropsKeys;
39  import com.liferay.portal.util.PropsUtil;
40  import com.liferay.portal.util.PropsValues;
41  import com.liferay.portal.util.WebKeys;
42  import com.liferay.portlet.wiki.PageContentException;
43  import com.liferay.portlet.wiki.WikiFormatException;
44  import com.liferay.portlet.wiki.engines.WikiEngine;
45  import com.liferay.portlet.wiki.model.WikiNode;
46  import com.liferay.portlet.wiki.model.WikiPage;
47  import com.liferay.portlet.wiki.service.WikiNodeLocalServiceUtil;
48  import com.liferay.portlet.wiki.service.permission.WikiNodePermission;
49  import com.liferay.portlet.wiki.util.comparator.VisibleNodesComparator;
50  
51  import java.io.IOException;
52  
53  import java.util.Collections;
54  import java.util.HashMap;
55  import java.util.Iterator;
56  import java.util.List;
57  import java.util.Map;
58  import java.util.regex.Matcher;
59  import java.util.regex.Pattern;
60  
61  import javax.portlet.PortletPreferences;
62  import javax.portlet.PortletURL;
63  import javax.portlet.RenderRequest;
64  
65  /**
66   * <a href="WikiUtil.java.html"><b><i>View Source</i></b></a>
67   *
68   * @author Brian Wing Shun Chan
69   * @author Jorge Ferrer
70   *
71   */
72  public class WikiUtil {
73  
74      public static final String POP_PORTLET_PREFIX = "wiki.";
75  
76      public static String convert(
77              WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
78              String attachmentURLPrefix)
79          throws PageContentException, WikiFormatException {
80  
81          return _instance._convert(
82              page, viewPageURL, editPageURL, attachmentURLPrefix);
83      }
84  
85      public static String getEditPage(String format) {
86          return _instance._getEditPage(format);
87      }
88  
89      public static String getEmailFromAddress(PortletPreferences prefs) {
90          String emailFromAddress = PropsUtil.get(
91              PropsKeys.WIKI_EMAIL_FROM_ADDRESS);
92  
93          return prefs.getValue("email-from-address", emailFromAddress);
94      }
95  
96      public static String getEmailFromName(PortletPreferences prefs) {
97          String emailFromName = PropsUtil.get(PropsKeys.WIKI_EMAIL_FROM_NAME);
98  
99          return prefs.getValue("email-from-name", emailFromName);
100     }
101 
102     public static boolean getEmailPageAddedEnabled(
103         PortletPreferences prefs) {
104 
105         String emailPageAddedEnabled = prefs.getValue(
106             "email-page-added-enabled", StringPool.BLANK);
107 
108         if (Validator.isNotNull(emailPageAddedEnabled)) {
109             return GetterUtil.getBoolean(emailPageAddedEnabled);
110         }
111         else {
112             return GetterUtil.getBoolean(PropsUtil.get(
113                 PropsKeys.WIKI_EMAIL_PAGE_ADDED_ENABLED));
114         }
115     }
116 
117     public static String getEmailPageAddedBody(PortletPreferences prefs) {
118         String emailPageAddedBody = prefs.getValue(
119             "email-page-added-body", StringPool.BLANK);
120 
121         if (Validator.isNotNull(emailPageAddedBody)) {
122             return emailPageAddedBody;
123         }
124         else {
125             return ContentUtil.get(PropsUtil.get(
126                 PropsKeys.WIKI_EMAIL_PAGE_ADDED_BODY));
127         }
128     }
129 
130     public static String getEmailPageAddedSignature(PortletPreferences prefs) {
131         String emailPageAddedSignature = prefs.getValue(
132             "email-page-added-signature", StringPool.BLANK);
133 
134         if (Validator.isNotNull(emailPageAddedSignature)) {
135             return emailPageAddedSignature;
136         }
137         else {
138             return ContentUtil.get(PropsUtil.get(
139                 PropsKeys.WIKI_EMAIL_PAGE_ADDED_SIGNATURE));
140         }
141     }
142 
143     public static String getEmailPageAddedSubjectPrefix(
144         PortletPreferences prefs) {
145 
146         String emailPageAddedSubjectPrefix = prefs.getValue(
147             "email-page-added-subject-prefix", StringPool.BLANK);
148 
149         if (Validator.isNotNull(emailPageAddedSubjectPrefix)) {
150             return emailPageAddedSubjectPrefix;
151         }
152         else {
153             return ContentUtil.get(PropsUtil.get(
154                 PropsKeys.WIKI_EMAIL_PAGE_ADDED_SUBJECT_PREFIX));
155         }
156     }
157 
158     public static boolean getEmailPageUpdatedEnabled(
159         PortletPreferences prefs) {
160 
161         String emailPageUpdatedEnabled = prefs.getValue(
162             "email-page-updated-enabled", StringPool.BLANK);
163 
164         if (Validator.isNotNull(emailPageUpdatedEnabled)) {
165             return GetterUtil.getBoolean(emailPageUpdatedEnabled);
166         }
167         else {
168             return GetterUtil.getBoolean(PropsUtil.get(
169                 PropsKeys.WIKI_EMAIL_PAGE_UPDATED_ENABLED));
170         }
171     }
172 
173     public static String getEmailPageUpdatedBody(PortletPreferences prefs) {
174         String emailPageUpdatedBody = prefs.getValue(
175             "email-page-updated-body", StringPool.BLANK);
176 
177         if (Validator.isNotNull(emailPageUpdatedBody)) {
178             return emailPageUpdatedBody;
179         }
180         else {
181             return ContentUtil.get(PropsUtil.get(
182                 PropsKeys.WIKI_EMAIL_PAGE_UPDATED_BODY));
183         }
184     }
185 
186     public static String getEmailPageUpdatedSignature(
187         PortletPreferences prefs) {
188 
189         String emailPageUpdatedSignature = prefs.getValue(
190             "email-page-updated-signature", StringPool.BLANK);
191 
192         if (Validator.isNotNull(emailPageUpdatedSignature)) {
193             return emailPageUpdatedSignature;
194         }
195         else {
196             return ContentUtil.get(PropsUtil.get(
197                 PropsKeys.WIKI_EMAIL_PAGE_UPDATED_SIGNATURE));
198         }
199     }
200 
201     public static String getEmailPageUpdatedSubjectPrefix(
202         PortletPreferences prefs) {
203 
204         String emailPageUpdatedSubject = prefs.getValue(
205             "email-page-updated-subject-prefix", StringPool.BLANK);
206 
207         if (Validator.isNotNull(emailPageUpdatedSubject)) {
208             return emailPageUpdatedSubject;
209         }
210         else {
211             return ContentUtil.get(PropsUtil.get(
212                 PropsKeys.WIKI_EMAIL_PAGE_UPDATED_SUBJECT_PREFIX));
213         }
214     }
215 
216     public static String getHelpPage(String format) {
217         return _instance._getHelpPage(format);
218     }
219 
220     public static String getHelpURL(String format) {
221         return _instance._getHelpURL(format);
222     }
223 
224     public static Map<String, Boolean> getLinks(WikiPage page)
225         throws PageContentException {
226 
227         return _instance._getLinks(page);
228     }
229 
230     public static String getMailId(String mx, long nodeId, long pageId) {
231         StringBuilder sb = new StringBuilder();
232 
233         sb.append(StringPool.LESS_THAN);
234         sb.append(POP_PORTLET_PREFIX);
235         sb.append(nodeId);
236         sb.append(StringPool.PERIOD);
237         sb.append(pageId);
238         sb.append(StringPool.AT);
239         sb.append(PropsValues.POP_SERVER_SUBDOMAIN);
240         sb.append(StringPool.PERIOD);
241         sb.append(mx);
242         sb.append(StringPool.GREATER_THAN);
243 
244         return sb.toString();
245     }
246 
247     public static List<WikiNode> getNodes(RenderRequest renderRequest)
248         throws PortalException, SystemException {
249 
250         ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
251             WebKeys.THEME_DISPLAY);
252 
253         long groupId = themeDisplay.getLayout().getGroupId();
254 
255         String allNodes = ListUtil.toString(
256             WikiNodeLocalServiceUtil.getNodes(groupId), "name");
257 
258         String[] visibleNodes = StringUtil.split(
259             renderRequest.getPreferences().getValue("visible-nodes", allNodes));
260         String[] hiddenNodes = StringUtil.split(
261             renderRequest.getPreferences().getValue(
262                 "hidden-nodes", StringPool.BLANK));
263 
264         return getNodes(
265             groupId, visibleNodes, hiddenNodes,
266             themeDisplay.getPermissionChecker());
267     }
268 
269     public static List<WikiNode> getNodes(
270             long groupId, String[] visibleNodes, String[] hiddenNodes,
271             PermissionChecker permissionChecker)
272         throws PortalException, SystemException {
273 
274         List<WikiNode> nodes = WikiNodeLocalServiceUtil.getNodes(groupId);
275 
276         nodes = ListUtil.sort(nodes, new VisibleNodesComparator(visibleNodes));
277 
278         Iterator<WikiNode> itr = nodes.iterator();
279 
280         while (itr.hasNext()) {
281             WikiNode node = itr.next();
282 
283             if (ArrayUtil.contains(hiddenNodes, node.getName()) ||
284                 !WikiNodePermission.contains(
285                     permissionChecker, node.getNodeId(), ActionKeys.VIEW)) {
286 
287                 itr.remove();
288             }
289         }
290 
291         return nodes;
292     }
293 
294     public static String processContent(String content) {
295         content = content.replaceAll("</p>", "</p>\n");
296         content = content.replaceAll("</br>", "</br>\n");
297         content = content.replaceAll("</div>", "</div>\n");
298 
299         return content;
300     }
301 
302     public static boolean validate(
303             long nodeId, String content, String format)
304         throws WikiFormatException {
305 
306         return _instance._validate(nodeId, content, format);
307     }
308 
309     private String _convert(
310             WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
311             String attachmentURLPrefix)
312         throws PageContentException, WikiFormatException {
313 
314         LiferayPortletURL liferayViewPageURL = (LiferayPortletURL)viewPageURL;
315         LiferayPortletURL liferayEditPageURL = (LiferayPortletURL)editPageURL;
316 
317         WikiEngine engine = _getEngine(page.getFormat());
318 
319         String content = engine.convert(page, editPageURL);
320 
321         liferayEditPageURL.setParameter("title", "__REPLACEMENT__", false);
322 
323         String editPageURLString = editPageURL.toString();
324 
325         editPageURLString = StringUtil.replace(
326             editPageURLString, "__REPLACEMENT__", "$1");
327 
328         Matcher matcher = _editPageURLPattern.matcher(content);
329 
330         content = matcher.replaceAll(editPageURLString);
331 
332         liferayViewPageURL.setParameter("title", "__REPLACEMENT__", false);
333 
334         String viewPageURLString = viewPageURL.toString();
335 
336         viewPageURLString = StringUtil.replace(
337             viewPageURLString, "__REPLACEMENT__", "$1");
338 
339         matcher = _viewPageURLPattern.matcher(content);
340 
341         content = matcher.replaceAll(viewPageURLString);
342 
343         content = _replaceAttachments(
344             content, page.getTitle(), attachmentURLPrefix);
345 
346         return content;
347     }
348 
349     private String _getEditPage(String format) {
350         return PropsUtil.get(
351             PropsKeys.WIKI_FORMATS_EDIT_PAGE, new Filter(format));
352     }
353 
354     private WikiEngine _getEngine(String format) throws WikiFormatException {
355         WikiEngine engine = _engines.get(format);
356 
357         if (engine == null) {
358             try {
359                 String engineClass = PropsUtil.get(
360                     PropsKeys.WIKI_FORMATS_ENGINE, new Filter(format));
361 
362                 if (engineClass != null) {
363                     if (!InstancePool.contains(engineClass)) {
364                         engine = (WikiEngine)InstancePool.get(engineClass);
365 
366                         engine.setMainConfiguration(
367                             _readConfigurationFile(
368                                 PropsKeys.WIKI_FORMATS_CONFIGURATION_MAIN,
369                                 format));
370 
371                         engine.setInterWikiConfiguration(
372                             _readConfigurationFile(
373                                 PropsKeys.WIKI_FORMATS_CONFIGURATION_INTERWIKI,
374                                 format));
375                     }
376                     else {
377                         engine = (WikiEngine)InstancePool.get(engineClass);
378                     }
379 
380                     _engines.put(format, engine);
381                 }
382             }
383             catch (Exception e) {
384                 throw new WikiFormatException(e);
385             }
386 
387             if (engine == null) {
388                 throw new WikiFormatException(format);
389             }
390         }
391 
392         return engine;
393     }
394 
395     private String _getHelpPage(String format) {
396         return PropsUtil.get(
397             PropsKeys.WIKI_FORMATS_HELP_PAGE, new Filter(format));
398     }
399 
400     private String _getHelpURL(String format) {
401         return PropsUtil.get(
402             PropsKeys.WIKI_FORMATS_HELP_URL, new Filter(format));
403     }
404 
405     private Map<String, Boolean> _getLinks(WikiPage page)
406         throws PageContentException {
407 
408         try {
409             return _getEngine(page.getFormat()).getOutgoingLinks(page);
410         }
411         catch (WikiFormatException wfe) {
412             return Collections.EMPTY_MAP;
413         }
414     }
415 
416     private String _readConfigurationFile(String propertyName, String format)
417         throws IOException {
418 
419         ClassLoader classLoader = getClass().getClassLoader();
420 
421         String configurationFile = PropsUtil.get(
422             propertyName, new Filter(format));
423 
424         if (Validator.isNotNull(configurationFile)) {
425             return HttpUtil.URLtoString(
426                 classLoader.getResource(configurationFile));
427         }
428         else {
429             return StringPool.BLANK;
430         }
431     }
432 
433     private String _replaceAttachments(
434         String content, String title, String attachmentURLPrefix) {
435 
436         content = StringUtil.replace(content, "[$WIKI_PAGE_NAME$]", title);
437 
438         content = StringUtil.replace(
439             content, "[$ATTACHMENT_URL_PREFIX$]", attachmentURLPrefix);
440 
441         return content;
442     }
443 
444     private boolean _validate(long nodeId, String content, String format)
445         throws WikiFormatException {
446 
447         return _getEngine(format).validate(nodeId, content);
448     }
449 
450     private static WikiUtil _instance = new WikiUtil();
451 
452     private static Pattern _editPageURLPattern = Pattern.compile(
453         "\\[\\$BEGIN_PAGE_TITLE_EDIT\\$\\](.*?)\\[\\$END_PAGE_TITLE_EDIT\\$\\]");
454     private static Pattern _viewPageURLPattern = Pattern.compile(
455         "\\[\\$BEGIN_PAGE_TITLE\\$\\](.*?)\\[\\$END_PAGE_TITLE\\$\\]");
456 
457     private Map<String, WikiEngine> _engines =
458         new HashMap<String, WikiEngine>();
459 
460 }