Download | Plain Text | No Line Numbers
- diff -Naur htscanner-cvs/ap_fnmatch.c htscanner/ap_fnmatch.c
- --- htscanner-cvs/ap_fnmatch.c 1970-01-01 01:00:00.000000000 +0100
- +++ htscanner/ap_fnmatch.c 2007-07-09 02:11:27.000000000 +0200
- @@ -0,0 +1,263 @@
- +/* Licensed to the Apache Software Foundation (ASF) under one or more
- + * contributor license agreements. See the NOTICE file distributed with
- + * this work for additional information regarding copyright ownership.
- + * The ASF licenses this file to You under the Apache License, Version 2.0
- + * (the "License"); you may not use this file except in compliance with
- + * the License. You may obtain a copy of the License at
- + *
- + * http://www.apache.org/licenses/LICENSE-2.0
- + *
- + * Unless required by applicable law or agreed to in writing, software
- + * distributed under the License is distributed on an "AS IS" BASIS,
- + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- + * See the License for the specific language governing permissions and
- + * limitations under the License.
- + */
- +
- +/*
- + * Copyright (c) 1989, 1993, 1994
- + * The Regents of the University of California. All rights reserved.
- + *
- + * This code is derived from software contributed to Berkeley by
- + * Guido van Rossum.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + * 3. All advertising materials mentioning features or use of this software
- + * must display the following acknowledgement:
- + * This product includes software developed by the University of
- + * California, Berkeley and its contributors.
- + * 4. Neither the name of the University nor the names of its contributors
- + * may be used to endorse or promote products derived from this software
- + * without specific prior written permission.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- + * SUCH DAMAGE.
- + */
- +
- +#if defined(LIBC_SCCS) && !defined(lint)
- +static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
- +#endif /* LIBC_SCCS and not lint */
- +
- +/*
- + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
- + * Compares a filename or pathname to a pattern.
- + */
- +
- +#include "ap_fnmatch.h"
- +#include <string.h>
- +#include <stdio.h>
- +
- +#define ap_tolower(c) (tolower(((unsigned char)(c))))
- +#define EOS '\0'
- +
- +static const char *rangematch(const char *, int, int);
- +
- +int ap_fnmatch(const char *pattern, const char *string, int flags)
- +{
- + const char *stringstart;
- + char c, test;
- +
- + for (stringstart = string;;) {
- + switch (c = *pattern++) {
- + case EOS:
- + return (*string == EOS ? 0 : FNM_NOMATCH);
- + case '?':
- + if (*string == EOS) {
- + return (FNM_NOMATCH);
- + }
- + if (*string == '/' && (flags & FNM_PATHNAME)) {
- + return (FNM_NOMATCH);
- + }
- + if (*string == '.' && (flags & FNM_PERIOD) &&
- + (string == stringstart ||
- + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
- + return (FNM_NOMATCH);
- + }
- + ++string;
- + break;
- + case '*':
- + c = *pattern;
- + /* Collapse multiple stars. */
- + while (c == '*') {
- + c = *++pattern;
- + }
- +
- + if (*string == '.' && (flags & FNM_PERIOD) &&
- + (string == stringstart ||
- + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
- + return (FNM_NOMATCH);
- + }
- +
- + /* Optimize for pattern with * at end or before /. */
- + if (c == EOS) {
- + if (flags & FNM_PATHNAME) {
- + return (strchr(string, '/') == NULL ? 0 : FNM_NOMATCH);
- + }
- + else {
- + return (0);
- + }
- + }
- + else if (c == '/' && flags & FNM_PATHNAME) {
- + if ((string = strchr(string, '/')) == NULL) {
- + return (FNM_NOMATCH);
- + }
- + break;
- + }
- +
- + /* General case, use recursion. */
- + while ((test = *string) != EOS) {
- + if (!ap_fnmatch(pattern, string, flags & ~FNM_PERIOD)) {
- + return (0);
- + }
- + if (test == '/' && flags & FNM_PATHNAME) {
- + break;
- + }
- + ++string;
- + }
- + return (FNM_NOMATCH);
- + case '[':
- + if (*string == EOS) {
- + return (FNM_NOMATCH);
- + }
- + if (*string == '/' && flags & FNM_PATHNAME) {
- + return (FNM_NOMATCH);
- + }
- + if (*string == '.' && (flags & FNM_PERIOD) &&
- + (string == stringstart ||
- + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
- + return (FNM_NOMATCH);
- + }
- + if ((pattern = rangematch(pattern, *string, flags)) == NULL) {
- + return (FNM_NOMATCH);
- + }
- + ++string;
- + break;
- + case '\\':
- + if (!(flags & FNM_NOESCAPE)) {
- + if ((c = *pattern++) == EOS) {
- + c = '\\';
- + --pattern;
- + }
- + }
- + /* FALLTHROUGH */
- + default:
- + if (flags & FNM_CASE_BLIND) {
- + if (ap_tolower(c) != ap_tolower(*string)) {
- + return (FNM_NOMATCH);
- + }
- + }
- + else if (c != *string) {
- + return (FNM_NOMATCH);
- + }
- + string++;
- + break;
- + }
- + /* NOTREACHED */
- + }
- +}
- +
- +static const char *rangematch(const char *pattern, int test, int flags)
- +{
- + int negate, ok;
- + char c, c2;
- +
- + /*
- + * A bracket expression starting with an unquoted circumflex
- + * character produces unspecified results (IEEE 1003.2-1992,
- + * 3.13.2). This implementation treats it like '!', for
- + * consistency with the regular expression syntax.
- + * J.T. Conklin (conklin@ngai.kaleida.com)
- + */
- + if ((negate = (*pattern == '!' || *pattern == '^'))) {
- + ++pattern;
- + }
- +
- + for (ok = 0; (c = *pattern++) != ']';) {
- + if (c == '\\' && !(flags & FNM_NOESCAPE)) {
- + c = *pattern++;
- + }
- + if (c == EOS) {
- + return (NULL);
- + }
- + if (*pattern == '-' && (c2 = *(pattern + 1)) != EOS && c2 != ']') {
- + pattern += 2;
- + if (c2 == '\\' && !(flags & FNM_NOESCAPE)) {
- + c2 = *pattern++;
- + }
- + if (c2 == EOS) {
- + return (NULL);
- + }
- + if ((c <= test && test <= c2)
- + || ((flags & FNM_CASE_BLIND)
- + && ((ap_tolower(c) <= ap_tolower(test))
- + && (ap_tolower(test) <= ap_tolower(c2))))) {
- + ok = 1;
- + }
- + }
- + else if ((c == test)
- + || ((flags & FNM_CASE_BLIND)
- + && (ap_tolower(c) == ap_tolower(test)))) {
- + ok = 1;
- + }
- + }
- + return (ok == negate ? NULL : pattern);
- +}
- +
- +
- +/* This function is an Apache addition */
- +/* return non-zero if pattern has any glob chars in it */
- +int ap_is_fnmatch(const char *pattern)
- +{
- + int nesting;
- +
- + nesting = 0;
- + while (*pattern) {
- + switch (*pattern) {
- + case '?':
- + case '*':
- + return 1;
- +
- + case '\\':
- + if (*pattern++ == '\0') {
- + return 0;
- + }
- + break;
- +
- + case '[': /* '[' is only a glob if it has a matching ']' */
- + ++nesting;
- + break;
- +
- + case ']':
- + if (nesting) {
- + return 1;
- + }
- + break;
- + }
- + ++pattern;
- + }
- + return 0;
- +}
- +/*
- + * Local variables:
- + * tab-width: 8
- + * c-basic-offset: 8
- + * End:
- + * vim600: noet sw=8 ts=8 fdm=marker
- + * vim<600: noet sw=8 ts=8
- + */
- diff -Naur htscanner-cvs/ap_fnmatch.h htscanner/ap_fnmatch.h
- --- htscanner-cvs/ap_fnmatch.h 1970-01-01 01:00:00.000000000 +0100
- +++ htscanner/ap_fnmatch.h 2007-07-09 02:11:48.000000000 +0200
- @@ -0,0 +1,70 @@
- +/*-
- + * Copyright (c) 1992, 1993
- + * The Regents of the University of California. All rights reserved.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + * 3. All advertising materials mentioning features or use of this software
- + * must display the following acknowledgement:
- + * This product includes software developed by the University of
- + * California, Berkeley and its contributors.
- + * 4. Neither the name of the University nor the names of its contributors
- + * may be used to endorse or promote products derived from this software
- + * without specific prior written permission.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- + * SUCH DAMAGE.
- + *
- + * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93
- + */
- +
- +/* This file has been modified by the Apache Group. */
- +
- +#ifndef _FNMATCH_H_
- +#define _FNMATCH_H_
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +#define FNM_NOMATCH 1 /* Match failed. */
- +
- +#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
- +#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
- +#define FNM_PERIOD 0x04 /* Period must be matched by period. */
- +/* This flag is an Apache addition */
- +#define FNM_CASE_BLIND 0x08 /* Compare characters case-insensitively. */
- +
- +int ap_fnmatch(const char *, const char *, int);
- +
- +/* this function is an Apache addition */
- +extern int ap_is_fnmatch(const char *);
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* !_FNMATCH_H_ */
- +/*
- + * Local variables:
- + * tab-width: 8
- + * c-basic-offset: 8
- + * End:
- + * vim600: noet sw=8 ts=8 fdm=marker
- + * vim<600: noet sw=8 ts=8
- + */
- diff -Naur htscanner-cvs/ap_util.c htscanner/ap_util.c
- --- htscanner-cvs/ap_util.c 1970-01-01 01:00:00.000000000 +0100
- +++ htscanner/ap_util.c 2007-07-09 02:12:19.000000000 +0200
- @@ -0,0 +1,111 @@
- +/* Licensed to the Apache Software Foundation (ASF) under one or more
- + * contributor license agreements. See the NOTICE file distributed with
- + * this work for additional information regarding copyright ownership.
- + * The ASF licenses this file to You under the Apache License, Version 2.0
- + * (the "License"); you may not use this file except in compliance with
- + * the License. You may obtain a copy of the License at
- + *
- + * http://www.apache.org/licenses/LICENSE-2.0
- + *
- + * Unless required by applicable law or agreed to in writing, software
- + * distributed under the License is distributed on an "AS IS" BASIS,
- + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- + * See the License for the specific language governing permissions and
- + * limitations under the License.
- + */
- +
- +/*
- + * util.c: string utility things
- + *
- + * 3/21/93 Rob McCool
- + * 1995-96 Many changes by the Apache Group
- + *
- + */
- +
- +#include "ap_util.h"
- +
- +void ap_no2slash(char *name)
- +{
- + char *d, *s;
- +
- + s = d = name;
- +
- +#ifdef PHP_WIN32
- + /* Check for UNC names. Leave leading two slashes. */
- + if (s[0] == '/' && s[1] == '/')
- + *d++ = *s++;
- +#endif
- +
- + while (*s) {
- + if ((*d++ = *s) == '/') {
- + do {
- + ++s;
- + } while (*s == '/');
- + }
- + else {
- + ++s;
- + }
- + }
- + *d = '\0';
- +}
- +
- +
- +/*
- + * copy at most n leading directories of s into d
- + * d should be at least as large as s plus 1 extra byte
- + * assumes n > 0
- + * the return value is the ever useful pointer to the trailing \0 of d
- + *
- + * examples:
- + * /a/b, 1 ==> /
- + * /a/b, 2 ==> /a/
- + * /a/b, 3 ==> /a/b/
- + * /a/b, 4 ==> /a/b/
- + *
- + * MODIFIED FOR HAVE_DRIVE_LETTERS and NETWARE environments,
- + * so that if n == 0, "/" is returned in d with n == 1
- + * and s == "e:/test.html", "e:/" is returned in d
- + * *** See also directory_walk in src/main/http_request.c
- + */
- +char * ap_make_dirstr_prefix(char *d, const char *s, int n)
- +{
- +#if defined(PHP_WIN32) || defined(NETWARE)
- + if (!n) {
- + *d = '/';
- + *++d = '\0';
- + return (d);
- + }
- +#endif /* def HAVE_DRIVE_LETTERS || NETWARE */
- + for (;;) {
- + *d = *s;
- + if (*d == '\0') {
- + *d = '/';
- + break;
- + }
- + if (*d == '/' && (--n) == 0)
- + break;
- + ++d;
- + ++s;
- + }
- + *++d = 0;
- + return (d);
- +}
- +
- +
- +int ap_count_dirs(const char *path)
- +{
- + register int x, n;
- +
- + for (x = 0, n = 0; path[x]; x++)
- + if (path[x] == '/')
- + n++;
- + return n;
- +}
- +/*
- + * Local variables:
- + * tab-width: 8
- + * c-basic-offset: 8
- + * End:
- + * vim600: noet sw=8 ts=8 fdm=marker
- + * vim<600: noet sw=8 ts=8
- + */
- diff -Naur htscanner-cvs/ap_util.h htscanner/ap_util.h
- --- htscanner-cvs/ap_util.h 1970-01-01 01:00:00.000000000 +0100
- +++ htscanner/ap_util.h 2007-07-09 02:11:55.000000000 +0200
- @@ -0,0 +1,40 @@
- +/* Licensed to the Apache Software Foundation (ASF) under one or more
- + * contributor license agreements. See the NOTICE file distributed with
- + * this work for additional information regarding copyright ownership.
- + * The ASF licenses this file to You under the Apache License, Version 2.0
- + * (the "License"); you may not use this file except in compliance with
- + * the License. You may obtain a copy of the License at
- + *
- + * http://www.apache.org/licenses/LICENSE-2.0
- + *
- + * Unless required by applicable law or agreed to in writing, software
- + * distributed under the License is distributed on an "AS IS" BASIS,
- + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- + * See the License for the specific language governing permissions and
- + * limitations under the License.
- + */
- +
- +#ifndef APACHE_UTIL_H
- +#define APACHE_UTIL_H
- +
- +#ifdef __cplusplus
- +extern "C" {
- +#endif
- +
- +void ap_no2slash(char *name);
- +char * ap_make_dirstr_prefix(char *d, const char *s, int n);
- +int ap_count_dirs(const char *path);
- +
- +#ifdef __cplusplus
- +}
- +#endif
- +
- +#endif /* !APACHE_UTIL_H */
- +/*
- + * Local variables:
- + * tab-width: 8
- + * c-basic-offset: 8
- + * End:
- + * vim600: noet sw=8 ts=8 fdm=marker
- + * vim<600: noet sw=8 ts=8
- + */
- diff -Naur htscanner-cvs/config.m4 htscanner/config.m4
- --- htscanner-cvs/config.m4 2006-11-30 02:54:09.000000000 +0100
- +++ htscanner/config.m4 2007-08-27 14:14:11.000000000 +0200
- @@ -2,8 +2,76 @@
- dnl config.m4 for extension htscanner
-
- PHP_ARG_ENABLE(htscanner, whether to enable htscanner support,
- -[ --enable-htscanner Enable htscanner support])
- +[ --enable-htscanner Enable htscanner support])
- +
- +PHP_ARG_ENABLE(htscanner-httpd, whether to enable htscanner httpd emulation support,
- +[ --enable-htscanner-httpd Enable htscanner support], no, no)
- +
- +if test -z "$PHP_LIBXML_DIR"; then
- + PHP_ARG_WITH(libxml-dir, libxml2 install dir,
- + [ --with-libxml-dir=DIR htscanner: libxml2 install prefix], no, no)
- +fi
- +
- +dnl needed for php4 support
- +m4_ifndef([PHP_ADD_EXTENSION_DEP], [
- + AC_DEFUN([PHP_ADD_EXTENSION_DEP], [])
- +])
- +
- +dnl needed for php4 support
- +m4_ifndef([PHP_SETUP_LIBXML], [
- + AC_DEFUN([PHP_SETUP_LIBXML], [
- + AC_CACHE_CHECK([for xml2-config path], ac_cv_php_xml2_config_path,
- + [
- + for i in $PHP_LIBXML_DIR /usr/local /usr; do
- + if test -x "$i/bin/xml2-config"; then
- + ac_cv_php_xml2_config_path="$i/bin/xml2-config"
- + break
- + fi
- + done
- + ])
- +
- + if test -x "$ac_cv_php_xml2_config_path"; then
- + XML2_CONFIG="$ac_cv_php_xml2_config_path"
- + libxml_full_version=`$XML2_CONFIG --version`
- + ac_IFS=$IFS
- + IFS="."
- + set $libxml_full_version
- + IFS=$ac_IFS
- + LIBXML_VERSION=`expr [$]1 \* 1000000 + [$]2 \* 1000 + [$]3`
- + if test "$LIBXML_VERSION" -ge "2004014"; then
- + LIBXML_LIBS=`$XML2_CONFIG --libs`
- + LIBXML_INCS=`$XML2_CONFIG --cflags`
- + PHP_EVAL_LIBLINE($LIBXML_LIBS, $1)
- + PHP_EVAL_INCLINE($LIBXML_INCS)
- + AC_DEFINE(HAVE_LIBXML, 1, [ ])
- + $2
- + else
- + AC_MSG_ERROR(libxml version 2.4.14 or greater required.)
- + fi
- + else
- + AC_MSG_RESULT(not found)
- + AC_MSG_ERROR(Please reinstall the libxml >= 2.4.14 distribution)
- + fi
- + ])
- +])
-
- if test "$PHP_HTSCANNER" != "no"; then
- - PHP_NEW_EXTENSION(htscanner, htscanner.c, $ext_shared)
- +
- + if test "$PHP_HTSCANNER_HTTPD" != "no" && test "$PHP_LIBXML" = "no"; then
- + AC_MSG_ERROR([htscanner httpd emulation requires LIBXML extension, add --enable-libxml])
- + fi
- +
- + if test "$PHP_HTSCANNER_HTTPD" != "no"; then
- + PHP_NEW_EXTENSION(htscanner, htscanner.c ap_fnmatch.c ap_util.c, $ext_shared)
- +
- + PHP_SETUP_LIBXML(HTSCANNER_SHARED_LIBADD, [
- + AC_DEFINE(HTSCANNER_HTTPD,1,[ ])
- + PHP_ADD_EXTENSION_DEP(htscanner, libxml)
- + PHP_SUBST(HTSCANNER_SHARED_LIBADD)
- + ], [
- + AC_MSG_ERROR([xml2-config not found. Please check your libxml2 installation.])
- + ])
- + else
- + PHP_NEW_EXTENSION(htscanner, htscanner.c, $ext_shared)
- + fi
- fi
- diff -Naur htscanner-cvs/CREDITS htscanner/CREDITS
- --- htscanner-cvs/CREDITS 2006-11-30 02:54:09.000000000 +0100
- +++ htscanner/CREDITS 2007-08-24 16:59:40.000000000 +0200
- @@ -1,2 +1,2 @@
- htscanner
- -Bart Vanbrabant, Pierre-Alain Joye
- +Bart Vanbrabant, Pierre-Alain Joye, Manuel Mausz
- diff -Naur htscanner-cvs/docs/htscanner.ini htscanner/docs/htscanner.ini
- --- htscanner-cvs/docs/htscanner.ini 2007-02-17 20:33:42.000000000 +0100
- +++ htscanner/docs/htscanner.ini 2007-08-27 20:56:18.000000000 +0200
- @@ -1,12 +1,17 @@
- -[htscanner]
- extension="htscanner.so"
-
- +[htscanner]
- ; The configuration file htscanner needs to scan for php_* directives
- -config_file=".htaccess"
- +htscanner.config_file=".htaccess"
- +
- +; The configuration file for httpd emulation. Must be placed at php's ini-directory
- +; Converter for apache configuration can be found in scripts-directory
- +; Note that this feature has to be enabled explicitly at compile time
- +htscanner.httpd_file="php_httpd.xml"
-
- ; The fallback docroot when htscanner can't determine the current docroot
- -default_docroot="/"
- -default_ttl=300
- +htscanner.default_docroot="/"
- +htscanner.default_ttl=300
-
- ; Stop when an error occured in RINIT (no document root, cannot get path_translated,...)
- -stop_on_error = 0
- +htscanner.stop_on_error = 0
- diff -Naur htscanner-cvs/htscanner.c htscanner/htscanner.c
- --- htscanner-cvs/htscanner.c 2007-07-25 14:59:42.000000000 +0200
- +++ htscanner/htscanner.c 2007-09-15 18:26:58.000000000 +0200
- @@ -14,6 +14,7 @@
- +----------------------------------------------------------------------+
- | Authors: Bart Vanbrabant <bart dot vanbrabant at zoeloelip dot be> |
- | Pierre-Alain Joye <pierre@php.net> |
- + | Manuel Mausz <manuel@mausz.at> |
- +----------------------------------------------------------------------+
- */
-
- @@ -31,10 +32,17 @@
- #include "ext/standard/file.h"
- #include "ext/standard/php_string.h"
-
- +#ifdef HTSCANNER_HTTPD
- +#include "ap_fnmatch.h"
- +#include "ap_util.h"
- +#endif
- +
- ZEND_DECLARE_MODULE_GLOBALS(htscanner)
-
- +int (*php_cgi_sapi_activate)(TSRMLS_D);
- +
- #define FILE_BUFFER 1000
- -#define HTSCANNER_DEBUG 1
- +#define HTSCANNER_DEBUG 0
- #define HTSCANNER_ENABLE_CACHE 0
-
- #if HTSCANNER_DEBUG
- @@ -42,21 +50,21 @@
- {
- char output_buf[512];
- va_list args;
- - char *debug;
-
- - debug = getenv("PHP_HTSCANNER_DEBUG");
- - if (debug == NULL) {
- + if (!getenv("PHP_HTSCANNER_DEBUG")) {
- return;
- }
- -
- - va_start (args, format);
- - vsnprintf (output_buf, sizeof (output_buf), format, args);
- - va_end (args);
-
- - fputs (output_buf, stderr);
- - fflush (stderr);
- + va_start(args, format);
- + vsnprintf(output_buf, sizeof (output_buf), format, args);
- + va_end(args);
- +
- + fputs(output_buf, stderr);
- + fflush(stderr);
- }
- /* }}} */
- +#else
- +#define htscanner_debug(...)
- #endif
-
- #define PHP_HTSCANNER_LTRIM(p) { \
- @@ -78,7 +86,7 @@
-
- static int php_htscanner_ini_check_path(char *option_name, int option_len, char *new_option_name, int new_option_len) /* {{{ */
- {
- - if ( option_len != (new_option_len-1) ) {
- + if (option_len != (new_option_len-1) ) {
- return 0;
- }
-
- @@ -87,100 +95,146 @@
- /* }}} */
-
- /* {{{ value_hnd
- - * Parse an option and try to set the option
- + * Parse an option and try to set the option
- */
- -static void value_hnd(char *string, int flag, int status, HashTable *ini_entries TSRMLS_DC)
- +static int value_hnd(char *name, char *value, int flag, int mode, HashTable *ini_entries TSRMLS_DC)
- {
- - char *name = string;
- - char *value;
- int name_len;
- + int value_len;
- +#ifdef HTSCANNER_HTTPD
- + int *altered_ini_mode;
- +#endif
-
- - name = string;
- - /* strip any leading whitespaces or tabs from the name */
- - PHP_HTSCANNER_LTRIM(name);
- - value = strchr(name, ' ');
- -
- - if (value) {
- - int len;
- - *value = 0;
- - name_len = strlen(name);
- - ++value;
- + name_len = strlen(name);
- + value_len = strlen(value);
-
- - /* strip any leading whitespaces or tabs from the value */
- - len = strlen(value);
- - PHP_HTSCANNER_LTRIM(value);
- - if (len > 2 && value[len - 2] == '\r') {
- - value[len - 2] = 0;
- - len -= 2;
- + if (flag) {
- + /* it's a flag */
- + if (!strcasecmp(value, "On") || (value[0] == '1' && value[1] == '\0')) {
- + value = "1";
- } else {
- - value[len - 1] = 0;
- - len--;
- + value = "0";
- }
- -
- - if (flag) {
- - /* it's a flag */
- - if (!strcasecmp(value, "On") || (value[0] == '1' && value[1] == '\0')) {
- - value = "1";
- - } else {
- - value = "0";
- - }
- - len = 1;
- - } else {
- - /* it's a value */
- - if (!strncasecmp(value, "none", sizeof("none"))) {
- - value = "";
- - len = 0;
- - }
- + value_len = 1;
- + } else {
- + /* it's a value */
- + if (!strncasecmp(value, "none", sizeof("none"))) {
- + value = "";
- + value_len = 0;
- }
- + }
-
- #define _CHECK_PATH(var, var_len, ini) php_htscanner_ini_check_path(var, var_len, ini, sizeof(ini))
-
- - /* safe_mode & basedir check */
- - if (PG(safe_mode) || PG(open_basedir)) {
- - if (_CHECK_PATH(name, name_len, "error_log") ||
- - _CHECK_PATH(name, name_len, "java.class.path") ||
- - _CHECK_PATH(name, name_len, "java.home") ||
- - _CHECK_PATH(name, name_len, "java.library.path") ||
- - _CHECK_PATH(name, name_len, "session.save_path") ||
- - _CHECK_PATH(name, name_len, "vpopmail.directory")) {
- - if (PG(safe_mode) && !php_checkuid(value, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
- - return;
- - }
- -
- - if (php_check_open_basedir(value TSRMLS_CC)) {
- - return;
- - }
- + /* safe_mode & basedir check */
- + if (mode != PHP_INI_SYSTEM && (PG(safe_mode) || PG(open_basedir))) {
- + if (_CHECK_PATH(name, name_len, "error_log") ||
- + _CHECK_PATH(name, name_len, "java.class.path") ||
- + _CHECK_PATH(name, name_len, "java.home") ||
- + _CHECK_PATH(name, name_len, "java.library.path") ||
- + _CHECK_PATH(name, name_len, "session.save_path") ||
- + _CHECK_PATH(name, name_len, "vpopmail.directory")) {
- + if (PG(safe_mode) && !php_checkuid(value, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
- + return FAILURE;
- }
- - }
-
- - /* checks that ensure the user does not overwrite certain ini settings when safe_mode is enabled */
- - if (PG(safe_mode)) {
- - if (!strncmp("max_execution_time", name, sizeof("max_execution_time")) ||
- - !strncmp("memory_limit", name, sizeof("memory_limit")) ||
- - !strncmp("child_terminate", name, sizeof("child_terminate")) ||
- - !strncmp("open_basedir", name, sizeof("open_basedir")) ||
- - !strncmp("safe_mode", name, sizeof("safe_mode")) ) {
- - return;
- + if (php_check_open_basedir(value TSRMLS_CC)) {
- + return FAILURE;
- }
- }
- + }
-
- - if (zend_alter_ini_entry(name, name_len + 1, value, len,
- - status, PHP_INI_STAGE_RUNTIME) == FAILURE) {
- - zend_error(E_WARNING, "Adding option (Name: %s Value: %s) (%i, %i) failed!\n", name, value, name_len, len);
- - return;
- + /* checks that ensure the user does not overwrite certain ini settings when safe_mode is enabled */
- + if (mode != PHP_INI_SYSTEM && PG(safe_mode)) {
- + if (!strncmp("max_execution_time", name, sizeof("max_execution_time")) ||
- + !strncmp("memory_limit", name, sizeof("memory_limit")) ||
- + !strncmp("child_terminate", name, sizeof("child_terminate")) ||
- + !strncmp("open_basedir", name, sizeof("open_basedir")) ||
- + !strncmp("safe_mode", name, sizeof("safe_mode")) ) {
- + return FAILURE;
- }
- + }
- +
- +#ifdef HTSCANNER_HTTPD
- + if (HTG(xml_doc_cache) && mode != PHP_INI_SYSTEM &&
- + zend_hash_find(&HTG(altered_ini_entries), name, name_len + 1, (void **) &altered_ini_mode) == SUCCESS &&
- + *altered_ini_mode == PHP_INI_SYSTEM) {
- + return FAILURE;
- + }
- +
- + if (HTG(xml_doc_cache) && mode == PHP_INI_SYSTEM &&
- + zend_hash_find(&HTG(altered_ini_entries), name, name_len + 1, (void **) &altered_ini_mode) == FAILURE) {
- + zend_hash_add(&HTG(altered_ini_entries), name, name_len + 1, &mode, sizeof(int), NULL);
- + }
- +#endif
- +
- + if (zend_alter_ini_entry(name, name_len + 1, value, value_len, mode, PHP_INI_STAGE_RUNTIME) == FAILURE) {
- + zend_error(E_WARNING, "Adding option (Name: %s Value: %s) (%i, %i) failed!\n", name, value, name_len, value_len);
- + return FAILURE;
- + }
- +
- #if HTSCANNER_ENABLE_CACHE
- - zend_hash_update(ini_entries, name, name_len + 1, value, len + 1, NULL);
- + if (ini_entries) {
- + zend_hash_update(ini_entries, name, name_len + 1, value, value_len + 1, NULL);
- + }
- #endif
- +
- + return SUCCESS;
- +}
- +/* }}} */
- +
- +/* {{{ value_hnd
- + * Parse an option and try to set the option
- + */
- +static int value_hnd_strip(char *string, int flag, int mode, HashTable *ini_entries TSRMLS_DC)
- +{
- + char *name;
- + char *value;
- + int value_len;
- +
- + name = string;
- + /* strip any leading whitespaces or tabs from the name */
- + PHP_HTSCANNER_LTRIM(name);
- + value = strchr(name, ' ');
- + if (!value) {
- + value = strchr(name, '\t');
- }
- + if (value) {
- + *value = 0;
- + ++value;
- + PHP_HTSCANNER_LTRIM(value);
- +
- + /* strip any leading whitespaces or tabs from the value */
- + value_len = strlen(value);
- + if (value_len > 2 && value[value_len - 2] == '\r') {
- + value[value_len - 2] = 0;
- + } else {
- + value[value_len - 1] = 0;
- + }
- +
- + /* strip quoting characters */
- + value_len = strlen(value);
- + if ((value[0] == '\'' && value[value_len - 1] == '\'') ||
- + (value[0] == '\"' && value[value_len - 1] == '\"')) {
- + value[value_len - 1] = 0;
- + value++;
- + }
- +
- + return value_hnd(name, value, flag, mode, ini_entries TSRMLS_CC);
- + }
- +
- + return FAILURE;
- }
- /* }}} */
-
- -/* {{{ parse_config_file
- - * Parse the configuration file
- +/* {{{ parse_htaccess_file
- + * Parse the htaccess configuration file
- */
- -static void parse_config_file(char *file, HashTable *ini_entries TSRMLS_DC)
- +static int parse_htaccess_file(char *file, HashTable *ini_entries TSRMLS_DC)
- {
- + struct stat sb;
- + char buf[FILE_BUFFER];
- + char *pos;
- php_stream *stream;
-
- /* see main/safemode.c:70
- @@ -191,56 +245,621 @@
- * pierre@php.net
- */
- if (PG(safe_mode)) {
- - struct stat sb;
- if (VCWD_STAT(file, &sb) != 0) {
- - return;
- + return FAILURE;
- }
- }
-
- stream = php_stream_open_wrapper(file, "rb", ENFORCE_SAFE_MODE, NULL);
- + if (!stream) {
- + return FAILURE;
- + }
-
- - if (stream != NULL) {
- - char buf[FILE_BUFFER];
- - char *pos;
- - while ((pos = php_stream_gets(stream, buf, FILE_BUFFER)) != NULL) {
- - /* strip leading spaces or tabs */
- - PHP_HTSCANNER_LTRIM(pos);
- + while ((pos = php_stream_gets(stream, buf, FILE_BUFFER))) {
- + /* strip leading spaces or tabs */
- + PHP_HTSCANNER_LTRIM(pos);
- +
- + if (strncmp(pos, "php_value", sizeof("php_value") - 1) == 0) {
- + value_hnd_strip(pos + sizeof("php_value"), 0, PHP_INI_PERDIR, ini_entries TSRMLS_CC);
- + } else if (strncmp(pos, "php_flag", sizeof("php_flag") - 1) == 0) {
- + value_hnd_strip(pos + sizeof("php_flag"), 1, PHP_INI_PERDIR, ini_entries TSRMLS_CC);
- + }
- + }
- + php_stream_close(stream);
-
- - if (strncmp(pos, "php_value", sizeof("php_value") - 1) == 0) {
- - value_hnd(pos + sizeof("php_value"), 0, PHP_INI_PERDIR, ini_entries TSRMLS_CC);
- - } else if (strncmp(pos, "php_flag", sizeof("php_flag") - 1) == 0) {
- - value_hnd(pos + sizeof("php_flag"), 1, PHP_INI_PERDIR, ini_entries TSRMLS_CC);
- - }
- + return SUCCESS;
- +}
- +/* }}} */
- +
- +#ifdef HTSCANNER_HTTPD
- +/* {{{ parse_httpd_php_node
- + * Parse a php node
- + */
- +static int parse_httpd_php_node(xmlNodePtr xml_node TSRMLS_DC)
- +{
- + xmlChar *prop_type, *prop_name, *node_content;
- + int flag;
- + int mode = -1;
- +
- + if (!xml_node || xml_node->type != XML_ELEMENT_NODE || xmlStrcmp(xml_node->name, (const xmlChar *) "php")) {
- + return FAILURE;
- + }
- +
- + prop_type = xmlGetProp(xml_node, (const xmlChar *) "type");
- + prop_name = xmlGetProp(xml_node, (const xmlChar *) "name");
- + node_content = xmlNodeGetContent(xml_node);
- + if (prop_type && prop_name && node_content) {
- + if (!xmlStrcmp(prop_type, (const xmlChar *) "php_admin_value")) {
- + mode = PHP_INI_SYSTEM;
- + flag = 0;
- + } else if (!xmlStrcmp(prop_type, (const xmlChar *) "php_admin_flag")) {
- + mode = PHP_INI_SYSTEM;
- + flag = 1;
- + } else if (!xmlStrcmp(prop_type, (const xmlChar *) "php_value")) {
- + mode = PHP_INI_PERDIR;
- + flag = 0;
- + } else if (!xmlStrcmp(prop_type, (const xmlChar *) "php_flag")) {
- + mode = PHP_INI_PERDIR;
- + flag = 1;
- + }
- +
- + if (mode > 0) {
- + /* there's no support for caching httpd settings as zend hash yet,
- + * thus ini_entries is NULL. But is there really a need for a cache,
- + * as we already cache the internal structure of libxml?
- + */
- + value_hnd((char *)prop_name, (char *)node_content, flag, mode, NULL TSRMLS_CC);
- }
- - php_stream_close(stream);
- }
- +
- + xmlFree(prop_type);
- + xmlFree(prop_name);
- + xmlFree(node_content);
- +
- + return SUCCESS;
- }
- /* }}} */
-
- -/* {{{ get_doc_root
- - * doc_root only seems to be available in _SERVER["doc_root"]
- - * so get it there.
- +/* {{{ check_httpd_vhost_nodes
- + * Parse the virtualhost nodes
- */
- -static char* get_doc_root(TSRMLS_D)
- +static xmlNodePtr check_httpd_vhost_nodes(xmlNodePtr xml_orignode, xmlChar *sapi TSRMLS_DC)
- {
- - zval **server, **data;
- -
- - if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &server) != FAILURE &&
- - (Z_TYPE_PP(server) == IS_ARRAY)
- - ) {
- - zend_hash_internal_pointer_reset(Z_ARRVAL_PP(server));
- - if (zend_hash_find(Z_ARRVAL_PP(server), "DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT"), (void **) &data) != FAILURE) {
- - if (Z_TYPE_PP(data) == IS_STRING) {
- - return Z_STRVAL_PP(data);
- + xmlNodePtr xml_node, xml_childnode, vhost_node, vhost_safe1, vhost_safe2, vhost_safe3, vhost_default, first_vhost;
- + xmlChar *vhost_addr, *vhost_port, *vhost_name;
- + char *server_addr, *server_port, *server_name;
- + int match_addr1, match_addr2, match_name;
- +
- + if (!xml_orignode) {
- + return NULL;
- + }
- +
- + /* Pseudo code for vhost handling. First matching vhost precedes
- + * - MATCH(ip) AND (MATCH(port) OR port = *) AND MATCH(servername)
- + * - MATCH(ip) AND (MATCH(port) OR port = *)
- + * - ip = * AND (MATCH(port) OR port = *) AND MATCH(servername)
- + * - ip = * AND (MATCH(port) OR port = *)
- + * - ip = "_default_" AND (MATCH(port) OR port = *)
- + * - first vhost
- + *
- + * TODO: maybe replace the vhost handling below with
- + * some equivalent semantic as apache's vhost handling
- + */
- +
- + server_addr = sapi_module.getenv("SERVER_ADDR", sizeof("SERVER_ADDR")-1 TSRMLS_CC);
- + server_port = sapi_module.getenv("SERVER_PORT", sizeof("SERVER_PORT")-1 TSRMLS_CC);
- + server_name = sapi_module.getenv("SERVER_NAME", sizeof("SERVER_NAME")-1 TSRMLS_CC);
- + if (!server_addr || !server_port) {
- + return NULL;
- + }
- +
- + vhost_node = vhost_safe1 = vhost_safe2 = vhost_safe3 = vhost_default = first_vhost = NULL;
- + for (xml_node = xml_orignode->xmlChildrenNode; !vhost_node && xml_node; xml_node = xml_node->next) {
- + if (xmlStrcmp(xml_node->name, (const xmlChar *) "virtualhost")) {
- + continue;
- + }
- +
- + /* safe for later use */
- + if (!first_vhost) {
- + first_vhost = xml_node;
- + }
- +
- + match_addr1 = match_addr2 = match_name = 0;
- + for (xml_childnode = xml_node->xmlChildrenNode; !vhost_node && xml_childnode; xml_childnode = xml_childnode->next) {
- + if (!xmlStrcmp(xml_childnode->name, (const xmlChar *) "address")) {
- + vhost_port = xmlGetProp(xml_childnode, (const xmlChar *) "port");
- + vhost_addr = xmlNodeGetContent(xml_childnode);
- +
- + if (!xmlStrcmp(vhost_addr, (xmlChar *)server_addr) &&
- + (!xmlStrcmp(vhost_port, (xmlChar *)server_port) || !xmlStrcmp(vhost_port, (const xmlChar *) "*"))) {
- + /* safe first matching node */
- + if (!vhost_safe1) {
- + vhost_safe1 = xml_node;
- + }
- + match_addr1 = 1;
- + }
- + else if (!vhost_safe2 && !xmlStrcmp(vhost_addr, (const xmlChar *) "*") &&
- + (!xmlStrcmp(vhost_port, (xmlChar *)server_port) || !xmlStrcmp(vhost_port, (const xmlChar *) "*"))) {
- + /* safe first matching node */
- + if (!vhost_safe3) {
- + vhost_safe3 = xml_node;
- + }
- + match_addr2 = 1;
- + }
- + /* this may safe some cpu time later */
- + else if (!vhost_default && !xmlStrcmp(vhost_addr, (const xmlChar *) "_default_") &&
- + (!xmlStrcmp(vhost_port, (xmlChar *)server_port) || !xmlStrcmp(vhost_port, (const xmlChar *) "*"))) {
- + vhost_default = xml_node;
- + }
- +
- + xmlFree(vhost_port);
- + xmlFree(vhost_addr);
- + }
- +
- + if (!xmlStrcmp(xml_childnode->name, (const xmlChar *) "servername")) {
- + vhost_name = xmlNodeGetContent(xml_childnode);
- +
- + if (!xmlStrcmp(vhost_name, (xmlChar *)server_name)) {
- + match_name = 1;
- + }
- +
- + xmlFree(vhost_name);
- }
- +
- +
- + if (match_addr1 && match_name) {
- + vhost_node = xml_node;
- + } else if (match_addr2 && match_name) {
- + /* safe matching node */
- + vhost_safe2 = xml_node;
- + }
- + }
- + }
- +
- + /* restore matching nodes accordingly */
- + if (!vhost_node) {
- + if (vhost_safe1) {
- + vhost_node = vhost_safe1;
- + } else if (vhost_safe2) {
- + vhost_node = vhost_safe2;
- + } else if (vhost_safe3) {
- + vhost_node = vhost_safe3;
- + } else if (vhost_default) {
- + vhost_node = vhost_default;
- + } else if (first_vhost) {
- + vhost_node = first_vhost;
- + }
- + }
- +
- + return vhost_node;
- +}
- +/* }}} */
- +
- +/* {{{ directive_entry_dtor
- + */
- +static void directive_entry_dtor(htscanner_directive_entry *dir_entry TSRMLS_DC)
- +{
- + if (dir_entry->path) {
- + pefree(dir_entry->path, 1);
- + }
- + if (dir_entry->regex) {
- + regfree(dir_entry->regex);
- + }
- +}
- +/* }}} */
- +
- +/* {{{ directive_entry_cmp
- + * see apache src/main/http_core.c reorder_sorter()
- + */
- +
- +#ifndef PHP_WIN32
- +# define IS_SPECIAL(entry) \
- + ((entry)->regex != NULL || ((entry)->path[0] != '/' && (entry)->path[1] != ':'))
- +#else
- +# define IS_SPECIAL(entry) \
- + ((entry)->regex != NULL || ((entry)->path[0] != '/')
- +#endif
- +
- +static int directive_entry_cmp(const void *a, const void *b TSRMLS_DC)
- +{
- + Bucket *f = *((Bucket **) a);
- + Bucket *s = *((Bucket **) b);
- + htscanner_directive_entry *entry_a;
- + htscanner_directive_entry *entry_b;
- +
- + entry_a = (htscanner_directive_entry *) f->pData;
- + entry_b = (htscanner_directive_entry *) s->pData;
- +
- + if (IS_SPECIAL(entry_a)) {
- + if (!IS_SPECIAL(entry_b)) {
- + return 1;
- }
- + } else if (IS_SPECIAL(entry_b)) {
- + return -1;
- } else {
- - return HTG(default_docroot);
- + if (entry_a->components < entry_b->components) {
- + return -1;
- + }
- + else if (entry_a->components > entry_b->components) {
- + return 1;
- + }
- + }
- + return entry_a->orig_index - entry_b->orig_index;
- +}
- +/* }}} */
- +
- +/* {{{ httpd_directory_walk
- + * Parse the httpd directory nodes.
- + * see apache src/main/http_request.c directory_walk()
- + * TODO: merge htaccess check into directory_walk (like apache does) ?
- + * contra: httpd_xml has to exist!
- + */
- +static int httpd_directory_walk(HashTable *directives TSRMLS_DC)
- +{
- + char *filename, *test_filename, *test_dirname;
- +#if defined(PHP_WIN32) || defined(NETWARE)
- + char *s;
- +#endif
- + htscanner_directive_entry *entry;
- + xmlNodePtr *xml_node_ptr, xml_node;
- + int test_filename_len, match;
- + uint num_dirs, i;
- + ulong num_key;
- +
- + if (!zend_hash_num_elements(directives)) {
- + return FAILURE;
- + }
- +
- + if (!(filename = SG(request_info).path_translated) &&
- + !(filename = sapi_module.getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1 TSRMLS_CC))) {
- + return FAILURE;
- + }
- +
- + test_filename = estrdup(filename);
- +
- +#if defined(PHP_WIN32) || defined(NETWARE)
- + s = test_filename;
- + while (*s) {
- + if (*s == '\\') {
- + *s = '/';
- + }
- + s++;
- + }
- +#endif
- +
- + ap_no2slash(test_filename);
- + num_dirs = ap_count_dirs(test_filename);
- + test_filename_len = strlen(test_filename);
- + test_dirname = emalloc(test_filename_len + 2);
- +
- + i = 1;
- +#if defined(PHP_WIN32) || defined(NETWARE)
- + if (test_filename[0] != '/') {
- + i = 0;
- + }
- +#endif
- +
- + zend_hash_internal_pointer_reset(directives);
- + for (; i <= num_dirs; i++) {
- + ap_make_dirstr_prefix(test_dirname, test_filename, i);
- +
- + /* this deals with not-regex directives only */
- + while (zend_hash_get_current_data(directives, (void **)&entry) == SUCCESS) {
- + match = 0;
- +
- + if (entry->regex
- +#if defined(PHP_WIN32) || defined(NETWARE)
- + || (entry->components > 1
- + && entry->components > i))
- +#else
- + || entry->components > i)
- +#endif
- + break;
- +
- + if (entry->is_fnmatch) {
- + if (!ap_fnmatch(entry->path, test_dirname, FNM_PATHNAME)) {
- + match = 1;
- + }
- + } else if (!strcmp(test_dirname, entry->path)) {
- + match = 1;
- + }
- +
- + if (match) {
- + zend_hash_get_current_key(directives, (char **)&xml_node_ptr, &num_key, 0);
- + for (xml_node = (*xml_node_ptr)->xmlChildrenNode; xml_node; xml_node = xml_node->next) {
- + parse_httpd_php_node(xml_node TSRMLS_CC);
- + }
- + }
- +
- + zend_hash_move_forward(directives);
- + }
- + }
- +
- + /* now deal with regex directives */
- + while (zend_hash_get_current_data(directives, (void **)&entry) == SUCCESS) {
- + if (entry->regex) {
- + if (!regexec(entry->regex, test_dirname, 0, NULL, REG_NOTEOL)) {
- + zend_hash_get_current_key(directives, (char **)&xml_node_ptr, &num_key, 0);
- + for (xml_node = (*xml_node_ptr)->xmlChildrenNode; xml_node; xml_node = xml_node->next) {
- + parse_httpd_php_node(xml_node TSRMLS_CC);
- + }
- + }
- + }
- +
- + zend_hash_move_forward(directives);
- + }
- +
- + efree(test_dirname);
- + efree(test_filename);
- +
- + return SUCCESS;
- +}
- +/* }}} */
- +
- +/* {{{ httpd_file_walk
- + * Parse the httpd file nodes.
- + * see apache src/main/http_request.c file_walk()
- + */
- +static int httpd_file_walk(HashTable *directives TSRMLS_DC)
- +{
- + char *filename, *test_file;
- + htscanner_directive_entry *entry;
- + xmlNodePtr *xml_node_ptr, xml_node;
- + size_t test_file_len;
- + ulong num_key;
- + int match;
- +
- + if (!zend_hash_num_elements(directives)) {
- + return FAILURE;
- + }
- +
- + if (!(filename = SG(request_info).path_translated) &&
- + !(filename = sapi_module.getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1 TSRMLS_CC))) {
- + return FAILURE;
- + }
- +
- +#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0)
- + php_basename(filename, strlen(filename), NULL, 0, &test_file, &test_file_len TSRMLS_CC);
- +#else
- + test_file = php_basename(filename, strlen(filename), NULL, 0);
- + test_file_len = strlen(test_file);
- +#endif
- +
- + zend_hash_internal_pointer_reset(directives);
- + while (zend_hash_get_current_data(directives, (void **)&entry) == SUCCESS) {
- + match = 0;
- +
- + if (entry->regex) {
- + if (!regexec(entry->regex, test_file, 0, NULL, 0)) {
- + match = 1;
- + }
- + } else if (entry->is_fnmatch) {
- + if (!ap_fnmatch(entry->path, test_file, FNM_PATHNAME)) {
- + match = 1;
- + }
- + } else if (!strcmp(test_file, entry->path)) {
- + match = 1;
- + }
- +
- + if (match) {
- + zend_hash_get_current_key(directives, (char **)&xml_node_ptr, &num_key, 0);
- + for (xml_node = (*xml_node_ptr)->xmlChildrenNode; xml_node; xml_node = xml_node->next) {
- + parse_httpd_php_node(xml_node TSRMLS_CC);
- + }
- + }
- +
- + zend_hash_move_forward(directives);
- }
- - return NULL;
- +
- + efree(test_file);
- +
- + return SUCCESS;
- }
- /* }}} */
-
- +/* {{{ httpd_location_walk
- + * Parse the httpd location nodes.
- + * see apache src/main/http_request.c location_walk()
- + */
- +static int httpd_location_walk(HashTable *directives TSRMLS_DC)
- +{
- + char *uri, *test_location;
- + htscanner_directive_entry *entry;
- + xmlNodePtr *xml_node_ptr, xml_node;
- + ulong num_key;
- + int len, match;
- +
- + if (!zend_hash_num_elements(directives)) {
- + return FAILURE;
- + }
- +
- + if (!(uri = SG(request_info).request_uri) &&
- + !(uri = sapi_module.getenv("REQUEST_URI", sizeof("REQUEST_URI")-1 TSRMLS_CC))) {
- + return FAILURE;
- + }
- +
- + test_location = estrdup(uri);
- + if (test_location[0] == '/') {
- + ap_no2slash(test_location);
- + }
- +
- + zend_hash_internal_pointer_reset(directives);
- + while (zend_hash_get_current_data(directives, (void **)&entry) == SUCCESS) {
- + match = 0;
- + len = strlen(entry->path);
- +
- + if (entry->regex) {
- + if (!regexec(entry->regex, uri, 0, NULL, 0)) {
- + match = 1;
- + }
- + } else if (entry->is_fnmatch) {
- + if (!ap_fnmatch(entry->path, test_location, FNM_PATHNAME)) {
- + match = 1;
- + }
- + } else if (!strncmp(test_location, entry->path, len) &&
- + (entry->path[len - 1] == '/' ||
- + test_location[len] == '/' || test_location[len] == '\0')) {
- + match = 1;
- + }
- +
- + if (match) {
- + zend_hash_get_current_key(directives, (char **)&xml_node_ptr, &num_key, 0);
- + for (xml_node = (*xml_node_ptr)->xmlChildrenNode; xml_node; xml_node = xml_node->next) {
- + parse_httpd_php_node(xml_node TSRMLS_CC);
- + }
- + }
- +
- + zend_hash_move_forward(directives);
- + }
- +
- + efree(test_location);
- +
- + return SUCCESS;
- +}
- +/* }}} */
- +
- +/* {{{ httpd_directive_map
- + */
- +typedef struct {
- + char *directive;
- + int (*handler) (HashTable * TSRMLS_DC);
- +} httpd_directive_map;
- +/* }}} */
- +
- +/* {{{ parse_httpd_directives
- + * Wrapper to parse the httpd directives (directory, files, location)
- + */
- +static int parse_httpd_directives(xmlNodePtr *nodes, httpd_directive_map directive_map, xmlChar *sapi TSRMLS_DC)
- +{
- + xmlNodePtr xml_node;
- + xmlChar *prop_path, *prop_regex;
- + HashTable directives;
- + htscanner_directive_entry dir_entry;
- + htscanner_directive_entry *dir_entry_ptr;
- + ulong index;
- + int i, prop_path_len, ret;
- +
- + /* create directive-cache */
- + if (!HTG(directive_cache)) {
- + HTG(directive_cache) = pemalloc(sizeof(HashTable), 1);
- + zend_hash_init(HTG(directive_cache), 0, NULL, (void (*)(void *)) directive_entry_dtor, 1);
- + }
- +
- + /* hashtable including the necessary directives */
- + zend_hash_init(&directives, 0, NULL, NULL, 1);
- + index = 1;
- +
- + /* fetch relevant nodes + precalc some data */
- + for (i = 0; nodes[i]; i++) {
- + xml_node = nodes[i];
- +
- + for (xml_node = xml_node->xmlChildrenNode; xml_node; xml_node = xml_node->next) {
- + if (xml_node->type != XML_ELEMENT_NODE || xmlStrcmp(xml_node->name, (xmlChar *) directive_map.directive)) {
- + continue;
- + }
- +
- + if (zend_hash_find(HTG(directive_cache), (char *)&xml_node, sizeof(xml_node), (void **) &dir_entry_ptr) == FAILURE) {
- + prop_path = xmlGetProp(xml_node, (const xmlChar *) "path");
- + prop_regex = xmlGetProp(xml_node, (const xmlChar *) "regex");
- + if (!prop_path) {
- + continue;
- + }
- +
- + prop_path_len = xmlStrlen(prop_path);
- + if (directive_map.handler == httpd_directory_walk && prop_path[prop_path_len - 1] != '/') {
- + dir_entry.path = pemalloc(prop_path_len + 2, 1);
- + strcpy(dir_entry.path, (char *)prop_path);
- + strcat(dir_entry.path, "/");
- + dir_entry.components = ap_count_dirs(dir_entry.path);
- + } else {
- + dir_entry.path = pestrdup((char *)prop_path, 1);
- + dir_entry.components = ap_count_dirs(dir_entry.path);
- + if (prop_path[prop_path_len - 1] != '/') {
- + dir_entry.components++;
- + }
- + }
- +
- + dir_entry.orig_index = index++;
- +
- + if (prop_regex && !xmlStrcmp(prop_regex, (const xmlChar *) "1")) {
- + dir_entry.is_fnmatch = 0;
- + dir_entry.regex = pemalloc(sizeof(regex_t), 1);
- + if (regcomp(dir_entry.regex, dir_entry.path, REG_EXTENDED | REG_ICASE)) {
- + regfree(dir_entry.regex);
- + dir_entry.regex = NULL;
- + }
- + } else {
- + dir_entry.is_fnmatch = ap_is_fnmatch(dir_entry.path);
- + dir_entry.regex = NULL;
- + }
- +
- + dir_entry_ptr = &dir_entry;
- + zend_hash_add(HTG(directive_cache), (char *)&xml_node, sizeof(xml_node), dir_entry_ptr, sizeof(htscanner_directive_entry), NULL);
- + xmlFree(prop_path);
- + xmlFree(prop_regex);
- + }
- +
- + zend_hash_add(&directives, (char *)&xml_node, sizeof(xml_node), dir_entry_ptr, sizeof(htscanner_directive_entry), NULL);
- + }
- + }
- +
- + /* only sort directory directives */
- + if (directive_map.handler == httpd_directory_walk) {
- + zend_hash_sort(&directives, zend_qsort, directive_entry_cmp, 0 TSRMLS_CC);
- + }
- +
- + ret = directive_map.handler(&directives TSRMLS_CC);
- +
- + zend_hash_destroy(&directives);
- +
- + return ret;
- +}
- +/* }}} */
- +
- +/* {{{ parse_httpd_file
- + * Parse the httpd configuration file
- + */
- +static int parse_httpd_file(xmlNodePtr xml_root, xmlChar *sapi TSRMLS_DC)
- +{
- + xmlNodePtr xml_node, vhost_node, nodes[3];
- + int i;
- +
- + static httpd_directive_map const directive_map[] = {
- + { "directory", httpd_directory_walk },
- + { "files", httpd_file_walk },
- + { "location", httpd_location_walk },
- + { NULL, NULL }
- + };
- +
- + /* get global php settings */
- + for (xml_node = xml_root->xmlChildrenNode; xml_node; xml_node = xml_node->next) {
- + parse_httpd_php_node(xml_node TSRMLS_CC);
- + }
- +
- + /* get and parse php settings inside vhost */
- + vhost_node = check_httpd_vhost_nodes(xml_root, sapi TSRMLS_CC);
- + if (vhost_node) {
- + for (xml_node = vhost_node->xmlChildrenNode; xml_node; xml_node = xml_node->next) {
- + parse_httpd_php_node(xml_node TSRMLS_CC);
- + }
- + }
- +
- + i = 0;
- + if (xml_root)
- + nodes[i++] = xml_root;
- + if (vhost_node)
- + nodes[i++] = vhost_node;
- + nodes[i] = NULL;
- +
- + /* parse directives */
- + for (i = 0; directive_map[i].handler; i++) {
- + parse_httpd_directives(nodes, directive_map[i], sapi TSRMLS_CC);
- + }
- + return SUCCESS;
- +}
- +/* }}} */
- +#endif
- +
- /* True global resources - no need for thread safety here */
-
- /* {{{ htscanner_functions[]
- @@ -261,7 +880,7 @@
- htscanner_functions,
- PHP_MINIT(htscanner),
- PHP_MSHUTDOWN(htscanner),
- - PHP_RINIT(htscanner),
- + NULL,
- PHP_RSHUTDOWN(htscanner),
- PHP_MINFO(htscanner),
- #if ZEND_MODULE_API_NO >= 20010901
- @@ -275,18 +894,26 @@
- ZEND_GET_MODULE(htscanner)
- #endif
-
- +#ifndef ZEND_ENGINE_2
- +# define OnUpdateLong OnUpdateInt
- +#endif
- +
- /* {{{ PHP_INI
- */
- PHP_INI_BEGIN()
- - STD_PHP_INI_ENTRY("htscanner.config_file", ".htaccess", PHP_INI_SYSTEM, OnUpdateString, config_file, zend_htscanner_globals, htscanner_globals)
- - STD_PHP_INI_ENTRY("htscanner.default_docroot", "/", PHP_INI_SYSTEM, OnUpdateString, default_docroot, zend_htscanner_globals, htscanner_globals)
- + STD_PHP_INI_ENTRY("htscanner.config_file", ".htaccess", PHP_INI_SYSTEM, OnUpdateString, htaccess_file, zend_htscanner_globals, htscanner_globals)
- + STD_PHP_INI_ENTRY("htscanner.default_docroot", "/", PHP_INI_SYSTEM, OnUpdateString, default_docroot, zend_htscanner_globals, htscanner_globals)
- #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0)
- - STD_PHP_INI_ENTRY("htscanner.default_ttl", "300", PHP_INI_SYSTEM, OnUpdateLong, default_ttl, zend_htscanner_globals, htscanner_globals)
- - STD_PHP_INI_ENTRY("htscanner.stop_on_error", "0", PHP_INI_SYSTEM, OnUpdateLong, stop_on_error, zend_htscanner_globals, htscanner_globals)
- + STD_PHP_INI_ENTRY("htscanner.default_ttl", "300", PHP_INI_SYSTEM, OnUpdateLong, default_ttl, zend_htscanner_globals, htscanner_globals)
- + STD_PHP_INI_ENTRY("htscanner.stop_on_error", "0", PHP_INI_SYSTEM, OnUpdateLong, stop_on_error, zend_htscanner_globals, htscanner_globals)
- #else
- - STD_PHP_INI_ENTRY("htscanner.default_ttl", "300", PHP_INI_SYSTEM, OnUpdateInt, default_ttl, zend_htscanner_globals, htscanner_globals)
- - STD_PHP_INI_ENTRY("htscanner.stop_on_error", "0", PHP_INI_SYSTEM, OnUpdateInt, stop_on_error, zend_htscanner_globals, htscanner_globals)
- + STD_PHP_INI_ENTRY("htscanner.default_ttl", "300", PHP_INI_SYSTEM, OnUpdateInt, default_ttl, zend_htscanner_globals, htscanner_globals)
- + STD_PHP_INI_ENTRY("htscanner.stop_on_error", "0", PHP_INI_SYSTEM, OnUpdateInt, stop_on_error, zend_htscanner_globals, htscanner_globals)
- +#endif
- +#ifdef HTSCANNER_HTTPD
- + STD_PHP_INI_ENTRY("htscanner.httpd_file", "php_httpd.xml", PHP_INI_SYSTEM, OnUpdateString, httpd_file, zend_htscanner_globals, htscanner_globals)
- #endif
- + STD_PHP_INI_ENTRY("engine", "1", PHP_INI_ALL, OnUpdateLong, engine, zend_htscanner_globals, htscanner_globals)
- PHP_INI_END()
- /* }}} */
-
- @@ -302,75 +929,51 @@
- }
- }
- /* }}} */
- -
- -static int php_htscanner_create_cache() /* {{{ */
- -{
- - if (ini_entries_cache) {
- - /* Already set up */
- - return SUCCESS;
- - }
- -
- - htscannerMutexSetup(ini_entries_cache_mutex);
- -
- - ini_entries_cache = pemalloc(sizeof(htscanner_cache), 1);
- - if (!ini_entries_cache) {
- - return FAILURE;
- - }
- -
- - ini_entries_cache->paths = malloc(sizeof(HashTable));
- - zend_hash_init(ini_entries_cache->paths, 0, NULL, ini_cache_entry_dtor, 1);
- - return SUCCESS;
- -}
- -/* }}} */
- #endif
-
- static void php_htscanner_init_globals(zend_htscanner_globals *htscanner_globals) /* {{{ */
- {
- - htscanner_globals->config_file = NULL;
- + htscanner_globals->htaccess_file = NULL;
- + htscanner_globals->engine = 1;
- htscanner_globals->default_docroot = NULL;
- htscanner_globals->default_ttl = 5*60;
- htscanner_globals->stop_on_error = 0;
- -}
- -/* }}} */
- -
- -PHP_MINIT_FUNCTION(htscanner) /* {{{ */
- -{
- - ZEND_INIT_MODULE_GLOBALS(htscanner, php_htscanner_init_globals, NULL);
- - REGISTER_INI_ENTRIES();
- - return SUCCESS;
- -}
- -/* }}} */
- -
- -PHP_MSHUTDOWN_FUNCTION(htscanner) /* {{{ */
- -{
- -#if HTSCANNER_ENABLE_CACHE
- - if (ini_entries_cache) {
- - htscannerMutexLock(ini_entries_cache_mutex);
- - if (ini_entries_cache->paths) {
- - free(ini_entries_cache->paths);
- - }
- - htscannerMutexShutdown(ini_entries_cache_mutex);
- - }
- +#ifdef HTSCANNER_HTTPD
- + htscanner_globals->httpd_file = NULL;
- + htscanner_globals->xml_doc_cache = NULL;
- + htscanner_globals->directive_cache = NULL;
- #endif
- - UNREGISTER_INI_ENTRIES();
- - return SUCCESS;
- }
- /* }}} */
-
- -PHP_RINIT_FUNCTION(htscanner) /* {{{ */
- +static int htscanner_main(TSRMLS_D) /* {{{ */
- {
- char *doc_root;
- char cwd[MAXPATHLEN + 1];
- int cwd_len, doc_root_len;
- HashTable *ini_entries;
- +#if HTSCANNER_ENABLE_CACHE
- time_t t;
- htscanner_cache_entry entry;
- htscanner_cache_entry *entry_fetched;
- +#endif
- +#ifdef HTSCANNER_HTTPD
- + PHPAPI extern char *php_ini_opened_path;
- + char httpd_file[MAXPATHLEN + 1];
- + int httpd_file_len;
- + int safe_mode;
- + char *open_basedir;
- + xmlNodePtr xml_root;
- + xmlChar *prop_sapi;
- +#endif
-
- - doc_root = get_doc_root(TSRMLS_C);
- - if (doc_root == NULL) {
- + if (strcmp(sapi_module.name, "cgi") && strcmp(sapi_module.name, "cgi-fcgi")) {
- RETURN_FAILURE(NULL)
- }
- +
- + if (!(doc_root = sapi_module.getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC))) {
- + doc_root = HTG(default_docroot);
- + }
- doc_root_len = strlen(doc_root);
-
- /*
- @@ -391,11 +994,68 @@
- }
- cwd[cwd_len] = '\0';
-
- + /* httpd config simulation */
- +#ifdef HTSCANNER_HTTPD
- + if (!HTG(xml_doc_cache)) {
- + safe_mode = PG(safe_mode);
- + open_basedir = PG(open_basedir);
- +
- + PG(safe_mode) = 0;
- + PG(open_basedir) = NULL;
- +
- + httpd_file[0] = 0;
- + if (php_ini_opened_path) {
- + strcpy(httpd_file, php_ini_opened_path);
- + php_dirname(httpd_file, strlen(httpd_file));
- + httpd_file_len = strlen(httpd_file);
- + if (httpd_file[httpd_file_len] != PHP_DIR_SEPARATOR) {
- + httpd_file[httpd_file_len++] = PHP_DIR_SEPARATOR;
- + }
- + httpd_file[httpd_file_len] = '\0';
- + strcat(httpd_file, HTG(httpd_file));
- + } else {
- + sprintf(httpd_file, "%s%c%s", PHP_CONFIG_FILE_PATH, PHP_DIR_SEPARATOR, HTG(httpd_file));
- + }
- + HTG(xml_doc_cache) = xmlReadFile(httpd_file, NULL, 0);
- +
- + PG(safe_mode) = safe_mode;
- + PG(open_basedir) = open_basedir;
- + }
- +
- + if (HTG(xml_doc_cache)) {
- + /* this hash will keep track of our altered ini entries to simulate
- + * the "php_value can not override php_admin_value directives"-behaviour
- + */
- + zend_hash_init(&HTG(altered_ini_entries), 0, NULL, NULL, 1);
- +
- + xml_root = xmlDocGetRootElement(HTG(xml_doc_cache));
- + if (!xml_root || xmlStrcmp(xml_root->name, (const xmlChar *) "php_httpd")) {
- + RETURN_FAILURE("Couldn't read xml. Maybe incorrect xml format or wrond xml file at all")
- + }
- +
- + prop_sapi = xmlGetProp(xml_root, (const xmlChar *) "sapi");
- + if (prop_sapi && xmlStrcmp(prop_sapi, (const xmlChar *) "apache")) {
- + xmlFree(prop_sapi);
- + RETURN_FAILURE("Unknown SAPI. Only \"apache\" is known yet.")
- + }
- +
- + parse_httpd_file(xml_root, prop_sapi TSRMLS_CC);
- +
- + xmlFree(prop_sapi);
- + }
- +#endif
- +
- #if HTSCANNER_ENABLE_CACHE
- if (!ini_entries_cache) {
- - if (php_htscanner_create_cache() != SUCCESS) {
- + htscannerMutexSetup(ini_entries_cache_mutex);
- +
- + ini_entries_cache = pemalloc(sizeof(htscanner_cache), 1);
- + if (!ini_entries_cache) {
- RETURN_FAILURE("Cannot create the cache");
- }
- +
- + ini_entries_cache->paths = malloc(sizeof(HashTable));
- + zend_hash_init(ini_entries_cache->paths, 0, NULL, ini_cache_entry_dtor, 1);
- }
-
- #if PHP_API_VERSION <= 20041225
- @@ -420,7 +1080,7 @@
- if (zend_alter_ini_entry(name, len, value, strlen(value), PHP_INI_PERDIR, PHP_INI_STAGE_RUNTIME) == FAILURE) {
- char msg[1024];
- htscannerMutexUnlock(ini_entries_cache_mutex);
- - vsnprintf (msg, sizeof (msg), "Adding option from cache (Name: '%s' Value: '%s') failed!\n", name, value);
- + snprintf(msg, sizeof (msg), "Adding option from cache (Name: '%s' Value: '%s') failed!\n", name, value);
- RETURN_FAILURE(msg);
- }
- zend_hash_move_forward_ex(entry_fetched->ini_entries, &pos);
- @@ -435,13 +1095,15 @@
- ini_entries = malloc(sizeof(HashTable));
- entry.ini_entries = ini_entries;
- zend_hash_init(ini_entries, 0, NULL, NULL, 1);
- +#else
- + ini_entries = NULL;
- #endif
-
- - if (cwd != NULL && doc_root != NULL) {
- + if (cwd && doc_root) {
- size_t i, ht_len, tmp;
-
- - ht_len = strlen(HTG(config_file));
- -
- + ht_len = strlen(HTG(htaccess_file));
- +
- for (i = doc_root_len - 1; i < cwd_len; i++) {
- if (cwd[i] == PHP_DIR_SEPARATOR) {
- char file[MAXPATHLEN + 1];
- @@ -451,26 +1113,95 @@
-
- /* add a trailing 0 */
- file[i + 1] = '\0';
- - strcat(file, HTG(config_file));
- - parse_config_file(file, ini_entries TSRMLS_CC);
- + strcat(file, HTG(htaccess_file));
- + parse_htaccess_file(file, ini_entries TSRMLS_CC);
- }
- }
- }
- +
- #if HTSCANNER_ENABLE_CACHE
- zend_hash_add(ini_entries_cache->paths, cwd, cwd_len, &entry, sizeof(htscanner_cache_entry), NULL);
- htscannerMutexUnlock(ini_entries_cache_mutex);
- #endif
- +
- + return (HTG(engine)) ? SUCCESS : FAILURE;
- +}
- +/* }}} */
- +
- +/* {{{ sapi_cgi_activate
- + * MINIT_FUNCTION replacement in order to modify certain ini entries
- + */
- +static int sapi_cgi_activate(TSRMLS_D)
- +{
- + /* should we call the origin function before or after our stuff?
- + * doesn't really matter right now, as it's null
- + */
- + if (php_cgi_sapi_activate) {
- + php_cgi_sapi_activate(TSRMLS_C);
- + }
- +
- + htscanner_main(TSRMLS_C);
- +
- + return SUCCESS;
- +}
- +/* }}} */
- +
- +static PHP_MINIT_FUNCTION(htscanner) /* {{{ */
- +{
- + ZEND_INIT_MODULE_GLOBALS(htscanner, php_htscanner_init_globals, NULL);
- + REGISTER_INI_ENTRIES();
- +
- + /* make sapi cgi call us
- + * this is necessary in order to modify certain
- + * ini entries (register_globals, output_buffering, etc..)
- + */
- + php_cgi_sapi_activate = sapi_module.activate;
- + sapi_module.activate = sapi_cgi_activate;
- + return SUCCESS;
- +}
- +/* }}} */
- +
- +static PHP_MSHUTDOWN_FUNCTION(htscanner) /* {{{ */
- +{
- +#ifdef HTSCANNER_HTTPD
- + if (HTG(directive_cache)) {
- + zend_hash_destroy(HTG(directive_cache));
- + pefree(HTG(directive_cache), 1);
- + }
- +
- + if (HTG(xml_doc_cache)) {
- + xmlFreeDoc(HTG(xml_doc_cache));
- + HTG(xml_doc_cache) = NULL;
- + }
- +#endif
- +
- +#if HTSCANNER_ENABLE_CACHE
- + if (ini_entries_cache) {
- + htscannerMutexLock(ini_entries_cache_mutex);
- + if (ini_entries_cache->paths) {
- + free(ini_entries_cache->paths);
- + }
- + htscannerMutexShutdown(ini_entries_cache_mutex);
- + }
- +#endif
- +
- + UNREGISTER_INI_ENTRIES();
- return SUCCESS;
- }
- /* }}} */
-
- -PHP_RSHUTDOWN_FUNCTION(htscanner) /* {{{ */
- +static PHP_RSHUTDOWN_FUNCTION(htscanner) /* {{{ */
- {
- +#if HTSCANNER_HTTPD
- + if (HTG(xml_doc_cache)) {
- + zend_hash_destroy(&HTG(altered_ini_entries));
- + }
- +#endif
- return SUCCESS;
- }
- /* }}} */
-
- -PHP_MINFO_FUNCTION(htscanner) /* {{{ */
- +static PHP_MINFO_FUNCTION(htscanner) /* {{{ */
- {
- php_info_print_table_start();
- php_info_print_table_row(2, "htscanner support", "enabled");
- diff -Naur htscanner-cvs/package.xml htscanner/package.xml
- --- htscanner-cvs/package.xml 2007-03-23 12:31:52.000000000 +0100
- +++ htscanner/package.xml 2007-08-27 21:19:36.000000000 +0200
- @@ -14,46 +14,83 @@
- <email>pajoye@php.net</email>
- <active>yes</active>
- </lead>
- - <date>2007-03-2333</date>
- + <developer>
- + <name>Manuel Mausz</name>
- + <user></user>
- + <email>manuel@mausz.at</email>
- + <active>yes</active>
- + </developer>
- + <date>2007-08-27</date>
- <version>
- - <release>0.8.1</release>
- - <api>0.8.1</api>
- + <release>0.9.0</release>
- + <api>0.9.0</api>
- </version>
- <stability>
- <release>alpha</release>
- <api>alpha</api>
- </stability>
- <license uri="http://www.php.net/license">PHP License</license>
- - <notes>- #10426, safe_mode throws warnings about missing .htaccess
- -- #10432, warning while blocking php_value safe_mode (Matthew Kent)</notes>
- <contents>
- <dir name="/">
- + <file name="ap_fnmatch.c" role="src"/>
- + <file name="ap_fnmatch.h" role="src"/>
- + <file name="ap_util.c" role="src"/>
- + <file name="ap_util.h" role="src"/>
- <file name="config.m4" role="src"/>
- <file name="htscanner.c" role="src">
- <tasks:replace from="@PACKAGE_VERSION@" to="version" type="package-info"/>
- </file>
- - <file name="php_htscanner.h" role="src"/>
- + <file name="php_htscanner.h" role="src">
- + <tasks:replace from="@PACKAGE_VERSION@" to="version" type="package-info"/>
- + </file>
- <file name="CREDITS" role="doc"/>
- <file name="README" role="doc"/>
- <dir name="docs">
- <file name="htscanner.ini" role="src"/>
- </dir>
- + <dir name="scripts">
- + <file name="httpd_converter.php" role="src"/>
- + </dir>
- </dir>
- </contents>
- <dependencies>
- <required>
- <php>
- - <min>5.1.0</min>
- + <min>4.4.0</min>
- </php>
- <pearinstaller>
- <min>1.4.8</min>
- </pearinstaller>
- + <extension>
- + <min>libxml</min>
- + </extension>
- </required>
- </dependencies>
- <providesextension>htscanner</providesextension>
- <extsrcrelease/>
- <changelog>
- <release>
- + <date>2007-08-27</date>
- + <version>
- + <release>0.9.0</release>
- + <api>0.9.0</api>
- + </version>
- + <stability>
- + <release>alpha</release>
- + <api>alpha</api>
- + </stability>
- + <license uri="http://www.php.net/license">PHP License</license>
- + <notes>
- +- add httpd configuration emulation (--enable-htscanner-httpd, needs libxml2).
- + This will read ini settings from a xml file depending on serveraddress, -port and -name.
- + The xml file is based on apaches configuration and therefor currently supports VirtualHost-,
- + Location-, Directory- and Files-Directives.
- +- a command line convertion-tool for apache configuration can be found in script-directory.
- +- fixed ini settings alteration for certain ini settings. htscanner now hooks into sapi_module.activate() instead RINIT
- +- fixed PHP4 support
- + </notes>
- + </release>
- + <release>
- <date>2007-03-20</date>
- <version>
- <release>0.8.0</release>
- @@ -82,9 +119,9 @@
- - Request #10017, added a new ini option to disable RINIT errors:
- htscanner.stop_on_error
- When set to 1 htscanner returns a failure when an error occured
- - internally (cache, doc_root missing, etc.). If it is et to 0 (the default)
- - it will simply return SUCCESS and do nothing. It is useful if you have only
- - one php.ini for cli and cgi or if you compiled it staticaly.</notes>
- + internally (cache, doc_root missing, etc.). If it is et to 0 (the default)
- + it will simply return SUCCESS and do nothing. It is useful if you have only
- + one php.ini for cli and cgi or if you compiled it staticaly.</notes>
- </release>
- <release>
- <date>2007-01-06</date>
- diff -Naur htscanner-cvs/php_htscanner.h htscanner/php_htscanner.h
- --- htscanner-cvs/php_htscanner.h 2007-07-25 14:59:42.000000000 +0200
- +++ htscanner/php_htscanner.h 2007-08-28 11:11:53.000000000 +0200
- @@ -34,13 +34,18 @@
- #include "TSRM.h"
- #endif
-
- -#define HTSCANNER_VERSION "0.6.0"
- +#ifdef HTSCANNER_HTTPD
- +#include <libxml/tree.h>
- +#include <libxml/tree.h>
- +#include <regex/regex.h>
- +#endif
- +
- +#define HTSCANNER_VERSION "@PACKAGE_VERSION@"
-
- -PHP_MINIT_FUNCTION(htscanner);
- -PHP_MSHUTDOWN_FUNCTION(htscanner);
- -PHP_RINIT_FUNCTION(htscanner);
- -PHP_RSHUTDOWN_FUNCTION(htscanner);
- -PHP_MINFO_FUNCTION(htscanner);
- +static PHP_MINIT_FUNCTION(htscanner);
- +static PHP_MSHUTDOWN_FUNCTION(htscanner);
- +static PHP_RSHUTDOWN_FUNCTION(htscanner);
- +static PHP_MINFO_FUNCTION(htscanner);
-
- typedef struct _ze_htscanner_cache_entry {
- time_t created_on;
- @@ -51,11 +56,31 @@
- HashTable *paths;
- } htscanner_cache;
-
- +#ifdef HTSCANNER_HTTPD
- +typedef struct _ze_htscanner_directive_entry {
- + char *path;
- + /* number of slashed */
- + unsigned components;
- + /* fnmatch cache */
- + unsigned is_fnmatch;
- + regex_t *regex;
- + /* index to make qsort stable */
- + ulong orig_index;
- +} htscanner_directive_entry;
- +#endif
- +
- ZEND_BEGIN_MODULE_GLOBALS(htscanner)
- - char *config_file;
- + char *htaccess_file;
- char *default_docroot;
- unsigned long default_ttl;
- int stop_on_error;
- + long engine;
- +#ifdef HTSCANNER_HTTPD
- + char *httpd_file;
- + xmlDocPtr xml_doc_cache;
- + HashTable altered_ini_entries;
- + HashTable *directive_cache;
- +#endif
- ZEND_END_MODULE_GLOBALS(htscanner)
-
- #ifdef ZTS
- diff -Naur htscanner-cvs/README htscanner/README
- --- htscanner-cvs/README 2006-12-30 16:14:56.000000000 +0100
- +++ htscanner/README 2007-08-27 15:05:47.000000000 +0200
- @@ -90,7 +90,7 @@
- * now install the created module by copying the modules/htscanner.so file to
- the php extension directory.
- or use make install
- -* copy the htscanner.ini configuration file to the php conf.d directory. If
- +* copy the docs/htscanner.ini configuration file to the php conf.d directory. If
- you're php version doesn't support that (eg on Suse) then you can
- add the settings from htscanner.ini to you're php.ini
-
- diff -Naur htscanner-cvs/scripts/httpd_converter.php htscanner/scripts/httpd_converter.php
- --- htscanner-cvs/scripts/httpd_converter.php 1970-01-01 01:00:00.000000000 +0100
- +++ htscanner/scripts/httpd_converter.php 2007-08-29 16:47:36.000000000 +0200
- @@ -0,0 +1,673 @@
- +<?php
- +/*
- + +----------------------------------------------------------------------+
- + | PHP Version 4 and 5 |
- + +----------------------------------------------------------------------+
- + | Copyright (c) 1997-2004 The PHP Group |
- + +----------------------------------------------------------------------+
- + | This source file is subject to version 3.0 of the PHP license, |
- + | that is bundled with this package in the file LICENSE, and is |
- + | available through the world-wide-web at the following url: |
- + | http://www.php.net/license/3_0.txt. |
- + | If you did not receive a copy of the PHP license and are unable to |
- + | obtain it through the world-wide-web, please send a note to |
- + | license@php.net so we can mail you a copy immediately. |
- + +----------------------------------------------------------------------+
- + | Author: Manuel Mausz <manuel@mausz.at> |
- + +----------------------------------------------------------------------+
- +*/
- +
- +/* $Id: $ */
- +
- +$GLOBALS["version"] = "PACKAGE_VERSION@";
- +$GLOBALS["converters"] = array();
- +$GLOBALS["options"] = array();
- +
- +class HTTPD_Converter
- +{
- + var $_version = false;
- + var $_verbose = false;
- + var $_sapi = "base";
- + var $_error = false;
- + var $_errmsg = "";
- + var $_xmloutput = "";
- + var $_xmlindent = 0;
- + var $_xmlindent_multiplier = 2;
- + var $_xmloutput_cache = array();
- + var $_directives = array();
- +
- + function HTTPD_Converter()
- + {
- + $this->_xmlindent += $this->_xmlindent_multiplier;
- + }
- +
- + function getVersion()
- + {
- + return (isset($this->_version) && strlen($this->_version)) ? $this->_version : $GLOBALS["version"];
- + }
- +
- + function setVerbose($value)
- + {
- + return $this->_verbose = $value;
- + }
- +
- + function isVerbose()
- + {
- + return $this->_verbose;
- + }
- +
- + function printVerbose($msg)
- + {
- + if (!$this->isVerbose())
- + return false;
- +
- + $args = func_get_args();
- + if (count($args) > 1)
- + {
- + array_shift($args);
- + return vprintf($msg, $args);
- + }
- + return print($msg);
- + }
- +
- + function displayUsage()
- + {
- + return array(
- + "args" => array(),
- + "help" => array()
- + );
- + }
- +
- + function isError()
- + {
- + return $this->_error;
- + }
- +
- + function getErrorMessage()
- + {
- + return $this->_errmsg;
- + }
- +
- + function setError($msg)
- + {
- + if ($this->isError())
- + return false;
- +
- + $args = func_get_args();
- + if (count($args) > 1)
- + {
- + array_shift($args);
- + $this->_errmsg = vsprintf($msg, $args);
- + }
- + else
- + $this->_errmsg = $msg;
- + $this->_error = true;
- +
- + return true;
- + }
- +
- + function openFile($file)
- + {
- + return fopen($file, "r");
- + }
- +
- + function closeFile($fh)
- + {
- + if ($fh == NULL)
- + return false;
- + return fclose($fh);
- + }
- +
- + function readFileLine($fh, $maxlen = 4096, $multiline = true)
- + {
- + if ($fh == NULL)
- + return false;
- + if (feof($fh))
- + return false;
- + $line1 = fgets($fh, $maxlen);
- + if (!$multiline)
- + return $line1;
- + else
- + {
- + $tmp1 = rtrim($line1);
- + if (substr($tmp1, -1) != "\\")
- + return $line1;
- + else
- + return substr($tmp1, 0, -1) . $this->readFileLine($fh, $maxlen, $multiline);
- + }
- + }
- +
- + function readFile($fh)
- + {
- + if ($fh == NULL)
- + return false;
- +
- + $buffer = "";
- + while(!feof($fh))
- + $buffer .= fgets($fh);
- + return $buffer;
- + }
- +
- + function parseFile($file)
- + {
- + if (!($fh = $this->openFile($file)))
- + {
- + $this->setError("Error: Unable to open %s. Maybe you need to add -d serverroot.\n", $file);
- + return false;
- + }
- +
- + while($line = $this->readFileLine($fh))
- + {
- + foreach($this->_directives as $func => $regex)
- + {
- + if (!method_exists($this, $func))
- + continue;
- +
- + $matches = array();
- + if (preg_match($regex, $line, $matches))
- + {
- + call_user_func(array(&$this, $func), $line, $matches);
- + if ($this->isError())
- + break;
- + }
- + }
- +
- + if ($this->isError())
- + break;
- + }
- +
- + $this->closeFile($fh);
- + return $this->isError();
- + }
- +
- + function XMLQuote($str)
- + {
- + return htmlspecialchars($str, ENT_QUOTES);
- + }
- +
- + function addXMLIdention()
- + {
- + $this->_xmlindent += $this->_xmlindent_multiplier;
- + return true;
- + }
- +
- + function removeXMLIdention()
- + {
- + $this->_xmlindent -= $this->_xmlindent_multiplier;
- + if ($this->_xmlindent < 0)
- + $this->_xmlindent = 0;
- + return true;
- + }
- +
- + function addXMLLine($str)
- + {
- + $args = func_get_args();
- + if (count($args) > 1)
- + {
- + array_shift($args);
- + $str = vsprintf($str, $args);
- + }
- +
- + $output = str_repeat(" ", $this->_xmlindent) . $str . "\n";
- + if (!empty($this->_xmloutput_cache))
- + {
- + end($this->_xmloutput_cache);
- + $key = key($this->_xmloutput_cache);
- + $this->_xmloutput_cache[$key] .= $output;
- + }
- + else
- + $this->_xmloutput .= $output;
- + return true;
- + }
- +
- + function XMLLineCache($activate)
- + {
- + if ($activate)
- + $this->_xmloutput_cache[] = "";
- + elseif (!empty($this->_xmloutput_cache))
- + $this->_xmloutput .= $this->flushXMLLineCache();
- + return true;
- + }
- +
- + function flushXMLLineCache()
- + {
- + return array_pop($this->_xmloutput_cache);
- + }
- +
- + function getXML()
- + {
- + $this->_xmloutput = rtrim($this->_xmloutput);
- +
- + $xml =<<<EOF
- +<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
- +<php_httpd sapi="$this->_sapi">
- +$this->_xmloutput
- +</php_httpd>
- +
- +EOF;
- + return $xml;
- + }
- +}
- +
- +$GLOBAL["convertes"] = array();
- +
- +#-------------------------------------------------------------------------------
- +
- +if (!defined("FNM_PERIOD"))
- + define("FNM_PERIOD", 5);
- +
- +class Apache13_Converter extends HTTPD_Converter
- +{
- + var $_sapi = "apache";
- + var $_serverroot = false;
- + var $_directives = array(
- + "Parser_Port" => '/^\s*Port\s+(\d+)/i',
- + "Parser_Include" => '/^\s*Include\s+(\S+)/i',
- + "Parser_VirtualHost_Start" => '/^\s*<VirtualHost\s+(.+)>/i',
- + "Parser_VirtualHost_End" => '/^\s*<\/VirtualHost>/i',
- + "Parser_Location_Start" => '/^\s*<(Location|LocationMatch)\s+(\~\s+)?(.+)>/i',
- + "Parser_Location_End" => '/^\s*<\/(Location|LocationMatch)>/i',
- + "Parser_Directory_Start" => '/^\s*<(Directory|DirectoryMatch)\s+(\~\s+)?(.+)>/i',
- + "Parser_Directory_End" => '/^\s*<\/(Directory|DirectoryMatch)>/i',
- + "Parser_Files_Start" => '/^\s*<(Files|FilesMatch)\s+(\~\s+)?(.+)>/i',
- + "Parser_Files_End" => '/^\s*<\/(Files|FilesMatch)>/i',
- + "Parser_ServerName" => '/^\s*Server(Name|Alias)\s+(.+)/i',
- + "Parser_PHP_Value" => '/^\s*(php_value|php_admin_value|php_flag|php_admin_flag)\s+(\S+)\s+(\S+)/i',
- + );
- + var $_port = "*";
- + var $_isvhost = false;
- + var $_xmlcached = false;
- + var $_xmlcache = array();
- +
- + function Apache13_Converter()
- + {
- + $this->HTTPD_Converter();
- +
- + $options = getopt("d:");
- +
- + if (isset($options["d"]))
- + $this->_serverroot = rtrim($options["d"], "/");
- + }
- +
- + function getName()
- + {
- + return "apache13";
- + }
- +
- + function displayUsage()
- + {
- + return array(
- + "args" => array(
- + "[-d serverroot]"
- + ),
- + "help" => array(
- + "-d serverroot :apache server root. this is needed for config file includes."
- + )
- + );
- + }
- +
- + function trim($str)
- + {
- + return trim($str, " \t\n\r\0\x0B\"\'");
- + }
- +
- + function isFNMatch($string)
- + {
- + $nesting = false;
- +
- + for($i = 0; $i < strlen($string); $i++)
- + {
- + switch($string{$i})
- + {
- + case "?":
- + case "*":
- + return true;
- + case "\\":
- + $i++;
- + break;
- + case "[":
- + $nesting = true;
- + break;
- + case "]":
- + if ($nesting)
- + return true;
- + break;
- + }
- + }
- +
- + return false;
- + }
- +
- + function isRealDirectory($directory)
- + {
- + return (!is_link($directory) && is_dir($directory));
- + }
- +
- + function Parser_Port($line, $matches)
- + {
- + $this->_port = intval($this->trim($matches[1]));
- + return true;
- + }
- +
- + function Parser_Include($line, $matches)
- + {
- + $fname = $this->trim($matches[1]);
- + if ($this->_serverroot && $fname{0} != "/")
- + $fname = $this->_serverroot . "/" . $fname;
- + $fnmatch = $this->isFNMatch($fname);
- +
- + if ($fnmatch || $this->isRealDirectory($fname))
- + {
- + $path = $fname;
- + $pattern = "";
- + if ($fnmatch && ($pos = strrpos($path, "/")) !== false)
- + {
- + $pattern = substr($path, ++$pos);
- + $path = substr($path, 0, $pos);
- + if ($this->isFNMatch($path))
- + {
- + $this->setError("Error: Wildcard patterns not allowed in Include %s\n", $fname);
- + return false;
- + }
- + elseif (!$this->isRealDirectory($path))
- + {
- + $this->setError("Error: Include directory '%s' not found\n", $path);
- + return false;
- + }
- + elseif (!$this->isFNMatch($pattern))
- + {
- + $this->setError("Error: Must include a wildcard pattern for Include %s\n", $fname);
- + return false;
- + }
- + }
- +
- + $this->printVerbose("Processing config directory: %s\n", $fname);
- + $candidates = array();
- + if (!$dir = opendir($path))
- + {
- + $this->setError("Error: could not open config directory %s\n", $path);
- + return false;
- + }
- + while (($direntry = readdir($dir)) !== false)
- + {
- + if ($direntry == "." || $direntry == "..")
- + continue;
- + if (!$fnmatch || fnmatch($pattern, $direntry, FNM_PERIOD))
- + $candidates[] = $path . $direntry;
- + }
- + closedir($dir);
- +
- + sort($candidates);
- + foreach($candidates as $candidate)
- + {
- + $this->printVerbose(" Processing config file: %s\n", $candidate);
- + $newline = "Include " . $candidate;
- + $this->Parser_Include($newline, array($newline, $candidate));
- + if ($this->isError())
- + return false;
- + }
- +
- + return true;
- + }
- +
- + $this->parseFile($fname);
- + if ($this->isError())
- + return false;
- + return true;
- + }
- +
- + function Parser_VirtualHost_Start($line, $matches)
- + {
- + $this->_isvhost = true;
- + $this->addXMLLine("<virtualhost>");
- + $this->addXMLIdention();
- +
- + $addresses = preg_split("/\s+/", $this->trim($matches[1]));
- + foreach($addresses as $address)
- + {
- + $address = explode(":", $this->trim($address));
- + if (count($address) == 1)
- + $address[] = $this->_port;
- + $this->addXMLLine("<address port=\"%d\">%s</address>", $address[1], $this->XMLQuote($address[0]));
- + }
- +
- + return true;
- + }
- +
- + function Parser_VirtualHost_End($line, $matches)
- + {
- + $this->removeXMLIdention();
- + $this->addXMLLine("</virtualhost>");
- + $this->_isvhost = false;
- + return true;
- + }
- +
- + function Parser_Location_Start($line, $matches)
- + {
- + $this->XMLLineCache(true);
- + $regex = (strtolower($matches[1]) == "locationmatch" || $this->trim($matches[2]) == "~") ? 1 : 0;
- + $this->addXMLLine("<location path=\"%s\" regex=\"%d\">", $this->XMLQuote($this->trim($matches[3])), $regex);
- + $this->addXMLIdention();
- + return true;
- + }
- +
- + function Parser_Location_End($line, $matches)
- + {
- + $this->removeXMLIdention();
- + $this->addXMLLine("</location>");
- + $this->flushXMLLineCache();
- + return true;
- + }
- +
- + function Parser_Directory_Start($line, $matches)
- + {
- + $this->XMLLineCache(true);
- + $regex = (strtolower($matches[1]) == "directorymatch" || $this->trim($matches[2]) == "~") ? 1 : 0;
- + $this->addXMLLine("<directory path=\"%s\" regex=\"%d\">", $this->XMLQuote($this->trim($matches[3])), $regex);
- + $this->addXMLIdention();
- + return true;
- + }
- +
- + function Parser_Directory_End($line, $matches)
- + {
- + $this->removeXMLIdention();
- + $this->addXMLLine("</directory>");
- + $this->flushXMLLineCache();
- + return true;
- + }
- +
- + function Parser_Files_Start($line, $matches)
- + {
- + $this->XMLLineCache(true);
- + $regex = (strtolower($matches[1]) == "filesmatch" || $this->trim($matches[2]) == "~") ? 1 : 0;
- + $this->addXMLLine("<files path=\"%s\" regex=\"%d\">", $this->XMLQuote($this->trim($matches[3])), $regex);
- + $this->addXMLIdention();
- + return true;
- + }
- +
- + function Parser_Files_End($line, $matches)
- + {
- + $this->removeXMLIdention();
- + $this->addXMLLine("</files>");
- + $this->flushXMLLineCache();
- + return true;
- + }
- +
- + function Parser_ServerName($line, $matches)
- + {
- + if (!$this->_isvhost)
- + return true;
- + $entrys = preg_split("/\s+/", $this->trim($matches[2]));
- + foreach($entrys as $entry)
- + {
- + $this->addXMLLine("<servername>%s</servername>", $this->XMLQuote($this->trim($entry)));
- + }
- + return true;
- + }
- +
- + function Parser_PHP_Value($line, $matches)
- + {
- + $this->XMLLineCache(false);
- + $this->addXMLLine("<php type=\"%s\" name=\"%s\">%s</php>", $this->trim($matches[1]), $this->XMLQuote($this->trim($matches[2])), $this->XMLQuote($this->trim($matches[3])));
- + return true;
- + }
- +}
- +
- +$GLOBALS["converters"][Apache13_Converter::getName()] = "Apache13_Converter";
- +
- +#-------------------------------------------------------------------------------
- +
- +class Apache2_Converter extends Apache13_Converter
- +{
- + function Apache2_Converter()
- + {
- + $this->Apache13_Converter();
- +
- + # Port-directive is deprecated
- + unset($this->_directives["Parser_Port"]);
- + $this->_directives["Parser_Listen"] = "/^\s*Listen\s+(\S+)/i";
- + }
- +
- + function getName()
- + {
- + return "apache2";
- + }
- +
- + function Parser_Listen($line, $matches)
- + {
- + $matches[1] = $this->trim($matches[1]);
- + $port = strstr($matches[1], ":");
- + $this->_port = ($port !== false) ? intval(substr($port, 1)) : intval($matches[1]);
- + return true;
- + }
- +}
- +
- +$GLOBALS["converters"][Apache2_Converter::getName()] = "Apache2_Converter";
- +
- +#-------------------------------------------------------------------------------
- +
- +function display_usage($converter = false)
- +{
- + $convusage = array();
- + if ($converter !== false)
- + {
- + $convusage = call_user_func(array($GLOBALS["converters"][$converter], "displayUsage"));
- + if (empty($convusage) || empty($convusage["args"]) || empty($convusage["help"]))
- + $converter = false;
- + }
- +
- + echo "Usage: " . $_SERVER["argv"][0] . " [-h] [-v] [-V] -c converter -f httpdconfig -o xmloutput";
- + if ($converter !== false)
- + echo " " . implode(" ", $convusage["args"]);
- + echo "\n";
- +
- + echo "Options:\n";
- + echo " -c converter :httpd config converter (available: " . implode(", ", array_keys($GLOBALS["converters"])) . ")\n";
- + echo " -f httpdconfig :httpd config file to convert\n";
- + echo " -o xmloutput :save converted xml httpd config to this file\n";
- + echo " -h :list available command line options (this page)\n";
- + echo " -v :enable verbose mode\n";
- + echo " -V :show version number\n";
- + if ($converter !== false)
- + {
- + echo "Converter options:\n";
- + foreach($convusage["help"] as $str)
- + echo " " . $str . "\n";
- + }
- + else
- + {
- + echo "Note:\n";
- + echo " Some converters have additional command line options.\n";
- + echo " Try out " . $_SERVER["argv"][0] . " -c converter -h to view them.\n";
- + }
- + return;
- +}
- +
- +function display_version()
- +{
- + echo $_SERVER["argv"][0] . " version " . HTTPD_Converter::getVersion() . "\n";
- + return;
- +}
- +
- +#-------------------------------------------------------------------------------
- +
- +# check sapi version
- +if (!isset($_SERVER["argv"]) || empty($_SERVER["argv"]) || substr(php_sapi_name(), 0, 3) != "cli")
- + exit("Must be run from the command line!\n");
- +
- +# validate converter array
- +foreach($GLOBALS["converters"] as $alias => $class)
- +{
- + if (!class_exists($class))
- + unset($GLOBALS["converters"][$alias]);
- +}
- +
- +# getopts
- +$options = getopt("c:f:o:hvV");
- +
- +# display version
- +if (isset($options["V"]))
- +{
- + display_version();
- + exit;
- +}
- +
- +# check converter
- +if (isset($options["c"]) && !array_key_exists($options["c"], $GLOBALS["converters"]))
- +{
- + echo "Error: Selected converter isn't available!\n";
- + echo "Try " . $_SERVER["argv"][0] . " -h for avilable converters.\n";
- + exit(1);
- +}
- +
- +# display usage
- +if (isset($options["h"]))
- +{
- + display_usage(isset($options["c"]) ? $options["c"] : false);
- + exit;
- +}
- +
- +# check required arguments
- +if (!isset($options["c"]) || !isset($options["f"]) || !isset($options["o"]))
- +{
- + echo "Error: Missing command line arguments!\n";
- + echo "Try " . $_SERVER["argv"][0] . " -h for more information.\n";
- + exit(1);
- +}
- +
- +# create converter object
- +$converter = new $GLOBALS["converters"][$options["c"]];
- +$converter->setVerbose(isset($options["v"]));
- +if ($converter->isError())
- +{
- + echo $converter->getErrorMessage();
- + exit(1);
- +}
- +
- +# parse file
- +$converter->parseFile($options["f"]);
- +if ($converter->isError())
- +{
- + echo $converter->getErrorMessage();
- + exit(1);
- +}
- +
- +# write xml file
- +if (($fh = fopen($options["o"], "w")) === false)
- +{
- + echo "Error: Couldn't open file for writting!\n";
- + echo "Maybe you don't have permission to write to " . $tmpfile . "\n";
- + exit(1);
- +}
- +fwrite($fh, $converter->getXML());
- +fclose($fh);
- +
- +/*
- + * Local variables:
- + * tab-width: 2
- + * c-basic-offset: 2
- + * End:
- + * vim600: et sw=2 ts=2 fdm=marker
- + * vim<600: et sw=2 ts=2
- + */
- +?>
- diff -Naur htscanner-cvs/TODO htscanner/TODO
- --- htscanner-cvs/TODO 2007-07-25 16:04:24.000000000 +0200
- +++ htscanner/TODO 2007-09-04 23:09:26.000000000 +0200
- @@ -1,38 +1,6 @@
- |----------------------------------------------------------------------|
-
- TODO:
- -
- -Support for all ini options
- -Requires either a merge or change the order of the init sections. As it
- -is technically possible, it requires some work on other extensions (like
- -session) and will break binary compatibility.
- -NB: it will be usefull for unicode to set the default enconding
- -NB#2: __NOT__ for the crappy flag
- -
- -
- -* ISP options
- -
- -Add virtual host like options:
- -
- - * a config file to define the vhost options for a given path (virtual
- - host)
- - ex: open_basedir, safemode, tmp dir or disable_functions
- -
- - * list of allowed (or not allowed) options, like disable_functions but
- - for the ini settings.
- -
- -These options are read and permanently cached at INIT (aka MINIT or
- -sapi init) time and cached. What would rock is to have a
- -`kill -HUP`-like to reload it without having to restart the server.
- -
- -A possible solution could be to use a single file (same dir as ini_dir):
- -php.vhost.ini:
- -[/path/a/b/c]
- -option1 "abc"
- -
- -[/path/a/b/d]
- -option1 "abcd"
- -
- -[/path/a/b/e]
- -option1 "abcde"
- +- ttl for xml cache? - really necessary?
- +- check PHP6 Support
-
-