Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:28152 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 39830 invoked by uid 1010); 26 Feb 2007 10:28:01 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 39779 invoked from network); 26 Feb 2007 10:28:01 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 26 Feb 2007 10:28:01 -0000 Authentication-Results: pb1.pair.com smtp.mail=francois.laupretre@ratp.fr; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=francois.laupretre@ratp.fr; sender-id=unknown Received-SPF: error (pb1.pair.com: domain ratp.fr from 81.255.174.8 cause and error) X-PHP-List-Original-Sender: francois.laupretre@ratp.fr X-Host-Fingerprint: 81.255.174.8 unknown Solaris 8 (2) Received: from [81.255.174.8] ([81.255.174.8:30086] helo=odii-smtp.ratp.fr) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 23/00-39127-D26B2E54 for ; Mon, 26 Feb 2007 05:27:58 -0500 Received: from nyplic28.info.ratp (unknown [188.20.209.28]) by odii-smtp.ratp.fr (Postfix) with ESMTP id 5F77D2694B; Mon, 26 Feb 2007 11:27:49 +0100 (MET) Received: from EXCHANGE04.info.ratp ([188.20.209.4]) by nyplic28.info.ratp with Microsoft SMTPSVC(6.0.3790.2499); Mon, 26 Feb 2007 11:26:55 +0100 X-MimeOLE: Produced By Microsoft Exchange V6.5 Content-class: urn:content-classes:message MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Date: Mon, 26 Feb 2007 11:26:54 +0100 Message-ID: In-Reply-To: <20070224031755.GA29737@melo.nevali.net> X-MS-Has-Attach: X-MS-TNEF-Correlator: Thread-Topic: [PHP-DEV] Simulating require_once within an extension Thread-Index: AcdXxlDe+TLzLRVgRlG7VtB+xT3OngBx0G6w To: "Mo McRoberts" , X-OriginalArrivalTime: 26 Feb 2007 10:26:55.0376 (UTC) FILETIME=[A354E100:01C75990] Subject: RE : [PHP-DEV] Simulating require_once within an extension From: francois.laupretre@ratp.fr (=?iso-8859-1?Q?LAUPRETRE_Fran=E7ois_=28P=29?=) References: <20070224031755.GA29737@melo.nevali.net> Sorry, I can't help with your C extension but I can give you a solution = I implemented in PHP=20 for the same needs. I did using two mechanisms : - A stream wrapper to allow require_once to reference a virtual path. = Not required if you=20 require 'real' files. In PHK, I need it because I implement a virtual = file system. - A 'tunneling' function like yours, used through an eval(). I agree it = is not very=20 elegant but, unfortunately, there is no 'uplevel' feature in PHP (could = be an interesting=20 addition, along with a who_called_me()). This function generally returns = a=20 'require_once ' string, but as we eval()uate the = result, it can return=20 any code, even a 'throw Exception', to be thrown from the calling scope. If you want to see more about this example, download the PHK_Creator = building kit from=20 http://www.tekwire.net/joomla/download/phk, and search for the = 'web_tunnel' function in=20 file PHK.php. Regards Fran=E7ois > -----Original Message----- > From: Mo McRoberts [mailto:mo@nevali.net]=20 > Sent: Saturday, February 24, 2007 4:18 AM > To: internals@lists.php.net > Subject: [PHP-DEV] Simulating require_once within an extension >=20 >=20 > Hi list, >=20 > Apologies if I'm sending this to the wrong list; I couldn't=20 > see another which was more appropriate on the PHP Mailing Lists page. >=20 > I'm developing a PHP extension for which part of the=20 > functionality can be described in a nutshell as: >=20 > * at request start-up time, build a map of identifiers to=20 > path-names, read > from a configuration file; > =20 > * whilst a user script is being processed, a function provided by the > extension can be called to add, remove or modify items in=20 > the mapping; > =20 > * a user script can call a function, passing it an identifier=20 > in the map, > and the extension should simulate require_once being called with the > corresponding pathname (with some transformation applied). > =20 > For example, if the configuration file specified that 'foo'=20 > mapped to /www/common/foo, calling the above function with a=20 > parameter of 'foo' might simulate=20 > require_once('/www/common/foo/script.php') (where the=20 > transformation applied in this case is appending 'script.php'=20 > to the given pathname). A prototype implementation written in=20 > PHP itself works well enough, but obviously there are scoping=20 > issues with such an implementation (i.e., any scripts=20 > included are included within the scope of the function, not the > caller) which I want to avoid through the use of an extension. >=20 > Obviously, much of this is pretty trivial and=20 > straightforward. My problem is the actual simulation of=20 > require_once itself. As it's a language intrinsic, there's no=20 > simply-exposed API for performing the same action. Digging=20 > through the PHP sources, I've come across=20 > zend_execute_scripts(), which seems to fit the bill, although=20 > there's no documentation and very few examples of it being=20 > used outside of the PHP engine itself. >=20 > From skimming as many bits of the PHP sources that actually use > zend_execute_scripts() that I could find, the code I've come=20 > up with isn't hugely dissimilar to this: >=20 > static int > do_required(const char *filename TSRMLS_DC) > { > int r; > zend_file_handle zh; > =09 > if(SUCCESS !=3D (r =3D zend_stream_open(filename, &zh TSRMLS_CC))) > { > return r; > } > if(NULL =3D=3D zh.opened_path) > { > zh.opened_path =3D estrdup(filename); > } > if(zend_hash_add_empty_element(&EG(included_files),=20 > zh.opened_path, strlen(zh.opened_path) + 1) =3D=3D SUCCESS) > { > r =3D zend_execute_scripts(ZEND_REQUIRE_ONCE=20 > TSRMLS_CC, NULL, 1, &zh); > } > zend_stream_close(TSRMLS_CC); > return r; > } >=20 > Simple enough, right? Wrong. >=20 > I'm hoping at this point that somebody who knows the Zend=20 > internals pretty well will immediately spot which things I'm=20 > not initialising, saving/restoring, or happen to be=20 > double-freeing at this point, because I'm at a loss. My=20 > symptoms are this: >=20 > * If calls to this function are nested, and an inner call results in > zend_stream_open() failing, I get faults in=20 > zend_get_executed_lineno(), > suggesting corruption somewhere. > =20 > * If I save, reset and restore return_value_ptr_ptr, active_op_array,=20 > opline_ptr before doing anything, things seem better, but=20 > the Warning > message reported when the file can't be opened gives the=20 > error location > as [no active file] on line 0, which is less than ideal. >=20 > * If I only save/reset/restore around the call to=20 > zend_get_executed_lineno() > itself, things seem to work until I get as far as=20 > installing the extension > for my Apache 2.2 module build of PHP: at which point, as=20 > soon as there's > some nesting things start to go bad (errors reported or=20 > not). Removing the > final zend_stream_close() call stops Apache from dying, but=20 > I strongly > suspect that I'm just masking the problem rather than fixing it. > =20 > So, my questions are: what am I doing wrong, and is there a=20 > better way to accomplish the same thing? I considered=20 > evaluating a script instead of trying to simulate=20 > require_once itself, but that seemed incredibly kludgy. >=20 > Any help appreciated. >=20 > Thanks, >=20 > Mo. >=20 > --=20 > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php >=20 >=20