From 41ffcdafcf3f9ba28c1196532e1d23f0aadd5117 Mon Sep 17 00:00:00 2001 From: Diomidis Spinellis Date: Wed, 30 Aug 2006 13:06:09 +0000 Subject: [PATCH] Escape & characters from generics in the HTML output. Reported by: Ivan F. Villanueva B. --- .../spinellis/umlgraph/doclet/ClassGraph.java | 47 ++++++++++++++----- src/org/umlgraph/doclet/ClassGraph.java | 47 ++++++++++++++----- 2 files changed, 72 insertions(+), 22 deletions(-) diff --git a/src/gr/spinellis/umlgraph/doclet/ClassGraph.java b/src/gr/spinellis/umlgraph/doclet/ClassGraph.java index e0c3525..97bb600 100644 --- a/src/gr/spinellis/umlgraph/doclet/ClassGraph.java +++ b/src/gr/spinellis/umlgraph/doclet/ClassGraph.java @@ -33,6 +33,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Pattern; import com.sun.javadoc.ClassDoc; import com.sun.javadoc.ConstructorDoc; @@ -142,12 +143,36 @@ class ClassGraph { } return r; } - - /** Escape < and > characters in the string with a backslash. */ - private String escapeLG(String s) { - if(s.contains("<")) - return s.replace("<", "<").replace(">", ">"); - else + + /** + * Escape <, >, and & characters in the string with + * the corresponding HTML entity code. + */ + private String escape(String s) { + final Pattern toEscape = Pattern.compile("[&<>]"); + + if (toEscape.matcher(s).find()) { + StringBuffer sb = new StringBuffer(s); + for (int i = 0; i < sb.length();) { + switch (sb.charAt(i)) { + case '&': + sb.replace(i, i + 1, "&"); + i += "&".length(); + break; + case '<': + sb.replace(i, i + 1, "<"); + i += "<".length(); + break; + case '>': + sb.replace(i, i + 1, ">"); + i += ">".length(); + break; + default: + i++; + } + } + return sb.toString(); + } else return s; } @@ -165,7 +190,7 @@ class ClassGraph { break; case '>': r.replace(i, i + 1, opt.guilClose); - i += opt.guilOpen.length(); + i += opt.guilClose.length(); break; default: i++; @@ -444,10 +469,10 @@ class ClassGraph { if(opt.postfixPackage && idx > 0 && idx < (qualifiedName.length() - 1)) { String packageName = qualifiedName.substring(0, idx); String cn = className.substring(idx + 1); - tableLine(Align.CENTER, escapeLG(cn), opt, font); + tableLine(Align.CENTER, escape(cn), opt, font); tableLine(Align.CENTER, packageName, opt, Font.PACKAGE); } else { - tableLine(Align.CENTER, escapeLG(qualifiedName), opt, font); + tableLine(Align.CENTER, escape(qualifiedName), opt, font); } tagvalue(opt, c); innerTableEnd(); @@ -652,10 +677,10 @@ class ClassGraph { if(opt.postfixPackage && idx > 0 && idx < (className.length() - 1)) { String packageName = className.substring(0, idx); String cn = className.substring(idx + 1); - tableLine(Align.CENTER, escapeLG(cn), opt, Font.CLASS); + tableLine(Align.CENTER, escape(cn), opt, Font.CLASS); tableLine(Align.CENTER, packageName, opt, Font.PACKAGE); } else { - tableLine(Align.CENTER, escapeLG(className), opt, Font.CLASS); + tableLine(Align.CENTER, escape(className), opt, Font.CLASS); } innerTableEnd(); externalTableEnd(); diff --git a/src/org/umlgraph/doclet/ClassGraph.java b/src/org/umlgraph/doclet/ClassGraph.java index e0c3525..97bb600 100644 --- a/src/org/umlgraph/doclet/ClassGraph.java +++ b/src/org/umlgraph/doclet/ClassGraph.java @@ -33,6 +33,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Pattern; import com.sun.javadoc.ClassDoc; import com.sun.javadoc.ConstructorDoc; @@ -142,12 +143,36 @@ class ClassGraph { } return r; } - - /** Escape < and > characters in the string with a backslash. */ - private String escapeLG(String s) { - if(s.contains("<")) - return s.replace("<", "<").replace(">", ">"); - else + + /** + * Escape <, >, and & characters in the string with + * the corresponding HTML entity code. + */ + private String escape(String s) { + final Pattern toEscape = Pattern.compile("[&<>]"); + + if (toEscape.matcher(s).find()) { + StringBuffer sb = new StringBuffer(s); + for (int i = 0; i < sb.length();) { + switch (sb.charAt(i)) { + case '&': + sb.replace(i, i + 1, "&"); + i += "&".length(); + break; + case '<': + sb.replace(i, i + 1, "<"); + i += "<".length(); + break; + case '>': + sb.replace(i, i + 1, ">"); + i += ">".length(); + break; + default: + i++; + } + } + return sb.toString(); + } else return s; } @@ -165,7 +190,7 @@ class ClassGraph { break; case '>': r.replace(i, i + 1, opt.guilClose); - i += opt.guilOpen.length(); + i += opt.guilClose.length(); break; default: i++; @@ -444,10 +469,10 @@ class ClassGraph { if(opt.postfixPackage && idx > 0 && idx < (qualifiedName.length() - 1)) { String packageName = qualifiedName.substring(0, idx); String cn = className.substring(idx + 1); - tableLine(Align.CENTER, escapeLG(cn), opt, font); + tableLine(Align.CENTER, escape(cn), opt, font); tableLine(Align.CENTER, packageName, opt, Font.PACKAGE); } else { - tableLine(Align.CENTER, escapeLG(qualifiedName), opt, font); + tableLine(Align.CENTER, escape(qualifiedName), opt, font); } tagvalue(opt, c); innerTableEnd(); @@ -652,10 +677,10 @@ class ClassGraph { if(opt.postfixPackage && idx > 0 && idx < (className.length() - 1)) { String packageName = className.substring(0, idx); String cn = className.substring(idx + 1); - tableLine(Align.CENTER, escapeLG(cn), opt, Font.CLASS); + tableLine(Align.CENTER, escape(cn), opt, Font.CLASS); tableLine(Align.CENTER, packageName, opt, Font.PACKAGE); } else { - tableLine(Align.CENTER, escapeLG(className), opt, Font.CLASS); + tableLine(Align.CENTER, escape(className), opt, Font.CLASS); } innerTableEnd(); externalTableEnd();