Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:28128 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 68832 invoked by uid 1010); 24 Feb 2007 19:09:22 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 68800 invoked from network); 24 Feb 2007 19:09:22 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 24 Feb 2007 19:09:22 -0000 Authentication-Results: pb1.pair.com smtp.mail=jochem@iamjochem.com; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=jochem@iamjochem.com; sender-id=unknown Received-SPF: error (pb1.pair.com: domain iamjochem.com from 194.109.193.121 cause and error) X-PHP-List-Original-Sender: jochem@iamjochem.com X-Host-Fingerprint: 194.109.193.121 mx1.moulin.nl Linux 2.6 Received: from [194.109.193.121] ([194.109.193.121:39542] helo=mx1.moulin.nl) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 91/A6-32716-16D80E54 for ; Sat, 24 Feb 2007 14:09:21 -0500 Received: from localhost (localhost [127.0.0.1]) by mx1.moulin.nl (Postfix) with ESMTP id 5864B154C14; Sat, 24 Feb 2007 20:09:26 +0100 (CET) X-Virus-Scanned: amavisd-new at moulin.nl Received: from mx1.moulin.nl ([127.0.0.1]) by localhost (mx1.moulin.nl [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id QbIjzZizkHKJ; Sat, 24 Feb 2007 20:09:19 +0100 (CET) Received: from [10.0.13.54] (ip129-15-211-87.adsl2.versatel.nl [87.211.15.129]) by mx1.moulin.nl (Postfix) with ESMTP id 59E1E153DBD; Sat, 24 Feb 2007 20:09:19 +0100 (CET) Message-ID: <45E08D56.9060802@iamjochem.com> Date: Sat, 24 Feb 2007 20:09:10 +0100 User-Agent: Thunderbird 1.5.0.9 (Windows/20061207) MIME-Version: 1.0 To: Mo McRoberts , php internals References: <20070224031755.GA29737@melo.nevali.net> In-Reply-To: <20070224031755.GA29737@melo.nevali.net> X-Enigmail-Version: 0.94.2.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] Simulating require_once within an extension From: jochem@iamjochem.com (Jochem Maas) I suspect you could implement the desired functionality using http://php.net/manual/en/function.stream-wrapper-register.php although I can't find any info on whether include/require actually work with registered stream wrappers .. maybe one of the devs could confirm/deny whether this is possible. which would allow you to do something like this (assuming it is possible to do): require_once 'momcr://foo/script.php'; Mo McRoberts wrote: > Hi list, > > Apologies if I'm sending this to the wrong list; I couldn't see another > which was more appropriate on the PHP Mailing Lists page. > > I'm developing a PHP extension for which part of the functionality can > be described in a nutshell as: > > * at request start-up time, build a map of identifiers to path-names, read > from a configuration file; > > * whilst a user script is being processed, a function provided by the > extension can be called to add, remove or modify items in the mapping; > > * a user script can call a function, passing it an identifier in the map, > and the extension should simulate require_once being called with the > corresponding pathname (with some transformation applied). > > For example, if the configuration file specified that 'foo' mapped to > /www/common/foo, calling the above function with a parameter of 'foo' > might simulate require_once('/www/common/foo/script.php') (where the > transformation applied in this case is appending 'script.php' to the given > pathname). A prototype implementation written in PHP itself works well enough, > but obviously there are scoping issues with such an implementation (i.e., > any scripts included are included within the scope of the function, not the > caller) which I want to avoid through the use of an extension. > > Obviously, much of this is pretty trivial and straightforward. My problem is > the actual simulation of require_once itself. As it's a language intrinsic, > there's no simply-exposed API for performing the same action. Digging through > the PHP sources, I've come across zend_execute_scripts(), which seems to > fit the bill, although there's no documentation and very few examples of it > being used outside of the PHP engine itself. > > From skimming as many bits of the PHP sources that actually use > zend_execute_scripts() that I could find, the code I've come up > with isn't hugely dissimilar to this: > > static int > do_required(const char *filename TSRMLS_DC) > { > int r; > zend_file_handle zh; > > if(SUCCESS != (r = zend_stream_open(filename, &zh TSRMLS_CC))) > { > return r; > } > if(NULL == zh.opened_path) > { > zh.opened_path = estrdup(filename); > } > if(zend_hash_add_empty_element(&EG(included_files), > zh.opened_path, strlen(zh.opened_path) + 1) == SUCCESS) > { > r = zend_execute_scripts(ZEND_REQUIRE_ONCE TSRMLS_CC, NULL, 1, &zh); > } > zend_stream_close(TSRMLS_CC); > return r; > } > > Simple enough, right? Wrong. > > I'm hoping at this point that somebody who knows the Zend internals pretty > well will immediately spot which things I'm not initialising, saving/restoring, > or happen to be double-freeing at this point, because I'm at a loss. My > symptoms are this: > > * If calls to this function are nested, and an inner call results in > zend_stream_open() failing, I get faults in zend_get_executed_lineno(), > suggesting corruption somewhere. > > * If I save, reset and restore return_value_ptr_ptr, active_op_array, > opline_ptr before doing anything, things seem better, but the Warning > message reported when the file can't be opened gives the error location > as [no active file] on line 0, which is less than ideal. > > * If I only save/reset/restore around the call to zend_get_executed_lineno() > itself, things seem to work until I get as far as installing the extension > for my Apache 2.2 module build of PHP: at which point, as soon as there's > some nesting things start to go bad (errors reported or not). Removing the > final zend_stream_close() call stops Apache from dying, but I strongly > suspect that I'm just masking the problem rather than fixing it. > > So, my questions are: what am I doing wrong, and is there a better way to > accomplish the same thing? I considered evaluating a script instead of > trying to simulate require_once itself, but that seemed incredibly kludgy. > > Any help appreciated. > > Thanks, > > Mo. >