1
1
/* attrs.c -- recognize HTML attributes
3
(c) 1998-2001 (W3C) MIT, INRIA, Keio University
4
See tidy.c for the copyright notice.
3
(c) 1998-2005 (W3C) MIT, ERCIM, Keio University
4
See tidy.h for the copyright notice.
9
$Date: 2002/03/01 04:47:12 $
14
#include "platform.h" /* platform independent stuff */
15
#include "html.h" /* to pull in definition of nodes */
21
Attribute *attr_summary;
23
Attribute *attr_longdesc;
24
Attribute *attr_usemap;
25
Attribute *attr_ismap;
26
Attribute *attr_language;
28
Attribute *attr_value;
29
Attribute *attr_content;
30
Attribute *attr_title;
31
Attribute *attr_xmlns;
32
Attribute *attr_datafld;
33
Attribute *attr_width;
34
Attribute *attr_height;
37
AttrCheck CheckScript;
41
AttrCheck CheckValign;
43
AttrCheck CheckLength;
44
AttrCheck CheckTarget;
45
AttrCheck CheckFsubmit;
48
AttrCheck CheckNumber;
52
AttrCheck CheckScroll;
53
AttrCheck CheckTextDir;
58
extern char *alt_text;
60
#define XHTML_NAMESPACE "http://www.w3.org/1999/xhtml"
64
static Attribute *hashtab[HASHSIZE];
67
Bind attribute types to procedures to check values.
68
You can add new procedures for better validation
69
and each procedure has access to the node in which
70
the attribute occurred as well as the attribute name
73
By default, attributes are checked without regard
74
to the element they are found on. You have the choice
75
of making the procedure test which element is involved
76
or in writing methods for each element which controls
77
exactly how the attributes of that element are checked.
78
This latter approach is best for detecting the absence
79
of required attributes.
85
#define CHARACTER null
88
#define SCRIPT CheckScript
89
#define ALIGN CheckAlign
90
#define VALIGN CheckValign
91
#define COLOR CheckColor
92
#define CLEAR CheckClear
93
#define BORDER CheckBool /* kludge */
94
#define LANG CheckLang
95
#define BOOL CheckBool
97
#define NUMBER CheckNumber
98
#define LENGTH CheckLength
101
#define TEXTDIR CheckTextDir
104
#define IDDEF CheckId
105
#define NAME CheckName
109
#define FSUBMIT CheckFsubmit
110
#define LINKTYPES null
112
#define SCOPE CheckScope
113
#define SHAPE CheckShape
114
#define SCROLL CheckScroll
115
#define TARGET CheckTarget
116
#define VTYPE CheckVType
118
static struct _attrlist
125
{"abbr", VERS_HTML40, TEXT},
126
{"accept-charset", VERS_HTML40, CHARSET},
127
{"accept", VERS_ALL, TYPE},
128
{"accesskey", VERS_HTML40, CHARACTER},
129
{"action", VERS_ALL, URL},
130
{"add_date", VERS_NETSCAPE, TEXT}, /* A */
131
{"align", VERS_ALL, ALIGN}, /* set varies with element */
132
{"alink", VERS_LOOSE, COLOR},
133
{"alt", VERS_ALL, TEXT},
134
{"archive", VERS_HTML40, URLS}, /* space or comma separated list */
135
{"axis", VERS_HTML40, TEXT},
136
{"background", VERS_LOOSE, URL},
137
{"bgcolor", VERS_LOOSE, COLOR},
138
{"bgproperties", VERS_PROPRIETARY, TEXT}, /* BODY "fixed" fixes background */
139
{"border", VERS_ALL, BORDER}, /* like LENGTH + "border" */
140
{"bordercolor", VERS_MICROSOFT, COLOR}, /* used on TABLE */
141
{"bottommargin", VERS_MICROSOFT, NUMBER}, /* used on BODY */
142
{"cellpadding", VERS_FROM32, LENGTH}, /* % or pixel values */
143
{"cellspacing", VERS_FROM32, LENGTH},
144
{"char", VERS_HTML40, CHARACTER},
145
{"charoff", VERS_HTML40, LENGTH},
146
{"charset", VERS_HTML40, CHARSET},
147
{"checked", VERS_ALL, BOOL}, /* i.e. "checked" or absent */
148
{"cite", VERS_HTML40, URL},
149
{"class", VERS_HTML40, TEXT},
150
{"classid", VERS_HTML40, URL},
151
{"clear", VERS_LOOSE, CLEAR}, /* BR: left, right, all */
152
{"code", VERS_LOOSE, TEXT}, /* APPLET */
153
{"codebase", VERS_HTML40, URL}, /* OBJECT */
154
{"codetype", VERS_HTML40, TYPE}, /* OBJECT */
155
{"color", VERS_LOOSE, COLOR}, /* BASEFONT, FONT */
156
{"cols", VERS_IFRAME, COLS}, /* TABLE & FRAMESET */
157
{"colspan", VERS_FROM32, NUMBER},
158
{"compact", VERS_ALL, BOOL}, /* lists */
159
{"content", VERS_ALL, TEXT}, /* META */
160
{"coords", VERS_FROM32, COORDS}, /* AREA, A */
161
{"data", VERS_HTML40, URL}, /* OBJECT */
162
{"datafld", VERS_MICROSOFT, TEXT}, /* used on DIV, IMG */
163
{"dataformatas", VERS_MICROSOFT, TEXT}, /* used on DIV, IMG */
164
{"datapagesize", VERS_MICROSOFT, NUMBER}, /* used on DIV, IMG */
165
{"datasrc", VERS_MICROSOFT, URL}, /* used on TABLE */
166
{"datetime", VERS_HTML40, DATE}, /* INS, DEL */
167
{"declare", VERS_HTML40, BOOL}, /* OBJECT */
168
{"defer", VERS_HTML40, BOOL}, /* SCRIPT */
169
{"dir", VERS_HTML40, TEXTDIR}, /* ltr or rtl */
170
{"disabled", VERS_HTML40, BOOL}, /* form fields */
171
{"enctype", VERS_ALL, TYPE}, /* FORM */
172
{"face", VERS_LOOSE, TEXT}, /* BASEFONT, FONT */
173
{"for", VERS_HTML40, IDREF}, /* LABEL */
174
{"frame", VERS_HTML40, TFRAME}, /* TABLE */
175
{"frameborder", VERS_FRAMESET, FBORDER}, /* 0 or 1 */
176
{"framespacing", VERS_PROPRIETARY, NUMBER}, /* pixel value */
177
{"gridx", VERS_PROPRIETARY, NUMBER}, /* TABLE Adobe golive*/
178
{"gridy", VERS_PROPRIETARY, NUMBER}, /* TABLE Adobe golive */
179
{"headers", VERS_HTML40, IDREFS}, /* table cells */
180
{"height", VERS_ALL, LENGTH}, /* pixels only for TH/TD */
181
{"href", VERS_ALL, URL}, /* A, AREA, LINK and BASE */
182
{"hreflang", VERS_HTML40, LANG}, /* A, LINK */
183
{"hspace", VERS_ALL, NUMBER}, /* APPLET, IMG, OBJECT */
184
{"http-equiv", VERS_ALL, TEXT}, /* META */
185
{"id", VERS_HTML40, IDDEF},
186
{"ismap", VERS_ALL, BOOL}, /* IMG */
187
{"label", VERS_HTML40, TEXT}, /* OPT, OPTGROUP */
188
{"lang", VERS_HTML40, LANG},
189
{"language", VERS_LOOSE, TEXT}, /* SCRIPT */
190
{"last_modified", VERS_NETSCAPE, TEXT}, /* A */
191
{"last_visit", VERS_NETSCAPE, TEXT}, /* A */
192
{"leftmargin", VERS_MICROSOFT, NUMBER}, /* used on BODY */
193
{"link", VERS_LOOSE, COLOR}, /* BODY */
194
{"longdesc", VERS_HTML40, URL}, /* IMG */
195
{"lowsrc", VERS_PROPRIETARY, URL}, /* IMG */
196
{"marginheight", VERS_IFRAME, NUMBER}, /* FRAME, IFRAME, BODY */
197
{"marginwidth", VERS_IFRAME, NUMBER}, /* ditto */
198
{"maxlength", VERS_ALL, NUMBER}, /* INPUT */
199
{"media", VERS_HTML40, MEDIA}, /* STYLE, LINK */
200
{"method", VERS_ALL, FSUBMIT}, /* FORM: get or post */
201
{"multiple", VERS_ALL, BOOL}, /* SELECT */
202
{"name", VERS_ALL, NAME},
203
{"nohref", VERS_FROM32, BOOL}, /* AREA */
204
{"noresize", VERS_FRAMESET, BOOL}, /* FRAME */
205
{"noshade", VERS_LOOSE, BOOL}, /* HR */
206
{"nowrap", VERS_LOOSE, BOOL}, /* table cells */
207
{"object", VERS_HTML40_LOOSE, TEXT}, /* APPLET */
208
{"onblur", VERS_EVENTS, SCRIPT}, /* event */
209
{"onchange", VERS_EVENTS, SCRIPT}, /* event */
210
{"onclick", VERS_EVENTS, SCRIPT}, /* event */
211
{"ondblclick", VERS_EVENTS, SCRIPT}, /* event */
212
{"onkeydown", VERS_EVENTS, SCRIPT}, /* event */
213
{"onkeypress", VERS_EVENTS, SCRIPT}, /* event */
214
{"onkeyup", VERS_EVENTS, SCRIPT}, /* event */
215
{"onload", VERS_EVENTS, SCRIPT}, /* event */
216
{"onmousedown", VERS_EVENTS, SCRIPT}, /* event */
217
{"onmousemove", VERS_EVENTS, SCRIPT}, /* event */
218
{"onmouseout", VERS_EVENTS, SCRIPT}, /* event */
219
{"onmouseover", VERS_EVENTS, SCRIPT}, /* event */
220
{"onmouseup", VERS_EVENTS, SCRIPT}, /* event */
221
{"onsubmit", VERS_EVENTS, SCRIPT}, /* event */
222
{"onreset", VERS_EVENTS, SCRIPT}, /* event */
223
{"onselect", VERS_EVENTS, SCRIPT}, /* event */
224
{"onunload", VERS_EVENTS, SCRIPT}, /* event */
225
{"onfocus", VERS_EVENTS, SCRIPT}, /* event */
226
{"onafterupdate", VERS_MICROSOFT, SCRIPT}, /* form fields */
227
{"onbeforeupdate", VERS_MICROSOFT, SCRIPT}, /* form fields */
228
{"onerrorupdate", VERS_MICROSOFT, SCRIPT}, /* form fields */
229
{"onrowenter", VERS_MICROSOFT, SCRIPT}, /* form fields */
230
{"onrowexit", VERS_MICROSOFT, SCRIPT}, /* form fields */
231
{"onbeforeunload", VERS_MICROSOFT, SCRIPT}, /* form fields */
232
{"ondatasetchanged", VERS_MICROSOFT, SCRIPT}, /* object, applet */
233
{"ondataavailable", VERS_MICROSOFT, SCRIPT}, /* object, applet */
234
{"ondatasetcomplete",VERS_MICROSOFT, SCRIPT}, /* object, applet */
235
{"profile", VERS_HTML40, URL}, /* HEAD */
236
{"prompt", VERS_LOOSE, TEXT}, /* ISINDEX */
237
{"readonly", VERS_HTML40, BOOL}, /* form fields */
238
{"rel", VERS_ALL, LINKTYPES}, /* A, LINK */
239
{"rev", VERS_ALL, LINKTYPES}, /* A, LINK */
240
{"rightmargin", VERS_MICROSOFT, NUMBER}, /* used on BODY */
241
{"rows", VERS_ALL, NUMBER}, /* TEXTAREA */
242
{"rowspan", VERS_ALL, NUMBER}, /* table cells */
243
{"rules", VERS_HTML40, TRULES}, /* TABLE */
244
{"scheme", VERS_HTML40, TEXT}, /* META */
245
{"scope", VERS_HTML40, SCOPE}, /* table cells */
246
{"scrolling", VERS_IFRAME, SCROLL}, /* yes, no or auto */
247
{"selected", VERS_ALL, BOOL}, /* OPTION */
248
{"shape", VERS_FROM32, SHAPE}, /* AREA, A */
249
{"showgrid", VERS_PROPRIETARY, BOOL}, /* TABLE Adobe golive */
250
{"showgridx", VERS_PROPRIETARY, BOOL}, /* TABLE Adobe golive*/
251
{"showgridy", VERS_PROPRIETARY, BOOL}, /* TABLE Adobe golive*/
252
{"size", VERS_LOOSE, NUMBER}, /* HR, FONT, BASEFONT, SELECT */
253
{"span", VERS_HTML40, NUMBER}, /* COL, COLGROUP */
254
{"src", VERS_ALL, URL}, /* IMG, FRAME, IFRAME */
255
{"standby", VERS_HTML40, TEXT}, /* OBJECT */
256
{"start", VERS_ALL, NUMBER}, /* OL */
257
{"style", VERS_HTML40, TEXT},
258
{"summary", VERS_HTML40, TEXT}, /* TABLE */
259
{"tabindex", VERS_HTML40, NUMBER}, /* fields, OBJECT and A */
260
{"target", VERS_HTML40, TARGET}, /* names a frame/window */
261
{"text", VERS_LOOSE, COLOR}, /* BODY */
262
{"title", VERS_HTML40, TEXT}, /* text tool tip */
263
{"topmargin", VERS_MICROSOFT, NUMBER}, /* used on BODY */
264
{"type", VERS_FROM32, TYPE}, /* also used by SPACER */
265
{"usemap", VERS_ALL, BOOL}, /* things with images */
266
{"valign", VERS_FROM32, VALIGN},
267
{"value", VERS_ALL, TEXT}, /* OPTION, PARAM */
268
{"valuetype", VERS_HTML40, VTYPE}, /* PARAM: data, ref, object */
269
{"version", VERS_ALL, TEXT}, /* HTML */
270
{"vlink", VERS_LOOSE, COLOR}, /* BODY */
271
{"vspace", VERS_LOOSE, NUMBER}, /* IMG, OBJECT, APPLET */
272
{"width", VERS_ALL, LENGTH}, /* pixels only for TD/TH */
273
{"wrap", VERS_NETSCAPE, TEXT}, /* textarea */
274
{"xml:lang", VERS_XML, TEXT}, /* XML language */
275
{"xml:space", VERS_XML, TEXT}, /* XML language */
276
{"xmlns", VERS_ALL, TEXT}, /* name space */
277
{"rbspan", VERS_XHTML11, NUMBER}, /* ruby markup */
279
/* this must be the final entry */
9
$Date: 2005/04/15 13:52:06 $
20
static const Attribute attribute_defs [] =
22
{ TidyAttr_UNKNOWN, "unknown!", VERS_PROPRIETARY, NULL },
23
{ TidyAttr_ABBR, "abbr", VERS_HTML40, PCDATA },
24
{ TidyAttr_ACCEPT, "accept", VERS_ALL, TYPE },
25
{ TidyAttr_ACCEPT_CHARSET, "accept-charset", VERS_HTML40, CHARSET },
26
{ TidyAttr_ACCESSKEY, "accesskey", VERS_HTML40, CHARACTER },
27
{ TidyAttr_ACTION, "action", VERS_ALL, URL },
28
{ TidyAttr_ADD_DATE, "add_date", VERS_NETSCAPE, PCDATA }, /* A */
29
{ TidyAttr_ALIGN, "align", VERS_ALL, ALIGN }, /* varies by element */
30
{ TidyAttr_ALINK, "alink", VERS_LOOSE, COLOR },
31
{ TidyAttr_ALT, "alt", VERS_ALL, PCDATA }, /* nowrap */
32
{ TidyAttr_ARCHIVE, "archive", VERS_HTML40, URLS }, /* space or comma separated list */
33
{ TidyAttr_AXIS, "axis", VERS_HTML40, PCDATA },
34
{ TidyAttr_BACKGROUND, "background", VERS_LOOSE, URL },
35
{ TidyAttr_BGCOLOR, "bgcolor", VERS_LOOSE, COLOR },
36
{ TidyAttr_BGPROPERTIES, "bgproperties", VERS_PROPRIETARY, PCDATA }, /* BODY "fixed" fixes background */
37
{ TidyAttr_BORDER, "border", VERS_ALL, BORDER }, /* like LENGTH + "border" */
38
{ TidyAttr_BORDERCOLOR, "bordercolor", VERS_MICROSOFT, COLOR }, /* used on TABLE */
39
{ TidyAttr_BOTTOMMARGIN, "bottommargin", VERS_MICROSOFT, NUMBER }, /* used on BODY */
40
{ TidyAttr_CELLPADDING, "cellpadding", VERS_FROM32, LENGTH }, /* % or pixel values */
41
{ TidyAttr_CELLSPACING, "cellspacing", VERS_FROM32, LENGTH },
42
{ TidyAttr_CHAR, "char", VERS_HTML40, CHARACTER },
43
{ TidyAttr_CHAROFF, "charoff", VERS_HTML40, LENGTH },
44
{ TidyAttr_CHARSET, "charset", VERS_HTML40, CHARSET },
45
{ TidyAttr_CHECKED, "checked", VERS_ALL, BOOL }, /* i.e. "checked" or absent */
46
{ TidyAttr_CITE, "cite", VERS_HTML40, URL },
47
{ TidyAttr_CLASS, "class", VERS_HTML40, PCDATA },
48
{ TidyAttr_CLASSID, "classid", VERS_HTML40, URL },
49
{ TidyAttr_CLEAR, "clear", VERS_LOOSE, CLEAR }, /* BR: left, right, all */
50
{ TidyAttr_CODE, "code", VERS_LOOSE, PCDATA }, /* APPLET */
51
{ TidyAttr_CODEBASE, "codebase", VERS_HTML40, URL }, /* OBJECT */
52
{ TidyAttr_CODETYPE, "codetype", VERS_HTML40, TYPE }, /* OBJECT */
53
{ TidyAttr_COLOR, "color", VERS_LOOSE, COLOR }, /* BASEFONT, FONT */
54
{ TidyAttr_COLS, "cols", VERS_IFRAME, COLS }, /* TABLE & FRAMESET */
55
{ TidyAttr_COLSPAN, "colspan", VERS_FROM32, NUMBER },
56
{ TidyAttr_COMPACT, "compact", VERS_ALL, BOOL }, /* lists */
57
{ TidyAttr_CONTENT, "content", VERS_ALL, PCDATA },
58
{ TidyAttr_COORDS, "coords", VERS_FROM32, COORDS }, /* AREA, A */
59
{ TidyAttr_DATA, "data", VERS_HTML40, URL }, /* OBJECT */
60
{ TidyAttr_DATAFLD, "datafld", VERS_MICROSOFT, PCDATA }, /* used on DIV, IMG */
61
{ TidyAttr_DATAFORMATAS, "dataformatas", VERS_MICROSOFT, PCDATA }, /* used on DIV, IMG */
62
{ TidyAttr_DATAPAGESIZE, "datapagesize", VERS_MICROSOFT, NUMBER }, /* used on DIV, IMG */
63
{ TidyAttr_DATASRC, "datasrc", VERS_MICROSOFT, URL }, /* used on TABLE */
64
{ TidyAttr_DATETIME, "datetime", VERS_HTML40, DATE }, /* INS, DEL */
65
{ TidyAttr_DECLARE, "declare", VERS_HTML40, BOOL }, /* OBJECT */
66
{ TidyAttr_DEFER, "defer", VERS_HTML40, BOOL }, /* SCRIPT */
67
{ TidyAttr_DIR, "dir", VERS_HTML40, TEXTDIR }, /* ltr or rtl */
68
{ TidyAttr_DISABLED, "disabled", VERS_HTML40, BOOL }, /* form fields */
69
{ TidyAttr_ENCODING, "encoding", VERS_XML, PCDATA }, /* <?xml?> */
70
{ TidyAttr_ENCTYPE, "enctype", VERS_ALL, TYPE }, /* FORM */
71
{ TidyAttr_FACE, "face", VERS_LOOSE, PCDATA }, /* BASEFONT, FONT */
72
{ TidyAttr_FOR, "for", VERS_HTML40, IDREF }, /* LABEL */
73
{ TidyAttr_FRAME, "frame", VERS_HTML40, TFRAME }, /* TABLE */
74
{ TidyAttr_FRAMEBORDER, "frameborder", VERS_FRAMESET, FBORDER }, /* 0 or 1 */
75
{ TidyAttr_FRAMESPACING, "framespacing", VERS_PROPRIETARY, NUMBER },
76
{ TidyAttr_GRIDX, "gridx", VERS_PROPRIETARY, NUMBER }, /* TABLE Adobe golive*/
77
{ TidyAttr_GRIDY, "gridy", VERS_PROPRIETARY, NUMBER }, /* TABLE Adobe golive */
78
{ TidyAttr_HEADERS, "headers", VERS_HTML40, IDREFS }, /* table cells */
79
{ TidyAttr_HEIGHT, "height", VERS_ALL, LENGTH }, /* pixels only for TH/TD */
80
{ TidyAttr_HREF, "href", VERS_ALL, URL }, /* A, AREA, LINK and BASE */
81
{ TidyAttr_HREFLANG, "hreflang", VERS_HTML40, LANG }, /* A, LINK */
82
{ TidyAttr_HSPACE, "hspace", VERS_ALL, NUMBER }, /* APPLET, IMG, OBJECT */
83
{ TidyAttr_HTTP_EQUIV, "http-equiv", VERS_ALL, PCDATA }, /* META */
84
{ TidyAttr_ID, "id", VERS_HTML40, IDDEF },
85
{ TidyAttr_ISMAP, "ismap", VERS_ALL, BOOL }, /* IMG */
86
{ TidyAttr_LABEL, "label", VERS_HTML40, PCDATA }, /* OPT, OPTGROUP */
87
{ TidyAttr_LANG, "lang", VERS_HTML40, LANG },
88
{ TidyAttr_LANGUAGE, "language", VERS_LOOSE, PCDATA }, /* SCRIPT */
89
{ TidyAttr_LAST_MODIFIED, "last_modified", VERS_NETSCAPE, PCDATA }, /* A */
90
{ TidyAttr_LAST_VISIT, "last_visit", VERS_NETSCAPE, PCDATA }, /* A */
91
{ TidyAttr_LEFTMARGIN, "leftmargin", VERS_MICROSOFT, NUMBER }, /* used on BODY */
92
{ TidyAttr_LINK, "link", VERS_LOOSE, COLOR }, /* BODY */
93
{ TidyAttr_LONGDESC, "longdesc", VERS_HTML40, URL }, /* IMG */
94
{ TidyAttr_LOWSRC, "lowsrc", VERS_PROPRIETARY, URL }, /* IMG */
95
{ TidyAttr_MARGINHEIGHT, "marginheight", VERS_IFRAME, NUMBER }, /* FRAME, IFRAME, BODY */
96
{ TidyAttr_MARGINWIDTH, "marginwidth", VERS_IFRAME, NUMBER }, /* ditto */
97
{ TidyAttr_MAXLENGTH, "maxlength", VERS_ALL, NUMBER }, /* INPUT */
98
{ TidyAttr_MEDIA, "media", VERS_HTML40, MEDIA }, /* STYLE, LINK */
99
{ TidyAttr_METHOD, "method", VERS_ALL, FSUBMIT }, /* FORM: get or post */
100
{ TidyAttr_MULTIPLE, "multiple", VERS_ALL, BOOL }, /* SELECT */
101
{ TidyAttr_NAME, "name", VERS_ALL, NAME },
102
{ TidyAttr_NOHREF, "nohref", VERS_FROM32, BOOL }, /* AREA */
103
{ TidyAttr_NORESIZE, "noresize", VERS_FRAMESET, BOOL }, /* FRAME */
104
{ TidyAttr_NOSHADE, "noshade", VERS_LOOSE, BOOL }, /* HR */
105
{ TidyAttr_NOWRAP, "nowrap", VERS_LOOSE, BOOL }, /* table cells */
106
{ TidyAttr_OBJECT, "object", VERS_HTML40_LOOSE, PCDATA }, /* APPLET */
107
{ TidyAttr_OnAFTERUPDATE, "onafterupdate", VERS_MICROSOFT, SCRIPT },
108
{ TidyAttr_OnBEFOREUNLOAD, "onbeforeunload", VERS_MICROSOFT, SCRIPT },
109
{ TidyAttr_OnBEFOREUPDATE, "onbeforeupdate", VERS_MICROSOFT, SCRIPT },
110
{ TidyAttr_OnBLUR, "onblur", VERS_EVENTS, SCRIPT }, /* event */
111
{ TidyAttr_OnCHANGE, "onchange", VERS_EVENTS, SCRIPT }, /* event */
112
{ TidyAttr_OnCLICK, "onclick", VERS_EVENTS, SCRIPT }, /* event */
113
{ TidyAttr_OnDATAAVAILABLE, "ondataavailable", VERS_MICROSOFT, SCRIPT }, /* object, applet */
114
{ TidyAttr_OnDATASETCHANGED, "ondatasetchanged", VERS_MICROSOFT, SCRIPT }, /* object, applet */
115
{ TidyAttr_OnDATASETCOMPLETE, "ondatasetcomplete", VERS_MICROSOFT, SCRIPT },
116
{ TidyAttr_OnDBLCLICK, "ondblclick", VERS_EVENTS, SCRIPT }, /* event */
117
{ TidyAttr_OnERRORUPDATE, "onerrorupdate", VERS_MICROSOFT, SCRIPT }, /* form fields */
118
{ TidyAttr_OnFOCUS, "onfocus", VERS_EVENTS, SCRIPT }, /* event */
119
{ TidyAttr_OnKEYDOWN, "onkeydown", VERS_EVENTS, SCRIPT }, /* event */
120
{ TidyAttr_OnKEYPRESS, "onkeypress", VERS_EVENTS, SCRIPT }, /* event */
121
{ TidyAttr_OnKEYUP, "onkeyup", VERS_EVENTS, SCRIPT }, /* event */
122
{ TidyAttr_OnLOAD, "onload", VERS_EVENTS, SCRIPT }, /* event */
123
{ TidyAttr_OnMOUSEDOWN, "onmousedown", VERS_EVENTS, SCRIPT }, /* event */
124
{ TidyAttr_OnMOUSEMOVE, "onmousemove", VERS_EVENTS, SCRIPT }, /* event */
125
{ TidyAttr_OnMOUSEOUT, "onmouseout", VERS_EVENTS, SCRIPT }, /* event */
126
{ TidyAttr_OnMOUSEOVER, "onmouseover", VERS_EVENTS, SCRIPT }, /* event */
127
{ TidyAttr_OnMOUSEUP, "onmouseup", VERS_EVENTS, SCRIPT }, /* event */
128
{ TidyAttr_OnRESET, "onreset", VERS_EVENTS, SCRIPT }, /* event */
129
{ TidyAttr_OnROWENTER, "onrowenter", VERS_MICROSOFT, SCRIPT }, /* form fields */
130
{ TidyAttr_OnROWEXIT, "onrowexit", VERS_MICROSOFT, SCRIPT }, /* form fields */
131
{ TidyAttr_OnSELECT, "onselect", VERS_EVENTS, SCRIPT }, /* event */
132
{ TidyAttr_OnSUBMIT, "onsubmit", VERS_EVENTS, SCRIPT }, /* event */
133
{ TidyAttr_OnUNLOAD, "onunload", VERS_EVENTS, SCRIPT }, /* event */
134
{ TidyAttr_PROFILE, "profile", VERS_HTML40, URL }, /* HEAD */
135
{ TidyAttr_PROMPT, "prompt", VERS_LOOSE, PCDATA }, /* ISINDEX */
136
{ TidyAttr_RBSPAN, "rbspan", VERS_XHTML11, NUMBER }, /* ruby markup */
137
{ TidyAttr_READONLY, "readonly", VERS_HTML40, BOOL }, /* form fields */
138
{ TidyAttr_REL, "rel", VERS_ALL, LINKTYPES },
139
{ TidyAttr_REV, "rev", VERS_ALL, LINKTYPES },
140
{ TidyAttr_RIGHTMARGIN, "rightmargin", VERS_MICROSOFT, NUMBER }, /* used on BODY */
141
{ TidyAttr_ROWS, "rows", VERS_ALL, NUMBER }, /* TEXTAREA */
142
{ TidyAttr_ROWSPAN, "rowspan", VERS_ALL, NUMBER }, /* table cells */
143
{ TidyAttr_RULES, "rules", VERS_HTML40, TRULES }, /* TABLE */
144
{ TidyAttr_SCHEME, "scheme", VERS_HTML40, PCDATA }, /* META */
145
{ TidyAttr_SCOPE, "scope", VERS_HTML40, SCOPE }, /* table cells */
146
{ TidyAttr_SCROLLING, "scrolling", VERS_IFRAME, SCROLL }, /* yes, no or auto */
147
{ TidyAttr_SELECTED, "selected", VERS_ALL, BOOL }, /* OPTION */
148
{ TidyAttr_SHAPE, "shape", VERS_FROM32, SHAPE }, /* AREA, A */
149
{ TidyAttr_SHOWGRID, "showgrid", VERS_PROPRIETARY, BOOL }, /* TABLE Adobe golive */
150
{ TidyAttr_SHOWGRIDX, "showgridx", VERS_PROPRIETARY, BOOL }, /* TABLE Adobe golive*/
151
{ TidyAttr_SHOWGRIDY, "showgridy", VERS_PROPRIETARY, BOOL }, /* TABLE Adobe golive*/
152
{ TidyAttr_SIZE, "size", VERS_LOOSE, NUMBER }, /* HR, FONT, BASEFONT, SELECT */
153
{ TidyAttr_SPAN, "span", VERS_HTML40, NUMBER }, /* COL, COLGROUP */
154
{ TidyAttr_SRC, "src", VERS_ALL, URL }, /* IMG, FRAME, IFRAME */
155
{ TidyAttr_STANDBY, "standby", VERS_HTML40, PCDATA }, /* OBJECT */
156
{ TidyAttr_START, "start", VERS_ALL, NUMBER }, /* OL */
157
{ TidyAttr_STYLE, "style", VERS_HTML40, PCDATA },
158
{ TidyAttr_SUMMARY, "summary", VERS_HTML40, PCDATA }, /* TABLE */
159
{ TidyAttr_TABINDEX, "tabindex", VERS_HTML40, NUMBER }, /* fields, OBJECT and A */
160
{ TidyAttr_TARGET, "target", VERS_HTML40, TARGET }, /* names a frame/window */
161
{ TidyAttr_TEXT, "text", VERS_LOOSE, COLOR }, /* BODY */
162
{ TidyAttr_TITLE, "title", VERS_HTML40, PCDATA }, /* text tool tip */
163
{ TidyAttr_TOPMARGIN, "topmargin", VERS_MICROSOFT, NUMBER }, /* used on BODY */
164
{ TidyAttr_TYPE, "type", VERS_FROM32, TYPE }, /* also used by SPACER */
165
{ TidyAttr_USEMAP, "usemap", VERS_ALL, URL }, /* things with images */
166
{ TidyAttr_VALIGN, "valign", VERS_FROM32, VALIGN },
167
{ TidyAttr_VALUE, "value", VERS_ALL, PCDATA },
168
{ TidyAttr_VALUETYPE, "valuetype", VERS_HTML40, VTYPE }, /* PARAM: data, ref, object */
169
{ TidyAttr_VERSION, "version", VERS_ALL|VERS_XML, PCDATA }, /* HTML <?xml?> */
170
{ TidyAttr_VLINK, "vlink", VERS_LOOSE, COLOR }, /* BODY */
171
{ TidyAttr_VSPACE, "vspace", VERS_LOOSE, NUMBER }, /* IMG, OBJECT, APPLET */
172
{ TidyAttr_WIDTH, "width", VERS_ALL, LENGTH }, /* pixels only for TD/TH */
173
{ TidyAttr_WRAP, "wrap", VERS_NETSCAPE, PCDATA }, /* textarea */
174
{ TidyAttr_XML_LANG, "xml:lang", VERS_XML, LANG }, /* XML language */
175
{ TidyAttr_XML_SPACE, "xml:space", VERS_XML, PCDATA }, /* XML white space */
177
/* todo: VERS_ALL is wrong! */
178
{ TidyAttr_XMLNS, "xmlns", VERS_ALL, PCDATA }, /* name space */
179
{ TidyAttr_EVENT, "event", VERS_HTML40, PCDATA }, /* reserved for <script> */
180
{ TidyAttr_METHODS, "methods", VERS_HTML20, PCDATA }, /* for <a>, never implemented */
181
{ TidyAttr_N, "n", VERS_HTML20, PCDATA }, /* for <nextid> */
182
{ TidyAttr_SDAFORM, "sdaform", VERS_HTML20, PCDATA }, /* SDATA attribute in HTML 2.0 */
183
{ TidyAttr_SDAPREF, "sdapref", VERS_HTML20, PCDATA }, /* SDATA attribute in HTML 2.0 */
184
{ TidyAttr_SDASUFF, "sdasuff", VERS_HTML20, PCDATA }, /* SDATA attribute in HTML 2.0 */
185
{ TidyAttr_URN, "urn", VERS_HTML20, PCDATA }, /* for <a>, never implemented */
187
/* this must be the final entry */
188
{ N_TIDY_ATTRIBS, NULL, VERS_UNKNOWN, NULL }
191
static uint AttributeVersions(Node* node, AttVal* attval)
195
if (!attval || !attval->dict)
198
if (!node || !node->tag || !node->tag->attrvers)
199
return attval->dict->versions;
201
for (i = 0; node->tag->attrvers[i].attribute; ++i)
202
if (node->tag->attrvers[i].attribute == attval->dict->id)
203
return node->tag->attrvers[i].versions;
205
return attval->dict->versions & VERS_ALL
207
: attval->dict->versions;
212
/* return the version of the attribute "id" of element "node" */
213
uint NodeAttributeVersions( Node* node, TidyAttrId id )
217
if (!node || !node->tag || !node->tag->attrvers)
220
for (i = 0; node->tag->attrvers[i].attribute; ++i)
221
if (node->tag->attrvers[i].attribute == id)
222
return node->tag->attrvers[i].versions;
227
/* returns true if the element is a W3C defined element */
228
/* but the element/attribute combination is not */
229
static Bool AttributeIsProprietary(Node* node, AttVal* attval)
231
if (!node || !attval)
237
if (!(node->tag->versions & VERS_ALL))
240
if (AttributeVersions(node, attval) & VERS_ALL)
283
246
/* used by CheckColor() */
284
static struct _colors
290
{"black", "#000000"}, {"green", "#008000"},
291
{"silver", "#C0C0C0"}, {"lime", "#00FF00"},
292
{"gray", "#808080"}, {"olive", "#808000"},
293
{"white", "#FFFFFF"}, {"yellow", "#FFFF00"},
294
{"maroon", "#800000"}, {"navy", "#000080"},
295
{"red", "#FF0000"}, {"blue", "#0000FF"},
296
{"purple", "#800080"}, {"teal", "#008080"},
297
{"fuchsia", "#FF00FF"}, {"aqua", "#00FFFF"},
301
static unsigned hash(char *s)
253
static const struct _colors colors[] =
255
{ "black", "#000000" },
256
{ "green", "#008000" },
257
{ "silver", "#C0C0C0" },
258
{ "lime", "#00FF00" },
259
{ "gray", "#808080" },
260
{ "olive", "#808000" },
261
{ "white", "#FFFFFF" },
262
{ "yellow", "#FFFF00" },
263
{ "maroon", "#800000" },
264
{ "navy", "#000080" },
265
{ "red", "#FF0000" },
266
{ "blue", "#0000FF" },
267
{ "purple", "#800080" },
268
{ "teal", "#008080" },
269
{ "fuchsia", "#FF00FF" },
270
{ "aqua", "#00FFFF" },
274
static ctmbstr GetColorCode(ctmbstr name)
278
for (i = 0; colors[i].name; ++i)
279
if (tmbstrcasecmp(name, colors[i].name) == 0)
280
return colors[i].hex;
285
static ctmbstr GetColorName(ctmbstr code)
289
for (i = 0; colors[i].name; ++i)
290
if (tmbstrcasecmp(code, colors[i].hex) == 0)
291
return colors[i].name;
297
static const struct _colors fancy_colors[] =
299
{ "darkgreen", "#006400" },
300
{ "antiquewhite", "#FAEBD7" },
301
{ "aqua", "#00FFFF" },
302
{ "aquamarine", "#7FFFD4" },
303
{ "azure", "#F0FFFF" },
304
{ "beige", "#F5F5DC" },
305
{ "bisque", "#FFE4C4" },
306
{ "black", "#000000" },
307
{ "blanchedalmond", "#FFEBCD" },
308
{ "blue", "#0000FF" },
309
{ "blueviolet", "#8A2BE2" },
310
{ "brown", "#A52A2A" },
311
{ "burlywood", "#DEB887" },
312
{ "cadetblue", "#5F9EA0" },
313
{ "chartreuse", "#7FFF00" },
314
{ "chocolate", "#D2691E" },
315
{ "coral", "#FF7F50" },
316
{ "cornflowerblue", "#6495ED" },
317
{ "cornsilk", "#FFF8DC" },
318
{ "crimson", "#DC143C" },
319
{ "cyan", "#00FFFF" },
320
{ "darkblue", "#00008B" },
321
{ "darkcyan", "#008B8B" },
322
{ "darkgoldenrod", "#B8860B" },
323
{ "darkgray", "#A9A9A9" },
324
{ "darkgreen", "#006400" },
325
{ "darkkhaki", "#BDB76B" },
326
{ "darkmagenta", "#8B008B" },
327
{ "darkolivegreen", "#556B2F" },
328
{ "darkorange", "#FF8C00" },
329
{ "darkorchid", "#9932CC" },
330
{ "darkred", "#8B0000" },
331
{ "darksalmon", "#E9967A" },
332
{ "darkseagreen", "#8FBC8F" },
333
{ "darkslateblue", "#483D8B" },
334
{ "darkslategray", "#2F4F4F" },
335
{ "darkturquoise", "#00CED1" },
336
{ "darkviolet", "#9400D3" },
337
{ "deeppink", "#FF1493" },
338
{ "deepskyblue", "#00BFFF" },
339
{ "dimgray", "#696969" },
340
{ "dodgerblue", "#1E90FF" },
341
{ "firebrick", "#B22222" },
342
{ "floralwhite", "#FFFAF0" },
343
{ "forestgreen", "#228B22" },
344
{ "fuchsia", "#FF00FF" },
345
{ "gainsboro", "#DCDCDC" },
346
{ "ghostwhite", "#F8F8FF" },
347
{ "gold", "#FFD700" },
348
{ "goldenrod", "#DAA520" },
349
{ "gray", "#808080" },
350
{ "green", "#008000" },
351
{ "greenyellow", "#ADFF2F" },
352
{ "honeydew", "#F0FFF0" },
353
{ "hotpink", "#FF69B4" },
354
{ "indianred", "#CD5C5C" },
355
{ "indigo", "#4B0082" },
356
{ "ivory", "#FFFFF0" },
357
{ "khaki", "#F0E68C" },
358
{ "lavender", "#E6E6FA" },
359
{ "lavenderblush", "#FFF0F5" },
360
{ "lawngreen", "#7CFC00" },
361
{ "lemonchiffon", "#FFFACD" },
362
{ "lightblue", "#ADD8E6" },
363
{ "lightcoral", "#F08080" },
364
{ "lightcyan", "#E0FFFF" },
365
{ "lightgoldenrodyellow", "#FAFAD2" },
366
{ "lightgreen", "#90EE90" },
367
{ "lightgrey", "#D3D3D3" },
368
{ "lightpink", "#FFB6C1" },
369
{ "lightsalmon", "#FFA07A" },
370
{ "lightseagreen", "#20B2AA" },
371
{ "lightskyblue", "#87CEFA" },
372
{ "lightslategray", "#778899" },
373
{ "lightsteelblue", "#B0C4DE" },
374
{ "lightyellow", "#FFFFE0" },
375
{ "lime", "#00FF00" },
376
{ "limegreen", "#32CD32" },
377
{ "linen", "#FAF0E6" },
378
{ "magenta", "#FF00FF" },
379
{ "maroon", "#800000" },
380
{ "mediumaquamarine", "#66CDAA" },
381
{ "mediumblue", "#0000CD" },
382
{ "mediumorchid", "#BA55D3" },
383
{ "mediumpurple", "#9370DB" },
384
{ "mediumseagreen", "#3CB371" },
385
{ "mediumslateblue", "#7B68EE" },
386
{ "mediumspringgreen", "#00FA9A" },
387
{ "mediumturquoise", "#48D1CC" },
388
{ "mediumvioletred", "#C71585" },
389
{ "midnightblue", "#191970" },
390
{ "mintcream", "#F5FFFA" },
391
{ "mistyrose", "#FFE4E1" },
392
{ "moccasin", "#FFE4B5" },
393
{ "navajowhite", "#FFDEAD" },
394
{ "navy", "#000080" },
395
{ "oldlace", "#FDF5E6" },
396
{ "olive", "#808000" },
397
{ "olivedrab", "#6B8E23" },
398
{ "orange", "#FFA500" },
399
{ "orangered", "#FF4500" },
400
{ "orchid", "#DA70D6" },
401
{ "palegoldenrod", "#EEE8AA" },
402
{ "palegreen", "#98FB98" },
403
{ "paleturquoise", "#AFEEEE" },
404
{ "palevioletred", "#DB7093" },
405
{ "papayawhip", "#FFEFD5" },
406
{ "peachpuff", "#FFDAB9" },
407
{ "peru", "#CD853F" },
408
{ "pink", "#FFC0CB" },
409
{ "plum", "#DDA0DD" },
410
{ "powderblue", "#B0E0E6" },
411
{ "purple", "#800080" },
412
{ "red", "#FF0000" },
413
{ "rosybrown", "#BC8F8F" },
414
{ "royalblue", "#4169E1" },
415
{ "saddlebrown", "#8B4513" },
416
{ "salmon", "#FA8072" },
417
{ "sandybrown", "#F4A460" },
418
{ "seagreen", "#2E8B57" },
419
{ "seashell", "#FFF5EE" },
420
{ "sienna", "#A0522D" },
421
{ "silver", "#C0C0C0" },
422
{ "skyblue", "#87CEEB" },
423
{ "slateblue", "#6A5ACD" },
424
{ "slategray", "#708090" },
425
{ "snow", "#FFFAFA" },
426
{ "springgreen", "#00FF7F" },
427
{ "steelblue", "#4682B4" },
428
{ "tan", "#D2B48C" },
429
{ "teal", "#008080" },
430
{ "thistle", "#D8BFD8" },
431
{ "tomato", "#FF6347" },
432
{ "turquoise", "#40E0D0" },
433
{ "violet", "#EE82EE" },
434
{ "wheat", "#F5DEB3" },
435
{ "white", "#FFFFFF" },
436
{ "whitesmoke", "#F5F5F5" },
437
{ "yellow", "#FFFF00" },
438
{ "yellowgreen", "#9ACD32" },
443
#ifdef ATTRIBUTE_HASH_LOOKUP
444
static uint hash(ctmbstr s)
305
448
for (hashval = 0; *s != '\0'; s++)
306
449
hashval = *s + 31*hashval;
308
return hashval % HASHSIZE;
311
static Attribute *lookup(char *s)
315
for (np = hashtab[hash(s)]; np != null; np = np->next)
316
if (wstrcmp(s, np->name) == 0)
321
static Attribute *install(char *name, uint versions, AttrCheck *attrchk)
326
if ((np = lookup(name)) == null)
328
np = (Attribute *)MemAlloc(sizeof(*np));
330
if (np == null || (np->name = wstrdup(name)) == null)
333
hashval = hash(name);
334
np->next = hashtab[hashval];
335
hashtab[hashval] = np;
338
np->versions = versions;
339
np->attrchk = attrchk;
451
return hashval % ATTRIBUTE_HASH_SIZE;
454
static Attribute *install(TidyAttribImpl * attribs, const Attribute* old)
459
np = (Attribute *)MemAlloc(sizeof(*np));
461
np->name = tmbstrdup(old->name);
463
hashval = hash(np->name);
464
np->next = attribs->hashtab[hashval];
465
attribs->hashtab[hashval] = np;
468
np->versions = old->versions;
469
np->attrchk = old->attrchk;
345
static void SetNoWrap(Attribute *attr)
347
attr->nowrap = yes; /* defaults to no */
475
static const Attribute* lookup(TidyAttribImpl* ARG_UNUSED(attribs),
483
#ifdef ATTRIBUTE_HASH_LOOKUP
484
for (np = attribs->hashtab[hash(atnam)]; np != NULL; np = np->next)
485
if (tmbstrcmp(atnam, np->name) == 0)
488
for (np = attribute_defs; np && np->name; ++np)
489
if (tmbstrcmp(atnam, np->name) == 0)
490
return install(attribs, np);
492
for (np = attribute_defs; np && np->name; ++np)
493
if (tmbstrcmp(atnam, np->name) == 0)
501
/* Locate attributes by type */
502
AttVal* AttrGetById( Node* node, TidyAttrId id )
505
for ( av = node->attributes; av; av = av->next )
507
if ( AttrIsId(av, id) )
350
513
/* public method for finding attribute definition by name */
351
Attribute *FindAttribute(AttVal *attval)
514
const Attribute* FindAttribute( TidyDocImpl* doc, AttVal *attval )
355
if (attval->attribute && (np = lookup(attval->attribute)))
517
return lookup( &doc->attribs, attval->attribute );
361
AttVal *GetAttrByName(Node *node, char *name)
521
AttVal* GetAttrByName( Node *node, ctmbstr name )
365
for (attr = node->attributes; attr != null; attr = attr->next)
524
for (attr = node->attributes; attr != NULL; attr = attr->next)
367
if (wstrcmp(attr->attribute, name) == 0)
526
if (attr->attribute && tmbstrcmp(attr->attribute, name) == 0)
374
void AddAttribute(Node *node, char *name, char *value)
532
AttVal* AddAttribute( TidyDocImpl* doc,
533
Node *node, ctmbstr name, ctmbstr value )
376
535
AttVal *av = NewAttribute();
378
av->attribute = wstrdup(name);
379
av->value = wstrdup(value);
380
av->dict = FindAttribute(av);
382
if (node->attributes == null)
383
node->attributes = av;
384
else /* append to end of attributes */
537
av->attribute = tmbstrdup(name);
540
av->value = tmbstrdup(value);
544
av->dict = lookup(&doc->attribs, name);
546
InsertAttributeAtEnd(node, av);
550
AttVal* RepairAttrValue(TidyDocImpl* doc, Node* node, ctmbstr name, ctmbstr value)
552
AttVal* old = GetAttrByName(node, name);
386
AttVal *here = node->attributes;
559
old->value = tmbstrdup(value);
395
Bool IsUrl(char *attrname)
399
return (Bool)((np = lookup(attrname)) && np->attrchk == URL);
402
Bool IsBool(char *attrname)
406
return (Bool)((np = lookup(attrname)) && np->attrchk == BOOL);
409
Bool IsScript(char *attrname)
413
return (Bool)((np = lookup(attrname)) && np->attrchk == SCRIPT);
416
Bool IsLiteralAttribute(char *attrname)
420
return (Bool)((np = lookup(attrname)) && np->literal);
566
return AddAttribute(doc, node, name, value);
569
static Bool CheckAttrType( TidyDocImpl* doc,
570
ctmbstr attrname, AttrCheck type )
572
const Attribute* np = lookup( &doc->attribs, attrname );
573
return (Bool)( np && np->attrchk == type );
576
Bool IsUrl( TidyDocImpl* doc, ctmbstr attrname )
578
return CheckAttrType( doc, attrname, URL );
581
Bool IsBool( TidyDocImpl* doc, ctmbstr attrname )
583
return CheckAttrType( doc, attrname, BOOL );
586
Bool IsScript( TidyDocImpl* doc, ctmbstr attrname )
588
return CheckAttrType( doc, attrname, SCRIPT );
423
591
/* may id or name serve as anchor? */
424
Bool IsAnchorElement(Node *node)
592
Bool IsAnchorElement( TidyDocImpl* ARG_UNUSED(doc), Node* node)
426
if (node->tag == tag_a ||
427
node->tag == tag_applet ||
428
node->tag == tag_form ||
429
node->tag == tag_frame ||
430
node->tag == tag_iframe ||
431
node->tag == tag_img ||
432
node->tag == tag_map)
594
TidyTagId tid = TagId( node );
595
if ( tid == TidyTag_A ||
596
tid == TidyTag_APPLET ||
597
tid == TidyTag_FORM ||
598
tid == TidyTag_FRAME ||
599
tid == TidyTag_IFRAME ||
600
tid == TidyTag_IMG ||
439
In CSS1, selectors can contain only the characters A-Z, 0-9, and Unicode characters 161-255, plus dash (-);
440
they cannot start with a dash or a digit; they can also contain escaped characters and any Unicode character
441
as a numeric code (see next item).
443
The backslash followed by at most four hexadecimal digits (0..9A..F) stands for the Unicode character with that number.
445
Any character except a hexadecimal digit can be escaped to remove its special meaning, by putting a backslash in front.
608
In CSS1, selectors can contain only the characters A-Z, 0-9,
609
and Unicode characters 161-255, plus dash (-); they cannot start
610
with a dash or a digit; they can also contain escaped characters
611
and any Unicode character as a numeric code (see next item).
613
The backslash followed by at most four hexadecimal digits
614
(0..9A..F) stands for the Unicode character with that number.
616
Any character except a hexadecimal digit can be escaped to remove
617
its special meaning, by putting a backslash in front.
447
619
#508936 - CSS class naming for -clean option
449
Bool IsCSS1Selector(char *buf)
621
Bool IsCSS1Selector( ctmbstr buf )
451
623
Bool valid = yes;
456
628
for ( pos=0; valid && (c = *buf++); ++pos )
1025
Lexer* lexer = doc->lexer;
863
1026
if (lexer->isvoyager)
864
ReportAttrError(lexer, node, attval, ATTR_VALUE_NOT_LCASE);
1027
ReportAttrError( doc, node, attval, ATTR_VALUE_NOT_LCASE);
866
if (lexer->isvoyager || LowerLiterals)
867
attval->value = wstrtolower(attval->value);
1029
if ( lexer->isvoyager || cfgBool(doc, TidyLowerLiterals) )
1030
attval->value = tmbstrtolower(attval->value);
871
1034
/* methods for checking value of a specific attribute */
873
void CheckUrl(Lexer *lexer, Node *node, AttVal *attval)
1036
void CheckUrl( TidyDocImpl* doc, Node *node, AttVal *attval)
876
1040
uint escape_count = 0, backslash_count = 0;
877
1041
uint i, pos = 0;
880
if (attval == null || attval->value == null)
1044
if (!AttrHasValue(attval))
882
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1046
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
886
1050
p = attval->value;
888
for (i = 0; c = p[i]; ++i)
1052
for (i = 0; 0 != (c = p[i]); ++i)
892
1056
++backslash_count;
1057
if ( cfgBool(doc, TidyFixBackslash) )
896
1060
else if ((c > 0x7e) || (c <= 0x20) || (strchr("<>", c)))
900
if (FixUri && escape_count)
1064
if ( cfgBool(doc, TidyFixUri) && escape_count )
902
len = wstrlen(p) + escape_count * 2 + 1;
903
dest = (char *)MemAlloc(len);
1066
len = tmbstrlen(p) + escape_count * 2 + 1;
1067
dest = (tmbstr) MemAlloc(len);
905
for (i = 0; c = p[i]; ++i)
1069
for (i = 0; 0 != (c = p[i]); ++i)
907
1071
if ((c > 0x7e) || (c <= 0x20) || (strchr("<>", c)))
908
pos += sprintf(dest + pos, "%%%02X", (unsigned char)c);
1072
pos += sprintf( dest + pos, "%%%02X", (byte)c );
910
1074
dest[pos++] = c;
914
1078
MemFree(attval->value);
915
1079
attval->value = dest;
920
ReportAttrError(lexer, node, attval, FIXED_BACKSLASH);
922
ReportAttrError(lexer, node, attval, BACKSLASH_IN_URI);
927
ReportAttrError(lexer, node, attval, ESCAPED_ILLEGAL_URI);
929
ReportAttrError(lexer, node, attval, ILLEGAL_URI_REFERENCE);
931
lexer->badChars |= INVALID_URI;
935
void CheckScript(Lexer *lexer, Node *node, AttVal *attval)
939
void CheckName(Lexer *lexer, Node *node, AttVal *attval)
943
if (attval == null || attval->value == null)
945
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
949
if (IsAnchorElement(node))
951
ConstrainVersion(lexer, ~VERS_XHTML11);
953
if ((old = GetNodeByAnchor(attval->value)) && old != node)
955
ReportAttrError(lexer, node, attval, ANCHOR_NOT_UNIQUE);
958
anchor_list = AddAnchor(attval->value, node);
962
void CheckId(Lexer *lexer, Node *node, AttVal *attval)
967
if (attval == null || attval->value == null)
969
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
977
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
982
if (!IsNamechar(*p++))
984
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
990
if ((old = GetNodeByAnchor(attval->value)) && old != node)
992
ReportAttrError(lexer, node, attval, ANCHOR_NOT_UNIQUE);
1081
if ( backslash_count )
1083
if ( cfgBool(doc, TidyFixBackslash) )
1084
ReportAttrError( doc, node, attval, FIXED_BACKSLASH );
1086
ReportAttrError( doc, node, attval, BACKSLASH_IN_URI );
1090
if ( cfgBool(doc, TidyFixUri) )
1091
ReportAttrError( doc, node, attval, ESCAPED_ILLEGAL_URI);
1093
ReportAttrError( doc, node, attval, ILLEGAL_URI_REFERENCE);
1095
doc->badChars |= BC_INVALID_URI;
1099
void CheckScript( TidyDocImpl* ARG_UNUSED(doc), Node* ARG_UNUSED(node),
1100
AttVal* ARG_UNUSED(attval))
1104
Bool IsValidHTMLID(ctmbstr id)
1111
if (!IsLetter(*s++))
1115
if (!IsNamechar(*s++))
1122
Bool IsValidXMLID(ctmbstr id)
1132
s += GetUTF8(s, &c);
1134
if (!(IsXMLLetter(c) || c == '_' || c == ':'))
1139
c = (unsigned char)*s;
1142
s += GetUTF8(s, &c);
1146
if (!IsXMLNamechar(c))
1153
static Bool IsValidNMTOKEN(ctmbstr name)
1163
c = (unsigned char)*s;
1166
s += GetUTF8(s, &c);
1170
if (!IsXMLNamechar(c))
1177
void CheckName( TidyDocImpl* doc, Node *node, AttVal *attval)
1181
if (!AttrHasValue(attval))
1183
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1187
if ( IsAnchorElement(doc, node) )
1189
if (cfgBool(doc, TidyXmlOut) && !IsValidNMTOKEN(attval->value))
1190
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1192
if ((old = GetNodeByAnchor(doc, attval->value)) && old != node)
1194
ReportAttrError( doc, node, attval, ANCHOR_NOT_UNIQUE);
1197
AddAnchor( doc, attval->value, node );
1201
void CheckId( TidyDocImpl* doc, Node *node, AttVal *attval )
1203
Lexer* lexer = doc->lexer;
1206
if (!AttrHasValue(attval))
1208
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1212
if (!IsValidHTMLID(attval->value))
1214
if (lexer->isvoyager && IsValidXMLID(attval->value))
1215
ReportAttrError( doc, node, attval, XML_ID_SYNTAX);
1217
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1220
if ((old = GetNodeByAnchor(doc, attval->value)) && old != node)
1222
ReportAttrError( doc, node, attval, ANCHOR_NOT_UNIQUE);
995
anchor_list = AddAnchor(attval->value, node);
1225
AddAnchor( doc, attval->value, node );
998
void CheckBool(Lexer *lexer, Node *node, AttVal *attval)
1228
void CheckBool( TidyDocImpl* doc, Node *node, AttVal *attval)
1000
if (attval == null || attval->value == null)
1230
if (!AttrHasValue(attval))
1003
CheckLowerCaseAttrValue(lexer, node, attval);
1233
CheckLowerCaseAttrValue( doc, node, attval );
1006
void CheckAlign(Lexer *lexer, Node *node, AttVal *attval)
1236
void CheckAlign( TidyDocImpl* doc, Node *node, AttVal *attval)
1010
1238
/* IMG, OBJECT, APPLET and EMBED use align for vertical position */
1011
1239
if (node->tag && (node->tag->model & CM_IMG))
1013
CheckValign(lexer, node, attval);
1017
if (attval == null || attval->value == null)
1019
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1023
CheckLowerCaseAttrValue(lexer, node, attval);
1025
value = attval->value;
1027
if (! (wstrcasecmp(value, "left") == 0 ||
1028
wstrcasecmp(value, "center") == 0 ||
1029
wstrcasecmp(value, "right") == 0 ||
1030
wstrcasecmp(value, "justify") == 0))
1031
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1241
CheckValign( doc, node, attval );
1245
if (!AttrHasValue(attval))
1247
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1251
CheckLowerCaseAttrValue( doc, node, attval);
1253
/* currently CheckCaption(...) takes care of the remaining cases */
1254
if (nodeIsCAPTION(node))
1257
if (!(AttrValueIs(attval, "left") ||
1258
AttrValueIs(attval, "right") ||
1259
AttrValueIs(attval, "center") ||
1260
AttrValueIs(attval, "justify")))
1262
/* align="char" is allowed for elements with CM_TABLE|CM_ROW
1263
except CAPTION which is excluded above, */
1264
if( !(AttrValueIs(attval, "char")
1265
&& node->tag && (node->tag->model & CM_TABLE|CM_ROW)))
1266
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1034
void CheckValign(Lexer *lexer, Node *node, AttVal *attval)
1270
void CheckValign( TidyDocImpl* doc, Node *node, AttVal *attval)
1038
if (attval == null || attval->value == null)
1272
if (!AttrHasValue(attval))
1040
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1274
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1044
CheckLowerCaseAttrValue(lexer, node, attval);
1046
value = attval->value;
1048
if (wstrcasecmp(value, "top") == 0 ||
1049
wstrcasecmp(value, "middle") == 0 ||
1050
wstrcasecmp(value, "bottom") == 0 ||
1051
wstrcasecmp(value, "baseline") == 0)
1278
CheckLowerCaseAttrValue( doc, node, attval );
1280
if (AttrValueIs(attval, "top") ||
1281
AttrValueIs(attval, "middle") ||
1282
AttrValueIs(attval, "bottom") ||
1283
AttrValueIs(attval, "baseline"))
1053
1285
/* all is fine */
1055
else if (wstrcasecmp(value, "left") == 0 ||
1056
wstrcasecmp(value, "right") == 0)
1287
else if (AttrValueIs(attval, "left") ||
1288
AttrValueIs(attval, "right"))
1058
1290
if (!(node->tag && (node->tag->model & CM_IMG)))
1059
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1291
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1061
else if (wstrcasecmp(value, "texttop") == 0 ||
1062
wstrcasecmp(value, "absmiddle") == 0 ||
1063
wstrcasecmp(value, "absbottom") == 0 ||
1064
wstrcasecmp(value, "textbottom") == 0)
1293
else if (AttrValueIs(attval, "texttop") ||
1294
AttrValueIs(attval, "absmiddle") ||
1295
AttrValueIs(attval, "absbottom") ||
1296
AttrValueIs(attval, "textbottom"))
1066
ConstrainVersion(lexer, VERS_PROPRIETARY);
1067
ReportAttrError(lexer, node, attval, PROPRIETARY_ATTR_VALUE);
1298
ConstrainVersion( doc, VERS_PROPRIETARY );
1299
ReportAttrError( doc, node, attval, PROPRIETARY_ATTR_VALUE);
1070
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1302
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1073
void CheckLength(Lexer *lexer, Node *node, AttVal *attval)
1305
void CheckLength( TidyDocImpl* doc, Node *node, AttVal *attval)
1077
if (attval == null || attval->value == null)
1309
if (!AttrHasValue(attval))
1079
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1311
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1315
/* don't check for <col width=...> and <colgroup width=...> */
1316
if (attrIsWIDTH(attval) && (nodeIsCOL(node) || nodeIsCOLGROUP(node)))
1083
1319
p = attval->value;
1085
1321
if (!IsDigit(*p++))
1087
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1323
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1092
1329
if (!IsDigit(*p) && *p != '%')
1094
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1331
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1102
void CheckTarget(Lexer *lexer, Node *node, AttVal *attval)
1106
if (attval == null || attval->value == null)
1108
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1113
target names must begin with A-Za-z or be one of
1114
_blank, _self, _parent and _top
1117
value = attval->value;
1119
if (IsLetter(value[0]))
1122
if (! (wstrcasecmp(value, "_blank") == 0 ||
1123
wstrcasecmp(value, "_self") == 0 ||
1124
wstrcasecmp(value, "_parent") == 0 ||
1125
wstrcasecmp(value, "_top") == 0))
1126
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1129
void CheckFsubmit(Lexer *lexer, Node *node, AttVal *attval)
1133
if (attval == null || attval->value == null)
1135
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1139
value = attval->value;
1141
CheckLowerCaseAttrValue(lexer, node, attval);
1143
if (! (wstrcasecmp(value, "get") == 0 ||
1144
wstrcasecmp(value, "post") == 0))
1145
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1148
void CheckClear(Lexer *lexer, Node *node, AttVal *attval)
1152
if (attval == null || attval->value == null)
1154
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1155
if (attval->value == null)
1156
attval->value = wstrdup( "none" );
1160
CheckLowerCaseAttrValue(lexer, node, attval);
1339
void CheckTarget( TidyDocImpl* doc, Node *node, AttVal *attval)
1341
if (!AttrHasValue(attval))
1343
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1347
/* target names must begin with A-Za-z ... */
1348
if (IsLetter(attval->value[0]))
1351
/* or be one of _blank, _self, _parent and _top */
1352
if (!(AttrValueIs(attval, "_blank") ||
1353
AttrValueIs(attval, "_self") ||
1354
AttrValueIs(attval, "_parent") ||
1355
AttrValueIs(attval, "_top")))
1356
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1359
void CheckFsubmit( TidyDocImpl* doc, Node *node, AttVal *attval)
1361
if (!AttrHasValue(attval))
1363
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1367
CheckLowerCaseAttrValue( doc, node, attval);
1369
if (!(AttrValueIs(attval, "get") ||
1370
AttrValueIs(attval, "post")))
1371
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1374
void CheckClear( TidyDocImpl* doc, Node *node, AttVal *attval)
1376
if (!AttrHasValue(attval))
1378
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1379
if (attval->value == NULL)
1380
attval->value = tmbstrdup( "none" );
1384
CheckLowerCaseAttrValue( doc, node, attval );
1162
value = attval->value;
1164
if (! (wstrcasecmp(value, "none") == 0 ||
1165
wstrcasecmp(value, "left") == 0 ||
1166
wstrcasecmp(value, "right") == 0 ||
1167
wstrcasecmp(value, "all") == 0))
1168
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1171
void CheckShape(Lexer *lexer, Node *node, AttVal *attval)
1175
if (attval == null || attval->value == null)
1177
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1181
CheckLowerCaseAttrValue(lexer, node, attval);
1183
value = attval->value;
1185
if (! (wstrcasecmp(value, "rect") == 0 ||
1186
wstrcasecmp(value, "default") == 0 ||
1187
wstrcasecmp(value, "circle") == 0 ||
1188
wstrcasecmp(value, "poly") == 0))
1189
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1192
void CheckScope(Lexer *lexer, Node *node, AttVal *attval)
1196
if (attval == null || attval->value == null)
1198
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1202
CheckLowerCaseAttrValue(lexer, node, attval);
1204
value = attval->value;
1206
if (! (wstrcasecmp(value, "row") == 0 ||
1207
wstrcasecmp(value, "rowgroup") == 0 ||
1208
wstrcasecmp(value, "col") == 0 ||
1209
wstrcasecmp(value, "colgroup") == 0))
1210
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1213
void CheckNumber(Lexer *lexer, Node *node, AttVal *attval)
1217
if (attval == null || attval->value == null)
1219
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1386
if (!(AttrValueIs(attval, "none") ||
1387
AttrValueIs(attval, "left") ||
1388
AttrValueIs(attval, "right") ||
1389
AttrValueIs(attval, "all")))
1390
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1393
void CheckShape( TidyDocImpl* doc, Node *node, AttVal *attval)
1395
if (!AttrHasValue(attval))
1397
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1401
CheckLowerCaseAttrValue( doc, node, attval );
1403
if (!(AttrValueIs(attval, "rect") ||
1404
AttrValueIs(attval, "default") ||
1405
AttrValueIs(attval, "circle") ||
1406
AttrValueIs(attval, "poly")))
1407
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1410
void CheckScope( TidyDocImpl* doc, Node *node, AttVal *attval)
1412
if (!AttrHasValue(attval))
1414
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1418
CheckLowerCaseAttrValue( doc, node, attval);
1420
if (!(AttrValueIs(attval, "row") ||
1421
AttrValueIs(attval, "rowgroup") ||
1422
AttrValueIs(attval, "col") ||
1423
AttrValueIs(attval, "colgroup")))
1424
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1427
void CheckNumber( TidyDocImpl* doc, Node *node, AttVal *attval)
1431
if (!AttrHasValue(attval))
1433
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1437
/* don't check <frameset cols=... rows=...> */
1438
if ( nodeIsFRAMESET(node) &&
1439
(attrIsCOLS(attval) || attrIsROWS(attval)))
1223
1442
p = attval->value;
1225
1444
/* font size may be preceded by + or - */
1226
if (node->tag == tag_font && (*p == '+' || *p == '-'))
1445
if ( nodeIsFONT(node) && (*p == '+' || *p == '-') )
1231
1450
if (!IsDigit(*p))
1233
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1452
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1459
/* check hexadecimal color value */
1460
static Bool IsValidColorCode(ctmbstr color)
1464
if (tmbstrlen(color) != 6)
1467
/* check if valid hex digits and letters */
1468
for (i = 0; i < 6; i++)
1469
if (!IsDigit(color[i]) && !strchr("abcdef", ToLower(color[i])))
1240
1475
/* check color syntax and beautify value by option */
1241
void CheckColor(Lexer *lexer, Node *node, AttVal *attval)
1476
void CheckColor( TidyDocImpl* doc, Node *node, AttVal *attval)
1243
/* Bool ReplaceColor = yes; */ /* #477643 - replace hex color attribute values with names */
1244
Bool HexUppercase = yes;
1248
struct _colors *color;
1251
if (attval == null || attval->value == null)
1481
if (!AttrHasValue(attval))
1253
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1483
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1257
1487
given = attval->value;
1259
for (color = colors; color->name; ++color)
1261
if (given[0] == '#')
1263
if (wstrlen(given) != 7)
1265
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1269
else if (wstrcasecmp(given, color->hex) == 0)
1273
MemFree(attval->value);
1274
attval->value = wstrdup(color->name);
1280
else if (IsLetter(given[0]))
1282
if (wstrcasecmp(given, color->name) == 0)
1286
MemFree(attval->value);
1287
attval->value = wstrdup(color->name);
1295
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1301
if (!found && !invalid)
1303
if (given[0] == '#')
1305
/* check if valid hex digits and letters */
1306
for (i = 1; i < 7; ++i)
1308
if (!IsDigit(given[i]) &&
1309
!strchr("abcdef", ToLower(given[i])))
1311
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1317
/* convert hex letters to uppercase */
1318
if (!invalid && HexUppercase)
1320
for (i = 1; i < 7; ++i)
1322
given[i] = ToUpper(given[i]);
1328
/* we could search for more colors and mark the file as HTML
1329
Proprietary, but I don't thinks it's worth the effort,
1330
so values not in HTML 4.01 are invalid */
1332
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1489
/* 727851 - add hash to hash-less color values */
1490
if (given[0] != '#' && (valid = IsValidColorCode(given)))
1494
cp = s = (tmbstr) MemAlloc(2 + tmbstrlen (given));
1496
while ('\0' != (*cp++ = *given++))
1499
ReportAttrError(doc, node, attval, BAD_ATTRIBUTE_VALUE_REPLACED);
1501
MemFree(attval->value);
1502
given = attval->value = s;
1505
if (!valid && given[0] == '#')
1506
valid = IsValidColorCode(given + 1);
1508
if (valid && given[0] == '#' && cfgBool(doc, TidyReplaceColor))
1510
ctmbstr newName = GetColorName(given);
1514
MemFree(attval->value);
1515
given = attval->value = tmbstrdup(newName);
1519
/* if it is not a valid color code, it is a color name */
1521
valid = GetColorCode(given) != NULL;
1523
if (valid && given[0] == '#')
1524
attval->value = tmbstrtoupper(attval->value);
1526
attval->value = tmbstrtolower(attval->value);
1529
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1337
1532
/* check valuetype attribute for element param */
1338
void CheckVType(Lexer *lexer, Node *node, AttVal *attval)
1533
void CheckVType( TidyDocImpl* doc, Node *node, AttVal *attval)
1342
if (attval == null || attval->value == null)
1535
if (!AttrHasValue(attval))
1344
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1537
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1348
CheckLowerCaseAttrValue(lexer, node, attval);
1350
value = attval->value;
1352
if (! (wstrcasecmp(value, "data") == 0 ||
1353
wstrcasecmp(value, "object") == 0 ||
1354
wstrcasecmp(value, "ref") == 0))
1355
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1541
CheckLowerCaseAttrValue( doc, node, attval );
1543
if (!(AttrValueIs(attval, "data") ||
1544
AttrValueIs(attval, "object") ||
1545
AttrValueIs(attval, "ref")))
1546
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1358
1549
/* checks scrolling attribute */
1359
void CheckScroll(Lexer *lexer, Node *node, AttVal *attval)
1550
void CheckScroll( TidyDocImpl* doc, Node *node, AttVal *attval)
1363
if (attval == null || attval->value == null)
1552
if (!AttrHasValue(attval))
1365
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1554
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1369
CheckLowerCaseAttrValue(lexer, node, attval);
1371
value = attval->value;
1373
if (! (wstrcasecmp(value, "no") == 0 ||
1374
wstrcasecmp(value, "auto") == 0 ||
1375
wstrcasecmp(value, "yes") == 0))
1376
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1558
CheckLowerCaseAttrValue( doc, node, attval );
1560
if (!(AttrValueIs(attval, "no") ||
1561
AttrValueIs(attval, "auto") ||
1562
AttrValueIs(attval, "yes")))
1563
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1379
1566
/* checks dir attribute */
1380
void CheckTextDir(Lexer *lexer, Node *node, AttVal *attval)
1567
void CheckTextDir( TidyDocImpl* doc, Node *node, AttVal *attval)
1384
if (attval == null || attval->value == null)
1569
if (!AttrHasValue(attval))
1386
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1571
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE);
1390
CheckLowerCaseAttrValue(lexer, node, attval);
1392
value = attval->value;
1394
if (! (wstrcasecmp(value, "rtl") == 0 ||
1395
wstrcasecmp(value, "ltr") == 0))
1396
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1575
CheckLowerCaseAttrValue( doc, node, attval);
1577
if (!(AttrValueIs(attval, "rtl") ||
1578
AttrValueIs(attval, "ltr")))
1579
ReportAttrError( doc, node, attval, BAD_ATTRIBUTE_VALUE);
1399
1582
/* checks lang and xml:lang attributes */
1400
void CheckLang(Lexer *lexer, Node *node, AttVal *attval)
1583
void CheckLang( TidyDocImpl* doc, Node *node, AttVal *attval)
1402
if (attval == null || attval->value == null)
1585
/* empty xml:lang is allowed through XML 1.0 SE errata */
1586
if (!AttrHasValue(attval) && !attrIsXML_LANG(attval))
1404
ReportAttrError(lexer, node, attval, MISSING_ATTR_VALUE);
1588
if ( cfg(doc, TidyAccessibilityCheckLevel) == 0 )
1590
ReportAttrError( doc, node, attval, MISSING_ATTR_VALUE );
1408
if (wstrcasecmp(attval->attribute, "lang") == 0)
1409
ConstrainVersion(lexer, ~VERS_XHTML11);
1412
/* default method for checking an element's attributes */
1413
void CheckAttributes(Lexer *lexer, Node *node)
1417
for (attval = node->attributes; attval != null; attval = attval->next)
1418
CheckAttribute(lexer, node, attval);
1421
/* methods for checking attributes for specific elements */
1423
void CheckHR(Lexer *lexer, Node *node)
1425
AttVal *av = GetAttrByName(node, "src");
1427
CheckAttributes(lexer, node);
1430
ReportAttrError(lexer, node, av, PROPRIETARY_ATTR_VALUE);
1433
void CheckIMG(Lexer *lexer, Node *node)
1436
Attribute *attribute;
1439
Bool HasUseMap = no;
1441
Bool HasDataFld = no;
1443
for (attval = node->attributes; attval != null; attval = attval->next)
1445
attribute = CheckAttribute(lexer, node, attval);
1447
if (attribute == attr_alt)
1449
else if (attribute == attr_src)
1451
else if (attribute == attr_usemap)
1453
else if (attribute == attr_ismap)
1455
else if (attribute == attr_datafld)
1457
else if (attribute == attr_width || attribute == attr_height)
1458
ConstrainVersion(lexer, ~VERS_HTML20);
1463
lexer->badAccess |= MISSING_IMAGE_ALT;
1464
ReportMissingAttr(lexer, node, "alt");
1467
AddAttribute(node, "alt", alt_text);
1470
if (!HasSrc && !HasDataFld)
1471
ReportMissingAttr(lexer, node, "src");
1473
if (HasIsMap && !HasUseMap)
1474
ReportMissingAttr(lexer, node, "ismap");
1477
void CheckAnchor(Lexer *lexer, Node *node)
1479
CheckAttributes(lexer, node);
1484
void CheckMap(Lexer *lexer, Node *node)
1486
CheckAttributes(lexer, node);
1491
void CheckTableCell(Lexer *lexer, Node *node)
1493
CheckAttributes(lexer, node);
1496
HTML4 strict doesn't allow mixed content for
1497
elements with %block; as their content model
1499
if (GetAttrByName(node, "width") || GetAttrByName(node, "height"))
1500
ConstrainVersion(lexer, ~VERS_HTML40_STRICT);
1503
void CheckCaption(Lexer *lexer, Node *node)
1508
CheckAttributes(lexer, node);
1510
for (attval = node->attributes; attval != null; attval = attval->next)
1512
if (wstrcasecmp(attval->attribute, "align") == 0)
1514
value = attval->value;
1521
if (wstrcasecmp(value, "left") == 0 || wstrcasecmp(value, "right") == 0)
1522
ConstrainVersion(lexer, VERS_HTML40_LOOSE);
1523
else if (wstrcasecmp(value, "top") == 0 || wstrcasecmp(value, "bottom") == 0)
1524
ConstrainVersion(lexer, ~(VERS_HTML20|VERS_HTML32));
1526
ReportAttrError(lexer, node, attval, BAD_ATTRIBUTE_VALUE);
1530
void CheckHTML(Lexer *lexer, Node *node)
1533
Attribute *attribute;
1535
for (attval = node->attributes; attval != null; attval = attval->next)
1537
attribute = CheckAttribute(lexer, node, attval);
1538
if (attribute == attr_xmlns && wstrcmp(attval->value, XHTML_NAMESPACE)==0 )
1540
lexer->isvoyager = yes;
1541
if ( ! HtmlOut ) /* Unless user has specified plain HTML output, */
1542
xHTML = yes; /* output format will be XHTML. */
1547
void CheckAREA(Lexer *lexer, Node *node)
1550
Attribute *attribute;
1554
for (attval = node->attributes; attval != null; attval = attval->next)
1556
attribute = CheckAttribute(lexer, node, attval);
1558
if (attribute == attr_alt)
1560
else if (attribute == attr_href)
1566
lexer->badAccess |= MISSING_LINK_ALT;
1567
ReportMissingAttr(lexer, node, "alt");
1570
ReportMissingAttr(lexer, node, "href");
1573
void CheckTABLE(Lexer *lexer, Node *node)
1576
Attribute *attribute;
1577
Bool HasSummary = no;
1579
for (attval = node->attributes; attval != null; attval = attval->next)
1581
attribute = CheckAttribute(lexer, node, attval);
1583
if (attribute == attr_summary)
1587
/* suppress warning for missing summary for HTML 2.0 and HTML 3.2 */
1588
if (!HasSummary && lexer->doctype != VERS_HTML20 && lexer->doctype != VERS_HTML32)
1590
lexer->badAccess |= MISSING_SUMMARY;
1591
ReportMissingAttr(lexer, node, "summary");
1594
/* convert <table border> to <table border="1"> */
1595
if (XmlOut && (attval = GetAttrByName(node, "border")))
1597
if (attval->value == null)
1598
attval->value = wstrdup("1");
1601
/* <table height="..."> is proprietary */
1602
if (attval = GetAttrByName(node, "height"))
1604
ReportAttrError(lexer, node, attval, PROPRIETARY_ATTRIBUTE);
1605
ConstrainVersion(lexer, VERS_PROPRIETARY);
1609
/* add missing type attribute when appropriate */
1610
void CheckSCRIPT(Lexer *lexer, Node *node)
1612
AttVal *lang, *type;
1615
CheckAttributes(lexer, node);
1617
lang = GetAttrByName(node, "language");
1618
type = GetAttrByName(node, "type");
1622
ReportMissingAttr(lexer, node, "type");
1624
/* check for javascript */
1628
wstrncpy(buf, lang->value, 10);
1631
if ( (wstrncasecmp(buf, "javascript", 10) == 0) ||
1632
(wstrncasecmp(buf, "jscript", 7) == 0) )
1634
AddAttribute(node, "type", "text/javascript");
1636
else if ( wstrcasecmp(buf, "vbscript") == 0 )
1638
/* per Randy Waki 8/6/01 */
1639
AddAttribute(node, "type", "text/vbscript");
1643
AddAttribute(node, "type", "text/javascript");
1648
/* add missing type attribute when appropriate */
1649
void CheckSTYLE(Lexer *lexer, Node *node)
1651
AttVal *type = GetAttrByName(node, "type");
1653
CheckAttributes(lexer, node);
1657
ReportMissingAttr(lexer, node, "type");
1659
AddAttribute(node, "type", "text/css");
1663
/* add missing type attribute when appropriate */
1664
void CheckLINK(Lexer *lexer, Node *node)
1666
AttVal *rel = GetAttrByName(node, "rel");
1668
CheckAttributes(lexer, node);
1670
if (rel && rel->value &&
1671
wstrcmp(rel->value, "stylesheet") == 0)
1673
AttVal *type = GetAttrByName(node, "type");
1677
ReportMissingAttr(lexer, node, "type");
1679
AddAttribute(node, "type", "text/css");
1684
/* reports missing action attribute */
1685
void CheckFORM(Lexer *lexer, Node *node)
1687
AttVal *action = GetAttrByName(node, "action");
1689
CheckAttributes(lexer, node);
1692
ReportMissingAttr(lexer, node, "action");
1695
/* reports missing content attribute */
1696
void CheckMETA(Lexer *lexer, Node *node)
1698
AttVal *content = GetAttrByName(node, "content");
1700
CheckAttributes(lexer, node);
1703
ReportMissingAttr(lexer, node, "content");
1705
/* name or http-equiv attribute must also be set */