001/* 002 * (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.apidoc.documentation; 020 021import java.util.LinkedList; 022 023import org.apache.commons.lang.StringUtils; 024import org.nuxeo.ecm.platform.htmlsanitizer.HtmlSanitizerService; 025import org.nuxeo.runtime.api.Framework; 026 027/** 028 * Helper to generate HTML for documentation strings. 029 */ 030public class DocumentationHelper { 031 032 private static final String BR = "<br/>"; 033 034 private static final String BR2 = "<br />"; 035 036 private static final String BR3 = "<br>"; 037 038 private static final String P = "<p/>"; 039 040 private static final String P2 = "<p />"; 041 042 // private static final String CODE_START = "<div class=\"code\"><pre>"; 043 private static final String CODE_START = "<code><pre>"; 044 045 // private static final String CODE_END = "</pre></div>"; 046 private static final String CODE_END = "</pre></code>"; 047 048 private static final String AUTHOR = "@author"; 049 050 // utility class 051 private DocumentationHelper() { 052 } 053 054 /** 055 * Transforms Nuxeo extension point {@code <documentation>} content into HTML. 056 * <p> 057 * <ul> 058 * <li>standalone newlines are turned into {@code <br/>}</li> 059 * <li>{@code <code>} blocks are turned into a {@code <div class="code">} with a {@code <pre>}</li> 060 * <li>{@code @author} blocks are removed</li> 061 * </ul> 062 */ 063 public static String getHtml(String doc) { 064 if (doc == null) { 065 return ""; 066 } 067 HtmlSanitizerService sanitizer = Framework.getService(HtmlSanitizerService.class); 068 if (sanitizer == null && !Framework.isTestModeSet()) { 069 throw new RuntimeException("Cannot find HtmlSanitizerService"); 070 } 071 072 LinkedList<String> lines = new LinkedList<String>(); 073 lines.add(P); 074 boolean newline = true; 075 boolean firstcode = false; 076 boolean code = false; 077 for (String line : doc.split("\n")) { 078 if (!code) { 079 line = line.trim(); 080 if ("".equals(line) || BR.equals(line) || BR2.equals(line) || BR3.equals(line) || P.equals(line) 081 || P2.equals(line)) { 082 if (!newline) { 083 lines.add(P); 084 newline = true; 085 } 086 } else { 087 if ("<code>".equals(line)) { 088 code = true; 089 firstcode = true; 090 line = CODE_START; 091 if (!newline) { 092 line = P + line; 093 } 094 lines.add(line); 095 newline = false; 096 } else if (line.startsWith(AUTHOR)) { 097 if (!newline) { 098 lines.add(P); 099 } 100 newline = true; 101 } else { 102 lines.add(line); 103 newline = false; 104 } 105 } 106 } else { // code 107 if ("</code>".equals(line.trim())) { 108 code = false; 109 line = CODE_END + P; 110 newline = true; 111 } else { 112 line = line.replace("&", "&").replace("<", "<"); 113 } 114 if (firstcode) { 115 // don't add a \n at the start of the code 116 firstcode = false; 117 line = lines.removeLast() + line; 118 } 119 lines.add(line); 120 } 121 } 122 if (code) { 123 lines.add(CODE_END); 124 } 125 String html = StringUtils.join(lines, "\n"); 126 if (sanitizer != null) { 127 html = sanitizer.sanitizeString(html, null); 128 } 129 return secureXML(html); 130 } 131 132 /** 133 * Makes sure no passwords are embedded in the XML. 134 */ 135 public static String secureXML(String xml) { 136 if (xml == null || !xml.contains("assword")) { 137 return xml; 138 } 139 xml = xml.replaceAll("<([a-zA-Z]*[pP])assword>[^<]*</([a-zA-Z]*)assword>", "<$1assword>********</$2assword>"); 140 // attributes: nuxeo-core-auth 141 xml = xml.replaceAll("([a-zA-Z]*[pP])assword=\"[^\"]*\"", "$1assword=\"********\""); 142 // property: default-repository-config 143 xml = xml.replaceAll("([a-zA-Z]*[pP])assword\">[^<]*<", "$1assword\">********<"); 144 return xml; 145 } 146 147}