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 056 * HTML. 057 * <p> 058 * <ul> 059 * <li>standalone newlines are turned into {@code <br/> 060 * }</li> 061 * <li>{@code <code>} blocks are turned into a {@code <div class="code">} 062 * with a {@code 063 * 064 * 065 066 <pre> 067 * }</li> 068 * <li>{@code @author} blocks are removed</li> 069 * </ul> 070 */ 071 public static String getHtml(String doc) { 072 if (doc == null) { 073 return ""; 074 } 075 HtmlSanitizerService sanitizer = Framework.getService(HtmlSanitizerService.class); 076 if (sanitizer == null && !Framework.isTestModeSet()) { 077 throw new RuntimeException("Cannot find HtmlSanitizerService"); 078 } 079 080 LinkedList<String> lines = new LinkedList<>(); 081 lines.add(P); 082 boolean newline = true; 083 boolean firstcode = false; 084 boolean code = false; 085 for (String line : doc.split("\n")) { 086 if (!code) { 087 line = line.trim(); 088 if ("".equals(line) || BR.equals(line) || BR2.equals(line) || BR3.equals(line) || P.equals(line) 089 || P2.equals(line)) { 090 if (!newline) { 091 lines.add(P); 092 newline = true; 093 } 094 } else { 095 if ("<code>".equals(line)) { 096 code = true; 097 firstcode = true; 098 line = CODE_START; 099 if (!newline) { 100 line = P + line; 101 } 102 lines.add(line); 103 newline = false; 104 } else if (line.startsWith(AUTHOR)) { 105 if (!newline) { 106 lines.add(P); 107 } 108 newline = true; 109 } else { 110 lines.add(line); 111 newline = false; 112 } 113 } 114 } else { // code 115 if ("</code>".equals(line.trim())) { 116 code = false; 117 line = CODE_END + P; 118 newline = true; 119 } else { 120 line = line.replace("&", "&").replace("<", "<"); 121 } 122 if (firstcode) { 123 // don't add a \n at the start of the code 124 firstcode = false; 125 line = lines.removeLast() + line; 126 } 127 lines.add(line); 128 } 129 } 130 if (code) { 131 lines.add(CODE_END); 132 } 133 String html = StringUtils.join(lines, "\n"); 134 if (sanitizer != null) { 135 html = sanitizer.sanitizeString(html, null); 136 } 137 return secureXML(html); 138 } 139 140 /** 141 * Makes sure no passwords are embedded in the XML. 142 */ 143 public static String secureXML(String xml) { 144 if (xml == null || !xml.contains("assword")) { 145 return xml; 146 } 147 xml = xml.replaceAll("<([a-zA-Z]*[pP])assword>[^<]*</([a-zA-Z]*)assword>", "<$1assword>********</$2assword>"); 148 // attributes: nuxeo-core-auth 149 xml = xml.replaceAll("([a-zA-Z]*[pP])assword=\"[^\"]*\"", "$1assword=\"********\""); 150 // property: default-repository-config 151 xml = xml.replaceAll("([a-zA-Z]*[pP])assword\">[^<]*<", "$1assword\">********<"); 152 return xml; 153 } 154 155}