KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > event > HTMLURIEscaper


1 package net.sf.saxon.event;
2 import net.sf.saxon.charcode.UnicodeCharacterSet;
3 import net.sf.saxon.om.FastStringBuffer;
4 import net.sf.saxon.om.NamePool;
5 import net.sf.saxon.trans.XPathException;
6
7 /**
8   * This class is used as a filter on the serialization pipeline; it performs the function
9   * of escaping URI-valued attributes in HTML
10   * @author Michael H. Kay
11   */

12
13 public class HTMLURIEscaper extends ProxyReceiver {
14
15     /**
16     * Table of attributes whose value is a URL
17     */

18
19     // we use two HashMaps to avoid unnecessary string concatenations
20

21     private static HTMLTagHashSet urlAttributes = new HTMLTagHashSet(47);
22     private static HTMLTagHashSet urlCombinations = new HTMLTagHashSet(101);
23
24     static {
25         setUrlAttribute("form", "action");
26         setUrlAttribute("body", "background");
27         setUrlAttribute("q", "cite");
28         setUrlAttribute("blockquote", "cite");
29         setUrlAttribute("del", "cite");
30         setUrlAttribute("ins", "cite");
31         setUrlAttribute("object", "classid");
32         setUrlAttribute("object", "codebase");
33         setUrlAttribute("applet", "codebase");
34         setUrlAttribute("object", "data");
35         setUrlAttribute("a", "href");
36         setUrlAttribute("a", "name"); // see second note in section B.2.1 of HTML 4 specification
37
setUrlAttribute("area", "href");
38         setUrlAttribute("link", "href");
39         setUrlAttribute("base", "href");
40         setUrlAttribute("img", "longdesc");
41         setUrlAttribute("frame", "longdesc");
42         setUrlAttribute("iframe", "longdesc");
43         setUrlAttribute("head", "profile");
44         setUrlAttribute("script", "src");
45         setUrlAttribute("input", "src");
46         setUrlAttribute("frame", "src");
47         setUrlAttribute("iframe", "src");
48         setUrlAttribute("img", "src");
49         setUrlAttribute("img", "usemap");
50         setUrlAttribute("input", "usemap");
51         setUrlAttribute("object", "usemap");
52     }
53
54     private static void setUrlAttribute(String JavaDoc element, String JavaDoc attribute) {
55         urlAttributes.add(attribute);
56         urlCombinations.add(element + '+' + attribute);
57     }
58
59     public boolean isUrlAttribute(int element, int attribute) {
60         String JavaDoc attributeName = pool.getDisplayName(attribute);
61         if (!urlAttributes.contains(attributeName)) {
62             return false;
63         }
64         String JavaDoc elementName = pool.getDisplayName(element);
65         return urlCombinations.contains(elementName + '+' + attributeName);
66     }
67
68     protected int currentElement;
69     protected boolean escapeURIAttributes = true;
70     protected NamePool pool;
71
72     /**
73      * Start of event stream
74      */

75
76     public void open() throws XPathException {
77         super.open();
78     }
79
80     /**
81      * Start of a document node.
82      */

83
84     public void startDocument(int properties) throws XPathException {
85         super.startDocument(properties);
86         pool = getPipelineConfiguration().getConfiguration().getNamePool();
87     }
88
89     /**
90      * Notify the start of an element
91      *
92      * @param nameCode integer code identifying the name of the element within the name pool.
93      * @param typeCode integer code identifying the element's type within the name pool.
94      * @param properties properties of the element node
95      */

96
97     public void startElement(int nameCode, int typeCode, int locationId, int properties) throws XPathException {
98         currentElement = nameCode;
99         getUnderlyingReceiver().startElement(nameCode, typeCode, locationId, properties);
100     }
101
102     /**
103      * Notify an attribute. Attributes are notified after the startElement event, and before any
104      * children. Namespaces and attributes may be intermingled.
105      *
106      * @param nameCode The name of the attribute, as held in the name pool
107      * @param typeCode The type of the attribute, as held in the name pool
108      * @param properties Bit significant value. The following bits are defined:
109      * <dd>DISABLE_ESCAPING</dd> <dt>Disable escaping for this attribute</dt>
110      * <dd>NO_SPECIAL_CHARACTERS</dd> <dt>Attribute value contains no special characters</dt>
111      * @throws IllegalStateException: attempt to output an attribute when there is no open element
112      * start tag
113      */

114
115     public void attribute(int nameCode, int typeCode, CharSequence JavaDoc value, int locationId, int properties) throws XPathException {
116         if (escapeURIAttributes &&
117                isUrlAttribute(currentElement, nameCode) &&
118                (properties & ReceiverOptions.DISABLE_ESCAPING) == 0) {
119             getUnderlyingReceiver().attribute(nameCode, typeCode, escapeURL(value), locationId,
120                     properties | ReceiverOptions.DISABLE_CHARACTER_MAPS);
121         } else {
122             getUnderlyingReceiver().attribute(nameCode, typeCode, value, locationId, properties);
123         }
124     }
125
126
127     public static CharSequence JavaDoc escapeURL(CharSequence JavaDoc url) {
128         FastStringBuffer sb = new FastStringBuffer(url.length() + 20);
129         final String JavaDoc hex = "0123456789ABCDEF";
130
131         for (int i=0; i<url.length(); i++) {
132             char ch = url.charAt(i);
133             if (ch<32 || ch>126) {
134                 byte[] array = new byte[4];
135                 int used = UnicodeCharacterSet.getUTF8Encoding(ch,
136                                                  (i+1 < url.length() ? url.charAt(i+1): ' '), array);
137                 for (int b=0; b<used; b++) {
138                     int v = (array[b]>=0 ? array[b] : 256 + array[b]);
139                     sb.append('%');
140                     sb.append(hex.charAt(v/16));
141                     sb.append(hex.charAt(v%16));
142                 }
143
144             } else {
145                 sb.append(ch);
146             }
147         }
148         return sb;
149     }
150 }
151
152 //
153
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
154
// you may not use this file except in compliance with the License. You may obtain a copy of the
155
// License at http://www.mozilla.org/MPL/
156
//
157
// Software distributed under the License is distributed on an "AS IS" basis,
158
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
159
// See the License for the specific language governing rights and limitations under the License.
160
//
161
// The Original Code is: all this file.
162
//
163
// The Initial Developer of the Original Code is Michael H. Kay.
164
//
165
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
166
//
167
// Contributor(s): none.
168
//
169
Popular Tags