1 package net.sf.statcvs.pages;
2
3 import java.text.SimpleDateFormat;
4 import java.util.Date;
5 import java.util.Set;
6 import java.util.regex.Matcher;
7 import java.util.regex.Pattern;
8
9 import net.sf.statcvs.Messages;
10 import net.sf.statcvs.model.Author;
11 import net.sf.statcvs.model.Directory;
12
13 /**
14 * TODO: Can we turn this into an abstract base class of MarkupHTML and MarkupXDoc?
15 *
16 * @author Anja Jentzsch
17 * @author Richard Cyganiak (richard@cyganiak.de)
18 * @version $Id: HTML.java,v 1.19 2009/08/05 16:32:10 benoitx Exp $
19 */
20 public final class HTML {
21 public static final SimpleDateFormat OUTPUT_DATE_FORMAT = new SimpleDateFormat(Messages.getString("DATE_FORMAT"));
22 public static final SimpleDateFormat OUTPUT_DATE_TIME_FORMAT = new SimpleDateFormat(Messages.getString("DATE_TIME_FORMAT"));
23 private static final Pattern HTTP_REGEXP2 = Pattern
24 .compile("\\b(http://|https://|www.)(\\w|\\d|\\.)+(\\.|/|\\w|\\d|%|;|&|=)*\\b", Pattern.CASE_INSENSITIVE);
25
26
27
28 /**
29 * Creates a HTML representation of a hyperlink
30 * @param link URL
31 * @param linkName Name of the Link
32 * @return String HTML code of the hyperlink
33 */
34 public static String getLink(final String link, final String linkName) {
35 return getLink(link, linkName, "", "");
36 }
37
38 /**
39 * Creates a HTML representation of a hyperlink
40 * @param link URL
41 * @param linkName Name of the Link
42 * @param prefix A prefix to be inserted before the link label; no HTML escaping is performed
43 * @param prefix A suffix to be inserted after the link label; no HTML escaping is performed
44 * @return String HTML code of the hyperlink
45 */
46 public static String getLink(final String link, final String linkName, final String prefix, final String suffix) {
47 if (link == null) {
48 return prefix + escape(linkName) + suffix;
49 }
50 return "<a href=\"" + escape(link) + "\">" + prefix + escape(linkName) + suffix + "</a>";
51 }
52
53 /**
54 * Returns HTML code for a link to an author page
55 * @param author the author
56 * @return HTML code for the link
57 */
58 public static String getAuthorLink(final Author author) {
59 return "<a href=\"" + escape(DeveloperPageMaker.getURL(author)) + "\" class=\"author\">" + escape(author.getRealName()) + "</a>";
60 }
61
62 /**
63 * Returns HTML code for a link to an author Id page
64 * @param author the author
65 * @return HTML code for the link
66 */
67 public static String getAuthorIdLink(final Author author) {
68 return "<a href=\"" + escape(DeveloperPageMaker.getURL(author)) + "\" class=\"author\">" + escape(author.getName()) + "</a>";
69 }
70
71 /**
72 * Returns HTML code for a date
73 * @param date the date
74 * @return HTML code for the date
75 */
76 public static String getDate(final Date date) {
77 return "<span class=\"date\">" + OUTPUT_DATE_FORMAT.format(date) + "</span>";
78 }
79
80 /**
81 * Returns HTML code for number of affected files
82 * @param files affected files
83 * @return HTML code for number of affected files
84 */
85 public static String getAffectedFilesCount(final Set files) {
86 final StringBuffer sb = new StringBuffer();
87 sb.append("<span class=\"files\">" + files.size());
88 if (files.size() <= 1) {
89 sb.append(" file");
90 } else {
91 sb.append(" files");
92 }
93 sb.append("</span>");
94 return sb.toString();
95 }
96
97 /**
98 * Returns HTML code for a date, including time
99 * @param date the date
100 * @return HTML code for the date
101 */
102 public static String getDateAndTime(final Date date) {
103 return "<span class=\"date\">" + OUTPUT_DATE_TIME_FORMAT.format(date) + "</span>";
104 }
105
106 /**
107 * Returns HTML code for a revision number
108 * @param revisionNumber a revision number
109 * @return HTML code for a revision number
110 */
111 public static String getRevisionNumber(final String revisionNumber) {
112 return "<span class=\"revisionNumberOuter\">Rev.: <span class=\"revisionNumberInner\">" + revisionNumber + "</span></span>";
113 }
114
115 /**
116 * Returns HTML code for a directory page link
117 * @param directory a directory
118 * @return HTML code for the link
119 */
120 public static String getDirectoryLink(final Directory directory) {
121 final String caption = directory.isRoot() ? "/" : directory.getPath();
122 return "<a href=\"" + escape(DirectoryPageMaker.getURL(directory)) + "\" class=\"directory\">" + escape(caption) + "</a>";
123 }
124
125 /**
126 * Generates HTML for an icon
127 * @param iconFilename an icon filename (HTMLOutput.XXXX_ICON constants)
128 * @return HTML string
129 */
130 public static String getIcon(final String iconFilename) {
131 final StringBuffer result = new StringBuffer("<img src=\"");
132 result.append(escape(iconFilename)).append("\" width=\"");
133 result.append(ReportSuiteMaker.ICON_WIDTH).append("\" height=\"");
134 result.append(ReportSuiteMaker.ICON_HEIGHT).append("\" alt=\"\"/>");
135 return result.toString();
136 }
137
138 /**
139 * Generates HTML for an icon
140 * @param iconFilename an icon filename (HTMLOutput.XXXX_ICON constants)
141 * @param title the title for the icon.
142 * @return HTML string
143 */
144 public static String getIcon(final String iconFilename, final String title) {
145 final StringBuffer result = new StringBuffer("<img src=\"");
146 result.append(escape(iconFilename)).append("\" width=\"");
147 result.append(ReportSuiteMaker.ICON_WIDTH).append("\" height=\"");
148 result.append(ReportSuiteMaker.ICON_HEIGHT).append("\" alt=\"").append(title).append("\"");
149 result.append(" title=\"").append(title).append("\"");
150 result.append("/>");
151 return result.toString();
152 }
153
154 /**
155 * <p>
156 * Escapes evil characters in author's names. E.g. "#" must be escaped
157 * because for an author "my#name" a page "author_my#name.html" will be
158 * created, and you can't link to that in HTML
159 * </p>
160 *
161 * TODO: Replace everything *but* known good characters, instead of just
162 * evil ones
163 *
164 * @param authorName an author's name
165 * @return a version safe for creation of files and URLs
166 */
167 public static String escapeAuthorName(final String authorName) {
168 return authorName.replaceAll("#", "_").replaceAll("\\\\", "_");
169 }
170
171 public static String escapeDirectoryName(String directoryName) {
172 if (!directoryName.startsWith("/")) {
173 directoryName = "/" + directoryName;
174 }
175 return directoryName.substring(0, directoryName.length() - 1).replaceAll("/", "_");
176 }
177
178 /**
179 * Escapes HTML meta characters "&", "<", ">" and turns "\n" line breaks
180 * into HTML line breaks ("<br />");
181 * @param text some string, for example "x > 0 && y < 100"
182 * @return HTML-escaped string, for example "x > 0 && y < 100"
183 */
184 public static String escape(final String text) {
185 String result = text.replaceAll("&", "&");
186 result = result.replaceAll("<", "<");
187 result = result.replaceAll(">", ">");
188 result = result.replaceAll("\n", "<br />\n");
189 return result;
190 }
191
192 /**
193 * Escapes HTML as well as " as it is not valid in URL.
194 * @param text some string, for example "x > 0 && y < 100"
195 * @return HTML-escaped string, for example "x > 0 && y < 100"
196 */
197 public static String escapeUrl(final String text) {
198 String result = escape(text);
199 result = result.replaceAll("\"", "");
200 result = result.replaceAll(" ", "%20");
201 return result;
202 }
203
204 /**
205 * Escapes HTML as well as " as it is not valid in URL.
206 * @param text some string, for example "x > 0 && y < 100"
207 * @return HTML-escaped string, for example "x > 0 && y < 100"
208 */
209 public static String escapeUrlParameters(final String text) {
210 String result = escape(text);
211
212 result = result.replaceAll("\\%", "%25");
213 result = result.replaceAll("\\$", "%24");
214 result = result.replaceAll("\\&", "%26");
215 result = result.replaceAll("\\+", "%2B");
216 result = result.replaceAll(",", "%2C");
217 result = result.replaceAll("/", "%2F");
218 result = result.replaceAll(":", "%3A");
219 result = result.replaceAll(";", "%3B");
220 result = result.replaceAll("=", "%3D");
221 result = result.replaceAll("\\?", "%3F");
222 result = result.replaceAll("@", "%40");
223 result = result.replaceAll("\"", "%22");
224
225
226 result = result.replaceAll("#", "%23");
227 result = result.replaceAll("\\{", "%7B");
228
229 result = result.replaceAll("\\\\", "%5C");
230 result = result.replaceAll("\\^", "%5E");
231 result = result.replaceAll("~", "%7E");
232 result = result.replaceAll("\\[", "%5B");
233 result = result.replaceAll("\\]", "%5D");
234 result = result.replaceAll("`", "%60");
235 result = result.replaceAll(" ", "%20");
236 return result;
237 }
238
239 /**
240 * A utility class (only static methods) should be final and have
241 * a private constructor.
242 */
243 private HTML() {
244 }
245
246 /**
247 * From a plain text comment identify the http: and https links and create a link for them.
248 * @param plainText
249 * @author Benoit Xhenseval
250 */
251 public static String webifyLinksFromPlainText(final String plainText) {
252 final String escapedText = HTML.escape(plainText);
253 final Matcher m = HTTP_REGEXP2.matcher(escapedText);
254
255
256
257
258
259 String res = m.replaceAll("<a href=\"$0\">$0</a>");
260 res = res.replaceAll("href=\"www.", "href=\"http://www.");
261
262
263
264 return res;
265 }
266 }