1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4: */
3//
4// +----------------------------------------------------------------------+
5// | PHP Version 4                                                        |
6// +----------------------------------------------------------------------+
7// | Copyright (c) 1997-2002 The PHP Group                                |
8// +----------------------------------------------------------------------+
9// | This source file is subject to version 2.02 of the PHP license,      |
10// | that is bundled with this package in the file LICENSE, and is        |
11// | available at through the world-wide-web at                           |
12// | http://www.php.net/license/3_0.txt.                                  |
13// | If you did not receive a copy of the PHP license and are unable to   |
14// | obtain it through the world-wide-web, please send a note to          |
15// | license@php.net so we can mail you a copy immediately.               |
16// +----------------------------------------------------------------------+
17// | Authors: Alexander Zhukov <alex@veresk.ru> Original port from Python |
18// | Authors: Harry Fuecks <hfuecks@phppatterns.com> Port to PEAR + more  |
19// | Authors: Many @ Sitepointforums Advanced PHP Forums                  |
20// +----------------------------------------------------------------------+
21//
22// $Id: XML_HTMLSax_States.php,v 1.7 2003/12/04 23:35:20 harryf Exp $
23//
24/**
25* Main parser components
26* @package XML_HTMLSax
27* @version $Id: XML_HTMLSax_States.php,v 1.7 2003/12/04 23:35:20 harryf Exp $
28*/
29/**
30* Define parser states
31*/
32define('XML_HTMLSAX_STATE_STOP', 0);
33define('XML_HTMLSAX_STATE_START', 1);
34define('XML_HTMLSAX_STATE_TAG', 2);
35define('XML_HTMLSAX_STATE_OPENING_TAG', 3);
36define('XML_HTMLSAX_STATE_CLOSING_TAG', 4);
37define('XML_HTMLSAX_STATE_ESCAPE', 6);
38define('XML_HTMLSAX_STATE_JASP', 7);
39define('XML_HTMLSAX_STATE_PI', 8);
40/**
41* StartingState searches for the start of any XML tag
42* @package XML_HTMLSax
43* @access protected
44*/
45class XML_HTMLSax_StartingState  {
46    /**
47    * @param XML_HTMLSax_StateParser subclass
48    * @return constant XML_HTMLSAX_STATE_TAG
49    * @access protected
50    */
51    function parse(&$context) {
52        $data = $context->scanUntilString('<');
53        if ($data != '') {
54            $context->handler_object_data->
55                {$context->handler_method_data}($context->htmlsax, $data);
56        }
57        $context->IgnoreCharacter();
58        return XML_HTMLSAX_STATE_TAG;
59    }
60}
61/**
62* Decides which state to move one from after StartingState
63* @package XML_HTMLSax
64* @access protected
65*/
66class XML_HTMLSax_TagState {
67    /**
68    * @param XML_HTMLSax_StateParser subclass
69    * @return constant the next state to move into
70    * @access protected
71    */
72    function parse(&$context) {
73        switch($context->ScanCharacter()) {
74        case '/':
75            return XML_HTMLSAX_STATE_CLOSING_TAG;
76            break;
77        case '?':
78            return XML_HTMLSAX_STATE_PI;
79            break;
80        case '%':
81            return XML_HTMLSAX_STATE_JASP;
82            break;
83        case '!':
84            return XML_HTMLSAX_STATE_ESCAPE;
85            break;
86        default:
87            $context->unscanCharacter();
88            return XML_HTMLSAX_STATE_OPENING_TAG;
89        }
90    }
91}
92/**
93* Dealing with closing XML tags
94* @package XML_HTMLSax
95* @access protected
96*/
97class XML_HTMLSax_ClosingTagState {
98    /**
99    * @param XML_HTMLSax_StateParser subclass
100    * @return constant XML_HTMLSAX_STATE_START
101    * @access protected
102    */
103    function parse(&$context) {
104        $tag = $context->scanUntilCharacters('/>');
105        if ($tag != '') {
106            $char = $context->scanCharacter();
107            if ($char == '/') {
108                $char = $context->scanCharacter();
109                if ($char != '>') {
110                    $context->unscanCharacter();
111                }
112            }
113            $context->handler_object_element->
114                {$context->handler_method_closing}($context->htmlsax, $tag, FALSE);
115        }
116        return XML_HTMLSAX_STATE_START;
117    }
118}
119/**
120* Dealing with opening XML tags
121* @package XML_HTMLSax
122* @access protected
123*/
124class XML_HTMLSax_OpeningTagState {
125    /**
126    * Handles attributes
127    * @param string attribute name
128    * @param string attribute value
129    * @return void
130    * @access protected
131    * @see XML_HTMLSax_AttributeStartState
132    */
133    function parseAttributes(&$context) {
134        $Attributes = array();
135
136        $context->ignoreWhitespace();
137        $attributename = $context->scanUntilCharacters("=/> \n\r\t");
138        while ($attributename != '') {
139            $attributevalue = NULL;
140            $context->ignoreWhitespace();
141            $char = $context->scanCharacter();
142            if ($char == '=') {
143                $context->ignoreWhitespace();
144                $char = $context->ScanCharacter();
145                if ($char == '"') {
146                    $attributevalue= $context->scanUntilString('"');
147                    $context->IgnoreCharacter();
148                } else if ($char == "'") {
149                    $attributevalue = $context->scanUntilString("'");
150                    $context->IgnoreCharacter();
151                } else {
152                    $context->unscanCharacter();
153                    $attributevalue =
154                        $context->scanUntilCharacters("> \n\r\t");
155                }
156            } else if ($char !== NULL) {
157                $attributevalue = true;
158                $context->unscanCharacter();
159            }
160            $Attributes[$attributename] = $attributevalue;
161
162            $context->ignoreWhitespace();
163            $attributename = $context->scanUntilCharacters("=/> \n\r\t");
164        }
165        return $Attributes;
166    }
167
168    /**
169    * @param XML_HTMLSax_StateParser subclass
170    * @return constant XML_HTMLSAX_STATE_START
171    * @access protected
172    */
173    function parse(&$context) {
174        $tag = $context->scanUntilCharacters("/> \n\r\t");
175        if ($tag != '') {
176            $this->attrs = array();
177            $Attributes = $this->parseAttributes($context);
178            $char = $context->scanCharacter();
179            if ($char == '/') {
180                $char = $context->scanCharacter();
181                if ($char != '>') {
182                    $context->unscanCharacter();
183                }
184                $context->handler_object_element->
185                    {$context->handler_method_opening}($context->htmlsax, $tag,
186                    $Attributes, TRUE);
187                $context->handler_object_element->
188                    {$context->handler_method_closing}($context->htmlsax, $tag,
189                    TRUE);
190            } else {
191                $context->handler_object_element->
192                    {$context->handler_method_opening}($context->htmlsax, $tag,
193                    $Attributes, FALSE);
194            }
195        }
196        return XML_HTMLSAX_STATE_START;
197    }
198}
199
200/**
201* Deals with XML escapes handling comments and CDATA correctly
202* @package XML_HTMLSax
203* @access protected
204*/
205class XML_HTMLSax_EscapeState {
206    /**
207    * @param XML_HTMLSax_StateParser subclass
208    * @return constant XML_HTMLSAX_STATE_START
209    * @access protected
210    */
211    function parse(&$context) {
212        if ($context->parser_options['XML_OPTION_FULL_ESCAPES']==0) {
213            $char = $context->ScanCharacter();
214            if ($char == '-') {
215                $char = $context->ScanCharacter();
216                if ($char == '-') {
217                    $text = $context->scanUntilString('-->');
218                    $context->IgnoreCharacter();
219                    $context->IgnoreCharacter();
220                } else {
221                    $context->unscanCharacter();
222                    $text = $context->scanUntilString('>');
223                }
224            } else if ( $char == '[') {
225                $context->scanUntilString('CDATA[');
226                for ( $i=0;$i<6;$i++ ) {
227                    $context->IgnoreCharacter();
228                }
229                $text = $context->scanUntilString(']]>');
230                $context->IgnoreCharacter();
231                $context->IgnoreCharacter();
232            } else {
233                $context->unscanCharacter();
234                $text = $context->scanUntilString('>');
235            }
236        } else {
237            $text = $context->scanUntilString('>');
238        }
239        $context->IgnoreCharacter();
240        if ($text != '') {
241            $context->handler_object_escape->
242            {$context->handler_method_escape}($context->htmlsax, $text);
243        }
244        return XML_HTMLSAX_STATE_START;
245    }
246}
247/**
248* Deals with JASP/ASP markup
249* @package XML_HTMLSax
250* @access protected
251*/
252class XML_HTMLSax_JaspState {
253    /**
254    * @param XML_HTMLSax_StateParser subclass
255    * @return constant XML_HTMLSAX_STATE_START
256    * @access protected
257    */
258    function parse(&$context) {
259        $text = $context->scanUntilString('%>');
260        if ($text != '') {
261            $context->handler_object_jasp->
262                {$context->handler_method_jasp}($context->htmlsax, $text);
263        }
264        $context->IgnoreCharacter();
265        $context->IgnoreCharacter();
266        return XML_HTMLSAX_STATE_START;
267    }
268}
269/**
270* Deals with XML processing instructions
271* @package XML_HTMLSax
272* @access protected
273*/
274class XML_HTMLSax_PiState {
275    /**
276    * @param XML_HTMLSax_StateParser subclass
277    * @return constant XML_HTMLSAX_STATE_START
278    * @access protected
279    */
280    function parse(&$context) {
281        $target = $context->scanUntilCharacters(" \n\r\t");
282        $data = $context->scanUntilString('?>');
283        if ($data != '') {
284            $context->handler_object_pi->
285            {$context->handler_method_pi}($context->htmlsax, $target, $data);
286        }
287        $context->IgnoreCharacter();
288        $context->IgnoreCharacter();
289        return XML_HTMLSAX_STATE_START;
290    }
291}
292?>