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