Clover coverage report - Maven Clover report
Coverage timestamp: Tue Aug 1 2006 15:09:51 CEST
file stats: LOC: 1,104   Methods: 20
NCLOC: 599   Classes: 20
 
 Source file Conditionals Statements Methods TOTAL
AttrCheckImpl.java 73.3% 76% 90% 75.7%
coverage coverage
 1    /*
 2    * Java HTML Tidy - JTidy
 3    * HTML parser and pretty printer
 4    *
 5    * Copyright (c) 1998-2000 World Wide Web Consortium (Massachusetts
 6    * Institute of Technology, Institut National de Recherche en
 7    * Informatique et en Automatique, Keio University). All Rights
 8    * Reserved.
 9    *
 10    * Contributing Author(s):
 11    *
 12    * Dave Raggett <dsr@w3.org>
 13    * Andy Quick <ac.quick@sympatico.ca> (translation to Java)
 14    * Gary L Peskin <garyp@firstech.com> (Java development)
 15    * Sami Lempinen <sami@lempinen.net> (release management)
 16    * Fabrizio Giustina <fgiust at users.sourceforge.net>
 17    *
 18    * The contributing author(s) would like to thank all those who
 19    * helped with testing, bug fixes, and patience. This wouldn't
 20    * have been possible without all of you.
 21    *
 22    * COPYRIGHT NOTICE:
 23    *
 24    * This software and documentation is provided "as is," and
 25    * the copyright holders and contributing author(s) make no
 26    * representations or warranties, express or implied, including
 27    * but not limited to, warranties of merchantability or fitness
 28    * for any particular purpose or that the use of the software or
 29    * documentation will not infringe any third party patents,
 30    * copyrights, trademarks or other rights.
 31    *
 32    * The copyright holders and contributing author(s) will not be
 33    * liable for any direct, indirect, special or consequential damages
 34    * arising out of any use of the software or documentation, even if
 35    * advised of the possibility of such damage.
 36    *
 37    * Permission is hereby granted to use, copy, modify, and distribute
 38    * this source code, or portions hereof, documentation and executables,
 39    * for any purpose, without fee, subject to the following restrictions:
 40    *
 41    * 1. The origin of this source code must not be misrepresented.
 42    * 2. Altered versions must be plainly marked as such and must
 43    * not be misrepresented as being the original source.
 44    * 3. This Copyright notice may not be removed or altered from any
 45    * source or altered source distribution.
 46    *
 47    * The copyright holders and contributing author(s) specifically
 48    * permit, without fee, and encourage the use of this source code
 49    * as a component for supporting the Hypertext Markup Language in
 50    * commercial products. If you use this source code in a product,
 51    * acknowledgment is not required but would be appreciated.
 52    *
 53    */
 54    package org.w3c.tidy;
 55   
 56    import java.util.HashMap;
 57    import java.util.Iterator;
 58    import java.util.Map;
 59   
 60   
 61    /**
 62    * Check attribute values implementations.
 63    * @author Dave Raggett <a href="mailto:dsr@w3.org">dsr@w3.org </a>
 64    * @author Andy Quick <a href="mailto:ac.quick@sympatico.ca">ac.quick@sympatico.ca </a> (translation to Java)
 65    * @author Fabrizio Giustina
 66    * @version $Revision: 779 $ ($Author: fgiust $)
 67    */
 68    public final class AttrCheckImpl
 69    {
 70   
 71    /**
 72    * checker for URLs.
 73    */
 74    public static final AttrCheck URL = new CheckUrl();
 75   
 76    /**
 77    * checker for scripts.
 78    */
 79    public static final AttrCheck SCRIPT = new CheckScript();
 80   
 81    /**
 82    * checker for "name" attribute.
 83    */
 84    public static final AttrCheck NAME = new CheckName();
 85   
 86    /**
 87    * checker for ids.
 88    */
 89    public static final AttrCheck ID = new CheckId();
 90   
 91    /**
 92    * checker for "align" attribute.
 93    */
 94    public static final AttrCheck ALIGN = new CheckAlign();
 95   
 96    /**
 97    * checker for "valign" attribute.
 98    */
 99    public static final AttrCheck VALIGN = new CheckValign();
 100   
 101    /**
 102    * checker for boolean attributes.
 103    */
 104    public static final AttrCheck BOOL = new CheckBool();
 105   
 106    /**
 107    * checker for "lenght" attribute.
 108    */
 109    public static final AttrCheck LENGTH = new CheckLength();
 110   
 111    /**
 112    * checker for "target" attribute.
 113    */
 114    public static final AttrCheck TARGET = new CheckTarget();
 115   
 116    /**
 117    * checker for "submit" attribute.
 118    */
 119    public static final AttrCheck FSUBMIT = new CheckFsubmit();
 120   
 121    /**
 122    * checker for "clear" attribute.
 123    */
 124    public static final AttrCheck CLEAR = new CheckClear();
 125   
 126    /**
 127    * checker for "shape" attribute.
 128    */
 129    public static final AttrCheck SHAPE = new CheckShape();
 130   
 131    /**
 132    * checker for "number" attribute.
 133    */
 134    public static final AttrCheck NUMBER = new CheckNumber();
 135   
 136    /**
 137    * checker for "scope" attribute.
 138    */
 139    public static final AttrCheck SCOPE = new CheckScope();
 140   
 141    /**
 142    * checker for "color" attribute.
 143    */
 144    public static final AttrCheck COLOR = new CheckColor();
 145   
 146    /**
 147    * checker for "vtype" attribute.
 148    */
 149    public static final AttrCheck VTYPE = new CheckVType();
 150   
 151    /**
 152    * checker for "scroll" attribute.
 153    */
 154    public static final AttrCheck SCROLL = new CheckScroll();
 155   
 156    /**
 157    * checker for "dir" attribute.
 158    */
 159    public static final AttrCheck TEXTDIR = new CheckTextDir();
 160   
 161    /**
 162    * checker for "lang" and "xml:lang" attributes.
 163    */
 164    public static final AttrCheck LANG = new CheckLang();
 165   
 166    /**
 167    * checker for text attributes. Actually null (no validation).
 168    */
 169    public static final AttrCheck TEXT = null;
 170   
 171    /**
 172    * checker for "charset" attribute. Actually null (no validation).
 173    */
 174    public static final AttrCheck CHARSET = null;
 175   
 176    /**
 177    * checker for "type" attribute. Actually null (no validation).
 178    */
 179    public static final AttrCheck TYPE = null;
 180   
 181    /**
 182    * checker for attributes that can contain a single character. Actually null (no validation).
 183    */
 184    public static final AttrCheck CHARACTER = null;
 185   
 186    /**
 187    * checker for attributes which contain a list of urls. Actually null (no validation).
 188    */
 189    public static final AttrCheck URLS = null;
 190   
 191    /**
 192    * checker for "cols" attribute. Actually null (no validation).
 193    */
 194    public static final AttrCheck COLS = null;
 195   
 196    /**
 197    * checker for "coords" attribute. Actually null (no validation).
 198    */
 199    public static final AttrCheck COORDS = null;
 200   
 201    /**
 202    * checker for attributes containing dates. Actually null (no validation).
 203    */
 204    public static final AttrCheck DATE = null;
 205   
 206    /**
 207    * checker for attributes referencng an id. Actually null (no validation).
 208    */
 209    public static final AttrCheck IDREF = null;
 210   
 211    /**
 212    * checker for table "frame" attribute. Actually null (no validation).
 213    */
 214    public static final AttrCheck TFRAME = null;
 215   
 216    /**
 217    * checker for "frameborder" attribute. Actually null (no validation).
 218    */
 219    public static final AttrCheck FBORDER = null;
 220   
 221    /**
 222    * checker for "media" attribute. Actually null (no validation).
 223    */
 224    public static final AttrCheck MEDIA = null;
 225   
 226    /**
 227    * checker for "rel" and "rev" attributes. Actually null (no validation).
 228    */
 229    public static final AttrCheck LINKTYPES = null;
 230   
 231    /**
 232    * checker for table "rules" attribute. Actually null (no validation).
 233    */
 234    public static final AttrCheck TRULES = null;
 235   
 236    /**
 237    * utility class, don't instantiate.
 238    */
 239  0 private AttrCheckImpl()
 240    {
 241    // empty private constructor
 242    }
 243   
 244    /**
 245    * AttrCheck implementation for checking URLs.
 246    */
 247    public static class CheckUrl implements AttrCheck
 248    {
 249   
 250    /**
 251    * @see AttrCheck#check(Lexer, Node, AttVal)
 252    */
 253  1268 public void check(Lexer lexer, Node node, AttVal attval)
 254    {
 255  1268 char c;
 256  1268 StringBuffer dest;
 257  1268 boolean escapeFound = false;
 258  1268 boolean backslashFound = false;
 259  1268 int i = 0;
 260   
 261  1268 if (attval.value == null)
 262    {
 263  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 264  0 return;
 265    }
 266   
 267  1268 String p = attval.value;
 268   
 269  1268 for (i = 0; i < p.length(); ++i)
 270    {
 271  29132 c = p.charAt(i);
 272    // find \
 273  29132 if (c == '\\')
 274    {
 275  6 backslashFound = true;
 276    }
 277    // find non-ascii chars
 278  29126 else if ((c > 0x7e) || (c <= 0x20) || (c == '<') || (c == '>'))
 279    {
 280  480 escapeFound = true;
 281    }
 282    }
 283   
 284    // backslashes found, fix them
 285  1268 if (lexer.configuration.fixBackslash && backslashFound)
 286    {
 287  5 attval.value = attval.value.replace('\\', '/');
 288  5 p = attval.value;
 289    }
 290   
 291    // non-ascii chars found, fix them
 292  1268 if (lexer.configuration.fixUri && escapeFound)
 293    {
 294  135 dest = new StringBuffer();
 295   
 296  135 for (i = 0; i < p.length(); ++i)
 297    {
 298  3495 c = p.charAt(i);
 299  3495 if ((c > 0x7e) || (c <= 0x20) || (c == '<') || (c == '>'))
 300    {
 301  480 dest.append('%');
 302  480 dest.append(Integer.toHexString(c).toUpperCase());
 303    }
 304    else
 305    {
 306  3015 dest.append(c);
 307    }
 308    }
 309   
 310  135 attval.value = dest.toString();
 311    }
 312  1268 if (backslashFound)
 313    {
 314  5 if (lexer.configuration.fixBackslash)
 315    {
 316  5 lexer.report.attrError(lexer, node, attval, Report.FIXED_BACKSLASH);
 317    }
 318    else
 319    {
 320  0 lexer.report.attrError(lexer, node, attval, Report.BACKSLASH_IN_URI);
 321    }
 322    }
 323  1268 if (escapeFound)
 324    {
 325  135 if (lexer.configuration.fixUri)
 326    {
 327  135 lexer.report.attrError(lexer, node, attval, Report.ESCAPED_ILLEGAL_URI);
 328    }
 329    else
 330    {
 331  0 lexer.report.attrError(lexer, node, attval, Report.ILLEGAL_URI_REFERENCE);
 332    }
 333   
 334  135 lexer.badChars |= Report.INVALID_URI;
 335    }
 336   
 337    }
 338    }
 339   
 340    /**
 341    * AttrCheck implementation for checking scripts.
 342    */
 343    public static class CheckScript implements AttrCheck
 344    {
 345   
 346    /**
 347    * @see AttrCheck#check(Lexer, Node, AttVal)
 348    */
 349  49 public void check(Lexer lexer, Node node, AttVal attval)
 350    {
 351    // not implemented
 352    }
 353   
 354    }
 355   
 356    /**
 357    * AttrCheck implementation for checking the "align" attribute.
 358    */
 359    public static class CheckAlign implements AttrCheck
 360    {
 361   
 362    /**
 363    * valid values for this attribute.
 364    */
 365    private static final String[] VALID_VALUES = new String[]{"left", "center", "right", "justify"};
 366   
 367    /**
 368    * @see AttrCheck#check(Lexer, Node, AttVal)
 369    */
 370  206 public void check(Lexer lexer, Node node, AttVal attval)
 371    {
 372    // IMG, OBJECT, APPLET and EMBED use align for vertical position
 373  206 if (node.tag != null && ((node.tag.model & Dict.CM_IMG) != 0))
 374    {
 375  68 VALIGN.check(lexer, node, attval);
 376  68 return;
 377    }
 378   
 379  138 if (attval.value == null)
 380    {
 381  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 382  0 return;
 383    }
 384   
 385  138 attval.checkLowerCaseAttrValue(lexer, node);
 386   
 387  138 if (!TidyUtils.isInValuesIgnoreCase(VALID_VALUES, attval.value))
 388    {
 389  2 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 390    }
 391    }
 392   
 393    }
 394   
 395    /**
 396    * AttrCheck implementation for checking the "valign" attribute.
 397    */
 398    public static class CheckValign implements AttrCheck
 399    {
 400   
 401    /**
 402    * valid values for this attribute.
 403    */
 404    private static final String[] VALID_VALUES = new String[]{"top", "middle", "bottom", "baseline"};
 405   
 406    /**
 407    * valid values for this attribute (only for img tag).
 408    */
 409    private static final String[] VALID_VALUES_IMG = new String[]{"left", "right"};
 410   
 411    /**
 412    * proprietary values for this attribute.
 413    */
 414    private static final String[] VALID_VALUES_PROPRIETARY = new String[]{
 415    "texttop",
 416    "absmiddle",
 417    "absbottom",
 418    "textbottom"};
 419   
 420    /**
 421    * @see AttrCheck#check(Lexer, Node, AttVal)
 422    */
 423  108 public void check(Lexer lexer, Node node, AttVal attval)
 424    {
 425  108 String value;
 426   
 427  108 if (attval.value == null)
 428    {
 429  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 430  0 return;
 431    }
 432   
 433  108 attval.checkLowerCaseAttrValue(lexer, node);
 434   
 435  108 value = attval.value;
 436   
 437  108 if (TidyUtils.isInValuesIgnoreCase(VALID_VALUES, value))
 438    {
 439    // all is fine
 440  42 return;
 441    }
 442   
 443  66 if (TidyUtils.isInValuesIgnoreCase(VALID_VALUES_IMG, value))
 444    {
 445  1 if (!(node.tag != null && ((node.tag.model & Dict.CM_IMG) != 0)))
 446    {
 447  0 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 448    }
 449    }
 450  65 else if (TidyUtils.isInValuesIgnoreCase(VALID_VALUES_PROPRIETARY, value))
 451    {
 452  52 lexer.constrainVersion(Dict.VERS_PROPRIETARY);
 453  52 lexer.report.attrError(lexer, node, attval, Report.PROPRIETARY_ATTR_VALUE);
 454    }
 455    else
 456    {
 457  13 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 458    }
 459    }
 460   
 461    }
 462   
 463    /**
 464    * AttrCheck implementation for checking boolean attributes.
 465    */
 466    public static class CheckBool implements AttrCheck
 467    {
 468   
 469    /**
 470    * @see AttrCheck#check(Lexer, Node, AttVal)
 471    */
 472  234 public void check(Lexer lexer, Node node, AttVal attval)
 473    {
 474  234 if (attval.value == null)
 475    {
 476  56 return;
 477    }
 478   
 479  178 attval.checkLowerCaseAttrValue(lexer, node);
 480    }
 481   
 482    }
 483   
 484    /**
 485    * AttrCheck implementation for checking the "length" attribute.
 486    */
 487    public static class CheckLength implements AttrCheck
 488    {
 489   
 490    /**
 491    * @see AttrCheck#check(Lexer, Node, AttVal)
 492    */
 493  520 public void check(Lexer lexer, Node node, AttVal attval)
 494    {
 495   
 496  520 if (attval.value == null)
 497    {
 498  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 499  0 return;
 500    }
 501   
 502    // don't check for <col width=...> and <colgroup width=...>
 503  520 if ("width".equalsIgnoreCase(attval.attribute)
 504    && (node.tag == lexer.configuration.tt.tagCol || node.tag == lexer.configuration.tt.tagColgroup))
 505    {
 506  1 return;
 507    }
 508   
 509  519 String p = attval.value;
 510   
 511  519 if (p.length() == 0 || (!Character.isDigit(p.charAt(0)) && !('%' == p.charAt(0))))
 512    {
 513  2 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 514    }
 515    else
 516    {
 517   
 518  517 TagTable tt = lexer.configuration.tt;
 519   
 520  517 for (int j = 1; j < p.length(); j++)
 521    {
 522    // elements th and td must not use percentages
 523  613 if ((!Character.isDigit(p.charAt(j)) && (node.tag == tt.tagTd || node.tag == tt.tagTh))
 524    || (!Character.isDigit(p.charAt(j)) && p.charAt(j) != '%'))
 525    {
 526  5 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 527  5 break;
 528    }
 529    }
 530    }
 531    }
 532    }
 533   
 534    /**
 535    * AttrCheck implementation for checking the "target" attribute.
 536    */
 537    public static class CheckTarget implements AttrCheck
 538    {
 539   
 540    /**
 541    * valid values for this attribute.
 542    */
 543    private static final String[] VALID_VALUES = new String[]{"_blank", "_self", "_parent", "_top"};
 544   
 545    /**
 546    * @see AttrCheck#check(Lexer, Node, AttVal)
 547    */
 548  497 public void check(Lexer lexer, Node node, AttVal attval)
 549    {
 550   
 551    // No target attribute in strict HTML versions
 552  497 lexer.constrainVersion(~Dict.VERS_HTML40_STRICT);
 553   
 554  497 if (attval.value == null || attval.value.length() == 0)
 555    {
 556  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 557  0 return;
 558    }
 559   
 560  497 String value = attval.value;
 561   
 562    // target names must begin with A-Za-z ...
 563  497 if (Character.isLetter(value.charAt(0)))
 564    {
 565  430 return;
 566    }
 567   
 568    // or be one of _blank, _self, _parent and _top
 569  67 if (!TidyUtils.isInValuesIgnoreCase(VALID_VALUES, value))
 570    {
 571  0 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 572    }
 573   
 574    }
 575    }
 576   
 577    /**
 578    * AttrCheck implementation for checking the "submit" attribute.
 579    */
 580    public static class CheckFsubmit implements AttrCheck
 581    {
 582   
 583    /**
 584    * valid values for this attribute.
 585    */
 586    private static final String[] VALID_VALUES = new String[]{"get", "post"};
 587   
 588    /**
 589    * @see AttrCheck#check(Lexer, Node, AttVal)
 590    */
 591  6 public void check(Lexer lexer, Node node, AttVal attval)
 592    {
 593  6 if (attval.value == null)
 594    {
 595  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 596  0 return;
 597    }
 598   
 599  6 attval.checkLowerCaseAttrValue(lexer, node);
 600   
 601  6 if (!TidyUtils.isInValuesIgnoreCase(VALID_VALUES, attval.value))
 602    {
 603  0 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 604    }
 605    }
 606    }
 607   
 608    /**
 609    * AttrCheck implementation for checking the "clear" attribute.
 610    */
 611    public static class CheckClear implements AttrCheck
 612    {
 613   
 614    /**
 615    * valid values for this attribute.
 616    */
 617    private static final String[] VALID_VALUES = new String[]{"none", "left", "right", "all"};
 618   
 619    /**
 620    * @see AttrCheck#check(Lexer, Node, AttVal)
 621    */
 622  3 public void check(Lexer lexer, Node node, AttVal attval)
 623    {
 624  3 if (attval.value == null)
 625    {
 626  1 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 627  1 attval.value = VALID_VALUES[0];
 628  1 return;
 629    }
 630   
 631  2 attval.checkLowerCaseAttrValue(lexer, node);
 632   
 633  2 if (!TidyUtils.isInValuesIgnoreCase(VALID_VALUES, attval.value))
 634    {
 635  1 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 636    }
 637   
 638    }
 639    }
 640   
 641    /**
 642    * AttrCheck implementation for checking the "shape" attribute.
 643    */
 644    public static class CheckShape implements AttrCheck
 645    {
 646   
 647    /**
 648    * valid values for this attribute.
 649    */
 650    private static final String[] VALID_VALUES = new String[]{"rect", "default", "circle", "poly"};
 651   
 652    /**
 653    * @see AttrCheck#check(Lexer, Node, AttVal)
 654    */
 655  1 public void check(Lexer lexer, Node node, AttVal attval)
 656    {
 657  1 if (attval.value == null)
 658    {
 659  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 660  0 return;
 661    }
 662   
 663  1 attval.checkLowerCaseAttrValue(lexer, node);
 664   
 665  1 if (!TidyUtils.isInValuesIgnoreCase(VALID_VALUES, attval.value))
 666    {
 667  0 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 668    }
 669   
 670    }
 671    }
 672   
 673    /**
 674    * AttrCheck implementation for checking Scope.
 675    */
 676    public static class CheckScope implements AttrCheck
 677    {
 678   
 679    /**
 680    * valid values for this attribute.
 681    */
 682    private static final String[] VALID_VALUES = new String[]{"row", "rowgroup", "col", "colgroup"};
 683   
 684    /**
 685    * @see AttrCheck#check(Lexer, Node, AttVal)
 686    */
 687  144 public void check(Lexer lexer, Node node, AttVal attval)
 688    {
 689   
 690  144 if (attval.value == null)
 691    {
 692  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 693  0 return;
 694    }
 695   
 696  144 attval.checkLowerCaseAttrValue(lexer, node);
 697   
 698  144 if (!TidyUtils.isInValuesIgnoreCase(VALID_VALUES, attval.value))
 699    {
 700  0 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 701    }
 702    }
 703    }
 704   
 705    /**
 706    * AttrCheck implementation for checking numbers.
 707    */
 708    public static class CheckNumber implements AttrCheck
 709    {
 710   
 711    /**
 712    * @see AttrCheck#check(Lexer, Node, AttVal)
 713    */
 714  138 public void check(Lexer lexer, Node node, AttVal attval)
 715    {
 716   
 717  138 if (attval.value == null)
 718    {
 719  2 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 720  2 return;
 721    }
 722   
 723    // don't check <frameset cols=... rows=...>
 724  136 if (("cols".equalsIgnoreCase(attval.attribute) || "rows".equalsIgnoreCase(attval.attribute))
 725    && node.tag == lexer.configuration.tt.tagFrameset)
 726    {
 727  1 return;
 728    }
 729   
 730  135 String value = attval.value;
 731   
 732  135 int j = 0;
 733   
 734    // font size may be preceded by + or -
 735  135 if (node.tag == lexer.configuration.tt.tagFont && (value.startsWith("+") || value.startsWith("-")))
 736    {
 737  16 ++j;
 738    }
 739   
 740  135 for (; j < value.length(); j++)
 741    {
 742  139 char p = value.charAt(j);
 743  139 if (!Character.isDigit(p))
 744    {
 745  0 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 746  0 break;
 747    }
 748    }
 749    }
 750    }
 751   
 752    /**
 753    * AttrCheck implementation for checking ids.
 754    */
 755    public static class CheckId implements AttrCheck
 756    {
 757   
 758    /**
 759    * @see AttrCheck#check(Lexer, Node, AttVal)
 760    */
 761  19 public void check(Lexer lexer, Node node, AttVal attval)
 762    {
 763  19 Node old;
 764   
 765  19 if (attval.value == null || attval.value.length() == 0)
 766    {
 767  1 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 768  1 return;
 769    }
 770   
 771  18 String p = attval.value;
 772  18 char s = p.charAt(0);
 773   
 774  18 if (p.length() == 0 || !Character.isLetter(p.charAt(0)))
 775    {
 776  4 if (lexer.isvoyager && (TidyUtils.isXMLLetter(s) || s == '_' || s == ':'))
 777    {
 778  2 lexer.report.attrError(lexer, node, attval, Report.XML_ID_SYNTAX);
 779    }
 780    else
 781    {
 782  2 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 783    }
 784    }
 785    else
 786    {
 787   
 788  14 for (int j = 1; j < p.length(); j++)
 789    {
 790  93 s = p.charAt(j);
 791   
 792  93 if (!TidyUtils.isNamechar(s))
 793    {
 794  0 if (lexer.isvoyager && TidyUtils.isXMLNamechar(s))
 795    {
 796  0 lexer.report.attrError(lexer, node, attval, Report.XML_ID_SYNTAX);
 797    }
 798    else
 799    {
 800  0 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 801    }
 802  0 break;
 803    }
 804    }
 805    }
 806   
 807  ? if (((old = lexer.configuration.tt.getNodeByAnchor(attval.value)) != null) && old != node)
 808    {
 809  0 lexer.report.attrError(lexer, node, attval, Report.ANCHOR_NOT_UNIQUE);
 810    }
 811    else
 812    {
 813  18 lexer.configuration.tt.anchorList = lexer.configuration.tt.addAnchor(attval.value, node);
 814    }
 815    }
 816   
 817    }
 818   
 819    /**
 820    * AttrCheck implementation for checking the "name" attribute.
 821    */
 822    public static class CheckName implements AttrCheck
 823    {
 824   
 825    /**
 826    * @see AttrCheck#check(Lexer, Node, AttVal)
 827    */
 828  229 public void check(Lexer lexer, Node node, AttVal attval)
 829    {
 830  229 Node old;
 831   
 832  229 if (attval.value == null)
 833    {
 834  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 835  0 return;
 836    }
 837  229 else if (lexer.configuration.tt.isAnchorElement(node))
 838    {
 839  123 lexer.constrainVersion(~Dict.VERS_XHTML11);
 840   
 841  ? if (((old = lexer.configuration.tt.getNodeByAnchor(attval.value)) != null) && old != node)
 842    {
 843  19 lexer.report.attrError(lexer, node, attval, Report.ANCHOR_NOT_UNIQUE);
 844    }
 845    else
 846    {
 847  104 lexer.configuration.tt.anchorList = lexer.configuration.tt.addAnchor(attval.value, node);
 848    }
 849    }
 850    }
 851   
 852    }
 853   
 854    /**
 855    * AttrCheck implementation for checking colors.
 856    */
 857    public static class CheckColor implements AttrCheck
 858    {
 859   
 860    /**
 861    * valid html colors.
 862    */
 863    private static final Map COLORS = new HashMap();
 864   
 865    static
 866    {
 867  1 COLORS.put("black", "#000000");
 868  1 COLORS.put("green", "#008000");
 869  1 COLORS.put("silver", "#C0C0C0");
 870  1 COLORS.put("lime", "#00FF00");
 871  1 COLORS.put("gray", "#808080");
 872  1 COLORS.put("olive", "#808000");
 873  1 COLORS.put("white", "#FFFFFF");
 874  1 COLORS.put("yellow", "#FFFF00");
 875  1 COLORS.put("maroon", "#800000");
 876  1 COLORS.put("navy", "#000080");
 877  1 COLORS.put("red", "#FF0000");
 878  1 COLORS.put("blue", "#0000FF");
 879  1 COLORS.put("purple", "#800080");
 880  1 COLORS.put("teal", "#008080");
 881  1 COLORS.put("fuchsia", "#FF00FF");
 882  1 COLORS.put("aqua", "#00FFFF");
 883    }
 884   
 885    /**
 886    * @see AttrCheck#check(Lexer, Node, AttVal)
 887    */
 888  667 public void check(Lexer lexer, Node node, AttVal attval)
 889    {
 890  667 boolean hexUppercase = true;
 891  667 boolean invalid = false;
 892  667 boolean found = false;
 893   
 894  667 if (attval.value == null || attval.value.length() == 0)
 895    {
 896  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 897  0 return;
 898    }
 899   
 900  667 String given = attval.value;
 901   
 902  667 Iterator colorIter = COLORS.entrySet().iterator();
 903   
 904  667 while (colorIter.hasNext())
 905    {
 906  8591 Map.Entry color = (Map.Entry) colorIter.next();
 907   
 908  8591 if (given.charAt(0) == '#')
 909    {
 910  7872 if (given.length() != 7)
 911    {
 912  3 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 913  3 invalid = true;
 914  3 break;
 915    }
 916  7869 else if (given.equalsIgnoreCase((String) color.getValue()))
 917    {
 918  35 if (lexer.configuration.replaceColor)
 919    {
 920  0 attval.value = (String) color.getKey();
 921    }
 922  35 found = true;
 923  35 break;
 924    }
 925    }
 926  719 else if (TidyUtils.isLetter(given.charAt(0)))
 927    {
 928  719 if (given.equalsIgnoreCase((String) color.getKey()))
 929    {
 930  150 if (lexer.configuration.replaceColor)
 931    {
 932  0 attval.value = (String) color.getKey();
 933    }
 934  150 found = true;
 935  150 break;
 936    }
 937    }
 938    else
 939    {
 940   
 941  0 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 942   
 943  0 invalid = true;
 944  0 break;
 945    }
 946    }
 947  667 if (!found && !invalid)
 948    {
 949  479 if (given.charAt(0) == '#')
 950    {
 951    // check if valid hex digits and letters
 952   
 953  477 for (int i = 1; i < 7; ++i)
 954    {
 955  2862 if (!TidyUtils.isDigit(given.charAt(i))
 956    && ("abcdef".indexOf(Character.toLowerCase(given.charAt(i))) == -1))
 957    {
 958  0 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 959  0 invalid = true;
 960  0 break;
 961    }
 962    }
 963    // convert hex letters to uppercase
 964  477 if (!invalid && hexUppercase)
 965    {
 966  477 for (int i = 1; i < 7; ++i)
 967    {
 968  2862 attval.value = given.toUpperCase();
 969    }
 970    }
 971    }
 972   
 973    else
 974    {
 975    // we could search for more colors and mark the file as HTML Proprietary, but I don't thinks
 976    // it's worth the effort, so values not in HTML 4.01 are invalid
 977  2 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 978  2 invalid = true;
 979    }
 980    }
 981    }
 982    }
 983   
 984    /**
 985    * AttrCheck implementation for checking valuetype.
 986    */
 987    public static class CheckVType implements AttrCheck
 988    {
 989   
 990    /**
 991    * valid values for this attribute.
 992    */
 993    private static final String[] VALID_VALUES = new String[]{"data", "object", "ref"};
 994   
 995    /**
 996    * @see AttrCheck#check(Lexer, Node, AttVal)
 997    */
 998  0 public void check(Lexer lexer, Node node, AttVal attval)
 999    {
 1000  0 if (attval.value == null)
 1001    {
 1002  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 1003  0 return;
 1004    }
 1005   
 1006  0 attval.checkLowerCaseAttrValue(lexer, node);
 1007   
 1008  0 if (!TidyUtils.isInValuesIgnoreCase(VALID_VALUES, attval.value))
 1009    {
 1010  0 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 1011    }
 1012    }
 1013    }
 1014   
 1015    /**
 1016    * AttrCheck implementation for checking scroll.
 1017    */
 1018    public static class CheckScroll implements AttrCheck
 1019    {
 1020   
 1021    /**
 1022    * valid values for this attribute.
 1023    */
 1024    private static final String[] VALID_VALUES = new String[]{"no", "yes", "auto"};
 1025   
 1026    /**
 1027    * @see AttrCheck#check(Lexer, Node, AttVal)
 1028    */
 1029  2 public void check(Lexer lexer, Node node, AttVal attval)
 1030    {
 1031   
 1032  2 if (attval.value == null)
 1033    {
 1034  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 1035  0 return;
 1036    }
 1037   
 1038  2 attval.checkLowerCaseAttrValue(lexer, node);
 1039   
 1040  2 if (!TidyUtils.isInValuesIgnoreCase(VALID_VALUES, attval.value))
 1041    {
 1042  0 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 1043    }
 1044    }
 1045    }
 1046   
 1047    /**
 1048    * AttrCheck implementation for checking dir.
 1049    */
 1050    public static class CheckTextDir implements AttrCheck
 1051    {
 1052   
 1053    /**
 1054    * valid values for this attribute.
 1055    */
 1056    private static final String[] VALID_VALUES = new String[]{"rtl", "ltr"};
 1057   
 1058    /**
 1059    * @see AttrCheck#check(Lexer, Node, AttVal)
 1060    */
 1061  2 public void check(Lexer lexer, Node node, AttVal attval)
 1062    {
 1063   
 1064  2 if (attval.value == null)
 1065    {
 1066  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 1067  0 return;
 1068    }
 1069   
 1070  2 attval.checkLowerCaseAttrValue(lexer, node);
 1071   
 1072  2 if (!TidyUtils.isInValuesIgnoreCase(VALID_VALUES, attval.value))
 1073    {
 1074  0 lexer.report.attrError(lexer, node, attval, Report.BAD_ATTRIBUTE_VALUE);
 1075    }
 1076    }
 1077    }
 1078   
 1079    /**
 1080    * AttrCheck implementation for checking lang and xml:lang.
 1081    */
 1082    public static class CheckLang implements AttrCheck
 1083    {
 1084   
 1085    /**
 1086    * @see AttrCheck#check(Lexer, Node, AttVal)
 1087    */
 1088  34 public void check(Lexer lexer, Node node, AttVal attval)
 1089    {
 1090   
 1091  34 if ("lang".equals(attval.attribute))
 1092    {
 1093  34 lexer.constrainVersion(~Dict.VERS_XHTML11);
 1094    }
 1095   
 1096  34 if (attval.value == null)
 1097    {
 1098  0 lexer.report.attrError(lexer, node, attval, Report.MISSING_ATTR_VALUE);
 1099  0 return;
 1100    }
 1101    }
 1102    }
 1103   
 1104    }