From 903ae8a581fac1e6917fc3e31d2ad8fb91df80c3 Mon Sep 17 00:00:00 2001 From: ctrlaltca <> Date: Thu, 12 Jul 2012 11:21:01 +0000 Subject: standardize the use of unix eol; use svn properties to enforce native eol --- framework/3rdParty/PhpShell/PHP/Shell.php | 2182 ++++++++--------- framework/3rdParty/PhpShell/php-shell-init.php | 174 +- framework/3rdParty/SafeHtml/HTMLSax3.php | 1388 +++++------ .../3rdParty/SafeHtml/HTMLSax3/Decorators.php | 724 +++--- framework/3rdParty/SafeHtml/HTMLSax3/States.php | 574 ++--- framework/3rdParty/SafeHtml/TSafeHtmlParser.php | 1344 +++++------ .../3rdParty/TextHighlighter/Text/Highlighter.php | 792 +++---- .../TextHighlighter/Text/Highlighter/ABAP.php | 98 +- .../TextHighlighter/Text/Highlighter/CPP.php | 90 +- .../TextHighlighter/Text/Highlighter/CSS.php | 90 +- .../TextHighlighter/Text/Highlighter/DIFF.php | 90 +- .../TextHighlighter/Text/Highlighter/DTD.php | 90 +- .../TextHighlighter/Text/Highlighter/Generator.php | 2508 ++++++++++---------- .../TextHighlighter/Text/Highlighter/HTML.php | 98 +- .../TextHighlighter/Text/Highlighter/JAVA.php | 90 +- .../Text/Highlighter/JAVASCRIPT.php | 90 +- .../TextHighlighter/Text/Highlighter/MYSQL.php | 90 +- .../TextHighlighter/Text/Highlighter/PERL.php | 90 +- .../TextHighlighter/Text/Highlighter/PHP.php | 2176 ++++++++--------- .../TextHighlighter/Text/Highlighter/PRADO.php | 506 ++-- .../TextHighlighter/Text/Highlighter/PYTHON.php | 90 +- .../TextHighlighter/Text/Highlighter/RUBY.php | 90 +- .../TextHighlighter/Text/Highlighter/Renderer.php | 302 +-- .../Text/Highlighter/Renderer/Array.php | 396 ++-- .../Text/Highlighter/Renderer/BB.php | 474 ++-- .../Text/Highlighter/Renderer/Console.php | 414 ++-- .../Text/Highlighter/Renderer/Html.php | 890 +++---- .../Text/Highlighter/Renderer/HtmlTags.php | 372 +-- .../Text/Highlighter/Renderer/JSON.php | 170 +- .../Text/Highlighter/Renderer/XML.php | 204 +- .../TextHighlighter/Text/Highlighter/SQL.php | 90 +- .../TextHighlighter/Text/Highlighter/XML.php | 90 +- 32 files changed, 8433 insertions(+), 8433 deletions(-) (limited to 'framework/3rdParty') diff --git a/framework/3rdParty/PhpShell/PHP/Shell.php b/framework/3rdParty/PhpShell/PHP/Shell.php index bf8c86c3..8012475e 100644 --- a/framework/3rdParty/PhpShell/PHP/Shell.php +++ b/framework/3rdParty/PhpShell/PHP/Shell.php @@ -1,1091 +1,1091 @@ - - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** -* A interactive PHP Shell -* -* The more I work with other languages like python and ruby I like their way how they -* work on problems. While PHP is very forgiving on errors, it is weak on the debugging -* side. It was missing a simple to use interactive shell for years. Python and Ruby have -* their ipython and iruby shell which give you a direct way to interact with the objects. -* No need to write a script and execute it afterwards. -* -* Starting the Shell: -* -* The package contains a shell wrapper for windows and unix: -*
-* sh>  php-shell.sh
-* win> php-shell
-* 
-* -* Both are calling the wrapper script php -q php-shell-cmd.php -* -* Inline Help -* -*
-* PHP-Shell - Version 0.2.0, with readline() support
-* (c) 2006, Jan Kneschke 
-*
-* >> use '?' to open the inline help
-*
-* >> ?
-* "inline help for the PHP-shell
-*
-*   >> ?
-*     print this help
-*   >> ? 
-*     get the doccomment for a class, method, property or function
-*   >> p 
-*     execute a verbose print (if implemented)
-*   >> quit
-*     leave shell
-* "
-* >> ? PHP_Shell
-* 
-* Alternatives -* -* - http://david.acz.org/phpa/ -* - http://www.hping.org/phpinteractive/ -* - the embedded interactive php-shell: $ php -a -* -* @package PHP -*/ - -/** -* PHP_Shell -* -* a interactive PHP Shell with tab-completion and history -* it can catch FATAL errors before executing the code -* -* Extensions are provided through three side-classes: -* -* - PHP_Shell_Commands -* - PHP_Shell_Options -* - PHP_Shell_Extensions -* -* @package PHP -*/ - -require_once(dirname(__FILE__)."/Shell/Commands.php"); -require_once(dirname(__FILE__)."/Shell/Options.php"); /* for the tab-complete */ - -class PHP_Shell { - /** - * current code-buffer - * @var string - */ - protected $code; - - /** - * set if readline support is enabled - * @var bool - */ - protected $have_readline; - - /** - * current version of the class - * @var string - */ - protected $version = '0.3.1'; - - /** - * - */ - protected $stdin; - - protected $code_buffer; - - public $has_semicolon=false; - - /** - * init the shell and change if readline support is available - */ - public function __construct() { - $this->code = ''; - - $this->stdin = null; - - $this->have_readline = function_exists('readline'); - - if ($this->have_readline) { - readline_completion_function('__shell_readline_complete'); - } - - $this->use_readline = true; - - $cmd = PHP_Shell_Commands::getInstance(); - - $cmd->registerCommand('#^quit$#', $this, 'cmdQuit', 'quit', 'leaves the shell'); - $cmd->registerCommand('#^\?$#', $this, 'cmdHelp', '?', 'show this help'); - $cmd->registerCommand('#^\?\s+license$#', $this, 'cmdLicense', '? license', 'show license of the shell'); - } - - - /** - * parse the PHP code - * - * we parse before we eval() the code to - * - fetch fatal errors before they come up - * - know about where we have to wait for closing braces - * - * @return int 0 if a executable statement is in the code-buffer, non-zero otherwise - */ - public function parse() { - ## remove empty lines - if (trim($this->code) == '') return 1; - - $t = token_get_all('code.' ?>'); - - $need_semicolon = 1; /* do we need a semicolon to complete the statement ? */ - $need_return = 1; /* can we prepend a return to the eval-string ? */ - $open_comment = 0; /* a open multi-line comment */ - $eval = ''; /* code to be eval()'ed later */ - $braces = array(); /* to track if we need more closing braces */ - - $methods = array(); /* to track duplicate methods in a class declaration */ - $ts = array(); /* tokens without whitespaces */ - - foreach ($t as $ndx => $token) { - if (is_array($token)) { - $ignore = 0; - - switch($token[0]) { - case T_WHITESPACE: - case T_OPEN_TAG: - case T_CLOSE_TAG: - $ignore = 1; - break; - case T_FOREACH: - case T_DO: - case T_WHILE: - case T_FOR: - - case T_IF: - case T_RETURN: - - case T_CLASS: - case T_FUNCTION: - case T_INTERFACE: - - case T_PRINT: - case T_ECHO: - - case T_COMMENT: - case T_UNSET: - - case T_INCLUDE: - case T_REQUIRE: - case T_INCLUDE_ONCE: - case T_REQUIRE_ONCE: - case T_TRY: - case T_SWITCH: - case T_DEFAULT: - case T_CASE: - case T_BREAK: - case T_DOC_COMMENT: - $need_return = 0; - break; - case T_EMPTY: - case T_ISSET: - case T_EVAL: - case T_EXIT: - - case T_VARIABLE: - case T_STRING: - case T_NEW: - case T_EXTENDS: - case T_IMPLEMENTS: - case T_OBJECT_OPERATOR: - case T_DOUBLE_COLON: - case T_INSTANCEOF: - - case T_CATCH: - case T_THROW: - - case T_ELSE: - case T_AS: - case T_LNUMBER: - case T_DNUMBER: - case T_CONSTANT_ENCAPSED_STRING: - case T_ENCAPSED_AND_WHITESPACE: - case T_CHARACTER: - case T_ARRAY: - case T_DOUBLE_ARROW: - - case T_CONST: - case T_PUBLIC: - case T_PROTECTED: - case T_PRIVATE: - case T_ABSTRACT: - case T_STATIC: - case T_VAR: - - case T_INC: - case T_DEC: - case T_SL: - case T_SL_EQUAL: - case T_SR: - case T_SR_EQUAL: - - case T_IS_EQUAL: - case T_IS_IDENTICAL: - case T_IS_GREATER_OR_EQUAL: - case T_IS_SMALLER_OR_EQUAL: - - case T_BOOLEAN_OR: - case T_LOGICAL_OR: - case T_BOOLEAN_AND: - case T_LOGICAL_AND: - case T_LOGICAL_XOR: - case T_MINUS_EQUAL: - case T_PLUS_EQUAL: - case T_MUL_EQUAL: - case T_DIV_EQUAL: - case T_MOD_EQUAL: - case T_XOR_EQUAL: - case T_AND_EQUAL: - case T_OR_EQUAL: - - case T_FUNC_C: - case T_CLASS_C: - case T_LINE: - case T_FILE: - - case T_BOOL_CAST: - case T_INT_CAST: - case T_STRING_CAST: - - /* just go on */ - break; - default: - /* debug unknown tags*/ - error_log(sprintf("unknown tag: %d (%s): %s".PHP_EOL, $token[0], token_name($token[0]), $token[1])); - - break; - } - if (!$ignore) { - $eval .= $token[1]." "; - $ts[] = array("token" => $token[0], "value" => $token[1]); - } - } else { - $ts[] = array("token" => $token, "value" => ''); - - $last = count($ts) - 1; - - switch ($token) { - case '(': - /* walk backwards through the tokens */ - - if ($last >= 4 && - $ts[$last - 1]['token'] == T_STRING && - $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && - $ts[$last - 3]['token'] == ')' ) { - /* func()->method() - * - * we can't know what func() is return, so we can't - * say if the method() exists or not - * - */ - } else if ($last >= 3 && - $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ - $ts[0]['token'] != T_ABSTRACT && /* if we are not in a class definition */ - $ts[1]['token'] != T_CLASS && /* if we are not in a class definition */ - $ts[$last - 1]['token'] == T_STRING && - $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && - $ts[$last - 3]['token'] == T_VARIABLE ) { - - /* $object->method( */ - - /* catch (Exception $e) does not set $e in $GLOBALS[] */ - $in_catch = 0; - - foreach ($ts as $v) { - if ($v['token'] == T_CATCH) { - $in_catch = 1; - } - } - - if (!$in_catch) { - /* $object has to exist and has to be a object */ - $objname = $ts[$last - 3]['value']; - - if (!isset($GLOBALS[ltrim($objname, '$')])) { - throw new Exception(sprintf('Variable \'%s\' is not set', $objname)); - } - $object = $GLOBALS[ltrim($objname, '$')]; - - if (!is_object($object)) { - throw new Exception(sprintf('Variable \'%s\' is not a class', $objname)); - } - - $method = $ts[$last - 1]['value']; - - /* obj */ - - if (!method_exists($object, $method)) { - throw new Exception(sprintf("Variable %s (Class '%s') doesn't have a method named '%s'", - $objname, get_class($object), $method)); - } - } - } else if ($last >= 3 && - $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ - $ts[$last - 1]['token'] == T_VARIABLE && - $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && - $ts[$last - 3]['token'] == T_VARIABLE ) { - - /* $object->$method( */ - - /* $object has to exist and has to be a object */ - $objname = $ts[$last - 3]['value']; - - if (!isset($GLOBALS[ltrim($objname, '$')])) { - throw new Exception(sprintf('Variable \'%s\' is not set', $objname)); - } - $object = $GLOBALS[ltrim($objname, '$')]; - - if (!is_object($object)) { - throw new Exception(sprintf('Variable \'%s\' is not a class', $objname)); - } - - $methodname = $ts[$last - 1]['value']; - - if (!isset($GLOBALS[ltrim($methodname, '$')])) { - throw new Exception(sprintf('Variable \'%s\' is not set', $methodname)); - } - $method = $GLOBALS[ltrim($methodname, '$')]; - - /* obj */ - - if (!method_exists($object, $method)) { - throw new Exception(sprintf("Variable %s (Class '%s') doesn't have a method named '%s'", - $objname, get_class($object), $method)); - } - - } else if ($last >= 6 && - $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ - $ts[$last - 1]['token'] == T_STRING && - $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && - $ts[$last - 3]['token'] == ']' && - /* might be anything as index */ - $ts[$last - 5]['token'] == '[' && - $ts[$last - 6]['token'] == T_VARIABLE ) { - - /* $object[...]->method( */ - - /* $object has to exist and has to be a object */ - $objname = $ts[$last - 6]['value']; - - if (!isset($GLOBALS[ltrim($objname, '$')])) { - throw new Exception(sprintf('Variable \'%s\' is not set', $objname)); - } - $array = $GLOBALS[ltrim($objname, '$')]; - - if (!is_array($array)) { - throw new Exception(sprintf('Variable \'%s\' is not a array', $objname)); - } - - $andx = $ts[$last - 4]['value']; - - if (!isset($array[$andx])) { - throw new Exception(sprintf('%s[\'%s\'] is not set', $objname, $andx)); - } - - $object = $array[$andx]; - - if (!is_object($object)) { - throw new Exception(sprintf('Variable \'%s\' is not a class', $objname)); - } - - $method = $ts[$last - 1]['value']; - - /* obj */ - - if (!method_exists($object, $method)) { - throw new Exception(sprintf("Variable %s (Class '%s') doesn't have a method named '%s'", - $objname, get_class($object), $method)); - } - - } else if ($last >= 3 && - $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ - $ts[$last - 1]['token'] == T_STRING && - $ts[$last - 2]['token'] == T_DOUBLE_COLON && - $ts[$last - 3]['token'] == T_STRING ) { - - /* Class::method() */ - - /* $object has to exist and has to be a object */ - $classname = $ts[$last - 3]['value']; - - if (!class_exists($classname)) { - throw new Exception(sprintf('Class \'%s\' doesn\'t exist', $classname)); - } - - $method = $ts[$last - 1]['value']; - - if (!in_array($method, get_class_methods($classname))) { - throw new Exception(sprintf("Class '%s' doesn't have a method named '%s'", - $classname, $method)); - } - } else if ($last >= 3 && - $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ - $ts[$last - 1]['token'] == T_VARIABLE && - $ts[$last - 2]['token'] == T_DOUBLE_COLON && - $ts[$last - 3]['token'] == T_STRING ) { - - /* $var::method() */ - - /* $object has to exist and has to be a object */ - $classname = $ts[$last - 3]['value']; - - if (!class_exists($classname)) { - throw new Exception(sprintf('Class \'%s\' doesn\'t exist', $classname)); - } - - $methodname = $ts[$last - 1]['value']; - - if (!isset($GLOBALS[ltrim($methodname, '$')])) { - throw new Exception(sprintf('Variable \'%s\' is not set', $methodname)); - } - $method = $GLOBALS[ltrim($methodname, '$')]; - - if (!in_array($method, get_class_methods($classname))) { - throw new Exception(sprintf("Class '%s' doesn't have a method named '%s'", - $classname, $method)); - } - - } else if ($last >= 2 && - $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ - $ts[$last - 1]['token'] == T_STRING && - $ts[$last - 2]['token'] == T_NEW ) { - - /* new Class() */ - - /* don't care about this in a class ... { ... } */ - - $classname = $ts[$last - 1]['value']; - - if (!class_exists($classname)) { - throw new Exception(sprintf('Class \'%s\' doesn\'t exist', $classname)); - } - - $r = new ReflectionClass($classname); - - if ($r->isAbstract()) { - throw new Exception(sprintf("Can't instantiate abstract Class '%s'", $classname)); - } - - if (!$r->isInstantiable()) { - throw new Exception(sprintf('Class \'%s\' can\'t be instantiated. Is the class abstract ?', $classname)); - } - - } else if ($last >= 2 && - $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ - $ts[$last - 1]['token'] == T_STRING && - $ts[$last - 2]['token'] == T_FUNCTION ) { - - /* make sure we are not a in class definition */ - - /* function a() */ - - $func = $ts[$last - 1]['value']; - - if (function_exists($func)) { - throw new Exception(sprintf('Function \'%s\' is already defined', $func)); - } - } else if ($last >= 4 && - $ts[0]['token'] == T_CLASS && - $ts[1]['token'] == T_STRING && - $ts[$last - 1]['token'] == T_STRING && - $ts[$last - 2]['token'] == T_FUNCTION ) { - - /* make sure we are not a in class definition */ - - /* class a { .. function a() ... } */ - - $func = $ts[$last - 1]['value']; - $classname = $ts[1]['value']; - - if (isset($methods[$func])) { - throw new Exception(sprintf("Can't redeclare method '%s' in Class '%s'", $func, $classname)); - } - - $methods[$func] = 1; - - } else if ($last >= 1 && - $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ - $ts[0]['token'] != T_ABSTRACT && /* if we are not in a class definition */ - $ts[1]['token'] != T_CLASS && /* if we are not in a class definition */ - $ts[$last - 1]['token'] == T_STRING ) { - /* func() */ - $funcname = $ts[$last - 1]['value']; - - if (!function_exists($funcname)) { - throw new Exception(sprintf("Function %s() doesn't exist", $funcname)); - } - } else if ($last >= 1 && - $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ - $ts[$last - 1]['token'] == T_VARIABLE ) { - - /* $object has to exist and has to be a object */ - $funcname = $ts[$last - 1]['value']; - - if (!isset($GLOBALS[ltrim($funcname, '$')])) { - throw new Exception(sprintf('Variable \'%s\' is not set', $funcname)); - } - $func = $GLOBALS[ltrim($funcname, '$')]; - - if (!function_exists($func)) { - throw new Exception(sprintf("Function %s() doesn't exist", $func)); - } - - } - - array_push($braces, $token); - break; - case '{': - $need_return = 0; - - if ($last >= 2 && - $ts[$last - 1]['token'] == T_STRING && - $ts[$last - 2]['token'] == T_CLASS ) { - - /* class name { */ - - $classname = $ts[$last - 1]['value']; - - if (class_exists($classname, false)) { - throw new Exception(sprintf("Class '%s' can't be redeclared", $classname)); - } - } else if ($last >= 4 && - $ts[$last - 1]['token'] == T_STRING && - $ts[$last - 2]['token'] == T_EXTENDS && - $ts[$last - 3]['token'] == T_STRING && - $ts[$last - 4]['token'] == T_CLASS ) { - - /* class classname extends classname { */ - - $classname = $ts[$last - 3]['value']; - $extendsname = $ts[$last - 1]['value']; - - if (class_exists($classname, false)) { - throw new Exception(sprintf("Class '%s' can't be redeclared", - $classname)); - } - if (!class_exists($extendsname, true)) { - throw new Exception(sprintf("Can't extend '%s' ... from not existing Class '%s'", - $classname, $extendsname)); - } - } else if ($last >= 4 && - $ts[$last - 1]['token'] == T_STRING && - $ts[$last - 2]['token'] == T_IMPLEMENTS && - $ts[$last - 3]['token'] == T_STRING && - $ts[$last - 4]['token'] == T_CLASS ) { - - /* class name implements interface { */ - - $classname = $ts[$last - 3]['value']; - $implements = $ts[$last - 1]['value']; - - if (class_exists($classname, false)) { - throw new Exception(sprintf("Class '%s' can't be redeclared", - $classname)); - } - if (!interface_exists($implements, false)) { - throw new Exception(sprintf("Can't implement not existing Interface '%s' for Class '%s'", - $implements, $classname)); - } - } - - array_push($braces, $token); - break; - case '}': - $need_return = 0; - case ')': - array_pop($braces); - break; - case '[': - if ($ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ - $ts[0]['token'] != T_ABSTRACT && /* if we are not in a class definition */ - $ts[1]['token'] != T_CLASS && /* if we are not in a class definition */ - $ts[$last - 1]['token'] == T_VARIABLE) { - /* $a[] only works on array and string */ - - /* $object has to exist and has to be a object */ - $objname = $ts[$last - 1]['value']; - - if (!isset($GLOBALS[ltrim($objname, '$')])) { - throw new Exception(sprintf('Variable \'%s\' is not set', $objname)); - } - $obj = $GLOBALS[ltrim($objname, '$')]; - - if (is_object($obj)) { - throw new Exception(sprintf('Objects (%s) don\'t support array access operators', $objname)); - } - } - break; - } - - $eval .= $token; - } - } - - $last = count($ts) - 1; - if ($last >= 2 && - $ts[$last - 0]['token'] == T_STRING && - $ts[$last - 1]['token'] == T_DOUBLE_COLON && - $ts[$last - 2]['token'] == T_STRING ) { - - /* Class::constant */ - - /* $object has to exist and has to be a object */ - $classname = $ts[$last - 2]['value']; - - if (!class_exists($classname)) { - throw new Exception(sprintf('Class \'%s\' doesn\'t exist', $classname)); - } - - $constname = $ts[$last - 0]['value']; - - $c = new ReflectionClass($classname); - if (!$c->hasConstant($constname)) { - throw new Exception(sprintf("Class '%s' doesn't have a constant named '%s'", - $classname, $constname)); - } - } else if ($last == 0 && - $ts[$last - 0]['token'] == T_VARIABLE ) { - - /* $var */ - - $varname = $ts[$last - 0]['value']; - - if (!isset($GLOBALS[ltrim($varname, '$')])) { - throw new Exception(sprintf('Variable \'%s\' is not set', $varname)); - } - } - - - $need_more = (count($braces) > 0) || $open_comment; - - if ($need_more || ';' === $token) { - $need_semicolon = 0; - } - - if ($need_return) { - $eval = "return ".$eval; - } - - /* add a traling ; if necessary */ - if ($need_semicolon) - { - $this->has_semicolon = preg_match('/;\s*$/', $eval); - $eval .= ';'; - } - - if (!$need_more) { - $this->code = $eval; - } - - return $need_more; - } - - /** - * show the prompt and fetch a single line - * - * uses readline() if avaialbe - * - * @return string a input-line - */ - public function readline() { - if (empty($this->code)) print PHP_EOL; - - $prompt = (empty($this->code)) ? '>> ' : '.. '; - - if (count($this->code_buffer) > 0) { - print $prompt; - - $line = array_shift($this->code_buffer); - - print $line.PHP_EOL; - - return $line.PHP_EOL; - } - - if ($this->have_readline) { - $l = readline($prompt); - - readline_add_history($l); - } else { - print $prompt; - - if (is_null($this->stdin)) { - if (false === ($this->stdin = fopen("php://stdin", "r"))) { - return false; - } - } - $l = fgets($this->stdin); - } - return $l; - } - - /** - * get the inline help - * - * @return string the inline help as string - */ - public function cmdHelp($l) { - $o = 'Inline Help:'.PHP_EOL; - - $cmds = PHP_Shell_Commands::getInstance()->getCommands(); - - $help = array(); - foreach ($cmds as $cmd) { - $help[] = sprintf(' >> %s'.PHP_EOL.' %s'.PHP_EOL, - $cmd['command'], - $cmd['description'] - ); - } - - return var_export(implode("\n", $help), 1); - } - - /** - * get the license string - * - * @return string the inline help as string - */ - public function cmdLicense($l) { - $o = << - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -EOF; - - return var_export($o, 1); - } - - /** - * handle the 'quit' command - * - * @return bool false to leave the input() call - * @see input - */ - protected function cmdQuit($l) { - return false; - } - - /** - * handle the input line - * - * read the input and handle the commands of the shell - * - * @return bool false on 'quit' or EOF, true otherwise - */ - public function input() { - $l = $this->readline(); - - /* got EOF ? */ - if (false === $l) return false; - - $l = trim($l); - - if (empty($this->code)) { - $this->verbose = 0; - - $cmds = PHP_Shell_Commands::getInstance()->getCommands(); - - foreach ($cmds as $cmd) { - if (preg_match($cmd['regex'], $l)) { - $obj = $cmd['obj']; - $func = $cmd['method']; - - if (false === ($l = $obj->$func($l))) { - ## quit - return false; - } - - if (is_array($l)) { - $this->code_buffer = $l; - $l = ''; - } - break; - } - } - } - - $this->appendCode($l); - - return true; - } - - /** - * get the code-buffer - * - * @return string the code-buffer - */ - public function getCode() { - return $this->code; - return $code; - } - - /** - * reset the code-buffer - */ - public function resetCode() { - $this->has_semicolon=false; - $this->code = ''; - } - - /** - * append code to the code-buffer - * - * @param string $code input buffer - */ - public function appendCode($code) { - if (strlen($code)) $code .= PHP_EOL; - - $this->code .= $code; - } - - /** - * check if readline support is enabled - * - * @return bool true if enabled, false otherwise - */ - public function hasReadline() { - return $this->have_readline; - } - - /** - * get version of the class - * - * @return string version-string - */ - public function getVersion() { - return $this->version; - } -} - -/** -* a readline completion callback -* -* @param string $str linebuffer -* @param integer $pos position in linebuffer -* @return array list of possible matches -*/ -function __shell_readline_complete($str, $pos) { - $in = readline_info('line_buffer'); - - /** - * parse the line-buffer backwards to see if we have a - * - constant - * - function - * - variable - */ - - $m = array(); - - if (preg_match('#\$([A-Za-z0-9_]+)->#', $in, $a)) { - /* check for $o->... */ - $name = $a[1]; - - if (isset($GLOBALS[$name]) && is_object($GLOBALS[$name])) { - $c = get_class_methods($GLOBALS[$name]); - - foreach ($c as $v) { - $m[] = $v.'('; - } - $c = get_class_vars(get_class($GLOBALS[$name])); - - foreach ($c as $k => $v) { - $m[] = $k; - } - - return $m; - } - } else if (preg_match('#\$([A-Za-z0-9_]+)\[([^\]]+)\]->#', $in, $a)) { - /* check for $o[...]->... */ - $name = $a[1]; - - if (isset($GLOBALS[$name]) && - is_array($GLOBALS[$name]) && - isset($GLOBALS[$name][$a[2]])) { - - $c = get_class_methods($GLOBALS[$name][$a[2]]); - - foreach ($c as $v) { - $m[] = $v.'('; - } - $c = get_class_vars(get_class($GLOBALS[$name][$a[2]])); - - foreach ($c as $k => $v) { - $m[] = $k; - } - return $m; - } - - } else if (preg_match('#([A-Za-z0-9_]+)::#', $in, $a)) { - /* check for Class:: */ - $name = $a[1]; - - if (class_exists($name, false)) { - $c = get_class_methods($name); - - foreach ($c as $v) { - $m[] = sprintf('%s::%s(', $name, $v); - } - - $cl = new ReflectionClass($name); - $c = $cl->getConstants(); - - foreach ($c as $k => $v) { - $m[] = sprintf('%s::%s', $name, $k); - } - - return $m; - } - } else if (preg_match('#\$([a-zA-Z]?[a-zA-Z0-9_]*)$#', $in)) { - $m = array_keys($GLOBALS); - - return $m; - } else if (preg_match('#new #', $in)) { - $c = get_declared_classes(); - - foreach ($c as $v) { - $m[] = $v.'('; - } - - return $m; - } else if (preg_match('#^:set #', $in)) { - foreach (PHP_Shell_Options::getInstance()->getOptions() as $v) { - $m[] = $v; - } - - return $m; - } - - $f = get_defined_functions(); - - foreach ($f['internal'] as $v) { - $m[] = $v.'('; - } - - foreach ($f['user'] as $v) { - $m[] = $v.'('; - } - - $c = get_declared_classes(); - - foreach ($c as $v) { - $m[] = $v.'::'; - } - - $c = get_defined_constants(); - - foreach ($c as $k => $v) { - $m[] = $k; - } - - /* taken from http://de3.php.net/manual/en/reserved.php */ - $m[] = 'abstract'; - $m[] = 'and'; - $m[] = 'array('; - $m[] = 'as'; - $m[] = 'break'; - $m[] = 'case'; - $m[] = 'catch'; - $m[] = 'class'; - $m[] = 'const'; - $m[] = 'continue'; - # $m[] = 'declare'; - $m[] = 'default'; - $m[] = 'die('; - $m[] = 'do'; - $m[] = 'echo('; - $m[] = 'else'; - $m[] = 'elseif'; - $m[] = 'empty('; - # $m[] = 'enddeclare'; - $m[] = 'eval('; - $m[] = 'exception'; - $m[] = 'extends'; - $m[] = 'exit('; - $m[] = 'extends'; - $m[] = 'final'; - $m[] = 'for ('; - $m[] = 'foreach ('; - $m[] = 'function'; - $m[] = 'global'; - $m[] = 'if'; - $m[] = 'implements'; - $m[] = 'include "'; - $m[] = 'include_once "'; - $m[] = 'interface'; - $m[] = 'isset('; - $m[] = 'list('; - $m[] = 'new'; - $m[] = 'or'; - $m[] = 'print('; - $m[] = 'private'; - $m[] = 'protected'; - $m[] = 'public'; - $m[] = 'require "'; - $m[] = 'require_once "'; - $m[] = 'return'; - $m[] = 'static'; - $m[] = 'switch ('; - $m[] = 'throw'; - $m[] = 'try'; - $m[] = 'unset('; - # $m[] = 'use'; - $m[] = 'var'; - $m[] = 'while'; - $m[] = 'xor'; - $m[] = '__FILE__'; - $m[] = '__FUNCTION__'; - $m[] = '__CLASS__'; - $m[] = '__LINE__'; - $m[] = '__METHOD__'; - - # printf("%s ... %s\n", $str, $pos); - return $m; -} - - + + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** +* A interactive PHP Shell +* +* The more I work with other languages like python and ruby I like their way how they +* work on problems. While PHP is very forgiving on errors, it is weak on the debugging +* side. It was missing a simple to use interactive shell for years. Python and Ruby have +* their ipython and iruby shell which give you a direct way to interact with the objects. +* No need to write a script and execute it afterwards. +* +* Starting the Shell: +* +* The package contains a shell wrapper for windows and unix: +*
+* sh>  php-shell.sh
+* win> php-shell
+* 
+* +* Both are calling the wrapper script php -q php-shell-cmd.php +* +* Inline Help +* +*
+* PHP-Shell - Version 0.2.0, with readline() support
+* (c) 2006, Jan Kneschke 
+*
+* >> use '?' to open the inline help
+*
+* >> ?
+* "inline help for the PHP-shell
+*
+*   >> ?
+*     print this help
+*   >> ? 
+*     get the doccomment for a class, method, property or function
+*   >> p 
+*     execute a verbose print (if implemented)
+*   >> quit
+*     leave shell
+* "
+* >> ? PHP_Shell
+* 
+* Alternatives +* +* - http://david.acz.org/phpa/ +* - http://www.hping.org/phpinteractive/ +* - the embedded interactive php-shell: $ php -a +* +* @package PHP +*/ + +/** +* PHP_Shell +* +* a interactive PHP Shell with tab-completion and history +* it can catch FATAL errors before executing the code +* +* Extensions are provided through three side-classes: +* +* - PHP_Shell_Commands +* - PHP_Shell_Options +* - PHP_Shell_Extensions +* +* @package PHP +*/ + +require_once(dirname(__FILE__)."/Shell/Commands.php"); +require_once(dirname(__FILE__)."/Shell/Options.php"); /* for the tab-complete */ + +class PHP_Shell { + /** + * current code-buffer + * @var string + */ + protected $code; + + /** + * set if readline support is enabled + * @var bool + */ + protected $have_readline; + + /** + * current version of the class + * @var string + */ + protected $version = '0.3.1'; + + /** + * + */ + protected $stdin; + + protected $code_buffer; + + public $has_semicolon=false; + + /** + * init the shell and change if readline support is available + */ + public function __construct() { + $this->code = ''; + + $this->stdin = null; + + $this->have_readline = function_exists('readline'); + + if ($this->have_readline) { + readline_completion_function('__shell_readline_complete'); + } + + $this->use_readline = true; + + $cmd = PHP_Shell_Commands::getInstance(); + + $cmd->registerCommand('#^quit$#', $this, 'cmdQuit', 'quit', 'leaves the shell'); + $cmd->registerCommand('#^\?$#', $this, 'cmdHelp', '?', 'show this help'); + $cmd->registerCommand('#^\?\s+license$#', $this, 'cmdLicense', '? license', 'show license of the shell'); + } + + + /** + * parse the PHP code + * + * we parse before we eval() the code to + * - fetch fatal errors before they come up + * - know about where we have to wait for closing braces + * + * @return int 0 if a executable statement is in the code-buffer, non-zero otherwise + */ + public function parse() { + ## remove empty lines + if (trim($this->code) == '') return 1; + + $t = token_get_all('code.' ?>'); + + $need_semicolon = 1; /* do we need a semicolon to complete the statement ? */ + $need_return = 1; /* can we prepend a return to the eval-string ? */ + $open_comment = 0; /* a open multi-line comment */ + $eval = ''; /* code to be eval()'ed later */ + $braces = array(); /* to track if we need more closing braces */ + + $methods = array(); /* to track duplicate methods in a class declaration */ + $ts = array(); /* tokens without whitespaces */ + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + $ignore = 0; + + switch($token[0]) { + case T_WHITESPACE: + case T_OPEN_TAG: + case T_CLOSE_TAG: + $ignore = 1; + break; + case T_FOREACH: + case T_DO: + case T_WHILE: + case T_FOR: + + case T_IF: + case T_RETURN: + + case T_CLASS: + case T_FUNCTION: + case T_INTERFACE: + + case T_PRINT: + case T_ECHO: + + case T_COMMENT: + case T_UNSET: + + case T_INCLUDE: + case T_REQUIRE: + case T_INCLUDE_ONCE: + case T_REQUIRE_ONCE: + case T_TRY: + case T_SWITCH: + case T_DEFAULT: + case T_CASE: + case T_BREAK: + case T_DOC_COMMENT: + $need_return = 0; + break; + case T_EMPTY: + case T_ISSET: + case T_EVAL: + case T_EXIT: + + case T_VARIABLE: + case T_STRING: + case T_NEW: + case T_EXTENDS: + case T_IMPLEMENTS: + case T_OBJECT_OPERATOR: + case T_DOUBLE_COLON: + case T_INSTANCEOF: + + case T_CATCH: + case T_THROW: + + case T_ELSE: + case T_AS: + case T_LNUMBER: + case T_DNUMBER: + case T_CONSTANT_ENCAPSED_STRING: + case T_ENCAPSED_AND_WHITESPACE: + case T_CHARACTER: + case T_ARRAY: + case T_DOUBLE_ARROW: + + case T_CONST: + case T_PUBLIC: + case T_PROTECTED: + case T_PRIVATE: + case T_ABSTRACT: + case T_STATIC: + case T_VAR: + + case T_INC: + case T_DEC: + case T_SL: + case T_SL_EQUAL: + case T_SR: + case T_SR_EQUAL: + + case T_IS_EQUAL: + case T_IS_IDENTICAL: + case T_IS_GREATER_OR_EQUAL: + case T_IS_SMALLER_OR_EQUAL: + + case T_BOOLEAN_OR: + case T_LOGICAL_OR: + case T_BOOLEAN_AND: + case T_LOGICAL_AND: + case T_LOGICAL_XOR: + case T_MINUS_EQUAL: + case T_PLUS_EQUAL: + case T_MUL_EQUAL: + case T_DIV_EQUAL: + case T_MOD_EQUAL: + case T_XOR_EQUAL: + case T_AND_EQUAL: + case T_OR_EQUAL: + + case T_FUNC_C: + case T_CLASS_C: + case T_LINE: + case T_FILE: + + case T_BOOL_CAST: + case T_INT_CAST: + case T_STRING_CAST: + + /* just go on */ + break; + default: + /* debug unknown tags*/ + error_log(sprintf("unknown tag: %d (%s): %s".PHP_EOL, $token[0], token_name($token[0]), $token[1])); + + break; + } + if (!$ignore) { + $eval .= $token[1]." "; + $ts[] = array("token" => $token[0], "value" => $token[1]); + } + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + /* walk backwards through the tokens */ + + if ($last >= 4 && + $ts[$last - 1]['token'] == T_STRING && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == ')' ) { + /* func()->method() + * + * we can't know what func() is return, so we can't + * say if the method() exists or not + * + */ + } else if ($last >= 3 && + $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ + $ts[0]['token'] != T_ABSTRACT && /* if we are not in a class definition */ + $ts[1]['token'] != T_CLASS && /* if we are not in a class definition */ + $ts[$last - 1]['token'] == T_STRING && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + /* $object->method( */ + + /* catch (Exception $e) does not set $e in $GLOBALS[] */ + $in_catch = 0; + + foreach ($ts as $v) { + if ($v['token'] == T_CATCH) { + $in_catch = 1; + } + } + + if (!$in_catch) { + /* $object has to exist and has to be a object */ + $objname = $ts[$last - 3]['value']; + + if (!isset($GLOBALS[ltrim($objname, '$')])) { + throw new Exception(sprintf('Variable \'%s\' is not set', $objname)); + } + $object = $GLOBALS[ltrim($objname, '$')]; + + if (!is_object($object)) { + throw new Exception(sprintf('Variable \'%s\' is not a class', $objname)); + } + + $method = $ts[$last - 1]['value']; + + /* obj */ + + if (!method_exists($object, $method)) { + throw new Exception(sprintf("Variable %s (Class '%s') doesn't have a method named '%s'", + $objname, get_class($object), $method)); + } + } + } else if ($last >= 3 && + $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ + $ts[$last - 1]['token'] == T_VARIABLE && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + /* $object->$method( */ + + /* $object has to exist and has to be a object */ + $objname = $ts[$last - 3]['value']; + + if (!isset($GLOBALS[ltrim($objname, '$')])) { + throw new Exception(sprintf('Variable \'%s\' is not set', $objname)); + } + $object = $GLOBALS[ltrim($objname, '$')]; + + if (!is_object($object)) { + throw new Exception(sprintf('Variable \'%s\' is not a class', $objname)); + } + + $methodname = $ts[$last - 1]['value']; + + if (!isset($GLOBALS[ltrim($methodname, '$')])) { + throw new Exception(sprintf('Variable \'%s\' is not set', $methodname)); + } + $method = $GLOBALS[ltrim($methodname, '$')]; + + /* obj */ + + if (!method_exists($object, $method)) { + throw new Exception(sprintf("Variable %s (Class '%s') doesn't have a method named '%s'", + $objname, get_class($object), $method)); + } + + } else if ($last >= 6 && + $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ + $ts[$last - 1]['token'] == T_STRING && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == ']' && + /* might be anything as index */ + $ts[$last - 5]['token'] == '[' && + $ts[$last - 6]['token'] == T_VARIABLE ) { + + /* $object[...]->method( */ + + /* $object has to exist and has to be a object */ + $objname = $ts[$last - 6]['value']; + + if (!isset($GLOBALS[ltrim($objname, '$')])) { + throw new Exception(sprintf('Variable \'%s\' is not set', $objname)); + } + $array = $GLOBALS[ltrim($objname, '$')]; + + if (!is_array($array)) { + throw new Exception(sprintf('Variable \'%s\' is not a array', $objname)); + } + + $andx = $ts[$last - 4]['value']; + + if (!isset($array[$andx])) { + throw new Exception(sprintf('%s[\'%s\'] is not set', $objname, $andx)); + } + + $object = $array[$andx]; + + if (!is_object($object)) { + throw new Exception(sprintf('Variable \'%s\' is not a class', $objname)); + } + + $method = $ts[$last - 1]['value']; + + /* obj */ + + if (!method_exists($object, $method)) { + throw new Exception(sprintf("Variable %s (Class '%s') doesn't have a method named '%s'", + $objname, get_class($object), $method)); + } + + } else if ($last >= 3 && + $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ + $ts[$last - 1]['token'] == T_STRING && + $ts[$last - 2]['token'] == T_DOUBLE_COLON && + $ts[$last - 3]['token'] == T_STRING ) { + + /* Class::method() */ + + /* $object has to exist and has to be a object */ + $classname = $ts[$last - 3]['value']; + + if (!class_exists($classname)) { + throw new Exception(sprintf('Class \'%s\' doesn\'t exist', $classname)); + } + + $method = $ts[$last - 1]['value']; + + if (!in_array($method, get_class_methods($classname))) { + throw new Exception(sprintf("Class '%s' doesn't have a method named '%s'", + $classname, $method)); + } + } else if ($last >= 3 && + $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ + $ts[$last - 1]['token'] == T_VARIABLE && + $ts[$last - 2]['token'] == T_DOUBLE_COLON && + $ts[$last - 3]['token'] == T_STRING ) { + + /* $var::method() */ + + /* $object has to exist and has to be a object */ + $classname = $ts[$last - 3]['value']; + + if (!class_exists($classname)) { + throw new Exception(sprintf('Class \'%s\' doesn\'t exist', $classname)); + } + + $methodname = $ts[$last - 1]['value']; + + if (!isset($GLOBALS[ltrim($methodname, '$')])) { + throw new Exception(sprintf('Variable \'%s\' is not set', $methodname)); + } + $method = $GLOBALS[ltrim($methodname, '$')]; + + if (!in_array($method, get_class_methods($classname))) { + throw new Exception(sprintf("Class '%s' doesn't have a method named '%s'", + $classname, $method)); + } + + } else if ($last >= 2 && + $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ + $ts[$last - 1]['token'] == T_STRING && + $ts[$last - 2]['token'] == T_NEW ) { + + /* new Class() */ + + /* don't care about this in a class ... { ... } */ + + $classname = $ts[$last - 1]['value']; + + if (!class_exists($classname)) { + throw new Exception(sprintf('Class \'%s\' doesn\'t exist', $classname)); + } + + $r = new ReflectionClass($classname); + + if ($r->isAbstract()) { + throw new Exception(sprintf("Can't instantiate abstract Class '%s'", $classname)); + } + + if (!$r->isInstantiable()) { + throw new Exception(sprintf('Class \'%s\' can\'t be instantiated. Is the class abstract ?', $classname)); + } + + } else if ($last >= 2 && + $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ + $ts[$last - 1]['token'] == T_STRING && + $ts[$last - 2]['token'] == T_FUNCTION ) { + + /* make sure we are not a in class definition */ + + /* function a() */ + + $func = $ts[$last - 1]['value']; + + if (function_exists($func)) { + throw new Exception(sprintf('Function \'%s\' is already defined', $func)); + } + } else if ($last >= 4 && + $ts[0]['token'] == T_CLASS && + $ts[1]['token'] == T_STRING && + $ts[$last - 1]['token'] == T_STRING && + $ts[$last - 2]['token'] == T_FUNCTION ) { + + /* make sure we are not a in class definition */ + + /* class a { .. function a() ... } */ + + $func = $ts[$last - 1]['value']; + $classname = $ts[1]['value']; + + if (isset($methods[$func])) { + throw new Exception(sprintf("Can't redeclare method '%s' in Class '%s'", $func, $classname)); + } + + $methods[$func] = 1; + + } else if ($last >= 1 && + $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ + $ts[0]['token'] != T_ABSTRACT && /* if we are not in a class definition */ + $ts[1]['token'] != T_CLASS && /* if we are not in a class definition */ + $ts[$last - 1]['token'] == T_STRING ) { + /* func() */ + $funcname = $ts[$last - 1]['value']; + + if (!function_exists($funcname)) { + throw new Exception(sprintf("Function %s() doesn't exist", $funcname)); + } + } else if ($last >= 1 && + $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ + $ts[$last - 1]['token'] == T_VARIABLE ) { + + /* $object has to exist and has to be a object */ + $funcname = $ts[$last - 1]['value']; + + if (!isset($GLOBALS[ltrim($funcname, '$')])) { + throw new Exception(sprintf('Variable \'%s\' is not set', $funcname)); + } + $func = $GLOBALS[ltrim($funcname, '$')]; + + if (!function_exists($func)) { + throw new Exception(sprintf("Function %s() doesn't exist", $func)); + } + + } + + array_push($braces, $token); + break; + case '{': + $need_return = 0; + + if ($last >= 2 && + $ts[$last - 1]['token'] == T_STRING && + $ts[$last - 2]['token'] == T_CLASS ) { + + /* class name { */ + + $classname = $ts[$last - 1]['value']; + + if (class_exists($classname, false)) { + throw new Exception(sprintf("Class '%s' can't be redeclared", $classname)); + } + } else if ($last >= 4 && + $ts[$last - 1]['token'] == T_STRING && + $ts[$last - 2]['token'] == T_EXTENDS && + $ts[$last - 3]['token'] == T_STRING && + $ts[$last - 4]['token'] == T_CLASS ) { + + /* class classname extends classname { */ + + $classname = $ts[$last - 3]['value']; + $extendsname = $ts[$last - 1]['value']; + + if (class_exists($classname, false)) { + throw new Exception(sprintf("Class '%s' can't be redeclared", + $classname)); + } + if (!class_exists($extendsname, true)) { + throw new Exception(sprintf("Can't extend '%s' ... from not existing Class '%s'", + $classname, $extendsname)); + } + } else if ($last >= 4 && + $ts[$last - 1]['token'] == T_STRING && + $ts[$last - 2]['token'] == T_IMPLEMENTS && + $ts[$last - 3]['token'] == T_STRING && + $ts[$last - 4]['token'] == T_CLASS ) { + + /* class name implements interface { */ + + $classname = $ts[$last - 3]['value']; + $implements = $ts[$last - 1]['value']; + + if (class_exists($classname, false)) { + throw new Exception(sprintf("Class '%s' can't be redeclared", + $classname)); + } + if (!interface_exists($implements, false)) { + throw new Exception(sprintf("Can't implement not existing Interface '%s' for Class '%s'", + $implements, $classname)); + } + } + + array_push($braces, $token); + break; + case '}': + $need_return = 0; + case ')': + array_pop($braces); + break; + case '[': + if ($ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ + $ts[0]['token'] != T_ABSTRACT && /* if we are not in a class definition */ + $ts[1]['token'] != T_CLASS && /* if we are not in a class definition */ + $ts[$last - 1]['token'] == T_VARIABLE) { + /* $a[] only works on array and string */ + + /* $object has to exist and has to be a object */ + $objname = $ts[$last - 1]['value']; + + if (!isset($GLOBALS[ltrim($objname, '$')])) { + throw new Exception(sprintf('Variable \'%s\' is not set', $objname)); + } + $obj = $GLOBALS[ltrim($objname, '$')]; + + if (is_object($obj)) { + throw new Exception(sprintf('Objects (%s) don\'t support array access operators', $objname)); + } + } + break; + } + + $eval .= $token; + } + } + + $last = count($ts) - 1; + if ($last >= 2 && + $ts[$last - 0]['token'] == T_STRING && + $ts[$last - 1]['token'] == T_DOUBLE_COLON && + $ts[$last - 2]['token'] == T_STRING ) { + + /* Class::constant */ + + /* $object has to exist and has to be a object */ + $classname = $ts[$last - 2]['value']; + + if (!class_exists($classname)) { + throw new Exception(sprintf('Class \'%s\' doesn\'t exist', $classname)); + } + + $constname = $ts[$last - 0]['value']; + + $c = new ReflectionClass($classname); + if (!$c->hasConstant($constname)) { + throw new Exception(sprintf("Class '%s' doesn't have a constant named '%s'", + $classname, $constname)); + } + } else if ($last == 0 && + $ts[$last - 0]['token'] == T_VARIABLE ) { + + /* $var */ + + $varname = $ts[$last - 0]['value']; + + if (!isset($GLOBALS[ltrim($varname, '$')])) { + throw new Exception(sprintf('Variable \'%s\' is not set', $varname)); + } + } + + + $need_more = (count($braces) > 0) || $open_comment; + + if ($need_more || ';' === $token) { + $need_semicolon = 0; + } + + if ($need_return) { + $eval = "return ".$eval; + } + + /* add a traling ; if necessary */ + if ($need_semicolon) + { + $this->has_semicolon = preg_match('/;\s*$/', $eval); + $eval .= ';'; + } + + if (!$need_more) { + $this->code = $eval; + } + + return $need_more; + } + + /** + * show the prompt and fetch a single line + * + * uses readline() if avaialbe + * + * @return string a input-line + */ + public function readline() { + if (empty($this->code)) print PHP_EOL; + + $prompt = (empty($this->code)) ? '>> ' : '.. '; + + if (count($this->code_buffer) > 0) { + print $prompt; + + $line = array_shift($this->code_buffer); + + print $line.PHP_EOL; + + return $line.PHP_EOL; + } + + if ($this->have_readline) { + $l = readline($prompt); + + readline_add_history($l); + } else { + print $prompt; + + if (is_null($this->stdin)) { + if (false === ($this->stdin = fopen("php://stdin", "r"))) { + return false; + } + } + $l = fgets($this->stdin); + } + return $l; + } + + /** + * get the inline help + * + * @return string the inline help as string + */ + public function cmdHelp($l) { + $o = 'Inline Help:'.PHP_EOL; + + $cmds = PHP_Shell_Commands::getInstance()->getCommands(); + + $help = array(); + foreach ($cmds as $cmd) { + $help[] = sprintf(' >> %s'.PHP_EOL.' %s'.PHP_EOL, + $cmd['command'], + $cmd['description'] + ); + } + + return var_export(implode("\n", $help), 1); + } + + /** + * get the license string + * + * @return string the inline help as string + */ + public function cmdLicense($l) { + $o = << + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +EOF; + + return var_export($o, 1); + } + + /** + * handle the 'quit' command + * + * @return bool false to leave the input() call + * @see input + */ + protected function cmdQuit($l) { + return false; + } + + /** + * handle the input line + * + * read the input and handle the commands of the shell + * + * @return bool false on 'quit' or EOF, true otherwise + */ + public function input() { + $l = $this->readline(); + + /* got EOF ? */ + if (false === $l) return false; + + $l = trim($l); + + if (empty($this->code)) { + $this->verbose = 0; + + $cmds = PHP_Shell_Commands::getInstance()->getCommands(); + + foreach ($cmds as $cmd) { + if (preg_match($cmd['regex'], $l)) { + $obj = $cmd['obj']; + $func = $cmd['method']; + + if (false === ($l = $obj->$func($l))) { + ## quit + return false; + } + + if (is_array($l)) { + $this->code_buffer = $l; + $l = ''; + } + break; + } + } + } + + $this->appendCode($l); + + return true; + } + + /** + * get the code-buffer + * + * @return string the code-buffer + */ + public function getCode() { + return $this->code; + return $code; + } + + /** + * reset the code-buffer + */ + public function resetCode() { + $this->has_semicolon=false; + $this->code = ''; + } + + /** + * append code to the code-buffer + * + * @param string $code input buffer + */ + public function appendCode($code) { + if (strlen($code)) $code .= PHP_EOL; + + $this->code .= $code; + } + + /** + * check if readline support is enabled + * + * @return bool true if enabled, false otherwise + */ + public function hasReadline() { + return $this->have_readline; + } + + /** + * get version of the class + * + * @return string version-string + */ + public function getVersion() { + return $this->version; + } +} + +/** +* a readline completion callback +* +* @param string $str linebuffer +* @param integer $pos position in linebuffer +* @return array list of possible matches +*/ +function __shell_readline_complete($str, $pos) { + $in = readline_info('line_buffer'); + + /** + * parse the line-buffer backwards to see if we have a + * - constant + * - function + * - variable + */ + + $m = array(); + + if (preg_match('#\$([A-Za-z0-9_]+)->#', $in, $a)) { + /* check for $o->... */ + $name = $a[1]; + + if (isset($GLOBALS[$name]) && is_object($GLOBALS[$name])) { + $c = get_class_methods($GLOBALS[$name]); + + foreach ($c as $v) { + $m[] = $v.'('; + } + $c = get_class_vars(get_class($GLOBALS[$name])); + + foreach ($c as $k => $v) { + $m[] = $k; + } + + return $m; + } + } else if (preg_match('#\$([A-Za-z0-9_]+)\[([^\]]+)\]->#', $in, $a)) { + /* check for $o[...]->... */ + $name = $a[1]; + + if (isset($GLOBALS[$name]) && + is_array($GLOBALS[$name]) && + isset($GLOBALS[$name][$a[2]])) { + + $c = get_class_methods($GLOBALS[$name][$a[2]]); + + foreach ($c as $v) { + $m[] = $v.'('; + } + $c = get_class_vars(get_class($GLOBALS[$name][$a[2]])); + + foreach ($c as $k => $v) { + $m[] = $k; + } + return $m; + } + + } else if (preg_match('#([A-Za-z0-9_]+)::#', $in, $a)) { + /* check for Class:: */ + $name = $a[1]; + + if (class_exists($name, false)) { + $c = get_class_methods($name); + + foreach ($c as $v) { + $m[] = sprintf('%s::%s(', $name, $v); + } + + $cl = new ReflectionClass($name); + $c = $cl->getConstants(); + + foreach ($c as $k => $v) { + $m[] = sprintf('%s::%s', $name, $k); + } + + return $m; + } + } else if (preg_match('#\$([a-zA-Z]?[a-zA-Z0-9_]*)$#', $in)) { + $m = array_keys($GLOBALS); + + return $m; + } else if (preg_match('#new #', $in)) { + $c = get_declared_classes(); + + foreach ($c as $v) { + $m[] = $v.'('; + } + + return $m; + } else if (preg_match('#^:set #', $in)) { + foreach (PHP_Shell_Options::getInstance()->getOptions() as $v) { + $m[] = $v; + } + + return $m; + } + + $f = get_defined_functions(); + + foreach ($f['internal'] as $v) { + $m[] = $v.'('; + } + + foreach ($f['user'] as $v) { + $m[] = $v.'('; + } + + $c = get_declared_classes(); + + foreach ($c as $v) { + $m[] = $v.'::'; + } + + $c = get_defined_constants(); + + foreach ($c as $k => $v) { + $m[] = $k; + } + + /* taken from http://de3.php.net/manual/en/reserved.php */ + $m[] = 'abstract'; + $m[] = 'and'; + $m[] = 'array('; + $m[] = 'as'; + $m[] = 'break'; + $m[] = 'case'; + $m[] = 'catch'; + $m[] = 'class'; + $m[] = 'const'; + $m[] = 'continue'; + # $m[] = 'declare'; + $m[] = 'default'; + $m[] = 'die('; + $m[] = 'do'; + $m[] = 'echo('; + $m[] = 'else'; + $m[] = 'elseif'; + $m[] = 'empty('; + # $m[] = 'enddeclare'; + $m[] = 'eval('; + $m[] = 'exception'; + $m[] = 'extends'; + $m[] = 'exit('; + $m[] = 'extends'; + $m[] = 'final'; + $m[] = 'for ('; + $m[] = 'foreach ('; + $m[] = 'function'; + $m[] = 'global'; + $m[] = 'if'; + $m[] = 'implements'; + $m[] = 'include "'; + $m[] = 'include_once "'; + $m[] = 'interface'; + $m[] = 'isset('; + $m[] = 'list('; + $m[] = 'new'; + $m[] = 'or'; + $m[] = 'print('; + $m[] = 'private'; + $m[] = 'protected'; + $m[] = 'public'; + $m[] = 'require "'; + $m[] = 'require_once "'; + $m[] = 'return'; + $m[] = 'static'; + $m[] = 'switch ('; + $m[] = 'throw'; + $m[] = 'try'; + $m[] = 'unset('; + # $m[] = 'use'; + $m[] = 'var'; + $m[] = 'while'; + $m[] = 'xor'; + $m[] = '__FILE__'; + $m[] = '__FUNCTION__'; + $m[] = '__CLASS__'; + $m[] = '__LINE__'; + $m[] = '__METHOD__'; + + # printf("%s ... %s\n", $str, $pos); + return $m; +} + + diff --git a/framework/3rdParty/PhpShell/php-shell-init.php b/framework/3rdParty/PhpShell/php-shell-init.php index 20c6af75..6ae8e8fe 100644 --- a/framework/3rdParty/PhpShell/php-shell-init.php +++ b/framework/3rdParty/PhpShell/php-shell-init.php @@ -1,88 +1,88 @@ -registerExtensions(array( - "options" => PHP_Shell_Options::getInstance(), /* the :set command */ - - "autoload" => new PHP_Shell_Extensions_Autoload(), - "autoload_debug" => new PHP_Shell_Extensions_AutoloadDebug(), - "colour" => new PHP_Shell_Extensions_Colour(), - "exectime" => new PHP_Shell_Extensions_ExecutionTime(), - "inlinehelp" => new PHP_Shell_Extensions_InlineHelp(), - "verboseprint" => new PHP_Shell_Extensions_VerbosePrint() - // "loadscript" => new PHP_Shell_Extensions_LoadScript() -)); - +registerExtensions(array( + "options" => PHP_Shell_Options::getInstance(), /* the :set command */ + + "autoload" => new PHP_Shell_Extensions_Autoload(), + "autoload_debug" => new PHP_Shell_Extensions_AutoloadDebug(), + "colour" => new PHP_Shell_Extensions_Colour(), + "exectime" => new PHP_Shell_Extensions_ExecutionTime(), + "inlinehelp" => new PHP_Shell_Extensions_InlineHelp(), + "verboseprint" => new PHP_Shell_Extensions_VerbosePrint() + // "loadscript" => new PHP_Shell_Extensions_LoadScript() +)); + ?> \ No newline at end of file diff --git a/framework/3rdParty/SafeHtml/HTMLSax3.php b/framework/3rdParty/SafeHtml/HTMLSax3.php index 1be7aede..80d166e9 100644 --- a/framework/3rdParty/SafeHtml/HTMLSax3.php +++ b/framework/3rdParty/SafeHtml/HTMLSax3.php @@ -1,695 +1,695 @@ - Original port from Python | -// | Authors: Harry Fuecks Port to PEAR + more | -// | Authors: Many @ Sitepointforums Advanced PHP Forums | -// +----------------------------------------------------------------------+ -// -// $Id$ -// -/** -* Main parser components -* @package System.Security.SafeHtml -* @version $Id$ -*/ -/** -* Required classes -*/ - -require_once(dirname(__FILE__).'/HTMLSax3/States.php'); -require_once(dirname(__FILE__).'/HTMLSax3/Decorators.php'); - -/** -* Base State Parser -* @package System.Security.SafeHtml -* @access protected -* @abstract -*/ -class TSax3_StateParser { - /** - * Instance of user front end class to be passed to callbacks - * @var TSax3 - * @access private - */ - public $htmlsax; - /** - * User defined object for handling elements - * @var object - * @access private - */ - public $handler_object_element; - /** - * User defined open tag handler method - * @var string - * @access private - */ - public $handler_method_opening; - /** - * User defined close tag handler method - * @var string - * @access private - */ - public $handler_method_closing; - /** - * User defined object for handling data in elements - * @var object - * @access private - */ - public $handler_object_data; - /** - * User defined data handler method - * @var string - * @access private - */ - public $handler_method_data; - /** - * User defined object for handling processing instructions - * @var object - * @access private - */ - public $handler_object_pi; - /** - * User defined processing instruction handler method - * @var string - * @access private - */ - public $handler_method_pi; - /** - * User defined object for handling JSP/ASP tags - * @var object - * @access private - */ - public $handler_object_jasp; - /** - * User defined JSP/ASP handler method - * @var string - * @access private - */ - public $handler_method_jasp; - /** - * User defined object for handling XML escapes - * @var object - * @access private - */ - public $handler_object_escape; - /** - * User defined XML escape handler method - * @var string - * @access private - */ - public $handler_method_escape; - /** - * User defined handler object or NullHandler - * @var object - * @access private - */ - public $handler_default; - /** - * Parser options determining parsing behavior - * @var array - * @access private - */ - protected $parser_options = array(); - /** - * XML document being parsed - * @var string - * @access private - */ - protected $rawtext; - /** - * Position in XML document relative to start (0) - * @var int - * @access private - */ - protected $position; - /** - * Length of the XML document in characters - * @var int - * @access private - */ - protected $length; - /** - * Array of state objects - * @var array - * @access private - */ - protected $State = array(); - - const TSAX3_STATE_STOP = 0; - const TSAX3_STATE_START = 1; - const TSAX3_STATE_TAG = 2; - const TSAX3_STATE_OPENING_TAG = 3; - const TSAX3_STATE_CLOSING_TAG = 4; - const TSAX3_STATE_ESCAPE = 6; - const TSAX3_STATE_JASP = 7; - const TSAX3_STATE_PI = 8; - - /** - * Constructs TSax3_StateParser setting up states - * @var TSax3 instance of user front end class - * @access protected - */ - protected function __construct($htmlsax) { - $this->htmlsax = $htmlsax; - $this->State[self::TSAX3_STATE_START] = new TSax3_StartingState(); - - $this->State[self::TSAX3_STATE_CLOSING_TAG] = new TSax3_ClosingTagState(); - $this->State[self::TSAX3_STATE_TAG] = new TSax3_TagState(); - $this->State[self::TSAX3_STATE_OPENING_TAG] = new TSax3_OpeningTagState(); - - $this->State[self::TSAX3_STATE_PI] = new TSax3_PiState(); - $this->State[self::TSAX3_STATE_JASP] = new TSax3_JaspState(); - $this->State[self::TSAX3_STATE_ESCAPE] = new TSax3_EscapeState(); - } - - /** - * Moves the position back one character - * @access protected - * @return void - */ - function unscanCharacter() { - $this->position -= 1; - } - - /** - * Moves the position forward one character - * @access protected - * @return void - */ - function ignoreCharacter() { - $this->position += 1; - } - - /** - * Returns the next character from the XML document or void if at end - * @access protected - * @return mixed - */ - function scanCharacter() { - if ($this->position < $this->length) { - return $this->rawtext{$this->position++}; - } - } - - /** - * Returns a string from the current position to the next occurance - * of the supplied string - * @param string string to search until - * @access protected - * @return string - */ - function scanUntilString($string) { - $start = $this->position; - $this->position = strpos($this->rawtext, $string, $start); - if ($this->position === FALSE) { - $this->position = $this->length; - } - return substr($this->rawtext, $start, $this->position - $start); - } - - /** - * Returns a string from the current position until the first instance of - * one of the characters in the supplied string argument - * @param string string to search until - * @access protected - * @return string - * @abstract - */ - function scanUntilCharacters($string) {} - - /** - * Moves the position forward past any whitespace characters - * @access protected - * @return void - * @abstract - */ - function ignoreWhitespace() {} - - /** - * Begins the parsing operation, setting up any decorators, depending on - * parse options invoking _parse() to execute parsing - * @param string XML document to parse - * @access protected - * @return void - */ - function parse($data) { - if ($this->parser_options['XML_OPTION_TRIM_DATA_NODES']==1) { - $decorator = new TSax3_Trim( - $this->handler_object_data, - $this->handler_method_data); - $this->handler_object_data =& $decorator; - $this->handler_method_data = 'trimData'; - } - if ($this->parser_options['XML_OPTION_CASE_FOLDING']==1) { - $open_decor = new TSax3_CaseFolding( - $this->handler_object_element, - $this->handler_method_opening, - $this->handler_method_closing); - $this->handler_object_element =& $open_decor; - $this->handler_method_opening ='foldOpen'; - $this->handler_method_closing ='foldClose'; - } - if ($this->parser_options['XML_OPTION_LINEFEED_BREAK']==1) { - $decorator = new TSax3_Linefeed( - $this->handler_object_data, - $this->handler_method_data); - $this->handler_object_data =& $decorator; - $this->handler_method_data = 'breakData'; - } - if ($this->parser_options['XML_OPTION_TAB_BREAK']==1) { - $decorator = new TSax3_Tab( - $this->handler_object_data, - $this->handler_method_data); - $this->handler_object_data =& $decorator; - $this->handler_method_data = 'breakData'; - } - if ($this->parser_options['XML_OPTION_ENTITIES_UNPARSED']==1) { - $decorator = new TSax3_Entities_Unparsed( - $this->handler_object_data, - $this->handler_method_data); - $this->handler_object_data =& $decorator; - $this->handler_method_data = 'breakData'; - } - if ($this->parser_options['XML_OPTION_ENTITIES_PARSED']==1) { - $decorator = new TSax3_Entities_Parsed( - $this->handler_object_data, - $this->handler_method_data); - $this->handler_object_data =& $decorator; - $this->handler_method_data = 'breakData'; - } - // Note switched on by default - if ($this->parser_options['XML_OPTION_STRIP_ESCAPES']==1) { - $decorator = new TSax3_Escape_Stripper( - $this->handler_object_escape, - $this->handler_method_escape); - $this->handler_object_escape =& $decorator; - $this->handler_method_escape = 'strip'; - } - $this->rawtext = $data; - $this->length = strlen($data); - $this->position = 0; - $this->_parse(); - } - - /** - * Performs the parsing itself, delegating calls to a specific parser - * state - * @param constant state object to parse with - * @access protected - * @return void - */ - function _parse($state = self::TSAX3_STATE_START) { - do { - $state = $this->State[$state]->parse($this); - } while ($state != self::TSAX3_STATE_STOP && - $this->position < $this->length); - } -} - -/** -* Parser for PHP Versions below 4.3.0. Uses a slower parsing mechanism than -* the equivalent PHP 4.3.0+ subclass of StateParser -* @package System.Security.SafeHtml -* @access protected -* @see TSax3_StateParser_Gtet430 -*/ -class TSax3_StateParser_Lt430 extends TSax3_StateParser { - /** - * Constructs TSax3_StateParser_Lt430 defining available - * parser options - * @var TSax3 instance of user front end class - * @access protected - */ - function __construct(& $htmlsax) { - parent::__construct($htmlsax); - $this->parser_options['XML_OPTION_TRIM_DATA_NODES'] = 0; - $this->parser_options['XML_OPTION_CASE_FOLDING'] = 0; - $this->parser_options['XML_OPTION_LINEFEED_BREAK'] = 0; - $this->parser_options['XML_OPTION_TAB_BREAK'] = 0; - $this->parser_options['XML_OPTION_ENTITIES_PARSED'] = 0; - $this->parser_options['XML_OPTION_ENTITIES_UNPARSED'] = 0; - $this->parser_options['XML_OPTION_STRIP_ESCAPES'] = 0; - //var_dump($this->parser_options); - } - - /** - * Returns a string from the current position until the first instance of - * one of the characters in the supplied string argument - * @param string string to search until - * @access protected - * @return string - */ - function scanUntilCharacters($string) { - $startpos = $this->position; - while ($this->position < $this->length && strpos($string, $this->rawtext{$this->position}) === FALSE) { - $this->position++; - } - return substr($this->rawtext, $startpos, $this->position - $startpos); - } - - /** - * Moves the position forward past any whitespace characters - * @access protected - * @return void - */ - function ignoreWhitespace() { - while ($this->position < $this->length && - strpos(" \n\r\t", $this->rawtext{$this->position}) !== FALSE) { - $this->position++; - } - } - - /** - * Begins the parsing operation, setting up the unparsed XML entities - * decorator if necessary then delegating further work to parent - * @param string XML document to parse - * @access protected - * @return void - */ - function parse($data) { - parent::parse($data); - } -} - -/** -* Parser for PHP Versions equal to or greater than 4.3.0. Uses a faster -* parsing mechanism than the equivalent PHP < 4.3.0 subclass of StateParser -* @package System.Security.SafeHtml -* @access protected -* @see TSax3_StateParser_Lt430 -*/ -class TSax3_StateParser_Gtet430 extends TSax3_StateParser { - /** - * Constructs TSax3_StateParser_Gtet430 defining available - * parser options - * @var TSax3 instance of user front end class - * @access protected - */ - function __construct(& $htmlsax) { - parent::__construct($htmlsax); - $this->parser_options['XML_OPTION_TRIM_DATA_NODES'] = 0; - $this->parser_options['XML_OPTION_CASE_FOLDING'] = 0; - $this->parser_options['XML_OPTION_LINEFEED_BREAK'] = 0; - $this->parser_options['XML_OPTION_TAB_BREAK'] = 0; - $this->parser_options['XML_OPTION_ENTITIES_PARSED'] = 0; - $this->parser_options['XML_OPTION_ENTITIES_UNPARSED'] = 0; - $this->parser_options['XML_OPTION_STRIP_ESCAPES'] = 0; - } - /** - * Returns a string from the current position until the first instance of - * one of the characters in the supplied string argument. - * @param string string to search until - * @access protected - * @return string - */ - function scanUntilCharacters($string) { - $startpos = $this->position; - $length = strcspn($this->rawtext, $string, $startpos); - $this->position += $length; - return substr($this->rawtext, $startpos, $length); - } - - /** - * Moves the position forward past any whitespace characters - * @access protected - * @return void - */ - function ignoreWhitespace() { - $this->position += strspn($this->rawtext, " \n\r\t", $this->position); - } - - /** - * Begins the parsing operation, setting up the parsed and unparsed - * XML entity decorators if necessary then delegating further work - * to parent - * @param string XML document to parse - * @access protected - * @return void - */ - function parse($data) { - parent::parse($data); - } -} - -/** -* Default NullHandler for methods which were not set by user -* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_NullHandler { - /** - * Generic handler method which does nothing - * @access protected - * @return void - */ - function DoNothing() { - } -} - -/** -* User interface class. All user calls should only be made to this class -* @package System.Security.SafeHtml -* @access public -*/ -class TSax3 { - /** - * Instance of concrete subclass of TSax3_StateParser - * @var TSax3_StateParser - * @access private - */ - private $state_parser; - - /** - * Constructs TSax3 selecting concrete StateParser subclass - * depending on PHP version being used as well as setting the default - * NullHandler for all callbacks
- * Example: - *
-    * $myHandler = & new MyHandler();
-    * $parser = new TSax3();
-    * $parser->set_object($myHandler);
-    * $parser->set_option('XML_OPTION_CASE_FOLDING');
-    * $parser->set_element_handler('myOpenHandler','myCloseHandler');
-    * $parser->set_data_handler('myDataHandler');
-    * $parser->parser($xml);
-    * 
- * @access public - */ - function __construct() { - if (version_compare(phpversion(), '4.3', 'ge')) { - $this->state_parser = new TSax3_StateParser_Gtet430($this); - } else { - $this->state_parser = new TSax3_StateParser_Lt430($this); - } - $nullhandler = new TSax3_NullHandler(); - $this->set_object($nullhandler); - $this->set_element_handler('DoNothing', 'DoNothing'); - $this->set_data_handler('DoNothing'); - $this->set_pi_handler('DoNothing'); - $this->set_jasp_handler('DoNothing'); - $this->set_escape_handler('DoNothing'); - } - - /** - * Sets the user defined handler object. Returns a PEAR Error - * if supplied argument is not an object. - * @param object handler object containing SAX callback methods - * @access public - * @return mixed - */ - function set_object(&$object) { - if ( is_object($object) ) { - $this->state_parser->handler_default =& $object; - return true; - } else { - require_once('PEAR.php'); - PEAR::raiseError('TSax3::set_object requires '. - 'an object instance'); - } - } - - /** - * Sets a parser option. By default all options are switched off. - * Returns a PEAR Error if option is invalid
- * Available options: - *
    - *
  • XML_OPTION_TRIM_DATA_NODES: trim whitespace off the beginning - * and end of data passed to the data handler
  • - *
  • XML_OPTION_LINEFEED_BREAK: linefeeds result in additional data - * handler calls
  • - *
  • XML_OPTION_TAB_BREAK: tabs result in additional data handler - * calls
  • - *
  • XML_OPTION_ENTITIES_UNPARSED: XML entities are returned as - * seperate data handler calls in unparsed form
  • - *
  • XML_OPTION_ENTITIES_PARSED: (PHP 4.3.0+ only) XML entities are - * returned as seperate data handler calls and are parsed with - * PHP's html_entity_decode() function
  • - *
  • XML_OPTION_STRIP_ESCAPES: strips out the -- -- comment markers - * or CDATA markup inside an XML escape, if found.
  • - *
- * To get HTMLSax to behave in the same way as the native PHP SAX parser, - * using it's default state, you need to switch on XML_OPTION_LINEFEED_BREAK, - * XML_OPTION_ENTITIES_PARSED and XML_OPTION_CASE_FOLDING - * @param string name of parser option - * @param int (optional) 1 to switch on, 0 for off - * @access public - * @return boolean - */ - function set_option($name, $value=1) { - if ( array_key_exists($name,$this->state_parser->parser_options) ) { - $this->state_parser->parser_options[$name] = $value; - return true; - } else { - require_once('PEAR.php'); - PEAR::raiseError('TSax3::set_option('.$name.') illegal'); - } - } - - /** - * Sets the data handler method which deals with the contents of XML - * elements.
- * The handler method must accept two arguments, the first being an - * instance of TSax3 and the second being the contents of an - * XML element e.g. - *
-    * function myDataHander(& $parser,$data){}
-    * 
- * @param string name of method - * @access public - * @return void - * @see set_object - */ - function set_data_handler($data_method) { - $this->state_parser->handler_object_data =& $this->state_parser->handler_default; - $this->state_parser->handler_method_data = $data_method; - } - - /** - * Sets the open and close tag handlers - *
The open handler method must accept three arguments; the parser, - * the tag name and an array of attributes e.g. - *
-    * function myOpenHander(& $parser,$tagname,$attrs=array()){}
-    * 
- * The close handler method must accept two arguments; the parser and - * the tag name e.g. - *
-    * function myCloseHander(& $parser,$tagname){}
-    * 
- * @param string name of open method - * @param string name of close method - * @access public - * @return void - * @see set_object - */ - function set_element_handler($opening_method, $closing_method) { - $this->state_parser->handler_object_element =& $this->state_parser->handler_default; - $this->state_parser->handler_method_opening = $opening_method; - $this->state_parser->handler_method_closing = $closing_method; - } - - /** - * Sets the processing instruction handler method e.g. for PHP open - * and close tags
- * The handler method must accept three arguments; the parser, the - * PI target and data inside the PI - *
-    * function myPIHander(& $parser,$target, $data){}
-    * 
- * @param string name of method - * @access public - * @return void - * @see set_object - */ - function set_pi_handler($pi_method) { - $this->state_parser->handler_object_pi =& $this->state_parser->handler_default; - $this->state_parser->handler_method_pi = $pi_method; - } - - /** - * Sets the XML escape handler method e.g. for comments and doctype - * declarations
- * The handler method must accept two arguments; the parser and the - * contents of the escaped section - *
-    * function myEscapeHander(& $parser, $data){}
-    * 
- * @param string name of method - * @access public - * @return void - * @see set_object - */ - function set_escape_handler($escape_method) { - $this->state_parser->handler_object_escape =& $this->state_parser->handler_default; - $this->state_parser->handler_method_escape = $escape_method; - } - - /** - * Sets the JSP/ASP markup handler
- * The handler method must accept two arguments; the parser and - * body of the JASP tag - *
-    * function myJaspHander(& $parser, $data){}
-    * 
- * @param string name of method - * @access public - * @return void - * @see set_object - */ - function set_jasp_handler ($jasp_method) { - $this->state_parser->handler_object_jasp =& $this->state_parser->handler_default; - $this->state_parser->handler_method_jasp = $jasp_method; - } - - /** - * Returns the current string position of the "cursor" inside the XML - * document - *
Intended for use from within a user defined handler called - * via the $parser reference e.g. - *
-    * function myDataHandler(& $parser,$data) {
-    *     echo( 'Current position: '.$parser->get_current_position() );
-    * }
-    * 
- * @access public - * @return int - * @see get_length - */ - function get_current_position() { - return $this->state_parser->position; - } - - /** - * Returns the string length of the XML document being parsed - * @access public - * @return int - */ - function get_length() { - return $this->state_parser->length; - } - - /** - * Start parsing some XML - * @param string XML document - * @access public - * @return void - */ - function parse($data) { - $this->state_parser->parse($data); - } -} + Original port from Python | +// | Authors: Harry Fuecks Port to PEAR + more | +// | Authors: Many @ Sitepointforums Advanced PHP Forums | +// +----------------------------------------------------------------------+ +// +// $Id$ +// +/** +* Main parser components +* @package System.Security.SafeHtml +* @version $Id$ +*/ +/** +* Required classes +*/ + +require_once(dirname(__FILE__).'/HTMLSax3/States.php'); +require_once(dirname(__FILE__).'/HTMLSax3/Decorators.php'); + +/** +* Base State Parser +* @package System.Security.SafeHtml +* @access protected +* @abstract +*/ +class TSax3_StateParser { + /** + * Instance of user front end class to be passed to callbacks + * @var TSax3 + * @access private + */ + public $htmlsax; + /** + * User defined object for handling elements + * @var object + * @access private + */ + public $handler_object_element; + /** + * User defined open tag handler method + * @var string + * @access private + */ + public $handler_method_opening; + /** + * User defined close tag handler method + * @var string + * @access private + */ + public $handler_method_closing; + /** + * User defined object for handling data in elements + * @var object + * @access private + */ + public $handler_object_data; + /** + * User defined data handler method + * @var string + * @access private + */ + public $handler_method_data; + /** + * User defined object for handling processing instructions + * @var object + * @access private + */ + public $handler_object_pi; + /** + * User defined processing instruction handler method + * @var string + * @access private + */ + public $handler_method_pi; + /** + * User defined object for handling JSP/ASP tags + * @var object + * @access private + */ + public $handler_object_jasp; + /** + * User defined JSP/ASP handler method + * @var string + * @access private + */ + public $handler_method_jasp; + /** + * User defined object for handling XML escapes + * @var object + * @access private + */ + public $handler_object_escape; + /** + * User defined XML escape handler method + * @var string + * @access private + */ + public $handler_method_escape; + /** + * User defined handler object or NullHandler + * @var object + * @access private + */ + public $handler_default; + /** + * Parser options determining parsing behavior + * @var array + * @access private + */ + protected $parser_options = array(); + /** + * XML document being parsed + * @var string + * @access private + */ + protected $rawtext; + /** + * Position in XML document relative to start (0) + * @var int + * @access private + */ + protected $position; + /** + * Length of the XML document in characters + * @var int + * @access private + */ + protected $length; + /** + * Array of state objects + * @var array + * @access private + */ + protected $State = array(); + + const TSAX3_STATE_STOP = 0; + const TSAX3_STATE_START = 1; + const TSAX3_STATE_TAG = 2; + const TSAX3_STATE_OPENING_TAG = 3; + const TSAX3_STATE_CLOSING_TAG = 4; + const TSAX3_STATE_ESCAPE = 6; + const TSAX3_STATE_JASP = 7; + const TSAX3_STATE_PI = 8; + + /** + * Constructs TSax3_StateParser setting up states + * @var TSax3 instance of user front end class + * @access protected + */ + protected function __construct($htmlsax) { + $this->htmlsax = $htmlsax; + $this->State[self::TSAX3_STATE_START] = new TSax3_StartingState(); + + $this->State[self::TSAX3_STATE_CLOSING_TAG] = new TSax3_ClosingTagState(); + $this->State[self::TSAX3_STATE_TAG] = new TSax3_TagState(); + $this->State[self::TSAX3_STATE_OPENING_TAG] = new TSax3_OpeningTagState(); + + $this->State[self::TSAX3_STATE_PI] = new TSax3_PiState(); + $this->State[self::TSAX3_STATE_JASP] = new TSax3_JaspState(); + $this->State[self::TSAX3_STATE_ESCAPE] = new TSax3_EscapeState(); + } + + /** + * Moves the position back one character + * @access protected + * @return void + */ + function unscanCharacter() { + $this->position -= 1; + } + + /** + * Moves the position forward one character + * @access protected + * @return void + */ + function ignoreCharacter() { + $this->position += 1; + } + + /** + * Returns the next character from the XML document or void if at end + * @access protected + * @return mixed + */ + function scanCharacter() { + if ($this->position < $this->length) { + return $this->rawtext{$this->position++}; + } + } + + /** + * Returns a string from the current position to the next occurance + * of the supplied string + * @param string string to search until + * @access protected + * @return string + */ + function scanUntilString($string) { + $start = $this->position; + $this->position = strpos($this->rawtext, $string, $start); + if ($this->position === FALSE) { + $this->position = $this->length; + } + return substr($this->rawtext, $start, $this->position - $start); + } + + /** + * Returns a string from the current position until the first instance of + * one of the characters in the supplied string argument + * @param string string to search until + * @access protected + * @return string + * @abstract + */ + function scanUntilCharacters($string) {} + + /** + * Moves the position forward past any whitespace characters + * @access protected + * @return void + * @abstract + */ + function ignoreWhitespace() {} + + /** + * Begins the parsing operation, setting up any decorators, depending on + * parse options invoking _parse() to execute parsing + * @param string XML document to parse + * @access protected + * @return void + */ + function parse($data) { + if ($this->parser_options['XML_OPTION_TRIM_DATA_NODES']==1) { + $decorator = new TSax3_Trim( + $this->handler_object_data, + $this->handler_method_data); + $this->handler_object_data =& $decorator; + $this->handler_method_data = 'trimData'; + } + if ($this->parser_options['XML_OPTION_CASE_FOLDING']==1) { + $open_decor = new TSax3_CaseFolding( + $this->handler_object_element, + $this->handler_method_opening, + $this->handler_method_closing); + $this->handler_object_element =& $open_decor; + $this->handler_method_opening ='foldOpen'; + $this->handler_method_closing ='foldClose'; + } + if ($this->parser_options['XML_OPTION_LINEFEED_BREAK']==1) { + $decorator = new TSax3_Linefeed( + $this->handler_object_data, + $this->handler_method_data); + $this->handler_object_data =& $decorator; + $this->handler_method_data = 'breakData'; + } + if ($this->parser_options['XML_OPTION_TAB_BREAK']==1) { + $decorator = new TSax3_Tab( + $this->handler_object_data, + $this->handler_method_data); + $this->handler_object_data =& $decorator; + $this->handler_method_data = 'breakData'; + } + if ($this->parser_options['XML_OPTION_ENTITIES_UNPARSED']==1) { + $decorator = new TSax3_Entities_Unparsed( + $this->handler_object_data, + $this->handler_method_data); + $this->handler_object_data =& $decorator; + $this->handler_method_data = 'breakData'; + } + if ($this->parser_options['XML_OPTION_ENTITIES_PARSED']==1) { + $decorator = new TSax3_Entities_Parsed( + $this->handler_object_data, + $this->handler_method_data); + $this->handler_object_data =& $decorator; + $this->handler_method_data = 'breakData'; + } + // Note switched on by default + if ($this->parser_options['XML_OPTION_STRIP_ESCAPES']==1) { + $decorator = new TSax3_Escape_Stripper( + $this->handler_object_escape, + $this->handler_method_escape); + $this->handler_object_escape =& $decorator; + $this->handler_method_escape = 'strip'; + } + $this->rawtext = $data; + $this->length = strlen($data); + $this->position = 0; + $this->_parse(); + } + + /** + * Performs the parsing itself, delegating calls to a specific parser + * state + * @param constant state object to parse with + * @access protected + * @return void + */ + function _parse($state = self::TSAX3_STATE_START) { + do { + $state = $this->State[$state]->parse($this); + } while ($state != self::TSAX3_STATE_STOP && + $this->position < $this->length); + } +} + +/** +* Parser for PHP Versions below 4.3.0. Uses a slower parsing mechanism than +* the equivalent PHP 4.3.0+ subclass of StateParser +* @package System.Security.SafeHtml +* @access protected +* @see TSax3_StateParser_Gtet430 +*/ +class TSax3_StateParser_Lt430 extends TSax3_StateParser { + /** + * Constructs TSax3_StateParser_Lt430 defining available + * parser options + * @var TSax3 instance of user front end class + * @access protected + */ + function __construct(& $htmlsax) { + parent::__construct($htmlsax); + $this->parser_options['XML_OPTION_TRIM_DATA_NODES'] = 0; + $this->parser_options['XML_OPTION_CASE_FOLDING'] = 0; + $this->parser_options['XML_OPTION_LINEFEED_BREAK'] = 0; + $this->parser_options['XML_OPTION_TAB_BREAK'] = 0; + $this->parser_options['XML_OPTION_ENTITIES_PARSED'] = 0; + $this->parser_options['XML_OPTION_ENTITIES_UNPARSED'] = 0; + $this->parser_options['XML_OPTION_STRIP_ESCAPES'] = 0; + //var_dump($this->parser_options); + } + + /** + * Returns a string from the current position until the first instance of + * one of the characters in the supplied string argument + * @param string string to search until + * @access protected + * @return string + */ + function scanUntilCharacters($string) { + $startpos = $this->position; + while ($this->position < $this->length && strpos($string, $this->rawtext{$this->position}) === FALSE) { + $this->position++; + } + return substr($this->rawtext, $startpos, $this->position - $startpos); + } + + /** + * Moves the position forward past any whitespace characters + * @access protected + * @return void + */ + function ignoreWhitespace() { + while ($this->position < $this->length && + strpos(" \n\r\t", $this->rawtext{$this->position}) !== FALSE) { + $this->position++; + } + } + + /** + * Begins the parsing operation, setting up the unparsed XML entities + * decorator if necessary then delegating further work to parent + * @param string XML document to parse + * @access protected + * @return void + */ + function parse($data) { + parent::parse($data); + } +} + +/** +* Parser for PHP Versions equal to or greater than 4.3.0. Uses a faster +* parsing mechanism than the equivalent PHP < 4.3.0 subclass of StateParser +* @package System.Security.SafeHtml +* @access protected +* @see TSax3_StateParser_Lt430 +*/ +class TSax3_StateParser_Gtet430 extends TSax3_StateParser { + /** + * Constructs TSax3_StateParser_Gtet430 defining available + * parser options + * @var TSax3 instance of user front end class + * @access protected + */ + function __construct(& $htmlsax) { + parent::__construct($htmlsax); + $this->parser_options['XML_OPTION_TRIM_DATA_NODES'] = 0; + $this->parser_options['XML_OPTION_CASE_FOLDING'] = 0; + $this->parser_options['XML_OPTION_LINEFEED_BREAK'] = 0; + $this->parser_options['XML_OPTION_TAB_BREAK'] = 0; + $this->parser_options['XML_OPTION_ENTITIES_PARSED'] = 0; + $this->parser_options['XML_OPTION_ENTITIES_UNPARSED'] = 0; + $this->parser_options['XML_OPTION_STRIP_ESCAPES'] = 0; + } + /** + * Returns a string from the current position until the first instance of + * one of the characters in the supplied string argument. + * @param string string to search until + * @access protected + * @return string + */ + function scanUntilCharacters($string) { + $startpos = $this->position; + $length = strcspn($this->rawtext, $string, $startpos); + $this->position += $length; + return substr($this->rawtext, $startpos, $length); + } + + /** + * Moves the position forward past any whitespace characters + * @access protected + * @return void + */ + function ignoreWhitespace() { + $this->position += strspn($this->rawtext, " \n\r\t", $this->position); + } + + /** + * Begins the parsing operation, setting up the parsed and unparsed + * XML entity decorators if necessary then delegating further work + * to parent + * @param string XML document to parse + * @access protected + * @return void + */ + function parse($data) { + parent::parse($data); + } +} + +/** +* Default NullHandler for methods which were not set by user +* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_NullHandler { + /** + * Generic handler method which does nothing + * @access protected + * @return void + */ + function DoNothing() { + } +} + +/** +* User interface class. All user calls should only be made to this class +* @package System.Security.SafeHtml +* @access public +*/ +class TSax3 { + /** + * Instance of concrete subclass of TSax3_StateParser + * @var TSax3_StateParser + * @access private + */ + private $state_parser; + + /** + * Constructs TSax3 selecting concrete StateParser subclass + * depending on PHP version being used as well as setting the default + * NullHandler for all callbacks
+ * Example: + *
+    * $myHandler = & new MyHandler();
+    * $parser = new TSax3();
+    * $parser->set_object($myHandler);
+    * $parser->set_option('XML_OPTION_CASE_FOLDING');
+    * $parser->set_element_handler('myOpenHandler','myCloseHandler');
+    * $parser->set_data_handler('myDataHandler');
+    * $parser->parser($xml);
+    * 
+ * @access public + */ + function __construct() { + if (version_compare(phpversion(), '4.3', 'ge')) { + $this->state_parser = new TSax3_StateParser_Gtet430($this); + } else { + $this->state_parser = new TSax3_StateParser_Lt430($this); + } + $nullhandler = new TSax3_NullHandler(); + $this->set_object($nullhandler); + $this->set_element_handler('DoNothing', 'DoNothing'); + $this->set_data_handler('DoNothing'); + $this->set_pi_handler('DoNothing'); + $this->set_jasp_handler('DoNothing'); + $this->set_escape_handler('DoNothing'); + } + + /** + * Sets the user defined handler object. Returns a PEAR Error + * if supplied argument is not an object. + * @param object handler object containing SAX callback methods + * @access public + * @return mixed + */ + function set_object(&$object) { + if ( is_object($object) ) { + $this->state_parser->handler_default =& $object; + return true; + } else { + require_once('PEAR.php'); + PEAR::raiseError('TSax3::set_object requires '. + 'an object instance'); + } + } + + /** + * Sets a parser option. By default all options are switched off. + * Returns a PEAR Error if option is invalid
+ * Available options: + *
    + *
  • XML_OPTION_TRIM_DATA_NODES: trim whitespace off the beginning + * and end of data passed to the data handler
  • + *
  • XML_OPTION_LINEFEED_BREAK: linefeeds result in additional data + * handler calls
  • + *
  • XML_OPTION_TAB_BREAK: tabs result in additional data handler + * calls
  • + *
  • XML_OPTION_ENTITIES_UNPARSED: XML entities are returned as + * seperate data handler calls in unparsed form
  • + *
  • XML_OPTION_ENTITIES_PARSED: (PHP 4.3.0+ only) XML entities are + * returned as seperate data handler calls and are parsed with + * PHP's html_entity_decode() function
  • + *
  • XML_OPTION_STRIP_ESCAPES: strips out the -- -- comment markers + * or CDATA markup inside an XML escape, if found.
  • + *
+ * To get HTMLSax to behave in the same way as the native PHP SAX parser, + * using it's default state, you need to switch on XML_OPTION_LINEFEED_BREAK, + * XML_OPTION_ENTITIES_PARSED and XML_OPTION_CASE_FOLDING + * @param string name of parser option + * @param int (optional) 1 to switch on, 0 for off + * @access public + * @return boolean + */ + function set_option($name, $value=1) { + if ( array_key_exists($name,$this->state_parser->parser_options) ) { + $this->state_parser->parser_options[$name] = $value; + return true; + } else { + require_once('PEAR.php'); + PEAR::raiseError('TSax3::set_option('.$name.') illegal'); + } + } + + /** + * Sets the data handler method which deals with the contents of XML + * elements.
+ * The handler method must accept two arguments, the first being an + * instance of TSax3 and the second being the contents of an + * XML element e.g. + *
+    * function myDataHander(& $parser,$data){}
+    * 
+ * @param string name of method + * @access public + * @return void + * @see set_object + */ + function set_data_handler($data_method) { + $this->state_parser->handler_object_data =& $this->state_parser->handler_default; + $this->state_parser->handler_method_data = $data_method; + } + + /** + * Sets the open and close tag handlers + *
The open handler method must accept three arguments; the parser, + * the tag name and an array of attributes e.g. + *
+    * function myOpenHander(& $parser,$tagname,$attrs=array()){}
+    * 
+ * The close handler method must accept two arguments; the parser and + * the tag name e.g. + *
+    * function myCloseHander(& $parser,$tagname){}
+    * 
+ * @param string name of open method + * @param string name of close method + * @access public + * @return void + * @see set_object + */ + function set_element_handler($opening_method, $closing_method) { + $this->state_parser->handler_object_element =& $this->state_parser->handler_default; + $this->state_parser->handler_method_opening = $opening_method; + $this->state_parser->handler_method_closing = $closing_method; + } + + /** + * Sets the processing instruction handler method e.g. for PHP open + * and close tags
+ * The handler method must accept three arguments; the parser, the + * PI target and data inside the PI + *
+    * function myPIHander(& $parser,$target, $data){}
+    * 
+ * @param string name of method + * @access public + * @return void + * @see set_object + */ + function set_pi_handler($pi_method) { + $this->state_parser->handler_object_pi =& $this->state_parser->handler_default; + $this->state_parser->handler_method_pi = $pi_method; + } + + /** + * Sets the XML escape handler method e.g. for comments and doctype + * declarations
+ * The handler method must accept two arguments; the parser and the + * contents of the escaped section + *
+    * function myEscapeHander(& $parser, $data){}
+    * 
+ * @param string name of method + * @access public + * @return void + * @see set_object + */ + function set_escape_handler($escape_method) { + $this->state_parser->handler_object_escape =& $this->state_parser->handler_default; + $this->state_parser->handler_method_escape = $escape_method; + } + + /** + * Sets the JSP/ASP markup handler
+ * The handler method must accept two arguments; the parser and + * body of the JASP tag + *
+    * function myJaspHander(& $parser, $data){}
+    * 
+ * @param string name of method + * @access public + * @return void + * @see set_object + */ + function set_jasp_handler ($jasp_method) { + $this->state_parser->handler_object_jasp =& $this->state_parser->handler_default; + $this->state_parser->handler_method_jasp = $jasp_method; + } + + /** + * Returns the current string position of the "cursor" inside the XML + * document + *
Intended for use from within a user defined handler called + * via the $parser reference e.g. + *
+    * function myDataHandler(& $parser,$data) {
+    *     echo( 'Current position: '.$parser->get_current_position() );
+    * }
+    * 
+ * @access public + * @return int + * @see get_length + */ + function get_current_position() { + return $this->state_parser->position; + } + + /** + * Returns the string length of the XML document being parsed + * @access public + * @return int + */ + function get_length() { + return $this->state_parser->length; + } + + /** + * Start parsing some XML + * @param string XML document + * @access public + * @return void + */ + function parse($data) { + $this->state_parser->parse($data); + } +} ?> \ No newline at end of file diff --git a/framework/3rdParty/SafeHtml/HTMLSax3/Decorators.php b/framework/3rdParty/SafeHtml/HTMLSax3/Decorators.php index ac82d073..2e2b6590 100644 --- a/framework/3rdParty/SafeHtml/HTMLSax3/Decorators.php +++ b/framework/3rdParty/SafeHtml/HTMLSax3/Decorators.php @@ -1,363 +1,363 @@ - Original port from Python | -// | Authors: Harry Fuecks Port to PEAR + more | -// | Authors: Many @ Sitepointforums Advanced PHP Forums | -// +----------------------------------------------------------------------+ -// -// $Id$ -// -/** -* Decorators for dealing with parser options -* @package System.Security.SafeHtml -* @version $Id$ -* @see TSax3::set_option -*/ -/** -* Trims the contents of element data from whitespace at start and end -* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_Trim { - /** - * Original handler object - * @var object - * @access private - */ - private $orig_obj; - /** - * Original handler method - * @var string - * @access private - */ - private $orig_method; - /** - * Constructs TSax3_Trim - * @param object handler object being decorated - * @param string original handler method - * @access protected - */ - function __construct(&$orig_obj, $orig_method) { - $this->orig_obj =& $orig_obj; - $this->orig_method = $orig_method; - } - /** - * Trims the data - * @param TSax3 - * @param string element data - * @access protected - */ - function trimData(&$parser, $data) { - $data = trim($data); - if ($data != '') { - $this->orig_obj->{$this->orig_method}($parser, $data); - } - } -} -/** -* Coverts tag names to upper case -* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_CaseFolding { - /** - * Original handler object - * @var object - * @access private - */ - private $orig_obj; - /** - * Original open handler method - * @var string - * @access private - */ - private $orig_open_method; - /** - * Original close handler method - * @var string - * @access private - */ - private $orig_close_method; - /** - * Constructs TSax3_CaseFolding - * @param object handler object being decorated - * @param string original open handler method - * @param string original close handler method - * @access protected - */ - function __construct(&$orig_obj, $orig_open_method, $orig_close_method) { - $this->orig_obj =& $orig_obj; - $this->orig_open_method = $orig_open_method; - $this->orig_close_method = $orig_close_method; - } - /** - * Folds up open tag callbacks - * @param TSax3 - * @param string tag name - * @param array tag attributes - * @access protected - */ - function foldOpen(&$parser, $tag, $attrs=array(), $empty = FALSE) { - $this->orig_obj->{$this->orig_open_method}($parser, strtoupper($tag), $attrs, $empty); - } - /** - * Folds up close tag callbacks - * @param TSax3 - * @param string tag name - * @access protected - */ - function foldClose(&$parser, $tag, $empty = FALSE) { - $this->orig_obj->{$this->orig_close_method}($parser, strtoupper($tag), $empty); - } -} -/** -* Breaks up data by linefeed characters, resulting in additional -* calls to the data handler -* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_Linefeed { - /** - * Original handler object - * @var object - * @access private - */ - private $orig_obj; - /** - * Original handler method - * @var string - * @access private - */ - private $orig_method; - /** - * Constructs TSax3_LineFeed - * @param object handler object being decorated - * @param string original handler method - * @access protected - */ - function __construct(&$orig_obj, $orig_method) { - $this->orig_obj =& $orig_obj; - $this->orig_method = $orig_method; - } - /** - * Breaks the data up by linefeeds - * @param TSax3 - * @param string element data - * @access protected - */ - function breakData(&$parser, $data) { - $data = explode("\n",$data); - foreach ( $data as $chunk ) { - $this->orig_obj->{$this->orig_method}($parser, $chunk); - } - } -} -/** -* Breaks up data by tab characters, resulting in additional -* calls to the data handler -* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_Tab { - /** - * Original handler object - * @var object - * @access private - */ - private $orig_obj; - /** - * Original handler method - * @var string - * @access private - */ - private $orig_method; - /** - * Constructs TSax3_Tab - * @param object handler object being decorated - * @param string original handler method - * @access protected - */ - function __construct(&$orig_obj, $orig_method) { - $this->orig_obj =& $orig_obj; - $this->orig_method = $orig_method; - } - /** - * Breaks the data up by linefeeds - * @param TSax3 - * @param string element data - * @access protected - */ - function breakData(&$parser, $data) { - $data = explode("\t",$data); - foreach ( $data as $chunk ) { - $this->orig_obj->{$this->orig_method}($this, $chunk); - } - } -} -/** -* Breaks up data by XML entities and parses them with html_entity_decode(), -* resulting in additional calls to the data handler
-* Requires PHP 4.3.0+ -* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_Entities_Parsed { - /** - * Original handler object - * @var object - * @access private - */ - private $orig_obj; - /** - * Original handler method - * @var string - * @access private - */ - private $orig_method; - /** - * Constructs TSax3_Entities_Parsed - * @param object handler object being decorated - * @param string original handler method - * @access protected - */ - function __construct(&$orig_obj, $orig_method) { - $this->orig_obj =& $orig_obj; - $this->orig_method = $orig_method; - } - /** - * Breaks the data up by XML entities - * @param TSax3 - * @param string element data - * @access protected - */ - function breakData(&$parser, $data) { - $data = preg_split('/(&.+?;)/',$data,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); - foreach ( $data as $chunk ) { - $chunk = html_entity_decode($chunk,ENT_NOQUOTES); - $this->orig_obj->{$this->orig_method}($this, $chunk); - } - } -} -/** -* Compatibility with older PHP versions -*/ -if (version_compare(phpversion(), '4.3', '<') && !function_exists('html_entity_decode') ) { - function html_entity_decode($str, $style=ENT_NOQUOTES) { - return strtr($str, - array_flip(get_html_translation_table(HTML_ENTITIES,$style))); - } -} -/** -* Breaks up data by XML entities but leaves them unparsed, -* resulting in additional calls to the data handler
-* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_Entities_Unparsed { - /** - * Original handler object - * @var object - * @access private - */ - private $orig_obj; - /** - * Original handler method - * @var string - * @access private - */ - private $orig_method; - /** - * Constructs TSax3_Entities_Unparsed - * @param object handler object being decorated - * @param string original handler method - * @access protected - */ - function __construct(&$orig_obj, $orig_method) { - $this->orig_obj =& $orig_obj; - $this->orig_method = $orig_method; - } - /** - * Breaks the data up by XML entities - * @param TSax3 - * @param string element data - * @access protected - */ - function breakData(&$parser, $data) { - $data = preg_split('/(&.+?;)/',$data,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); - foreach ( $data as $chunk ) { - $this->orig_obj->{$this->orig_method}($this, $chunk); - } - } -} - -/** -* Strips the HTML comment markers or CDATA sections from an escape. -* If XML_OPTIONS_FULL_ESCAPES is on, this decorator is not used.
-* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_Escape_Stripper { - /** - * Original handler object - * @var object - * @access private - */ - private $orig_obj; - /** - * Original handler method - * @var string - * @access private - */ - private $orig_method; - /** - * Constructs TSax3_Entities_Unparsed - * @param object handler object being decorated - * @param string original handler method - * @access protected - */ - function __construct(&$orig_obj, $orig_method) { - $this->orig_obj =& $orig_obj; - $this->orig_method = $orig_method; - } - /** - * Breaks the data up by XML entities - * @param TSax3 - * @param string element data - * @access protected - */ - function strip(&$parser, $data) { - // Check for HTML comments first - if ( substr($data,0,2) == '--' ) { - $patterns = array( - '/^\-\-/', // Opening comment: -- - '/\-\-$/', // Closing comment: -- - ); - $data = preg_replace($patterns,'',$data); - - // Check for XML CDATA sections (note: don't do both!) - } else if ( substr($data,0,1) == '[' ) { - $patterns = array( - '/^\[.*CDATA.*\[/s', // Opening CDATA - '/\].*\]$/s', // Closing CDATA - ); - $data = preg_replace($patterns,'',$data); - } - - $this->orig_obj->{$this->orig_method}($this, $data); - } -} + Original port from Python | +// | Authors: Harry Fuecks Port to PEAR + more | +// | Authors: Many @ Sitepointforums Advanced PHP Forums | +// +----------------------------------------------------------------------+ +// +// $Id$ +// +/** +* Decorators for dealing with parser options +* @package System.Security.SafeHtml +* @version $Id$ +* @see TSax3::set_option +*/ +/** +* Trims the contents of element data from whitespace at start and end +* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_Trim { + /** + * Original handler object + * @var object + * @access private + */ + private $orig_obj; + /** + * Original handler method + * @var string + * @access private + */ + private $orig_method; + /** + * Constructs TSax3_Trim + * @param object handler object being decorated + * @param string original handler method + * @access protected + */ + function __construct(&$orig_obj, $orig_method) { + $this->orig_obj =& $orig_obj; + $this->orig_method = $orig_method; + } + /** + * Trims the data + * @param TSax3 + * @param string element data + * @access protected + */ + function trimData(&$parser, $data) { + $data = trim($data); + if ($data != '') { + $this->orig_obj->{$this->orig_method}($parser, $data); + } + } +} +/** +* Coverts tag names to upper case +* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_CaseFolding { + /** + * Original handler object + * @var object + * @access private + */ + private $orig_obj; + /** + * Original open handler method + * @var string + * @access private + */ + private $orig_open_method; + /** + * Original close handler method + * @var string + * @access private + */ + private $orig_close_method; + /** + * Constructs TSax3_CaseFolding + * @param object handler object being decorated + * @param string original open handler method + * @param string original close handler method + * @access protected + */ + function __construct(&$orig_obj, $orig_open_method, $orig_close_method) { + $this->orig_obj =& $orig_obj; + $this->orig_open_method = $orig_open_method; + $this->orig_close_method = $orig_close_method; + } + /** + * Folds up open tag callbacks + * @param TSax3 + * @param string tag name + * @param array tag attributes + * @access protected + */ + function foldOpen(&$parser, $tag, $attrs=array(), $empty = FALSE) { + $this->orig_obj->{$this->orig_open_method}($parser, strtoupper($tag), $attrs, $empty); + } + /** + * Folds up close tag callbacks + * @param TSax3 + * @param string tag name + * @access protected + */ + function foldClose(&$parser, $tag, $empty = FALSE) { + $this->orig_obj->{$this->orig_close_method}($parser, strtoupper($tag), $empty); + } +} +/** +* Breaks up data by linefeed characters, resulting in additional +* calls to the data handler +* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_Linefeed { + /** + * Original handler object + * @var object + * @access private + */ + private $orig_obj; + /** + * Original handler method + * @var string + * @access private + */ + private $orig_method; + /** + * Constructs TSax3_LineFeed + * @param object handler object being decorated + * @param string original handler method + * @access protected + */ + function __construct(&$orig_obj, $orig_method) { + $this->orig_obj =& $orig_obj; + $this->orig_method = $orig_method; + } + /** + * Breaks the data up by linefeeds + * @param TSax3 + * @param string element data + * @access protected + */ + function breakData(&$parser, $data) { + $data = explode("\n",$data); + foreach ( $data as $chunk ) { + $this->orig_obj->{$this->orig_method}($parser, $chunk); + } + } +} +/** +* Breaks up data by tab characters, resulting in additional +* calls to the data handler +* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_Tab { + /** + * Original handler object + * @var object + * @access private + */ + private $orig_obj; + /** + * Original handler method + * @var string + * @access private + */ + private $orig_method; + /** + * Constructs TSax3_Tab + * @param object handler object being decorated + * @param string original handler method + * @access protected + */ + function __construct(&$orig_obj, $orig_method) { + $this->orig_obj =& $orig_obj; + $this->orig_method = $orig_method; + } + /** + * Breaks the data up by linefeeds + * @param TSax3 + * @param string element data + * @access protected + */ + function breakData(&$parser, $data) { + $data = explode("\t",$data); + foreach ( $data as $chunk ) { + $this->orig_obj->{$this->orig_method}($this, $chunk); + } + } +} +/** +* Breaks up data by XML entities and parses them with html_entity_decode(), +* resulting in additional calls to the data handler
+* Requires PHP 4.3.0+ +* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_Entities_Parsed { + /** + * Original handler object + * @var object + * @access private + */ + private $orig_obj; + /** + * Original handler method + * @var string + * @access private + */ + private $orig_method; + /** + * Constructs TSax3_Entities_Parsed + * @param object handler object being decorated + * @param string original handler method + * @access protected + */ + function __construct(&$orig_obj, $orig_method) { + $this->orig_obj =& $orig_obj; + $this->orig_method = $orig_method; + } + /** + * Breaks the data up by XML entities + * @param TSax3 + * @param string element data + * @access protected + */ + function breakData(&$parser, $data) { + $data = preg_split('/(&.+?;)/',$data,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + foreach ( $data as $chunk ) { + $chunk = html_entity_decode($chunk,ENT_NOQUOTES); + $this->orig_obj->{$this->orig_method}($this, $chunk); + } + } +} +/** +* Compatibility with older PHP versions +*/ +if (version_compare(phpversion(), '4.3', '<') && !function_exists('html_entity_decode') ) { + function html_entity_decode($str, $style=ENT_NOQUOTES) { + return strtr($str, + array_flip(get_html_translation_table(HTML_ENTITIES,$style))); + } +} +/** +* Breaks up data by XML entities but leaves them unparsed, +* resulting in additional calls to the data handler
+* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_Entities_Unparsed { + /** + * Original handler object + * @var object + * @access private + */ + private $orig_obj; + /** + * Original handler method + * @var string + * @access private + */ + private $orig_method; + /** + * Constructs TSax3_Entities_Unparsed + * @param object handler object being decorated + * @param string original handler method + * @access protected + */ + function __construct(&$orig_obj, $orig_method) { + $this->orig_obj =& $orig_obj; + $this->orig_method = $orig_method; + } + /** + * Breaks the data up by XML entities + * @param TSax3 + * @param string element data + * @access protected + */ + function breakData(&$parser, $data) { + $data = preg_split('/(&.+?;)/',$data,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + foreach ( $data as $chunk ) { + $this->orig_obj->{$this->orig_method}($this, $chunk); + } + } +} + +/** +* Strips the HTML comment markers or CDATA sections from an escape. +* If XML_OPTIONS_FULL_ESCAPES is on, this decorator is not used.
+* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_Escape_Stripper { + /** + * Original handler object + * @var object + * @access private + */ + private $orig_obj; + /** + * Original handler method + * @var string + * @access private + */ + private $orig_method; + /** + * Constructs TSax3_Entities_Unparsed + * @param object handler object being decorated + * @param string original handler method + * @access protected + */ + function __construct(&$orig_obj, $orig_method) { + $this->orig_obj =& $orig_obj; + $this->orig_method = $orig_method; + } + /** + * Breaks the data up by XML entities + * @param TSax3 + * @param string element data + * @access protected + */ + function strip(&$parser, $data) { + // Check for HTML comments first + if ( substr($data,0,2) == '--' ) { + $patterns = array( + '/^\-\-/', // Opening comment: -- + '/\-\-$/', // Closing comment: -- + ); + $data = preg_replace($patterns,'',$data); + + // Check for XML CDATA sections (note: don't do both!) + } else if ( substr($data,0,1) == '[' ) { + $patterns = array( + '/^\[.*CDATA.*\[/s', // Opening CDATA + '/\].*\]$/s', // Closing CDATA + ); + $data = preg_replace($patterns,'',$data); + } + + $this->orig_obj->{$this->orig_method}($this, $data); + } +} ?> \ No newline at end of file diff --git a/framework/3rdParty/SafeHtml/HTMLSax3/States.php b/framework/3rdParty/SafeHtml/HTMLSax3/States.php index 6dfead17..7d7b9b34 100644 --- a/framework/3rdParty/SafeHtml/HTMLSax3/States.php +++ b/framework/3rdParty/SafeHtml/HTMLSax3/States.php @@ -1,288 +1,288 @@ - Original port from Python | -// | Authors: Harry Fuecks Port to PEAR + more | -// | Authors: Many @ Sitepointforums Advanced PHP Forums | -// +----------------------------------------------------------------------+ -// -// $Id$ -// -/** -* Parsing states. -* @package System.Security.SafeHtml -* @version $Id$ -*/ -/** -* Define parser states -*/ -/*define('TSAX3_STATE_STOP', 0); -define('TSAX3_STATE_START', 1); -define('TSAX3_STATE_TAG', 2); -define('TSAX3_STATE_OPENING_TAG', 3); -define('TSAX3_STATE_CLOSING_TAG', 4); -define('TSAX3_STATE_ESCAPE', 6); -define('TSAX3_STATE_JASP', 7); -define('TSAX3_STATE_PI', 8); -*/ -/** -* StartingState searches for the start of any XML tag -* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_StartingState { - /** - * @param TSax3_StateParser subclass - * @return constant TSAX3_STATE_TAG - * @access protected - */ - function parse(&$context) { - $data = $context->scanUntilString('<'); - if ($data != '') { - $context->handler_object_data-> - {$context->handler_method_data}($context->htmlsax, $data); - } - $context->IgnoreCharacter(); - return TSax3_StateParser::TSAX3_STATE_TAG; - } -} -/** -* Decides which state to move one from after StartingState -* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_TagState { - /** - * @param TSax3_StateParser subclass - * @return constant the next state to move into - * @access protected - */ - function parse(&$context) { - switch($context->ScanCharacter()) { - case '/': - return TSax3_StateParser::TSAX3_STATE_CLOSING_TAG; - break; - case '?': - return TSax3_StateParser::TSAX3_STATE_PI; - break; - case '%': - return TSax3_StateParser::TSAX3_STATE_JASP; - break; - case '!': - return TSax3_StateParser::TSAX3_STATE_ESCAPE; - break; - default: - $context->unscanCharacter(); - return TSax3_StateParser::TSAX3_STATE_OPENING_TAG; - } - } -} -/** -* Dealing with closing XML tags -* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_ClosingTagState { - /** - * @param TSax3_StateParser subclass - * @return constant TSAX3_STATE_START - * @access protected - */ - function parse(&$context) { - $tag = $context->scanUntilCharacters('/>'); - if ($tag != '') { - $char = $context->scanCharacter(); - if ($char == '/') { - $char = $context->scanCharacter(); - if ($char != '>') { - $context->unscanCharacter(); - } - } - $context->handler_object_element-> - {$context->handler_method_closing}($context->htmlsax, $tag, FALSE); - } - return TSax3_StateParser::TSAX3_STATE_START; - } -} -/** -* Dealing with opening XML tags -* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_OpeningTagState { - /** - * Handles attributes - * @param string attribute name - * @param string attribute value - * @return void - * @access protected - * @see TSax3_AttributeStartState - */ - function parseAttributes(&$context) { - $Attributes = array(); - - $context->ignoreWhitespace(); - $attributename = $context->scanUntilCharacters("=/> \n\r\t"); - while ($attributename != '') { - $attributevalue = NULL; - $context->ignoreWhitespace(); - $char = $context->scanCharacter(); - if ($char == '=') { - $context->ignoreWhitespace(); - $char = $context->ScanCharacter(); - if ($char == '"') { - $attributevalue= $context->scanUntilString('"'); - $context->IgnoreCharacter(); - } else if ($char == "'") { - $attributevalue = $context->scanUntilString("'"); - $context->IgnoreCharacter(); - } else { - $context->unscanCharacter(); - $attributevalue = - $context->scanUntilCharacters("> \n\r\t"); - } - } else if ($char !== NULL) { - $attributevalue = NULL; - $context->unscanCharacter(); - } - $Attributes[$attributename] = $attributevalue; - - $context->ignoreWhitespace(); - $attributename = $context->scanUntilCharacters("=/> \n\r\t"); - } - return $Attributes; - } - - /** - * @param TSax3_StateParser subclass - * @return constant TSAX3_STATE_START - * @access protected - */ - function parse(&$context) { - $tag = $context->scanUntilCharacters("/> \n\r\t"); - if ($tag != '') { - $this->attrs = array(); - $Attributes = $this->parseAttributes($context); - $char = $context->scanCharacter(); - if ($char == '/') { - $char = $context->scanCharacter(); - if ($char != '>') { - $context->unscanCharacter(); - } - $context->handler_object_element-> - {$context->handler_method_opening}($context->htmlsax, $tag, - $Attributes, TRUE); - $context->handler_object_element-> - {$context->handler_method_closing}($context->htmlsax, $tag, - TRUE); - } else { - $context->handler_object_element-> - {$context->handler_method_opening}($context->htmlsax, $tag, - $Attributes, FALSE); - } - } - return TSax3_StateParser::TSAX3_STATE_START; - } -} - -/** -* Deals with XML escapes handling comments and CDATA correctly -* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_EscapeState { - /** - * @param TSax3_StateParser subclass - * @return constant TSAX3_STATE_START - * @access protected - */ - function parse(&$context) { - $char = $context->ScanCharacter(); - if ($char == '-') { - $char = $context->ScanCharacter(); - if ($char == '-') { - $context->unscanCharacter(); - $context->unscanCharacter(); - $text = $context->scanUntilString('-->'); - $text .= $context->scanCharacter(); - $text .= $context->scanCharacter(); - } else { - $context->unscanCharacter(); - $text = $context->scanUntilString('>'); - } - } else if ( $char == '[') { - $context->unscanCharacter(); - $text = $context->scanUntilString(']>'); - $text.= $context->scanCharacter(); - } else { - $context->unscanCharacter(); - $text = $context->scanUntilString('>'); - } - - $context->IgnoreCharacter(); - if ($text != '') { - $context->handler_object_escape-> - {$context->handler_method_escape}($context->htmlsax, $text); - } - return TSax3_StateParser::TSAX3_STATE_START; - } -} -/** -* Deals with JASP/ASP markup -* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_JaspState { - /** - * @param TSax3_StateParser subclass - * @return constant TSAX3_STATE_START - * @access protected - */ - function parse(&$context) { - $text = $context->scanUntilString('%>'); - if ($text != '') { - $context->handler_object_jasp-> - {$context->handler_method_jasp}($context->htmlsax, $text); - } - $context->IgnoreCharacter(); - $context->IgnoreCharacter(); - return TSax3_StateParser::TSAX3_STATE_START; - } -} -/** -* Deals with XML processing instructions -* @package System.Security.SafeHtml -* @access protected -*/ -class TSax3_PiState { - /** - * @param TSax3_StateParser subclass - * @return constant TSAX3_STATE_START - * @access protected - */ - function parse(&$context) { - $target = $context->scanUntilCharacters(" \n\r\t"); - $data = $context->scanUntilString('?>'); - if ($data != '') { - $context->handler_object_pi-> - {$context->handler_method_pi}($context->htmlsax, $target, $data); - } - $context->IgnoreCharacter(); - $context->IgnoreCharacter(); - return TSax3_StateParser::TSAX3_STATE_START; - } -} + Original port from Python | +// | Authors: Harry Fuecks Port to PEAR + more | +// | Authors: Many @ Sitepointforums Advanced PHP Forums | +// +----------------------------------------------------------------------+ +// +// $Id$ +// +/** +* Parsing states. +* @package System.Security.SafeHtml +* @version $Id$ +*/ +/** +* Define parser states +*/ +/*define('TSAX3_STATE_STOP', 0); +define('TSAX3_STATE_START', 1); +define('TSAX3_STATE_TAG', 2); +define('TSAX3_STATE_OPENING_TAG', 3); +define('TSAX3_STATE_CLOSING_TAG', 4); +define('TSAX3_STATE_ESCAPE', 6); +define('TSAX3_STATE_JASP', 7); +define('TSAX3_STATE_PI', 8); +*/ +/** +* StartingState searches for the start of any XML tag +* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_StartingState { + /** + * @param TSax3_StateParser subclass + * @return constant TSAX3_STATE_TAG + * @access protected + */ + function parse(&$context) { + $data = $context->scanUntilString('<'); + if ($data != '') { + $context->handler_object_data-> + {$context->handler_method_data}($context->htmlsax, $data); + } + $context->IgnoreCharacter(); + return TSax3_StateParser::TSAX3_STATE_TAG; + } +} +/** +* Decides which state to move one from after StartingState +* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_TagState { + /** + * @param TSax3_StateParser subclass + * @return constant the next state to move into + * @access protected + */ + function parse(&$context) { + switch($context->ScanCharacter()) { + case '/': + return TSax3_StateParser::TSAX3_STATE_CLOSING_TAG; + break; + case '?': + return TSax3_StateParser::TSAX3_STATE_PI; + break; + case '%': + return TSax3_StateParser::TSAX3_STATE_JASP; + break; + case '!': + return TSax3_StateParser::TSAX3_STATE_ESCAPE; + break; + default: + $context->unscanCharacter(); + return TSax3_StateParser::TSAX3_STATE_OPENING_TAG; + } + } +} +/** +* Dealing with closing XML tags +* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_ClosingTagState { + /** + * @param TSax3_StateParser subclass + * @return constant TSAX3_STATE_START + * @access protected + */ + function parse(&$context) { + $tag = $context->scanUntilCharacters('/>'); + if ($tag != '') { + $char = $context->scanCharacter(); + if ($char == '/') { + $char = $context->scanCharacter(); + if ($char != '>') { + $context->unscanCharacter(); + } + } + $context->handler_object_element-> + {$context->handler_method_closing}($context->htmlsax, $tag, FALSE); + } + return TSax3_StateParser::TSAX3_STATE_START; + } +} +/** +* Dealing with opening XML tags +* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_OpeningTagState { + /** + * Handles attributes + * @param string attribute name + * @param string attribute value + * @return void + * @access protected + * @see TSax3_AttributeStartState + */ + function parseAttributes(&$context) { + $Attributes = array(); + + $context->ignoreWhitespace(); + $attributename = $context->scanUntilCharacters("=/> \n\r\t"); + while ($attributename != '') { + $attributevalue = NULL; + $context->ignoreWhitespace(); + $char = $context->scanCharacter(); + if ($char == '=') { + $context->ignoreWhitespace(); + $char = $context->ScanCharacter(); + if ($char == '"') { + $attributevalue= $context->scanUntilString('"'); + $context->IgnoreCharacter(); + } else if ($char == "'") { + $attributevalue = $context->scanUntilString("'"); + $context->IgnoreCharacter(); + } else { + $context->unscanCharacter(); + $attributevalue = + $context->scanUntilCharacters("> \n\r\t"); + } + } else if ($char !== NULL) { + $attributevalue = NULL; + $context->unscanCharacter(); + } + $Attributes[$attributename] = $attributevalue; + + $context->ignoreWhitespace(); + $attributename = $context->scanUntilCharacters("=/> \n\r\t"); + } + return $Attributes; + } + + /** + * @param TSax3_StateParser subclass + * @return constant TSAX3_STATE_START + * @access protected + */ + function parse(&$context) { + $tag = $context->scanUntilCharacters("/> \n\r\t"); + if ($tag != '') { + $this->attrs = array(); + $Attributes = $this->parseAttributes($context); + $char = $context->scanCharacter(); + if ($char == '/') { + $char = $context->scanCharacter(); + if ($char != '>') { + $context->unscanCharacter(); + } + $context->handler_object_element-> + {$context->handler_method_opening}($context->htmlsax, $tag, + $Attributes, TRUE); + $context->handler_object_element-> + {$context->handler_method_closing}($context->htmlsax, $tag, + TRUE); + } else { + $context->handler_object_element-> + {$context->handler_method_opening}($context->htmlsax, $tag, + $Attributes, FALSE); + } + } + return TSax3_StateParser::TSAX3_STATE_START; + } +} + +/** +* Deals with XML escapes handling comments and CDATA correctly +* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_EscapeState { + /** + * @param TSax3_StateParser subclass + * @return constant TSAX3_STATE_START + * @access protected + */ + function parse(&$context) { + $char = $context->ScanCharacter(); + if ($char == '-') { + $char = $context->ScanCharacter(); + if ($char == '-') { + $context->unscanCharacter(); + $context->unscanCharacter(); + $text = $context->scanUntilString('-->'); + $text .= $context->scanCharacter(); + $text .= $context->scanCharacter(); + } else { + $context->unscanCharacter(); + $text = $context->scanUntilString('>'); + } + } else if ( $char == '[') { + $context->unscanCharacter(); + $text = $context->scanUntilString(']>'); + $text.= $context->scanCharacter(); + } else { + $context->unscanCharacter(); + $text = $context->scanUntilString('>'); + } + + $context->IgnoreCharacter(); + if ($text != '') { + $context->handler_object_escape-> + {$context->handler_method_escape}($context->htmlsax, $text); + } + return TSax3_StateParser::TSAX3_STATE_START; + } +} +/** +* Deals with JASP/ASP markup +* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_JaspState { + /** + * @param TSax3_StateParser subclass + * @return constant TSAX3_STATE_START + * @access protected + */ + function parse(&$context) { + $text = $context->scanUntilString('%>'); + if ($text != '') { + $context->handler_object_jasp-> + {$context->handler_method_jasp}($context->htmlsax, $text); + } + $context->IgnoreCharacter(); + $context->IgnoreCharacter(); + return TSax3_StateParser::TSAX3_STATE_START; + } +} +/** +* Deals with XML processing instructions +* @package System.Security.SafeHtml +* @access protected +*/ +class TSax3_PiState { + /** + * @param TSax3_StateParser subclass + * @return constant TSAX3_STATE_START + * @access protected + */ + function parse(&$context) { + $target = $context->scanUntilCharacters(" \n\r\t"); + $data = $context->scanUntilString('?>'); + if ($data != '') { + $context->handler_object_pi-> + {$context->handler_method_pi}($context->htmlsax, $target, $data); + } + $context->IgnoreCharacter(); + $context->IgnoreCharacter(); + return TSax3_StateParser::TSAX3_STATE_START; + } +} ?> \ No newline at end of file diff --git a/framework/3rdParty/SafeHtml/TSafeHtmlParser.php b/framework/3rdParty/SafeHtml/TSafeHtmlParser.php index b80f31a6..ad14baf9 100644 --- a/framework/3rdParty/SafeHtml/TSafeHtmlParser.php +++ b/framework/3rdParty/SafeHtml/TSafeHtmlParser.php @@ -1,673 +1,673 @@ - - * @copyright 2004-2005 Roman Ivanov - * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version 1.3.7 - * @link http://pixel-apes.com/safehtml/ - */ - - -/** - * This package requires HTMLSax3 package - */ -Prado::using('System.3rdParty.SafeHtml.HTMLSax3'); - - -/** - * - * TSafeHtmlParser - * - * This parser strips down all potentially dangerous content within HTML: - *
    - *
  • opening tag without its closing tag
  • - *
  • closing tag without its opening tag
  • - *
  • any of these tags: "base", "basefont", "head", "html", "body", "applet", - * "object", "iframe", "frame", "frameset", "script", "layer", "ilayer", "embed", - * "bgsound", "link", "meta", "style", "title", "blink", "xml" etc.
  • - *
  • any of these attributes: on*, data*, dynsrc
  • - *
  • javascript:/vbscript:/about: etc. protocols
  • - *
  • expression/behavior etc. in styles
  • - *
  • any other active content
  • - *
- * It also tries to convert code to XHTML valid, but htmltidy is far better - * solution for this task. - * - * Example: - *
- * $parser = Prado::createComponent('System.3rdParty.SafeHtml.TSafeHtmlParser');
- * $result = $parser->parse($doc);
- * 
- * - * @category HTML - * @package System.Security - * @author Roman Ivanov - * @copyright 1997-2005 Roman Ivanov - * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version Release: @package_version@ - * @link http://pear.php.net/package/SafeHTML - */ -class TSafeHtmlParser -{ - /** - * Storage for resulting HTML output - * - * @var string - * @access private - */ - private $_xhtml = ''; - - /** - * Array of counters for each tag - * - * @var array - * @access private - */ - private $_counter = array(); - - /** - * Stack of unclosed tags - * - * @var array - * @access private - */ - private $_stack = array(); - - /** - * Array of counters for tags that must be deleted with all content - * - * @var array - * @access private - */ - private $_dcCounter = array(); - - /** - * Stack of unclosed tags that must be deleted with all content - * - * @var array - * @access private - */ - private $_dcStack = array(); - - /** - * Stores level of list (ol/ul) nesting - * - * @var int - * @access private - */ - private $_listScope = 0; - - /** - * Stack of unclosed list tags - * - * @var array - * @access private - */ - private $_liStack = array(); - - /** - * Array of prepared regular expressions for protocols (schemas) matching - * - * @var array - * @access private - */ - private $_protoRegexps = array(); - - /** - * Array of prepared regular expressions for CSS matching - * - * @var array - * @access private - */ - private $_cssRegexps = array(); - - /** - * List of single tags ("") - * - * @var array - * @access public - */ - public $singleTags = array('area', 'br', 'img', 'input', 'hr', 'wbr', ); - - /** - * List of dangerous tags (such tags will be deleted) - * - * @var array - * @access public - */ - public $deleteTags = array( - 'applet', 'base', 'basefont', 'bgsound', 'blink', 'body', - 'embed', 'frame', 'frameset', 'head', 'html', 'ilayer', - 'iframe', 'layer', 'link', 'meta', 'object', 'style', - 'title', 'script', - ); - - /** - * List of dangerous tags (such tags will be deleted, and all content - * inside this tags will be also removed) - * - * @var array - * @access public - */ - public $deleteTagsContent = array('script', 'style', 'title', 'xml', ); - - /** - * Type of protocols filtering ('white' or 'black') - * - * @var string - * @access public - */ - public $protocolFiltering = 'white'; - - /** - * List of "dangerous" protocols (used for blacklist-filtering) - * - * @var array - * @access public - */ - public $blackProtocols = array( - 'about', 'chrome', 'data', 'disk', 'hcp', - 'help', 'javascript', 'livescript', 'lynxcgi', 'lynxexec', - 'ms-help', 'ms-its', 'mhtml', 'mocha', 'opera', - 'res', 'resource', 'shell', 'vbscript', 'view-source', - 'vnd.ms.radio', 'wysiwyg', - ); - - /** - * List of "safe" protocols (used for whitelist-filtering) - * - * @var array - * @access public - */ - public $whiteProtocols = array( - 'ed2k', 'file', 'ftp', 'gopher', 'http', 'https', - 'irc', 'mailto', 'news', 'nntp', 'telnet', 'webcal', - 'xmpp', 'callto', - ); - - /** - * List of attributes that can contain protocols - * - * @var array - * @access public - */ - public $protocolAttributes = array( - 'action', 'background', 'codebase', 'dynsrc', 'href', 'lowsrc', 'src', - ); - - /** - * List of dangerous CSS keywords - * - * Whole style="" attribute will be removed, if parser will find one of - * these keywords - * - * @var array - * @access public - */ - public $cssKeywords = array( - 'absolute', 'behavior', 'behaviour', 'content', 'expression', - 'fixed', 'include-source', 'moz-binding', - ); - - /** - * List of tags that can have no "closing tag" - * - * @var array - * @access public - * @deprecated XHTML does not allow such tags - */ - public $noClose = array(); - - /** - * List of block-level tags that terminates paragraph - * - * Paragraph will be closed when this tags opened - * - * @var array - * @access public - */ - public $closeParagraph = array( - 'address', 'blockquote', 'center', 'dd', 'dir', 'div', - 'dl', 'dt', 'h1', 'h2', 'h3', 'h4', - 'h5', 'h6', 'hr', 'isindex', 'listing', 'marquee', - 'menu', 'multicol', 'ol', 'p', 'plaintext', 'pre', - 'table', 'ul', 'xmp', - ); - - /** - * List of table tags, all table tags outside a table will be removed - * - * @var array - * @access public - */ - public $tableTags = array( - 'caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', - 'thead', 'tr', - ); - - /** - * List of list tags - * - * @var array - * @access public - */ - public $listTags = array('dir', 'menu', 'ol', 'ul', 'dl', ); - - /** - * List of dangerous attributes - * - * @var array - * @access public - */ - public $attributes = array('dynsrc'); - //public $attributes = array('dynsrc', 'id', 'name', ); //id and name are dangerous? - - /** - * List of allowed "namespaced" attributes - * - * @var array - * @access public - */ - public $attributesNS = array('xml:lang', ); - - /** - * Constructs class - * - * @access public - */ - public function __construct() - { - //making regular expressions based on Proto & CSS arrays - foreach ($this->blackProtocols as $proto) { - $preg = "/[\s\x01-\x1F]*"; - for ($i=0; $i_protoRegexps[] = $preg; - } - - foreach ($this->cssKeywords as $css) { - $this->_cssRegexps[] = '/' . $css . '/i'; - } - return true; - } - - /** - * Handles the writing of attributes - called from $this->_openHandler() - * - * @param array $attrs array of attributes $name => $value - * @return boolean - * @access private - */ - private function _writeAttrs ($attrs) - { - if (is_array($attrs)) { - foreach ($attrs as $name => $value) { - - $name = strtolower($name); - - if (strpos($name, 'on') === 0) { - continue; - } - if (strpos($name, 'data') === 0) { - continue; - } - if (in_array($name, $this->attributes)) { - continue; - } - if (!preg_match("/^[a-z0-9]+$/i", $name)) { - if (!in_array($name, $this->attributesNS)) - { - continue; - } - } - - if (($value === TRUE) || (is_null($value))) { - $value = $name; - } - - if ($name == 'style') { - - // removes insignificant backslahes - $value = str_replace("\\", '', $value); - - // removes CSS comments - while (1) - { - $_value = preg_replace("!/\*.*?\*/!s", '', $value); - if ($_value == $value) break; - $value = $_value; - } - - // replace all & to & - $value = str_replace('&', '&', $value); - $value = str_replace('&', '&', $value); - - foreach ($this->_cssRegexps as $css) { - if (preg_match($css, $value)) { - continue 2; - } - } - foreach ($this->_protoRegexps as $proto) { - if (preg_match($proto, $value)) { - continue 2; - } - } - } - - $tempval = preg_replace('/&#(\d+);?/me', "chr('\\1')", $value); //"' - $tempval = preg_replace('/&#x([0-9a-f]+);?/mei', "chr(hexdec('\\1'))", $tempval); - - if ((in_array($name, $this->protocolAttributes)) && - (strpos($tempval, ':') !== false)) - { - if ($this->protocolFiltering == 'black') { - foreach ($this->_protoRegexps as $proto) { - if (preg_match($proto, $tempval)) continue 2; - } - } else { - $_tempval = explode(':', $tempval); - $proto = $_tempval[0]; - if (!in_array($proto, $this->whiteProtocols)) { - continue; - } - } - } - - $value = str_replace("\"", """, $value); - $this->_xhtml .= ' ' . $name . '="' . $value . '"'; - } - } - return true; - } - - /** - * Opening tag handler - called from HTMLSax - * - * @param object $parser HTML Parser - * @param string $name tag name - * @param array $attrs tag attributes - * @return boolean - * @access private - */ - public function _openHandler(&$parser, $name, $attrs) - { - $name = strtolower($name); - - if (in_array($name, $this->deleteTagsContent)) { - array_push($this->_dcStack, $name); - $this->_dcCounter[$name] = isset($this->_dcCounter[$name]) ? $this->_dcCounter[$name]+1 : 1; - } - if (count($this->_dcStack) != 0) { - return true; - } - - if (in_array($name, $this->deleteTags)) { - return true; - } - - if (!preg_match("/^[a-z0-9]+$/i", $name)) { - if (preg_match("!(?:\@|://)!i", $name)) { - $this->_xhtml .= '<' . $name . '>'; - } - return true; - } - - if (in_array($name, $this->singleTags)) { - $this->_xhtml .= '<' . $name; - $this->_writeAttrs($attrs); - $this->_xhtml .= ' />'; - return true; - } - - // TABLES: cannot open table elements when we are not inside table - if ((isset($this->_counter['table'])) && ($this->_counter['table'] <= 0) - && (in_array($name, $this->tableTags))) - { - return true; - } - - // PARAGRAPHS: close paragraph when closeParagraph tags opening - if ((in_array($name, $this->closeParagraph)) && (in_array('p', $this->_stack))) { - $this->_closeHandler($parser, 'p'); - } - - // LISTS: we should close
  • if
  • of the same level opening - if ($name == 'li' && count($this->_liStack) && - $this->_listScope == $this->_liStack[count($this->_liStack)-1]) - { - $this->_closeHandler($parser, 'li'); - } - - // LISTS: we want to know on what nesting level of lists we are - if (in_array($name, $this->listTags)) { - $this->_listScope++; - } - if ($name == 'li') { - array_push($this->_liStack, $this->_listScope); - } - - $this->_xhtml .= '<' . $name; - $this->_writeAttrs($attrs); - $this->_xhtml .= '>'; - array_push($this->_stack,$name); - $this->_counter[$name] = isset($this->_counter[$name]) ? $this->_counter[$name]+1 : 1; - return true; - } - - /** - * Closing tag handler - called from HTMLSax - * - * @param object $parsers HTML parser - * @param string $name tag name - * @return boolean - * @access private - */ - public function _closeHandler(&$parser, $name) - { - - $name = strtolower($name); - - if (isset($this->_dcCounter[$name]) && ($this->_dcCounter[$name] > 0) && - (in_array($name, $this->deleteTagsContent))) - { - while ($name != ($tag = array_pop($this->_dcStack))) { - $this->_dcCounter[$tag]--; - } - - $this->_dcCounter[$name]--; - } - - if (count($this->_dcStack) != 0) { - return true; - } - - if ((isset($this->_counter[$name])) && ($this->_counter[$name] > 0)) { - while ($name != ($tag = array_pop($this->_stack))) { - $this->_closeTag($tag); - } - - $this->_closeTag($name); - } - return true; - } - - /** - * Closes tag - * - * @param string $tag tag name - * @return boolean - * @access private - */ - public function _closeTag($tag) - { - if (!in_array($tag, $this->noClose)) { - $this->_xhtml .= ''; - } - - $this->_counter[$tag]--; - - if (in_array($tag, $this->listTags)) { - $this->_listScope--; - } - - if ($tag == 'li') { - array_pop($this->_liStack); - } - return true; - } - - /** - * Character data handler - called from HTMLSax - * - * @param object $parser HTML parser - * @param string $data textual data - * @return boolean - * @access private - */ - public function _dataHandler(&$parser, $data) - { - if (count($this->_dcStack) == 0) { - $this->_xhtml .= $data; - } - return true; - } - - /** - * Escape handler - called from HTMLSax - * - * @param object $parser HTML parser - * @param string $data comments or other type of data - * @return boolean - * @access private - */ - public function _escapeHandler(&$parser, $data) - { - return true; - } - - /** - * Returns the XHTML document - * - * @return string Processed (X)HTML document - * @access public - */ - public function getXHTML () - { - while ($tag = array_pop($this->_stack)) { - $this->_closeTag($tag); - } - - return $this->_xhtml; - } - - /** - * Clears current document data - * - * @return boolean - * @access public - */ - public function clear() - { - $this->_xhtml = ''; - return true; - } - - /** - * Main parsing fuction - * - * @param string $doc HTML document for processing - * @return string Processed (X)HTML document - * @access public - */ - public function parse($doc, $isUTF7=false) - { - $this->clear(); - - // Save all '<' symbols - $doc = preg_replace("/<(?=[^a-zA-Z\/\!\?\%])/", '<', (string)$doc); - - // Web documents shouldn't contains \x00 symbol - $doc = str_replace("\x00", '', $doc); - - // Opera6 bug workaround - $doc = str_replace("\xC0\xBC", '<', $doc); - - // UTF-7 encoding ASCII decode - if($isUTF7) - $doc = $this->repackUTF7($doc); - - // Instantiate the parser - $parser= new TSax3(); - - // Set up the parser - $parser->set_object($this); - - $parser->set_element_handler('_openHandler','_closeHandler'); - $parser->set_data_handler('_dataHandler'); - $parser->set_escape_handler('_escapeHandler'); - - $parser->parse($doc); - - return $this->getXHTML(); - - } - - - /** - * UTF-7 decoding fuction - * - * @param string $str HTML document for recode ASCII part of UTF-7 back to ASCII - * @return string Decoded document - * @access private - */ - private function repackUTF7($str) - { - return preg_replace_callback('!\+([0-9a-zA-Z/]+)\-!', array($this, 'repackUTF7Callback'), $str); - } - - /** - * Additional UTF-7 decoding fuction - * - * @param string $str String for recode ASCII part of UTF-7 back to ASCII - * @return string Recoded string - * @access private - */ - private function repackUTF7Callback($str) - { - $str = base64_decode($str[1]); - $str = preg_replace_callback('/^((?:\x00.)*)((?:[^\x00].)+)/', array($this, 'repackUTF7Back'), $str); - return preg_replace('/\x00(.)/', '$1', $str); - } - - /** - * Additional UTF-7 encoding fuction - * - * @param string $str String for recode ASCII part of UTF-7 back to ASCII - * @return string Recoded string - * @access private - */ - private function repackUTF7Back($str) - { - return $str[1].'+'.rtrim(base64_encode($str[2]), '=').'-'; - } -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * c-hanging-comment-ender-p: nil - * End: - */ - + + * @copyright 2004-2005 Roman Ivanov + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version 1.3.7 + * @link http://pixel-apes.com/safehtml/ + */ + + +/** + * This package requires HTMLSax3 package + */ +Prado::using('System.3rdParty.SafeHtml.HTMLSax3'); + + +/** + * + * TSafeHtmlParser + * + * This parser strips down all potentially dangerous content within HTML: + *
      + *
    • opening tag without its closing tag
    • + *
    • closing tag without its opening tag
    • + *
    • any of these tags: "base", "basefont", "head", "html", "body", "applet", + * "object", "iframe", "frame", "frameset", "script", "layer", "ilayer", "embed", + * "bgsound", "link", "meta", "style", "title", "blink", "xml" etc.
    • + *
    • any of these attributes: on*, data*, dynsrc
    • + *
    • javascript:/vbscript:/about: etc. protocols
    • + *
    • expression/behavior etc. in styles
    • + *
    • any other active content
    • + *
    + * It also tries to convert code to XHTML valid, but htmltidy is far better + * solution for this task. + * + * Example: + *
    + * $parser = Prado::createComponent('System.3rdParty.SafeHtml.TSafeHtmlParser');
    + * $result = $parser->parse($doc);
    + * 
    + * + * @category HTML + * @package System.Security + * @author Roman Ivanov + * @copyright 1997-2005 Roman Ivanov + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version Release: @package_version@ + * @link http://pear.php.net/package/SafeHTML + */ +class TSafeHtmlParser +{ + /** + * Storage for resulting HTML output + * + * @var string + * @access private + */ + private $_xhtml = ''; + + /** + * Array of counters for each tag + * + * @var array + * @access private + */ + private $_counter = array(); + + /** + * Stack of unclosed tags + * + * @var array + * @access private + */ + private $_stack = array(); + + /** + * Array of counters for tags that must be deleted with all content + * + * @var array + * @access private + */ + private $_dcCounter = array(); + + /** + * Stack of unclosed tags that must be deleted with all content + * + * @var array + * @access private + */ + private $_dcStack = array(); + + /** + * Stores level of list (ol/ul) nesting + * + * @var int + * @access private + */ + private $_listScope = 0; + + /** + * Stack of unclosed list tags + * + * @var array + * @access private + */ + private $_liStack = array(); + + /** + * Array of prepared regular expressions for protocols (schemas) matching + * + * @var array + * @access private + */ + private $_protoRegexps = array(); + + /** + * Array of prepared regular expressions for CSS matching + * + * @var array + * @access private + */ + private $_cssRegexps = array(); + + /** + * List of single tags ("") + * + * @var array + * @access public + */ + public $singleTags = array('area', 'br', 'img', 'input', 'hr', 'wbr', ); + + /** + * List of dangerous tags (such tags will be deleted) + * + * @var array + * @access public + */ + public $deleteTags = array( + 'applet', 'base', 'basefont', 'bgsound', 'blink', 'body', + 'embed', 'frame', 'frameset', 'head', 'html', 'ilayer', + 'iframe', 'layer', 'link', 'meta', 'object', 'style', + 'title', 'script', + ); + + /** + * List of dangerous tags (such tags will be deleted, and all content + * inside this tags will be also removed) + * + * @var array + * @access public + */ + public $deleteTagsContent = array('script', 'style', 'title', 'xml', ); + + /** + * Type of protocols filtering ('white' or 'black') + * + * @var string + * @access public + */ + public $protocolFiltering = 'white'; + + /** + * List of "dangerous" protocols (used for blacklist-filtering) + * + * @var array + * @access public + */ + public $blackProtocols = array( + 'about', 'chrome', 'data', 'disk', 'hcp', + 'help', 'javascript', 'livescript', 'lynxcgi', 'lynxexec', + 'ms-help', 'ms-its', 'mhtml', 'mocha', 'opera', + 'res', 'resource', 'shell', 'vbscript', 'view-source', + 'vnd.ms.radio', 'wysiwyg', + ); + + /** + * List of "safe" protocols (used for whitelist-filtering) + * + * @var array + * @access public + */ + public $whiteProtocols = array( + 'ed2k', 'file', 'ftp', 'gopher', 'http', 'https', + 'irc', 'mailto', 'news', 'nntp', 'telnet', 'webcal', + 'xmpp', 'callto', + ); + + /** + * List of attributes that can contain protocols + * + * @var array + * @access public + */ + public $protocolAttributes = array( + 'action', 'background', 'codebase', 'dynsrc', 'href', 'lowsrc', 'src', + ); + + /** + * List of dangerous CSS keywords + * + * Whole style="" attribute will be removed, if parser will find one of + * these keywords + * + * @var array + * @access public + */ + public $cssKeywords = array( + 'absolute', 'behavior', 'behaviour', 'content', 'expression', + 'fixed', 'include-source', 'moz-binding', + ); + + /** + * List of tags that can have no "closing tag" + * + * @var array + * @access public + * @deprecated XHTML does not allow such tags + */ + public $noClose = array(); + + /** + * List of block-level tags that terminates paragraph + * + * Paragraph will be closed when this tags opened + * + * @var array + * @access public + */ + public $closeParagraph = array( + 'address', 'blockquote', 'center', 'dd', 'dir', 'div', + 'dl', 'dt', 'h1', 'h2', 'h3', 'h4', + 'h5', 'h6', 'hr', 'isindex', 'listing', 'marquee', + 'menu', 'multicol', 'ol', 'p', 'plaintext', 'pre', + 'table', 'ul', 'xmp', + ); + + /** + * List of table tags, all table tags outside a table will be removed + * + * @var array + * @access public + */ + public $tableTags = array( + 'caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', + 'thead', 'tr', + ); + + /** + * List of list tags + * + * @var array + * @access public + */ + public $listTags = array('dir', 'menu', 'ol', 'ul', 'dl', ); + + /** + * List of dangerous attributes + * + * @var array + * @access public + */ + public $attributes = array('dynsrc'); + //public $attributes = array('dynsrc', 'id', 'name', ); //id and name are dangerous? + + /** + * List of allowed "namespaced" attributes + * + * @var array + * @access public + */ + public $attributesNS = array('xml:lang', ); + + /** + * Constructs class + * + * @access public + */ + public function __construct() + { + //making regular expressions based on Proto & CSS arrays + foreach ($this->blackProtocols as $proto) { + $preg = "/[\s\x01-\x1F]*"; + for ($i=0; $i_protoRegexps[] = $preg; + } + + foreach ($this->cssKeywords as $css) { + $this->_cssRegexps[] = '/' . $css . '/i'; + } + return true; + } + + /** + * Handles the writing of attributes - called from $this->_openHandler() + * + * @param array $attrs array of attributes $name => $value + * @return boolean + * @access private + */ + private function _writeAttrs ($attrs) + { + if (is_array($attrs)) { + foreach ($attrs as $name => $value) { + + $name = strtolower($name); + + if (strpos($name, 'on') === 0) { + continue; + } + if (strpos($name, 'data') === 0) { + continue; + } + if (in_array($name, $this->attributes)) { + continue; + } + if (!preg_match("/^[a-z0-9]+$/i", $name)) { + if (!in_array($name, $this->attributesNS)) + { + continue; + } + } + + if (($value === TRUE) || (is_null($value))) { + $value = $name; + } + + if ($name == 'style') { + + // removes insignificant backslahes + $value = str_replace("\\", '', $value); + + // removes CSS comments + while (1) + { + $_value = preg_replace("!/\*.*?\*/!s", '', $value); + if ($_value == $value) break; + $value = $_value; + } + + // replace all & to & + $value = str_replace('&', '&', $value); + $value = str_replace('&', '&', $value); + + foreach ($this->_cssRegexps as $css) { + if (preg_match($css, $value)) { + continue 2; + } + } + foreach ($this->_protoRegexps as $proto) { + if (preg_match($proto, $value)) { + continue 2; + } + } + } + + $tempval = preg_replace('/&#(\d+);?/me', "chr('\\1')", $value); //"' + $tempval = preg_replace('/&#x([0-9a-f]+);?/mei', "chr(hexdec('\\1'))", $tempval); + + if ((in_array($name, $this->protocolAttributes)) && + (strpos($tempval, ':') !== false)) + { + if ($this->protocolFiltering == 'black') { + foreach ($this->_protoRegexps as $proto) { + if (preg_match($proto, $tempval)) continue 2; + } + } else { + $_tempval = explode(':', $tempval); + $proto = $_tempval[0]; + if (!in_array($proto, $this->whiteProtocols)) { + continue; + } + } + } + + $value = str_replace("\"", """, $value); + $this->_xhtml .= ' ' . $name . '="' . $value . '"'; + } + } + return true; + } + + /** + * Opening tag handler - called from HTMLSax + * + * @param object $parser HTML Parser + * @param string $name tag name + * @param array $attrs tag attributes + * @return boolean + * @access private + */ + public function _openHandler(&$parser, $name, $attrs) + { + $name = strtolower($name); + + if (in_array($name, $this->deleteTagsContent)) { + array_push($this->_dcStack, $name); + $this->_dcCounter[$name] = isset($this->_dcCounter[$name]) ? $this->_dcCounter[$name]+1 : 1; + } + if (count($this->_dcStack) != 0) { + return true; + } + + if (in_array($name, $this->deleteTags)) { + return true; + } + + if (!preg_match("/^[a-z0-9]+$/i", $name)) { + if (preg_match("!(?:\@|://)!i", $name)) { + $this->_xhtml .= '<' . $name . '>'; + } + return true; + } + + if (in_array($name, $this->singleTags)) { + $this->_xhtml .= '<' . $name; + $this->_writeAttrs($attrs); + $this->_xhtml .= ' />'; + return true; + } + + // TABLES: cannot open table elements when we are not inside table + if ((isset($this->_counter['table'])) && ($this->_counter['table'] <= 0) + && (in_array($name, $this->tableTags))) + { + return true; + } + + // PARAGRAPHS: close paragraph when closeParagraph tags opening + if ((in_array($name, $this->closeParagraph)) && (in_array('p', $this->_stack))) { + $this->_closeHandler($parser, 'p'); + } + + // LISTS: we should close
  • if
  • of the same level opening + if ($name == 'li' && count($this->_liStack) && + $this->_listScope == $this->_liStack[count($this->_liStack)-1]) + { + $this->_closeHandler($parser, 'li'); + } + + // LISTS: we want to know on what nesting level of lists we are + if (in_array($name, $this->listTags)) { + $this->_listScope++; + } + if ($name == 'li') { + array_push($this->_liStack, $this->_listScope); + } + + $this->_xhtml .= '<' . $name; + $this->_writeAttrs($attrs); + $this->_xhtml .= '>'; + array_push($this->_stack,$name); + $this->_counter[$name] = isset($this->_counter[$name]) ? $this->_counter[$name]+1 : 1; + return true; + } + + /** + * Closing tag handler - called from HTMLSax + * + * @param object $parsers HTML parser + * @param string $name tag name + * @return boolean + * @access private + */ + public function _closeHandler(&$parser, $name) + { + + $name = strtolower($name); + + if (isset($this->_dcCounter[$name]) && ($this->_dcCounter[$name] > 0) && + (in_array($name, $this->deleteTagsContent))) + { + while ($name != ($tag = array_pop($this->_dcStack))) { + $this->_dcCounter[$tag]--; + } + + $this->_dcCounter[$name]--; + } + + if (count($this->_dcStack) != 0) { + return true; + } + + if ((isset($this->_counter[$name])) && ($this->_counter[$name] > 0)) { + while ($name != ($tag = array_pop($this->_stack))) { + $this->_closeTag($tag); + } + + $this->_closeTag($name); + } + return true; + } + + /** + * Closes tag + * + * @param string $tag tag name + * @return boolean + * @access private + */ + public function _closeTag($tag) + { + if (!in_array($tag, $this->noClose)) { + $this->_xhtml .= ''; + } + + $this->_counter[$tag]--; + + if (in_array($tag, $this->listTags)) { + $this->_listScope--; + } + + if ($tag == 'li') { + array_pop($this->_liStack); + } + return true; + } + + /** + * Character data handler - called from HTMLSax + * + * @param object $parser HTML parser + * @param string $data textual data + * @return boolean + * @access private + */ + public function _dataHandler(&$parser, $data) + { + if (count($this->_dcStack) == 0) { + $this->_xhtml .= $data; + } + return true; + } + + /** + * Escape handler - called from HTMLSax + * + * @param object $parser HTML parser + * @param string $data comments or other type of data + * @return boolean + * @access private + */ + public function _escapeHandler(&$parser, $data) + { + return true; + } + + /** + * Returns the XHTML document + * + * @return string Processed (X)HTML document + * @access public + */ + public function getXHTML () + { + while ($tag = array_pop($this->_stack)) { + $this->_closeTag($tag); + } + + return $this->_xhtml; + } + + /** + * Clears current document data + * + * @return boolean + * @access public + */ + public function clear() + { + $this->_xhtml = ''; + return true; + } + + /** + * Main parsing fuction + * + * @param string $doc HTML document for processing + * @return string Processed (X)HTML document + * @access public + */ + public function parse($doc, $isUTF7=false) + { + $this->clear(); + + // Save all '<' symbols + $doc = preg_replace("/<(?=[^a-zA-Z\/\!\?\%])/", '<', (string)$doc); + + // Web documents shouldn't contains \x00 symbol + $doc = str_replace("\x00", '', $doc); + + // Opera6 bug workaround + $doc = str_replace("\xC0\xBC", '<', $doc); + + // UTF-7 encoding ASCII decode + if($isUTF7) + $doc = $this->repackUTF7($doc); + + // Instantiate the parser + $parser= new TSax3(); + + // Set up the parser + $parser->set_object($this); + + $parser->set_element_handler('_openHandler','_closeHandler'); + $parser->set_data_handler('_dataHandler'); + $parser->set_escape_handler('_escapeHandler'); + + $parser->parse($doc); + + return $this->getXHTML(); + + } + + + /** + * UTF-7 decoding fuction + * + * @param string $str HTML document for recode ASCII part of UTF-7 back to ASCII + * @return string Decoded document + * @access private + */ + private function repackUTF7($str) + { + return preg_replace_callback('!\+([0-9a-zA-Z/]+)\-!', array($this, 'repackUTF7Callback'), $str); + } + + /** + * Additional UTF-7 decoding fuction + * + * @param string $str String for recode ASCII part of UTF-7 back to ASCII + * @return string Recoded string + * @access private + */ + private function repackUTF7Callback($str) + { + $str = base64_decode($str[1]); + $str = preg_replace_callback('/^((?:\x00.)*)((?:[^\x00].)+)/', array($this, 'repackUTF7Back'), $str); + return preg_replace('/\x00(.)/', '$1', $str); + } + + /** + * Additional UTF-7 encoding fuction + * + * @param string $str String for recode ASCII part of UTF-7 back to ASCII + * @return string Recoded string + * @access private + */ + private function repackUTF7Back($str) + { + return $str[1].'+'.rtrim(base64_encode($str[2]), '=').'-'; + } +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ + ?> \ No newline at end of file diff --git a/framework/3rdParty/TextHighlighter/Text/Highlighter.php b/framework/3rdParty/TextHighlighter/Text/Highlighter.php index b597b909..9ec09cdb 100644 --- a/framework/3rdParty/TextHighlighter/Text/Highlighter.php +++ b/framework/3rdParty/TextHighlighter/Text/Highlighter.php @@ -1,397 +1,397 @@ - - * @copyright 2004-2006 Andrey Demenev - * @license http://www.php.net/license/3_0.txt PHP License - * @version CVS: $Id: Highlighter.php,v 1.1 2007/06/03 02:35:28 ssttoo Exp $ - * @link http://pear.php.net/package/Text_Highlighter - */ - -// {{{ BC constants - -// BC trick : define constants related to default -// renderer if needed -if (!defined('HL_NUMBERS_LI')) { - /**#@+ - * Constant for use with $options['numbers'] - * @see Text_Highlighter_Renderer_Html::_init() - */ - /** - * use numbered list - */ - define ('HL_NUMBERS_LI' , 1); - /** - * Use 2-column table with line numbers in left column and code in right column. - * Forces $options['tag'] = HL_TAG_PRE - */ - define ('HL_NUMBERS_TABLE' , 2); - /**#@-*/ -} - -// }}} -// {{{ constants -/** - * for our purpose, it is infinity - */ -define ('HL_INFINITY', 1000000000); - -// }}} - -/** - * Text highlighter base class - * - * @author Andrey Demenev - * @copyright 2004-2006 Andrey Demenev - * @license http://www.php.net/license/3_0.txt PHP License - * @version Release: 0.7.0 - * @link http://pear.php.net/package/Text_Highlighter - */ - -// {{{ Text_Highlighter - -/** - * Text highlighter base class - * - * This class implements all functions necessary for highlighting, - * but it does not contain highlighting rules. Actual highlighting is - * done using a descendent of this class. - * - * One is not supposed to manually create descendent classes. - * Instead, describe highlighting rules in XML format and - * use {@link Text_Highlighter_Generator} to create descendent class. - * Alternatively, an instance of a descendent class can be created - * directly. - * - * Use {@link Text_Highlighter::factory()} to create an - * object for particular language highlighter - * - * Usage example - * - *require_once 'Text/Highlighter.php'; - *$hlSQL =& Text_Highlighter::factory('SQL',array('numbers'=>true)); - *echo $hlSQL->highlight('SELECT * FROM table a WHERE id = 12'); - * - * - * @author Andrey Demenev - * @package Text_Highlighter - * @access public - */ - -class Text_Highlighter -{ - // {{{ members - - /** - * Syntax highlighting rules. - * Auto-generated classes set this var - * - * @access protected - * @see _init - * @var array - */ - var $_syntax; - - /** - * Renderer object. - * - * @access private - * @var array - */ - var $_renderer; - - /** - * Options. Keeped for BC - * - * @access protected - * @var array - */ - var $_options = array(); - - /** - * Conditionds - * - * @access protected - * @var array - */ - var $_conditions = array(); - - /** - * Disabled keywords - * - * @access protected - * @var array - */ - var $_disabled = array(); - - /** - * Language - * - * @access protected - * @var string - */ - var $_language = ''; - - // }}} - // {{{ _checkDefines - - /** - * Called by subclssses' constructors to enable/disable - * optional highlighter rules - * - * @param array $defines Conditional defines - * - * @access protected - */ - function _checkDefines() - { - if (isset($this->_options['defines'])) { - $defines = $this->_options['defines']; - } else { - $defines = array(); - } - foreach ($this->_conditions as $name => $actions) { - foreach($actions as $action) { - $present = in_array($name, $defines); - if (!$action[1]) { - $present = !$present; - } - if ($present) { - unset($this->_disabled[$action[0]]); - } else { - $this->_disabled[$action[0]] = true; - } - } - } - } - - // }}} - // {{{ factory - - /** - * Create a new Highlighter object for specified language - * - * @param string $lang language, for example "SQL" - * @param array $options Rendering options. This - * parameter is only keeped for BC reasons, use - * {@link Text_Highlighter::setRenderer()} instead - * - * @return mixed a newly created Highlighter object, or - * a PEAR error object on error - * - * @static - * @access public - */ - public static function factory($lang, $options = array()) - { - $lang = strtoupper($lang); - $langFile = dirname(__FILE__)."/Highlighter/$lang.php"; - if (is_file($langFile)) - include_once $langFile; - else - return false; - - $classname = 'Text_Highlighter_' . $lang; - - if (!class_exists($classname)) - return false; - - return new $classname($options); - } - - // }}} - // {{{ setRenderer - - /** - * Set renderer object - * - * @param object $renderer Text_Highlighter_Renderer - * - * @access public - */ - function setRenderer($renderer) - { - $this->_renderer = $renderer; - } - - // }}} - - /** - * Helper function to find matching brackets - * - * @access private - */ - function _matchingBrackets($str) - { - return strtr($str, '()<>[]{}', ')(><][}{'); - } - - - - - function _getToken() - { - if (!empty($this->_tokenStack)) { - return array_pop($this->_tokenStack); - } - if ($this->_pos >= $this->_len) { - return NULL; - } - - if ($this->_state != -1 && preg_match($this->_endpattern, $this->_str, $m, PREG_OFFSET_CAPTURE, $this->_pos)) { - $endpos = $m[0][1]; - $endmatch = $m[0][0]; - } else { - $endpos = -1; - } - preg_match ($this->_regs[$this->_state], $this->_str, $m, PREG_OFFSET_CAPTURE, $this->_pos); - $n = 1; - - - foreach ($this->_counts[$this->_state] as $i=>$count) { - if (!isset($m[$n])) { - break; - } - if ($m[$n][1]>-1 && ($endpos == -1 || $m[$n][1] < $endpos)) { - if ($this->_states[$this->_state][$i] != -1) { - $this->_tokenStack[] = array($this->_delim[$this->_state][$i], $m[$n][0]); - } else { - $inner = $this->_inner[$this->_state][$i]; - if (isset($this->_parts[$this->_state][$i])) { - $parts = array(); - $partpos = $m[$n][1]; - for ($j=1; $j<=$count; $j++) { - if ($m[$j+$n][1] < 0) { - continue; - } - if (isset($this->_parts[$this->_state][$i][$j])) { - if ($m[$j+$n][1] > $partpos) { - array_unshift($parts, array($inner, substr($this->_str, $partpos, $m[$j+$n][1]-$partpos))); - } - array_unshift($parts, array($this->_parts[$this->_state][$i][$j], $m[$j+$n][0])); - } - $partpos = $m[$j+$n][1] + strlen($m[$j+$n][0]); - } - if ($partpos < $m[$n][1] + strlen($m[$n][0])) { - array_unshift($parts, array($inner, substr($this->_str, $partpos, $m[$n][1] - $partpos + strlen($m[$n][0])))); - } - $this->_tokenStack = array_merge($this->_tokenStack, $parts); - } else { - foreach ($this->_keywords[$this->_state][$i] as $g => $re) { - if (isset($this->_disabled[$g])) { - continue; - } - if (preg_match($re, $m[$n][0])) { - $inner = $this->_kwmap[$g]; - break; - } - } - $this->_tokenStack[] = array($inner, $m[$n][0]); - } - } - if ($m[$n][1] > $this->_pos) { - $this->_tokenStack[] = array($this->_lastinner, substr($this->_str, $this->_pos, $m[$n][1]-$this->_pos)); - } - $this->_pos = $m[$n][1] + strlen($m[$n][0]); - if ($this->_states[$this->_state][$i] != -1) { - $this->_stack[] = array($this->_state, $this->_lastdelim, $this->_lastinner, $this->_endpattern); - $this->_lastinner = $this->_inner[$this->_state][$i]; - $this->_lastdelim = $this->_delim[$this->_state][$i]; - $l = $this->_state; - $this->_state = $this->_states[$this->_state][$i]; - $this->_endpattern = $this->_end[$this->_state]; - if ($this->_subst[$l][$i]) { - for ($k=0; $k<=$this->_counts[$l][$i]; $k++) { - if (!isset($m[$i+$k])) { - break; - } - $quoted = preg_quote($m[$n+$k][0], '/'); - $this->_endpattern = str_replace('%'.$k.'%', $quoted, $this->_endpattern); - $this->_endpattern = str_replace('%b'.$k.'%', $this->_matchingBrackets($quoted), $this->_endpattern); - } - } - } - return array_pop($this->_tokenStack); - } - $n += $count + 1; - } - - if ($endpos > -1) { - $this->_tokenStack[] = array($this->_lastdelim, $endmatch); - if ($endpos > $this->_pos) { - $this->_tokenStack[] = array($this->_lastinner, substr($this->_str, $this->_pos, $endpos-$this->_pos)); - } - list($this->_state, $this->_lastdelim, $this->_lastinner, $this->_endpattern) = array_pop($this->_stack); - $this->_pos = $endpos + strlen($endmatch); - return array_pop($this->_tokenStack); - } - $p = $this->_pos; - $this->_pos = HL_INFINITY; - return array($this->_lastinner, substr($this->_str, $p)); - } - - - - - // {{{ highlight - - /** - * Highlights code - * - * @param string $str Code to highlight - * @access public - * @return string Highlighted text - * - */ - - function highlight($str) - { - if (!($this->_renderer)) { - include_once('Text/Highlighter/Renderer/Html.php'); - $this->_renderer = new Text_Highlighter_Renderer_Html($this->_options); - } - $this->_state = -1; - $this->_pos = 0; - $this->_stack = array(); - $this->_tokenStack = array(); - $this->_lastinner = $this->_defClass; - $this->_lastdelim = $this->_defClass; - $this->_endpattern = ''; - $this->_renderer->reset(); - $this->_renderer->setCurrentLanguage($this->_language); - $this->_str = $this->_renderer->preprocess($str); - $this->_len = strlen($this->_str); - while ($token = $this->_getToken()) { - $this->_renderer->acceptToken($token[0], $token[1]); - } - $this->_renderer->finalize(); - return $this->_renderer->getOutput(); - } - - // }}} - -} - -// }}} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * c-hanging-comment-ender-p: nil - * End: - */ - + + * @copyright 2004-2006 Andrey Demenev + * @license http://www.php.net/license/3_0.txt PHP License + * @version CVS: $Id: Highlighter.php,v 1.1 2007/06/03 02:35:28 ssttoo Exp $ + * @link http://pear.php.net/package/Text_Highlighter + */ + +// {{{ BC constants + +// BC trick : define constants related to default +// renderer if needed +if (!defined('HL_NUMBERS_LI')) { + /**#@+ + * Constant for use with $options['numbers'] + * @see Text_Highlighter_Renderer_Html::_init() + */ + /** + * use numbered list + */ + define ('HL_NUMBERS_LI' , 1); + /** + * Use 2-column table with line numbers in left column and code in right column. + * Forces $options['tag'] = HL_TAG_PRE + */ + define ('HL_NUMBERS_TABLE' , 2); + /**#@-*/ +} + +// }}} +// {{{ constants +/** + * for our purpose, it is infinity + */ +define ('HL_INFINITY', 1000000000); + +// }}} + +/** + * Text highlighter base class + * + * @author Andrey Demenev + * @copyright 2004-2006 Andrey Demenev + * @license http://www.php.net/license/3_0.txt PHP License + * @version Release: 0.7.0 + * @link http://pear.php.net/package/Text_Highlighter + */ + +// {{{ Text_Highlighter + +/** + * Text highlighter base class + * + * This class implements all functions necessary for highlighting, + * but it does not contain highlighting rules. Actual highlighting is + * done using a descendent of this class. + * + * One is not supposed to manually create descendent classes. + * Instead, describe highlighting rules in XML format and + * use {@link Text_Highlighter_Generator} to create descendent class. + * Alternatively, an instance of a descendent class can be created + * directly. + * + * Use {@link Text_Highlighter::factory()} to create an + * object for particular language highlighter + * + * Usage example + * + *require_once 'Text/Highlighter.php'; + *$hlSQL =& Text_Highlighter::factory('SQL',array('numbers'=>true)); + *echo $hlSQL->highlight('SELECT * FROM table a WHERE id = 12'); + * + * + * @author Andrey Demenev + * @package Text_Highlighter + * @access public + */ + +class Text_Highlighter +{ + // {{{ members + + /** + * Syntax highlighting rules. + * Auto-generated classes set this var + * + * @access protected + * @see _init + * @var array + */ + var $_syntax; + + /** + * Renderer object. + * + * @access private + * @var array + */ + var $_renderer; + + /** + * Options. Keeped for BC + * + * @access protected + * @var array + */ + var $_options = array(); + + /** + * Conditionds + * + * @access protected + * @var array + */ + var $_conditions = array(); + + /** + * Disabled keywords + * + * @access protected + * @var array + */ + var $_disabled = array(); + + /** + * Language + * + * @access protected + * @var string + */ + var $_language = ''; + + // }}} + // {{{ _checkDefines + + /** + * Called by subclssses' constructors to enable/disable + * optional highlighter rules + * + * @param array $defines Conditional defines + * + * @access protected + */ + function _checkDefines() + { + if (isset($this->_options['defines'])) { + $defines = $this->_options['defines']; + } else { + $defines = array(); + } + foreach ($this->_conditions as $name => $actions) { + foreach($actions as $action) { + $present = in_array($name, $defines); + if (!$action[1]) { + $present = !$present; + } + if ($present) { + unset($this->_disabled[$action[0]]); + } else { + $this->_disabled[$action[0]] = true; + } + } + } + } + + // }}} + // {{{ factory + + /** + * Create a new Highlighter object for specified language + * + * @param string $lang language, for example "SQL" + * @param array $options Rendering options. This + * parameter is only keeped for BC reasons, use + * {@link Text_Highlighter::setRenderer()} instead + * + * @return mixed a newly created Highlighter object, or + * a PEAR error object on error + * + * @static + * @access public + */ + public static function factory($lang, $options = array()) + { + $lang = strtoupper($lang); + $langFile = dirname(__FILE__)."/Highlighter/$lang.php"; + if (is_file($langFile)) + include_once $langFile; + else + return false; + + $classname = 'Text_Highlighter_' . $lang; + + if (!class_exists($classname)) + return false; + + return new $classname($options); + } + + // }}} + // {{{ setRenderer + + /** + * Set renderer object + * + * @param object $renderer Text_Highlighter_Renderer + * + * @access public + */ + function setRenderer($renderer) + { + $this->_renderer = $renderer; + } + + // }}} + + /** + * Helper function to find matching brackets + * + * @access private + */ + function _matchingBrackets($str) + { + return strtr($str, '()<>[]{}', ')(><][}{'); + } + + + + + function _getToken() + { + if (!empty($this->_tokenStack)) { + return array_pop($this->_tokenStack); + } + if ($this->_pos >= $this->_len) { + return NULL; + } + + if ($this->_state != -1 && preg_match($this->_endpattern, $this->_str, $m, PREG_OFFSET_CAPTURE, $this->_pos)) { + $endpos = $m[0][1]; + $endmatch = $m[0][0]; + } else { + $endpos = -1; + } + preg_match ($this->_regs[$this->_state], $this->_str, $m, PREG_OFFSET_CAPTURE, $this->_pos); + $n = 1; + + + foreach ($this->_counts[$this->_state] as $i=>$count) { + if (!isset($m[$n])) { + break; + } + if ($m[$n][1]>-1 && ($endpos == -1 || $m[$n][1] < $endpos)) { + if ($this->_states[$this->_state][$i] != -1) { + $this->_tokenStack[] = array($this->_delim[$this->_state][$i], $m[$n][0]); + } else { + $inner = $this->_inner[$this->_state][$i]; + if (isset($this->_parts[$this->_state][$i])) { + $parts = array(); + $partpos = $m[$n][1]; + for ($j=1; $j<=$count; $j++) { + if ($m[$j+$n][1] < 0) { + continue; + } + if (isset($this->_parts[$this->_state][$i][$j])) { + if ($m[$j+$n][1] > $partpos) { + array_unshift($parts, array($inner, substr($this->_str, $partpos, $m[$j+$n][1]-$partpos))); + } + array_unshift($parts, array($this->_parts[$this->_state][$i][$j], $m[$j+$n][0])); + } + $partpos = $m[$j+$n][1] + strlen($m[$j+$n][0]); + } + if ($partpos < $m[$n][1] + strlen($m[$n][0])) { + array_unshift($parts, array($inner, substr($this->_str, $partpos, $m[$n][1] - $partpos + strlen($m[$n][0])))); + } + $this->_tokenStack = array_merge($this->_tokenStack, $parts); + } else { + foreach ($this->_keywords[$this->_state][$i] as $g => $re) { + if (isset($this->_disabled[$g])) { + continue; + } + if (preg_match($re, $m[$n][0])) { + $inner = $this->_kwmap[$g]; + break; + } + } + $this->_tokenStack[] = array($inner, $m[$n][0]); + } + } + if ($m[$n][1] > $this->_pos) { + $this->_tokenStack[] = array($this->_lastinner, substr($this->_str, $this->_pos, $m[$n][1]-$this->_pos)); + } + $this->_pos = $m[$n][1] + strlen($m[$n][0]); + if ($this->_states[$this->_state][$i] != -1) { + $this->_stack[] = array($this->_state, $this->_lastdelim, $this->_lastinner, $this->_endpattern); + $this->_lastinner = $this->_inner[$this->_state][$i]; + $this->_lastdelim = $this->_delim[$this->_state][$i]; + $l = $this->_state; + $this->_state = $this->_states[$this->_state][$i]; + $this->_endpattern = $this->_end[$this->_state]; + if ($this->_subst[$l][$i]) { + for ($k=0; $k<=$this->_counts[$l][$i]; $k++) { + if (!isset($m[$i+$k])) { + break; + } + $quoted = preg_quote($m[$n+$k][0], '/'); + $this->_endpattern = str_replace('%'.$k.'%', $quoted, $this->_endpattern); + $this->_endpattern = str_replace('%b'.$k.'%', $this->_matchingBrackets($quoted), $this->_endpattern); + } + } + } + return array_pop($this->_tokenStack); + } + $n += $count + 1; + } + + if ($endpos > -1) { + $this->_tokenStack[] = array($this->_lastdelim, $endmatch); + if ($endpos > $this->_pos) { + $this->_tokenStack[] = array($this->_lastinner, substr($this->_str, $this->_pos, $endpos-$this->_pos)); + } + list($this->_state, $this->_lastdelim, $this->_lastinner, $this->_endpattern) = array_pop($this->_stack); + $this->_pos = $endpos + strlen($endmatch); + return array_pop($this->_tokenStack); + } + $p = $this->_pos; + $this->_pos = HL_INFINITY; + return array($this->_lastinner, substr($this->_str, $p)); + } + + + + + // {{{ highlight + + /** + * Highlights code + * + * @param string $str Code to highlight + * @access public + * @return string Highlighted text + * + */ + + function highlight($str) + { + if (!($this->_renderer)) { + include_once('Text/Highlighter/Renderer/Html.php'); + $this->_renderer = new Text_Highlighter_Renderer_Html($this->_options); + } + $this->_state = -1; + $this->_pos = 0; + $this->_stack = array(); + $this->_tokenStack = array(); + $this->_lastinner = $this->_defClass; + $this->_lastdelim = $this->_defClass; + $this->_endpattern = ''; + $this->_renderer->reset(); + $this->_renderer->setCurrentLanguage($this->_language); + $this->_str = $this->_renderer->preprocess($str); + $this->_len = strlen($this->_str); + while ($token = $this->_getToken()) { + $this->_renderer->acceptToken($token[0], $token[1]); + } + $this->_renderer->finalize(); + return $this->_renderer->getOutput(); + } + + // }}} + +} + +// }}} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ + ?> \ No newline at end of file diff --git a/framework/3rdParty/TextHighlighter/Text/Highlighter/ABAP.php b/framework/3rdParty/TextHighlighter/Text/Highlighter/ABAP.php index adeaabf9..153ce9fe 100644 --- a/framework/3rdParty/TextHighlighter/Text/Highlighter/ABAP.php +++ b/framework/3rdParty/TextHighlighter/Text/Highlighter/ABAP.php @@ -1,53 +1,53 @@ - - * - */ - -/** - * @ignore - */ - -/** - * Auto-generated class. ABAP syntax highlighting - * + * + */ + +/** + * @ignore + */ + +/** + * Auto-generated class. ABAP syntax highlighting + * * @author Stoyan Stefanov - * @category Text - * @package Text_Highlighter - * @copyright 2004-2006 Andrey Demenev - * @license http://www.php.net/license/3_0.txt PHP License - * @version Release: 0.7.0 - * @link http://pear.php.net/package/Text_Highlighter - */ -class Text_Highlighter_ABAP extends Text_Highlighter -{ + * @category Text + * @package Text_Highlighter + * @copyright 2004-2006 Andrey Demenev + * @license http://www.php.net/license/3_0.txt PHP License + * @version Release: 0.7.0 + * @link http://pear.php.net/package/Text_Highlighter + */ +class Text_Highlighter_ABAP extends Text_Highlighter +{ var $_language = 'abap'; - /** - * Constructor - * - * @param array $options - * @access public - */ - function __construct($options=array()) - { - + /** + * Constructor + * + * @param array $options + * @access public + */ + function __construct($options=array()) + { + $this->_options = $options; $this->_regs = array ( -1 => '/((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)^\\*|")|((?i)\')|((?i)[a-z_\\-]\\w*)/', @@ -498,8 +498,8 @@ class Text_Highlighter_ABAP extends Text_Highlighter 'reserved' => 'reserved', 'constants' => 'reserved', ); - $this->_defClass = 'code'; - $this->_checkDefines(); - } - + $this->_defClass = 'code'; + $this->_checkDefines(); + } + } \ No newline at end of file diff --git a/framework/3rdParty/TextHighlighter/Text/Highlighter/CPP.php b/framework/3rdParty/TextHighlighter/Text/Highlighter/CPP.php index 7be6add9..761297ac 100644 --- a/framework/3rdParty/TextHighlighter/Text/Highlighter/CPP.php +++ b/framework/3rdParty/TextHighlighter/Text/Highlighter/CPP.php @@ -1,56 +1,56 @@ - - * - */ - -/** - * Auto-generated class. CPP syntax highlighting - * + * + */ + +/** + * Auto-generated class. CPP syntax highlighting + * * @author Aaron Kalin * @author Andrey Demenev - * @category Text - * @package Text_Highlighter - * @copyright 2004-2006 Andrey Demenev - * @license http://www.php.net/license/3_0.txt PHP License - * @version Release: 0.7.0 - * @link http://pear.php.net/package/Text_Highlighter - */ -class Text_Highlighter_CPP extends Text_Highlighter -{ + * @category Text + * @package Text_Highlighter + * @copyright 2004-2006 Andrey Demenev + * @license http://www.php.net/license/3_0.txt PHP License + * @version Release: 0.7.0 + * @link http://pear.php.net/package/Text_Highlighter + */ +class Text_Highlighter_CPP extends Text_Highlighter +{ var $_language = 'cpp'; - /** - * Constructor - * - * @param array $options - * @access public - */ - function __construct($options=array()) - { - + /** + * Constructor + * + * @param array $options + * @access public + */ + function __construct($options=array()) + { + $this->_options = $options; $this->_regs = array ( -1 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/', @@ -833,8 +833,8 @@ class Text_Highlighter_CPP extends Text_Highlighter 'types' => 'types', 'Common Macros' => 'prepro', ); - $this->_defClass = 'code'; - $this->_checkDefines(); - } - + $this->_defClass = 'code'; + $this->_checkDefines(); + } + } \ No newline at end of file diff --git a/framework/3rdParty/TextHighlighter/Text/Highlighter/CSS.php b/framework/3rdParty/TextHighlighter/Text/Highlighter/CSS.php index 04705ff6..28f92f34 100644 --- a/framework/3rdParty/TextHighlighter/Text/Highlighter/CSS.php +++ b/framework/3rdParty/TextHighlighter/Text/Highlighter/CSS.php @@ -1,49 +1,49 @@ - - * - */ - -/** - * Auto-generated class. CSS syntax highlighting - * + * + */ + +/** + * Auto-generated class. CSS syntax highlighting + * * @author Andrey Demenev - * @category Text - * @package Text_Highlighter - * @copyright 2004-2006 Andrey Demenev - * @license http://www.php.net/license/3_0.txt PHP License - * @version Release: 0.7.0 - * @link http://pear.php.net/package/Text_Highlighter - */ -class Text_Highlighter_CSS extends Text_Highlighter -{ + * @category Text + * @package Text_Highlighter + * @copyright 2004-2006 Andrey Demenev + * @license http://www.php.net/license/3_0.txt PHP License + * @version Release: 0.7.0 + * @link http://pear.php.net/package/Text_Highlighter + */ +class Text_Highlighter_CSS extends Text_Highlighter +{ var $_language = 'css'; - /** - * Constructor - * - * @param array $options - * @access public - */ - function __construct($options=array()) - { - + /** + * Constructor + * + * @param array $options + * @access public + */ + function __construct($options=array()) + { + $this->_options = $options; $this->_regs = array ( -1 => '/((?i)(@[a-z\\d]+))|((?i)(((\\.|#)?[a-z]+[a-z\\d\\-]*(?![a-z\\d\\-]))|(\\*))(?!\\s*:\\s*[\\s\\{]))|((?i):[a-z][a-z\\d\\-]*)|((?i)\\[)|((?i)\\{)/', @@ -376,8 +376,8 @@ class Text_Highlighter_CSS extends Text_Highlighter 'propertyValue' => 'string', 'namedcolor' => 'var', ); - $this->_defClass = 'code'; - $this->_checkDefines(); - } - + $this->_defClass = 'code'; + $this->_checkDefines(); + } + } \ No newline at end of file diff --git a/framework/3rdParty/TextHighlighter/Text/Highlighter/DIFF.php b/framework/3rdParty/TextHighlighter/Text/Highlighter/DIFF.php index c27301f5..21e97087 100644 --- a/framework/3rdParty/TextHighlighter/Text/Highlighter/DIFF.php +++ b/framework/3rdParty/TextHighlighter/Text/Highlighter/DIFF.php @@ -1,49 +1,49 @@ - - * - */ - -/** - * Auto-generated class. DIFF syntax highlighting - * + * + */ + +/** + * Auto-generated class. DIFF syntax highlighting + * * @author Andrey Demenev - * @category Text - * @package Text_Highlighter - * @copyright 2004-2006 Andrey Demenev - * @license http://www.php.net/license/3_0.txt PHP License - * @version Release: 0.7.0 - * @link http://pear.php.net/package/Text_Highlighter - */ -class Text_Highlighter_DIFF extends Text_Highlighter -{ + * @category Text + * @package Text_Highlighter + * @copyright 2004-2006 Andrey Demenev + * @license http://www.php.net/license/3_0.txt PHP License + * @version Release: 0.7.0 + * @link http://pear.php.net/package/Text_Highlighter + */ +class Text_Highlighter_DIFF extends Text_Highlighter +{ var $_language = 'diff'; - /** - * Constructor - * - * @param array $options - * @access public - */ - function __construct($options=array()) - { - + /** + * Constructor + * + * @param array $options + * @access public + */ + function __construct($options=array()) + { + $this->_options = $options; $this->_regs = array ( -1 => '/((?m)^\\\\\\sNo\\snewline.+$)|((?m)^\\-\\-\\-$)|((?m)^(diff\\s+\\-|Only\\s+|Index).*$)|((?m)^(\\-\\-\\-|\\+\\+\\+)\\s.+$)|((?m)^\\*.*$)|((?m)^\\+.*$)|((?m)^!.*$)|((?m)^\\<\\s.*$)|((?m)^\\>\\s.*$)|((?m)^\\d+(\\,\\d+)?[acd]\\d+(,\\d+)?$)|((?m)^\\-.*$)|((?m)^\\+.*$)|((?m)^@@.+@@$)|((?m)^d\\d+\\s\\d+$)|((?m)^a\\d+\\s\\d+$)|((?m)^(\\d+)(,\\d+)?(a)$)|((?m)^(\\d+)(,\\d+)?(c)$)|((?m)^(\\d+)(,\\d+)?(d)$)|((?m)^a(\\d+)(\\s\\d+)?$)|((?m)^c(\\d+)(\\s\\d+)?$)|((?m)^d(\\d+)(\\s\\d+)?$)/', @@ -359,8 +359,8 @@ class Text_Highlighter_DIFF extends Text_Highlighter ); $this->_kwmap = array ( ); - $this->_defClass = 'default'; - $this->_checkDefines(); - } - + $this->_defClass = 'default'; + $this->_checkDefines(); + } + } \ No newline at end of file diff --git a/framework/3rdParty/TextHighlighter/Text/Highlighter/DTD.php b/framework/3rdParty/TextHighlighter/Text/Highlighter/DTD.php index ad33e528..1d4a403e 100644 --- a/framework/3rdParty/TextHighlighter/Text/Highlighter/DTD.php +++ b/framework/3rdParty/TextHighlighter/Text/Highlighter/DTD.php @@ -1,49 +1,49 @@ - - * - */ - -/** - * Auto-generated class. DTD syntax highlighting - * + * + */ + +/** + * Auto-generated class. DTD syntax highlighting + * * @author Andrey Demenev - * @category Text - * @package Text_Highlighter - * @copyright 2004-2006 Andrey Demenev - * @license http://www.php.net/license/3_0.txt PHP License - * @version Release: 0.7.0 - * @link http://pear.php.net/package/Text_Highlighter - */ -class Text_Highlighter_DTD extends Text_Highlighter -{ + * @category Text + * @package Text_Highlighter + * @copyright 2004-2006 Andrey Demenev + * @license http://www.php.net/license/3_0.txt PHP License + * @version Release: 0.7.0 + * @link http://pear.php.net/package/Text_Highlighter + */ +class Text_Highlighter_DTD extends Text_Highlighter +{ var $_language = 'dtd'; - /** - * Constructor - * - * @param array $options - * @access public - */ - function __construct($options=array()) - { - + /** + * Constructor + * + * @param array $options + * @access public + */ + function __construct($options=array()) + { + $this->_options = $options; $this->_regs = array ( -1 => '/(\\