Forms.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. /**
  3. * XHTML 1.1 Forms module, defines all form-related elements found in HTML 4.
  4. */
  5. class HTMLPurifier_HTMLModule_Forms extends HTMLPurifier_HTMLModule
  6. {
  7. /**
  8. * @type string
  9. */
  10. public $name = 'Forms';
  11. /**
  12. * @type bool
  13. */
  14. public $safe = false;
  15. /**
  16. * @type array
  17. */
  18. public $content_sets = array(
  19. 'Block' => 'Form',
  20. 'Inline' => 'Formctrl',
  21. );
  22. /**
  23. * @param HTMLPurifier_Config $config
  24. */
  25. public function setup($config)
  26. {
  27. $form = $this->addElement(
  28. 'form',
  29. 'Form',
  30. 'Required: Heading | List | Block | fieldset',
  31. 'Common',
  32. array(
  33. 'accept' => 'ContentTypes',
  34. 'accept-charset' => 'Charsets',
  35. 'action*' => 'URI',
  36. 'method' => 'Enum#get,post',
  37. // really ContentType, but these two are the only ones used today
  38. 'enctype' => 'Enum#application/x-www-form-urlencoded,multipart/form-data',
  39. )
  40. );
  41. $form->excludes = array('form' => true);
  42. $input = $this->addElement(
  43. 'input',
  44. 'Formctrl',
  45. 'Empty',
  46. 'Common',
  47. array(
  48. 'accept' => 'ContentTypes',
  49. 'accesskey' => 'Character',
  50. 'alt' => 'Text',
  51. 'checked' => 'Bool#checked',
  52. 'disabled' => 'Bool#disabled',
  53. 'maxlength' => 'Number',
  54. 'name' => 'CDATA',
  55. 'readonly' => 'Bool#readonly',
  56. 'size' => 'Number',
  57. 'src' => 'URI#embedded',
  58. 'tabindex' => 'Number',
  59. 'type' => 'Enum#text,password,checkbox,button,radio,submit,reset,file,hidden,image',
  60. 'value' => 'CDATA',
  61. )
  62. );
  63. $input->attr_transform_post[] = new HTMLPurifier_AttrTransform_Input();
  64. $this->addElement(
  65. 'select',
  66. 'Formctrl',
  67. 'Required: optgroup | option',
  68. 'Common',
  69. array(
  70. 'disabled' => 'Bool#disabled',
  71. 'multiple' => 'Bool#multiple',
  72. 'name' => 'CDATA',
  73. 'size' => 'Number',
  74. 'tabindex' => 'Number',
  75. )
  76. );
  77. $this->addElement(
  78. 'option',
  79. false,
  80. 'Optional: #PCDATA',
  81. 'Common',
  82. array(
  83. 'disabled' => 'Bool#disabled',
  84. 'label' => 'Text',
  85. 'selected' => 'Bool#selected',
  86. 'value' => 'CDATA',
  87. )
  88. );
  89. // It's illegal for there to be more than one selected, but not
  90. // be multiple. Also, no selected means undefined behavior. This might
  91. // be difficult to implement; perhaps an injector, or a context variable.
  92. $textarea = $this->addElement(
  93. 'textarea',
  94. 'Formctrl',
  95. 'Optional: #PCDATA',
  96. 'Common',
  97. array(
  98. 'accesskey' => 'Character',
  99. 'cols*' => 'Number',
  100. 'disabled' => 'Bool#disabled',
  101. 'name' => 'CDATA',
  102. 'readonly' => 'Bool#readonly',
  103. 'rows*' => 'Number',
  104. 'tabindex' => 'Number',
  105. )
  106. );
  107. $textarea->attr_transform_pre[] = new HTMLPurifier_AttrTransform_Textarea();
  108. $button = $this->addElement(
  109. 'button',
  110. 'Formctrl',
  111. 'Optional: #PCDATA | Heading | List | Block | Inline',
  112. 'Common',
  113. array(
  114. 'accesskey' => 'Character',
  115. 'disabled' => 'Bool#disabled',
  116. 'name' => 'CDATA',
  117. 'tabindex' => 'Number',
  118. 'type' => 'Enum#button,submit,reset',
  119. 'value' => 'CDATA',
  120. )
  121. );
  122. // For exclusions, ideally we'd specify content sets, not literal elements
  123. $button->excludes = $this->makeLookup(
  124. 'form',
  125. 'fieldset', // Form
  126. 'input',
  127. 'select',
  128. 'textarea',
  129. 'label',
  130. 'button', // Formctrl
  131. 'a', // as per HTML 4.01 spec, this is omitted by modularization
  132. 'isindex',
  133. 'iframe' // legacy items
  134. );
  135. // Extra exclusion: img usemap="" is not permitted within this element.
  136. // We'll omit this for now, since we don't have any good way of
  137. // indicating it yet.
  138. // This is HIGHLY user-unfriendly; we need a custom child-def for this
  139. $this->addElement('fieldset', 'Form', 'Custom: (#WS?,legend,(Flow|#PCDATA)*)', 'Common');
  140. $label = $this->addElement(
  141. 'label',
  142. 'Formctrl',
  143. 'Optional: #PCDATA | Inline',
  144. 'Common',
  145. array(
  146. 'accesskey' => 'Character',
  147. // 'for' => 'IDREF', // IDREF not implemented, cannot allow
  148. )
  149. );
  150. $label->excludes = array('label' => true);
  151. $this->addElement(
  152. 'legend',
  153. false,
  154. 'Optional: #PCDATA | Inline',
  155. 'Common',
  156. array(
  157. 'accesskey' => 'Character',
  158. )
  159. );
  160. $this->addElement(
  161. 'optgroup',
  162. false,
  163. 'Required: option',
  164. 'Common',
  165. array(
  166. 'disabled' => 'Bool#disabled',
  167. 'label*' => 'Text',
  168. )
  169. );
  170. // Don't forget an injector for <isindex>. This one's a little complex
  171. // because it maps to multiple elements.
  172. }
  173. }
  174. // vim: et sw=4 sts=4