File indexing completed on 2024-05-05 16:10:07

0001 /**
0002  * This file is part of the DOM implementation for KDE.
0003  *
0004  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
0005  *           (C) 2006-2007 Allan Sandfeld Jensen (kde@carewolf.com)
0006  *
0007  * This library is free software; you can redistribute it and/or
0008  * modify it under the terms of the GNU Library General Public
0009  * License as published by the Free Software Foundation; either
0010  * version 2 of the License, or (at your option) any later version.
0011  *
0012  * This library is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Library General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Library General Public License
0018  * along with this library; see the file COPYING.LIB.  If not, write to
0019  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020  * Boston, MA 02110-1301, USA.
0021  *
0022  */
0023 
0024 #include "html/dtd.h"
0025 
0026 using namespace DOM;
0027 
0028 #include "khtml_debug.h"
0029 
0030 // priority of tags. Closing tags of higher priority close tags of lower
0031 // priority.
0032 // Update this list, whenever you change htmltags.*
0033 //
0034 // 0 elements with forbidden close tag and text. They don't get pushed
0035 //   to the stack.
0036 // 1 formatting elements
0037 // 3 form nobr noscript
0038 // 5 phrasing elements
0039 // 6 TD TH SELECT
0040 // 7 TR
0041 // 8 tbody thead tfoot
0042 // 9 table
0043 // 10 body frameset head noembed noframes
0044 // 11 html
0045 
0046 const unsigned short DOM::tagPriorityArray[] = {
0047     0, // 0
0048     1, // ID_A == 1
0049     1, // ID_ABBR
0050     1, // ID_ACRONYM
0051     5, // ID_ADDRESS
0052     1, // ID_APPLET
0053     0, // ID_AREA
0054     1, // ID_AUDIO
0055     1, // ID_B
0056     0, // ID_BASE
0057     0, // ID_BASEFONT
0058     1, // ID_BDO
0059     1, // ID_BIG
0060     5, // ID_BLOCKQUOTE
0061     10, // ID_BODY
0062     0, // ID_BR
0063     1, // ID_BUTTON
0064     1, // ID_CANVAS
0065     5, // ID_CAPTION
0066     5, // ID_CENTER
0067     1, // ID_CITE
0068     1, // ID_CODE
0069     0, // ID_COL
0070     1, // ID_COLGROUP
0071     5, // ID_DD
0072     1, // ID_DEL
0073     1, // ID_DFN
0074     5, // ID_DIR
0075     5, // ID_DIV
0076     5, // ID_DL
0077     5, // ID_DT
0078     1, // ID_EM
0079     0, // ID_EMBED
0080     5, // ID_FIELDSET
0081     1, // ID_FONT
0082     3, // ID_FORM
0083     0, // ID_FRAME
0084     10,// ID_FRAMESET
0085     5, // ID_H1
0086     5, // ID_H2
0087     5, // ID_H3
0088     5, // ID_H4
0089     5, // ID_H5
0090     5, // ID_H6
0091     10,// ID_HEAD
0092     0, // ID_HR
0093     11,// ID_HTML
0094     1, // ID_I
0095     1, // ID_IFRAME
0096     1, // ID_ILAYER
0097     0, // ID_IMAGE
0098     0, // ID_IMG
0099     0, // ID_INPUT
0100     1, // ID_INS
0101     0, // ID_ISINDEX
0102     1, // ID_KBD
0103     0, // ID_KEYGEN
0104     1, // ID_LABEL
0105     1, // ID_LAYER
0106     1, // ID_LEGEND
0107     5, // ID_LI
0108     0, // ID_LINK
0109     5, // ID_LISTING
0110     1, // ID_MAP
0111     5, // ID_MARQUEE
0112     5, // ID_MENU
0113     0, // ID_META
0114     5, // ID_NOBR
0115     10,// ID_NOEMBED
0116     10,// ID_NOFRAMES
0117     3, // ID_NOSCRIPT
0118     1, // ID_NOLAYER
0119     5, // ID_OBJECT
0120     5, // ID_OL
0121     1, // ID_OPTGROUP
0122     2, // ID_OPTION
0123     5, // ID_P
0124     0, // ID_PARAM
0125     5, // ID_PLAINTEXT
0126     5, // ID_PRE
0127     1, // ID_Q
0128     1, // ID_S
0129     1, // ID_SAMP
0130     1, // ID_SCRIPT
0131     6, // ID_SELECT
0132     1, // ID_SMALL
0133     0, // ID_SOURCE
0134     1, // ID_SPAN
0135     1, // ID_STRIKE
0136     1, // ID_STRONG
0137     1, // ID_STYLE
0138     1, // ID_SUB
0139     1, // ID_SUP
0140     9, // ID_TABLE
0141     8, // ID_TBODY
0142     6, // ID_TD
0143     1, // ID_TEXTAREA
0144     8, // ID_TFOOT
0145     6, // ID_TH
0146     8, // ID_THEAD
0147     1, // ID_TITLE
0148     7, // ID_TR
0149     1, // ID_TT
0150     1, // ID_U
0151     5, // ID_UL
0152     1, // ID_VAR
0153     1, // ID_VIDEO
0154     0, // ID_WBR
0155     5, // ID_XMP
0156     0, // ID_TEXT
0157     0  // ID_COMMENT
0158 };
0159 
0160 const tagStatus DOM::endTagArray[] = {
0161     REQUIRED,  // 0
0162     REQUIRED,  // ID_A == 1
0163     REQUIRED,  // ID_ABBR
0164     REQUIRED,  // ID_ACRONYM
0165     REQUIRED,  // ID_ADDRESS
0166     REQUIRED,  // ID_APPLET
0167     FORBIDDEN, // ID_AREA
0168     REQUIRED,  // ID_AUDIO
0169     REQUIRED,  // ID_B
0170     FORBIDDEN, // ID_BASE
0171     FORBIDDEN, // ID_BASEFONT
0172     REQUIRED,  // ID_BDO
0173     REQUIRED,  // ID_BIG
0174     REQUIRED,  // ID_BLOCKQUOTE
0175     REQUIRED,  // ID_BODY
0176     FORBIDDEN, // ID_BR
0177     REQUIRED,  // ID_BUTTON
0178     REQUIRED,  // ID_CANVAS
0179     REQUIRED,  // ID_CAPTION
0180     REQUIRED,  // ID_CENTER
0181     REQUIRED,  // ID_CITE
0182     REQUIRED,  // ID_CODE
0183     FORBIDDEN, // ID_COL
0184     OPTIONAL,  // ID_COLGROUP
0185     OPTIONAL,  // ID_DD
0186     REQUIRED,  // ID_DEL
0187     REQUIRED,  // ID_DFN
0188     REQUIRED,  // ID_DIR
0189     REQUIRED,  // ID_DIV
0190     REQUIRED,  // ID_DL
0191     OPTIONAL,  // ID_DT
0192     REQUIRED,  // ID_EM
0193     REQUIRED,  // ID_EMBED
0194     REQUIRED,  // ID_FIELDSET
0195     REQUIRED,  // ID_FONT
0196     REQUIRED,  // ID_FORM
0197     FORBIDDEN, // ID_FRAME
0198     REQUIRED,  // ID_FRAMESET
0199     REQUIRED,  // ID_H1
0200     REQUIRED,  // ID_H2
0201     REQUIRED,  // ID_H3
0202     REQUIRED,  // ID_H4
0203     REQUIRED,  // ID_H5
0204     REQUIRED,  // ID_H6
0205     OPTIONAL,  // ID_HEAD
0206     FORBIDDEN, // ID_HR
0207     REQUIRED,  // ID_HTML
0208     REQUIRED,  // ID_I
0209     REQUIRED,  // ID_IFRAME
0210     REQUIRED,  // ID_ILAYER
0211     FORBIDDEN, // ID_IMAGE
0212     FORBIDDEN, // ID_IMG
0213     FORBIDDEN, // ID_INPUT
0214     REQUIRED,  // ID_INS
0215     FORBIDDEN, // ID_ISINDEX
0216     REQUIRED,  // ID_KBD
0217     REQUIRED,  // ID_KEYGEN
0218     REQUIRED,  // ID_LABEL
0219     REQUIRED,  // ID_LAYER
0220     REQUIRED,  // ID_LEGEND
0221     OPTIONAL,  // ID_LI
0222     FORBIDDEN, // ID_LINK
0223     REQUIRED,  // ID_LISTING
0224     REQUIRED,  // ID_MAP
0225     REQUIRED,  // ID_MARQUEE
0226     REQUIRED,  // ID_MENU
0227     FORBIDDEN, // ID_META
0228     REQUIRED,  // ID_NOBR
0229     REQUIRED,  // ID_NOEMBED
0230     REQUIRED,  // ID_NOFRAMES
0231     REQUIRED,  // ID_NOSCRIPT
0232     REQUIRED,  // ID_NOLAYER
0233     REQUIRED,  // ID_OBJECT
0234     REQUIRED,  // ID_OL
0235     REQUIRED,  // ID_OPTGROUP
0236     OPTIONAL,  // ID_OPTION
0237     OPTIONAL,  // ID_P
0238     FORBIDDEN, // ID_PARAM
0239     REQUIRED,  // ID_PLAINTEXT
0240     REQUIRED,  // ID_PRE
0241     REQUIRED,  // ID_Q
0242     REQUIRED,  // ID_S
0243     REQUIRED,  // ID_SAMP
0244     REQUIRED,  // ID_SCRIPT
0245     REQUIRED,  // ID_SELECT
0246     REQUIRED,  // ID_SMALL
0247     FORBIDDEN, // ID_SOURCE
0248     REQUIRED,  // ID_SPAN
0249     REQUIRED,  // ID_STRIKE
0250     REQUIRED,  // ID_STRONG
0251     REQUIRED,  // ID_STYLE
0252     REQUIRED,  // ID_SUB
0253     REQUIRED,  // ID_SUP
0254     REQUIRED,  // ID_TABLE
0255     OPTIONAL,  // ID_TBODY
0256     OPTIONAL,  // ID_TD
0257     REQUIRED,  // ID_TEXTAREA
0258     OPTIONAL,  // ID_TFOOT
0259     OPTIONAL,  // ID_TH
0260     OPTIONAL,  // ID_THEAD
0261     REQUIRED,  // ID_TITLE
0262     OPTIONAL,  // ID_TR
0263     REQUIRED,  // ID_TT
0264     REQUIRED,  // ID_U
0265     REQUIRED,  // ID_UL
0266     REQUIRED,  // ID_VAR
0267     REQUIRED,  // ID_VIDEO
0268     FORBIDDEN, // ID_WBR
0269     REQUIRED,  // ID_XMP
0270     REQUIRED,  // ID_TEXT
0271     REQUIRED   // ID_COMMENT
0272 };
0273 
0274 // This a combination of HTML4.dtd XHTML11.dtd and various extensions
0275 // and deprecated elements
0276 static const ushort tag_list_inline[] = {
0277     ID_TEXT,
0278     // %fontstyle
0279     ID_TT,
0280     ID_I,
0281     ID_B,
0282     ID_BIG,
0283     ID_SMALL,
0284     ID_U,           // legacy
0285     ID_S,           // legacy
0286     ID_STRIKE,      // legacy
0287     ID_FONT,        // legacy
0288     ID_BASEFONT,    // legacy
0289     // %phrase
0290     ID_EM,
0291     ID_STRONG,
0292     ID_DFN,
0293     ID_CODE,
0294     ID_Q,
0295     ID_SAMP,
0296     ID_KBD,
0297     ID_VAR,
0298     ID_CITE,
0299     ID_ABBR,
0300     ID_ACRONYM,
0301     ID_SUB,
0302     ID_SUP,
0303     // %inline.forms
0304     ID_INPUT,
0305     ID_SELECT,
0306     ID_TEXTAREA,
0307     ID_LABEL,
0308     ID_BUTTON,
0309     // %special
0310     ID_A,
0311     ID_OBJECT,
0312     ID_IMAGE,
0313     ID_IMG,
0314     ID_APPLET,
0315     ID_IFRAME,
0316     ID_EMBED,       // ?
0317     // %special.pre
0318     ID_BR,
0319     ID_SPAN,
0320     ID_BDO,
0321     ID_MAP,
0322     // %misc.inline
0323     ID_SCRIPT,
0324     ID_INS,
0325     ID_DEL,
0326     // non-standard:
0327     ID_ILAYER,      // deprecated
0328     ID_NOBR,        // ?
0329     ID_WBR,         // ?
0330     ID_CANVAS,
0331     ID_AUDIO,
0332     ID_VIDEO,
0333     0
0334 };
0335 
0336 static const ushort tag_list_quirk_inline[] = {
0337     ID_NOSCRIPT,    // block, but parsed as inline in Mozilla and MSIE
0338     0
0339 };
0340 
0341 static const ushort tag_list_block[] = {
0342     ID_TEXT, // white-space is allowed
0343     ID_P,
0344     // %headings
0345     ID_H1,
0346     ID_H2,
0347     ID_H3,
0348     ID_H4,
0349     ID_H5,
0350     ID_H6,
0351     // %lists
0352     ID_UL,
0353     ID_OL,
0354     ID_DL,
0355     ID_DIR,         // legacy
0356     ID_MENU,        // legacy
0357     // %blocktext
0358     ID_LISTING,
0359     ID_PRE,
0360     ID_HR,
0361     ID_BLOCKQUOTE,
0362     ID_ADDRESS,
0363     ID_PLAINTEXT,   // ?
0364     ID_XMP,         // ?
0365     ID_CENTER,      // legacy
0366     // other
0367     ID_DIV,
0368     ID_FIELDSET,
0369     ID_TABLE,
0370     ID_NOSCRIPT,
0371     ID_NOFRAMES,
0372     ID_FORM,
0373     ID_ISINDEX,     // legacy
0374     // non-standard:
0375     ID_LAYER,       // deprecated
0376     ID_MARQUEE,     // extension
0377     0
0378 };
0379 
0380 // block elements allowed for quirky error recovery
0381 static const ushort tag_list_quirk_block[] = {
0382     ID_LI,
0383     ID_DD,
0384     0
0385 };
0386 
0387 static const ushort tag_list_select[] = {
0388     ID_TEXT,
0389     ID_OPTGROUP,
0390     ID_OPTION,
0391     ID_COMMENT,
0392     ID_SCRIPT,
0393     0
0394 };
0395 
0396 static const ushort tag_list_frame[] = {
0397     ID_FRAMESET,
0398     ID_FRAME,
0399     ID_NOFRAMES,
0400     ID_COMMENT,
0401     0
0402 };
0403 
0404 static const ushort tag_list_head[] = {
0405     ID_SCRIPT,
0406     ID_STYLE,
0407     ID_META,
0408     ID_LINK,
0409     ID_TITLE,
0410     ID_ISINDEX,
0411     ID_BASE,
0412     ID_COMMENT,
0413     0
0414 };
0415 
0416 // cf. HTML5 8.2.3.2
0417 static const ushort scope_boundary[] = {
0418     ID_APPLET,
0419     ID_CAPTION,
0420     ID_HTML,
0421     ID_TABLE,
0422     ID_TD,
0423     ID_TH,
0424     ID_BUTTON,
0425     ID_MARQUEE,
0426     ID_OBJECT,
0427 //    ID_FOREIGNOBJECT, - only in SVG namespace
0428     0
0429 };
0430 
0431 static bool check_array(ushort child, const ushort *tagList)
0432 {
0433     int i = 0;
0434     while (tagList[i] != 0) {
0435         if (tagList[i] == child) {
0436             return true;
0437         }
0438         i++;
0439     }
0440     return false;
0441 }
0442 
0443 static bool check_block(ushort childID, bool strict)
0444 {
0445     return check_array(childID, tag_list_block) ||
0446            (!strict && check_array(childID, tag_list_quirk_block));
0447 }
0448 
0449 static bool check_inline(ushort childID, bool strict)
0450 {
0451     return check_array(childID, tag_list_inline) ||
0452            (!strict && check_array(childID, tag_list_quirk_inline));
0453 }
0454 
0455 static bool check_flow(ushort childID, bool strict)
0456 {
0457     return check_block(childID, strict) || check_inline(childID, strict);
0458 }
0459 
0460 bool DOM::checkIsScopeBoundary(ushort tagID)
0461 {
0462     return check_array(tagID, scope_boundary);
0463 }
0464 
0465 bool DOM::checkChild(ushort tagID, ushort childID, bool strict)
0466 {
0467     //qCDebug(KHTML_LOG) << "checkChild: " << tagID << "/" << childID;
0468 
0469     if (childID == ID_COMMENT) {
0470         return true;
0471     }
0472 
0473     // Treat custom elements the same as <span>.
0474     if (tagID > ID_LAST_TAG) {
0475         tagID = ID_SPAN;
0476     }
0477     if (childID > ID_LAST_TAG) {
0478         childID = ID_SPAN;
0479     }
0480 
0481     switch (tagID) {
0482     case ID_TT:
0483     case ID_I:
0484     case ID_B:
0485     case ID_U:
0486     case ID_S:
0487     case ID_STRIKE:
0488     case ID_BIG:
0489     case ID_SMALL:
0490     case ID_EM:
0491     case ID_STRONG:
0492     case ID_DFN:
0493     case ID_CODE:
0494     case ID_SAMP:
0495     case ID_KBD:
0496     case ID_VAR:
0497     case ID_CITE:
0498     case ID_ABBR:
0499     case ID_ACRONYM:
0500     case ID_SUB:
0501     case ID_SUP:
0502     case ID_BDO:
0503     case ID_FONT:
0504     case ID_LEGEND:
0505     case ID_Q:
0506     case ID_A:
0507     case ID_NOBR:
0508     case ID_WBR:
0509         // %inline *
0510         return check_inline(childID, strict) || check_block(childID, strict);
0511     case ID_P:
0512         // P: %inline *
0513         return check_inline(childID, strict) ||
0514                (!strict && childID == ID_TABLE);
0515     case ID_H1:
0516     case ID_H2:
0517     case ID_H3:
0518     case ID_H4:
0519     case ID_H5:
0520     case ID_H6:
0521         // %inline *
0522         return check_inline(childID, strict) ||
0523                (!strict && check_block(childID, true) && (childID < ID_H1 || childID > ID_H6));
0524     case ID_BASEFONT:
0525     case ID_BR:
0526     case ID_AREA:
0527     case ID_LINK:
0528     case ID_IMAGE:
0529     case ID_IMG:
0530     case ID_PARAM:
0531     case ID_HR:
0532     case ID_INPUT:
0533     case ID_COL:
0534     case ID_FRAME:
0535     case ID_ISINDEX:
0536     case ID_BASE:
0537     case ID_META:
0538     case ID_COMMENT:
0539         // BASEFONT: EMPTY
0540         return false;
0541     case ID_BODY:
0542         // BODY: %block | SCRIPT (but even strict sites expect %flow)
0543         return check_flow(childID, strict);
0544     case ID_ADDRESS:
0545         // ADDRESS: %inline *
0546         return check_inline(childID, strict) ||
0547                (!strict && childID == ID_P);
0548     case ID_DT:
0549         // DT: %inline *
0550         return check_inline(childID, strict) ||
0551                (!strict && check_block(childID, true) && childID != ID_DL);
0552     case ID_LI:
0553     case ID_DIV:
0554     case ID_SPAN:
0555     case ID_ILAYER:
0556     case ID_LAYER:
0557     case ID_CENTER:
0558     case ID_BLOCKQUOTE:
0559     case ID_INS:
0560     case ID_DEL:
0561     case ID_DD:
0562     case ID_TH:
0563     case ID_TD:
0564     case ID_IFRAME:
0565     case ID_NOFRAMES:
0566     case ID_NOSCRIPT:
0567     case ID_CAPTION:
0568     case ID_MARQUEE:
0569     case ID_CANVAS:
0570         // DIV: %flow *
0571         return check_flow(childID, strict);
0572     case ID_MAP:
0573         // MAP: ( %block | AREA ) (but "prose" in HTML5)
0574         return check_flow(childID, true) || childID == ID_AREA ||
0575                (!strict && childID == ID_SCRIPT);
0576     case ID_OBJECT:
0577     case ID_EMBED:
0578     case ID_APPLET:
0579         // OBJECT: %flow | PARAM *
0580         return check_flow(childID, true) || childID == ID_PARAM;
0581     case ID_AUDIO:
0582     case ID_VIDEO:
0583         return check_flow(childID, true) || childID == ID_SOURCE;
0584     case ID_PRE:
0585     case ID_XMP:
0586     case ID_PLAINTEXT:
0587     case ID_LISTING:
0588         // PRE: %flow * - _5
0589         return check_flow(childID, true);
0590     case ID_DL:
0591         // DL: DT | DD +
0592         return (childID == ID_DT || childID == ID_DD || check_flow(childID, strict));
0593     case ID_OL:
0594     case ID_UL:
0595     case ID_DIR:
0596     case ID_MENU:
0597         // OL: LI +
0598         // For DIR and MENU, the DTD says - %block, but it contradicts spec language..
0599         return (childID == ID_LI || check_flow(childID, strict));
0600     case ID_FORM:
0601         // FORM: %flow * - FORM
0602         return check_flow(childID, strict);
0603     case ID_LABEL:
0604         // LABEL: %inline * - LABEL
0605         return check_inline(childID, strict) ||
0606                (!strict && check_block(childID, true));
0607     case ID_KEYGEN:
0608     // KEYGEN does not really allow any children
0609     // from outside, just need this to be able
0610     // to add the keylengths ourself
0611     // Yes, consider it a hack (Dirk)
0612     case ID_SELECT:
0613         // SELECT: _7 +
0614         return check_array(childID, tag_list_select);
0615     case ID_OPTGROUP:
0616         // OPTGROUP: OPTION +
0617         if (childID == ID_OPTION) {
0618             return true;
0619         }
0620         return false;
0621     case ID_OPTION:
0622         if (childID == ID_SCRIPT) {
0623             return true;
0624         }
0625     // fallthrough intentional
0626     case ID_TEXTAREA:
0627     case ID_TITLE:
0628     case ID_STYLE:
0629     case ID_SCRIPT:
0630         // OPTION: TEXT
0631         if (childID == ID_TEXT) {
0632             return true;
0633         }
0634         return false;
0635     case ID_FIELDSET:
0636         // FIELDSET: ( TEXT , LEGEND , %flow * )
0637         if (childID == ID_TEXT) {
0638             return true;
0639         }
0640         if (childID == ID_LEGEND) {
0641             return true;
0642         }
0643         return check_flow(childID, strict);
0644     case ID_BUTTON:
0645         // BUTTON: %flow * - _8
0646         return check_flow(childID, strict);
0647     case ID_TABLE:
0648         // TABLE: ( CAPTION ? , ( COL * | COLGROUP * ) , THEAD ? , TFOOT ? , TBODY + )
0649         switch (childID) {
0650         case ID_CAPTION:
0651         case ID_COL:
0652         case ID_COLGROUP:
0653         case ID_THEAD:
0654         case ID_TFOOT:
0655         case ID_TBODY:
0656         case ID_FORM:
0657         case ID_SCRIPT:
0658             return true;
0659         default:
0660             return false;
0661         }
0662     case ID_THEAD:
0663     case ID_TFOOT:
0664     case ID_TBODY:
0665         // THEAD: TR +
0666         if (childID == ID_TR || childID == ID_SCRIPT) {
0667             return true;
0668         }
0669         return false;
0670     case ID_COLGROUP:
0671         // COLGROUP: COL *
0672         if (childID == ID_COL) {
0673             return true;
0674         }
0675         return false;
0676     case ID_TR:
0677         // TR: (TD, TH)
0678         return (childID == ID_TH || childID == ID_TD || childID == ID_SCRIPT);
0679     case ID_FRAMESET:
0680         // FRAMESET: _10
0681         return check_array(childID, tag_list_frame);
0682     case ID_HEAD:
0683         // HEAD: _11
0684         return check_array(childID, tag_list_head);
0685     case ID_HTML:
0686         // HTML: ( HEAD , COMMENT, ( BODY | ( FRAMESET & NOFRAMES ? ) ) )
0687         switch (childID) {
0688         case ID_HEAD:
0689         case ID_BODY:
0690         case ID_FRAMESET:
0691         case ID_NOFRAMES:
0692         case ID_SCRIPT:
0693             return true;
0694         default:
0695             return false;
0696         }
0697     default:
0698         // qCDebug(KHTML_LOG) << "unhandled tag in dtd.cpp:checkChild(): tagID=" << tagID << "!";
0699         return false;
0700     }
0701 }
0702 
0703 void DOM::addForbidden(int tagId, ushort *forbiddenTags)
0704 {
0705     switch (tagId) {
0706     case ID_A:
0707         // we allow nested anchors. The innermost one wil be taken...
0708         //forbiddenTags[ID_A]++;
0709         break;
0710     case ID_NOBR:
0711         forbiddenTags[ID_PRE]++;
0712         forbiddenTags[ID_LISTING]++;
0713     // fall through
0714     case ID_PRE:
0715     case ID_LISTING:
0716     case ID_PLAINTEXT:
0717     case ID_XMP:
0718         //forbiddenTags[ID_IMAGE]++;
0719         //forbiddenTags[ID_IMG]++;
0720         forbiddenTags[ID_OBJECT]++;
0721         forbiddenTags[ID_EMBED]++;
0722         forbiddenTags[ID_APPLET]++;
0723         // why forbid them. We can deal with them in PRE
0724         //forbiddenTags[ID_BIG]++;
0725         //forbiddenTags[ID_SMALL]++;
0726         //forbiddenTags[ID_SUB]++;
0727         //forbiddenTags[ID_SUP]++;
0728         forbiddenTags[ID_BASEFONT]++;
0729         break;
0730     case ID_LABEL:
0731         forbiddenTags[ID_LABEL]++;
0732         break;
0733     case ID_BUTTON:
0734         forbiddenTags[ID_A]++;
0735         forbiddenTags[ID_INPUT]++;
0736         forbiddenTags[ID_SELECT]++;
0737         forbiddenTags[ID_TEXTAREA]++;
0738         forbiddenTags[ID_LABEL]++;
0739         forbiddenTags[ID_BUTTON]++;
0740         forbiddenTags[ID_FORM]++;
0741         forbiddenTags[ID_ISINDEX]++;
0742         forbiddenTags[ID_FIELDSET]++;
0743         forbiddenTags[ID_IFRAME]++;
0744         break;
0745     default:
0746         break;
0747     }
0748 }
0749 
0750 void DOM::removeForbidden(int tagId, ushort *forbiddenTags)
0751 {
0752     switch (tagId) {
0753     case ID_A:
0754         //forbiddenTags[ID_A]--;
0755         break;
0756     case ID_NOBR:
0757         forbiddenTags[ID_PRE]--;
0758         forbiddenTags[ID_LISTING]--;
0759     // fall through
0760     case ID_PRE:
0761     case ID_LISTING:
0762     case ID_XMP:
0763     case ID_PLAINTEXT:
0764         //forbiddenTags[ID_IMAGE]--;
0765         //forbiddenTags[ID_IMG]--;
0766         forbiddenTags[ID_OBJECT]--;
0767         forbiddenTags[ID_EMBED]--;
0768         forbiddenTags[ID_APPLET]--;
0769         //forbiddenTags[ID_BIG]--;
0770         //forbiddenTags[ID_SMALL]--;
0771         //forbiddenTags[ID_SUB]--;
0772         //forbiddenTags[ID_SUP]--;
0773         forbiddenTags[ID_BASEFONT]--;
0774         break;
0775     case ID_LABEL:
0776         forbiddenTags[ID_LABEL]--;
0777         break;
0778     case ID_BUTTON:
0779         forbiddenTags[ID_A]--;
0780         forbiddenTags[ID_INPUT]--;
0781         forbiddenTags[ID_SELECT]--;
0782         forbiddenTags[ID_TEXTAREA]--;
0783         forbiddenTags[ID_LABEL]--;
0784         forbiddenTags[ID_BUTTON]--;
0785         forbiddenTags[ID_FORM]--;
0786         forbiddenTags[ID_ISINDEX]--;
0787         forbiddenTags[ID_FIELDSET]--;
0788         forbiddenTags[ID_IFRAME]--;
0789         break;
0790     default:
0791         break;
0792     }
0793 }
0794