Attached file, implements validate_file(), which implements a php space syntax
check for PHP scripts. It returns a boolean true/false value indicating
whether the script has parse errors or not. Essentially a "php -l" from
within PHP.
strip_file() is added for completion (might as well :) ) and implements "php
-w", which strips comments & whitespace from a PHP file. A quick obfuscater
of sorts.
Any comments?
Ilia
Index: basic_functions.c
===================================================================
RCS file: /repository/php-src/ext/standard/basic_functions.c,v
retrieving revision 1.543.2.22
diff -u -3 -p -r1.543.2.22 basic_functions.c
--- basic_functions.c 29 Sep 2003 14:02:55 -0000 1.543.2.22
+++ basic_functions.c 3 Oct 2003 00:56:51 -0000
@@ -32,6 +32,72 @@
#include "ext/session/php_session.h"
#include "zend_operators.h"
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+typedef unsigned int yy_size_t;
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+ };
+
+#include "zend.h"
+#include "zend_language_scanner.h"
+#include "zend_language_parser.h"
+
+#define zendtext LANG_SCNG(yy_text)
+#define zendleng LANG_SCNG(yy_leng)
+
#include <stdarg.h>
#include <stdlib.h>
#include <math.h>
@@ -561,6 +627,8 @@ function_entry basic_functions[] = {
PHP_FE(highlight_file,
NULL)
PHP_FALIAS(show_source, highlight_file,
NULL)
PHP_FE(highlight_string,
NULL)
+ PHP_FE(strip_file,
NULL)
+ PHP_FE(validate_file,
NULL)
PHP_FE(ini_get,
NULL)
PHP_FE(ini_get_all,
NULL)
@@ -2179,6 +2247,107 @@ PHP_FUNCTION(highlight_file)
}
/* }}} */
+/* {{{ proto string strip_file(string file_name)
+ Return source with stripped comments and whitespace */
+PHP_FUNCTION(strip_file)
+{
+ char *filename;
+ int filename_len;
+ zend_lex_state original_lex_state;
+ zend_file_handle file_handle = {0};
+ char resolved_path[MAXPATHLEN];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename,
&filename_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (!VCWD_REALPATH(filename, resolved_path)) {
+ RETURN_FALSE;
+ }
+
+ if (PG(safe_mode) && (!php_checkuid(resolved_path, NULL,
CHECKUID_ALLOW_ONLY_FILE))) {
+ RETURN_FALSE;
+ }
+
+ if (php_check_open_basedir(resolved_path TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC);
+
+ file_handle.type = ZEND_HANDLE_FILENAME;
+ file_handle.filename = resolved_path;
+ file_handle.free_filename = 0;
+ file_handle.opened_path = NULL;
+ zend_save_lexical_state(&original_lex_state TSRMLS_CC);
+ if (open_file_for_scanning(&file_handle TSRMLS_CC)==FAILURE) {
+ RETURN_EMPTY_STRING();
+ }
+
+ zend_strip(TSRMLS_C);
+
+ zend_destroy_file_handle(&file_handle TSRMLS_CC);
+ zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
+
+ php_ob_get_buffer(return_value TSRMLS_CC);
+ php_end_ob_buffer(0, 0 TSRMLS_CC);
+
+ return;
+}
+/* }}} */
+
+/* {{{ proto bool validate_file(string file_name)
+ Check the syntax of the specified file. */
+PHP_FUNCTION(validate_file)
+{
+ char *filename;
+ int filename_len;
+ zend_file_handle file_handle = {0};
+ char resolved_path[MAXPATHLEN];
+ zend_lex_state original_lex_state;
+
+ int old_errors = PG(display_errors);
+ int old_track_errors = PG(track_errors);
+ int log_errors = PG(log_errors);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename,
&filename_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (!VCWD_REALPATH(filename, resolved_path)) {
+ RETURN_FALSE;
+ }
+
+ if (PG(safe_mode) && (!php_checkuid(resolved_path, NULL,
CHECKUID_ALLOW_ONLY_FILE))) {
+ RETURN_FALSE;
+ }
+
+ if (php_check_open_basedir(resolved_path TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ file_handle.type = ZEND_HANDLE_FILENAME;
+ file_handle.filename = resolved_path;
+ file_handle.free_filename = 0;
+ file_handle.opened_path = NULL;
+
+ PG(log_errors) = PG(display_errors) = 0;
+ PG(track_errors) = 1;
+
+ if (php_lint_script(&file_handle TSRMLS_CC) != SUCCESS) {
+ RETVAL_FALSE;
+ } else {
+ RETVAL_TRUE;
+ }
+
+ PG(display_errors) = old_errors;
+ PG(log_errors) = log_errors;
+ PG(track_errors) = old_track_errors;
+
+ return;
+}
+/* }}} */
+
/* {{{ proto bool highlight_string(string string [, bool return] )
Syntax highlight a string or optionally return it */
PHP_FUNCTION(highlight_string)
@@ -2187,6 +2356,7 @@ PHP_FUNCTION(highlight_string)
zend_syntax_highlighter_ini syntax_highlighter_ini;
char *hicompiled_string_description;
zend_bool i = 0;
+ int old_error_reporting = EG(error_reporting);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &expr, &i) ==
FAILURE) {
RETURN_FALSE;
@@ -2197,6 +2367,8 @@ PHP_FUNCTION(highlight_string)
php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
}
+ EG(error_reporting) = E_ERROR;
+
php_get_highlight_struct(&syntax_highlighter_ini);
hicompiled_string_description =
zend_make_compiled_string_description("highlighted code" TSRMLS_CC);
@@ -2206,6 +2378,8 @@ PHP_FUNCTION(highlight_string)
RETURN_FALSE;
}
efree(hicompiled_string_description);
+
+ EG(error_reporting) = old_error_reporting;
if (i) {
php_ob_get_buffer (return_value TSRMLS_CC);
Index: basic_functions.h
===================================================================
RCS file: /repository/php-src/ext/standard/basic_functions.h,v
retrieving revision 1.109.2.1
diff -u -3 -p -r1.109.2.1 basic_functions.h
--- basic_functions.h 31 Dec 2002 16:35:25 -0000 1.109.2.1
+++ basic_functions.h 3 Oct 2003 00:56:51 -0000
@@ -72,6 +72,8 @@ PHP_FUNCTION(call_user_method_array);
PHP_FUNCTION(register_shutdown_function);
PHP_FUNCTION(highlight_file);
PHP_FUNCTION(highlight_string);
+PHP_FUNCTION(strip_file);
+PHP_FUNCTION(validate_file);
ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini
*syntax_highlighter_ini);
PHP_FUNCTION(ini_get);
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php