diff options
author | Olly Betts <olly@survex.com> | 2021-03-23 11:49:57 +1300 |
---|---|---|
committer | Olly Betts <olly@survex.com> | 2021-05-03 18:42:28 +1200 |
commit | 586eb24efe52137a81b7b23fcf9ec3934df12476 (patch) | |
tree | 7e3ab2c5fa452c45bf1fa64cc52a875faf5e9e13 | |
parent | 1eabe1b29bde6ac2b7f38d8730b300f867c80ca9 (diff) | |
download | swig-586eb24efe52137a81b7b23fcf9ec3934df12476.tar.gz |
php: Stop using dl()
With modern PHP it only works with the CLI version of PHP, so it's
better to direct users to load the extension via "extension=" in
php.ini.
Suggested by ferdynator in #1529.
-rw-r--r-- | Doc/Manual/Php.html | 21 | ||||
-rw-r--r-- | Examples/Makefile.in | 3 | ||||
-rw-r--r-- | Examples/test-suite/php/Makefile.in | 4 | ||||
-rw-r--r-- | Examples/test-suite/php/tests.php | 2 | ||||
-rw-r--r-- | Lib/php/const.i | 10 | ||||
-rw-r--r-- | Source/Modules/php.cxx | 39 |
6 files changed, 43 insertions, 36 deletions
diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index ad9773cdf..ad6192a28 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -152,9 +152,9 @@ If the module is in PHP's default extension directory, you can omit the path. </p> <p> -For some SAPIs (for example, the CLI SAPI) you can instead use the -<a href="https://www.php.net/manual/en/function.dl.php">dl() function</a> to load -an extension at run time, by adding a line like this to the start of each +If you're using the PHP CLI SAPI it's possible (but not recommended) to use the +<a href="https://www.php.net/manual/en/function.dl.php">dl() function</a> to +load an extension at run time, by adding a line like this to the start of each PHP script which uses your extension: </p> @@ -163,25 +163,22 @@ PHP script which uses your extension: </pre></div> <p> -But note that <tt>dl()</tt> isn't supported when running PHP through a -webserver - you'll need to use <tt>extension</tt> in <tt>php.ini</tt> as +But to do this portably you need to take into account that pathnames and the +filename extension vary by platform, and for security reasons PHP no longer +supports <tt>dl()</tt> when running PHP through a webserver. Overall it's +probably better to instead use <tt>extension</tt> in <tt>php.ini</tt> as described above. </p> <p> -The PHP module which SWIG generates will also attempt to do the <tt>dl()</tt> -call for you if the extension isn't already loaded: +SWIG also generates a PHP module which defines PHP classes for the wrapped +API, which you'll need to load, for example: </p> <div class="code"><pre> include("example.php"); </pre></div> -<p> -This PHP module also defines the PHP classes for the wrapped API, so you'll -almost certainly want to include it anyway. -</p> - <H2><a name="Php_nn2">32.2 Basic PHP interface</a></H2> diff --git a/Examples/Makefile.in b/Examples/Makefile.in index 2e719a603..16973c918 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -1053,6 +1053,7 @@ PHP = @PHP@ PHP_INCLUDE = @PHPINC@ PHP_SO = @PHP_SO@ PHP_SCRIPT = $(SRCDIR)$(RUNME).php +PHP_EXTENSION = example$(PHP_SO) # ------------------------------------------------------------------- # Build a PHP dynamically loadable module (C) @@ -1077,7 +1078,7 @@ php_cpp: $(SRCDIR_SRCS) # ----------------------------------------------------------------- php_run: - $(RUNTOOL) $(PHP) -n -d extension_dir=. -d display_errors=stderr -r 'set_error_handler(function($$n,$$s,$$f,$$l){if($$f!==Null){print$$f;if($$l!==Null)print":$$l";print": ";}print"$$s\n";exit(1);});include($$argv[1]);' $(PHP_SCRIPT) $(RUNPIPE) + $(RUNTOOL) $(PHP) -n -d extension_dir=. -d extension=$(PHP_EXTENSION) -d display_errors=stderr -r 'set_error_handler(function($$n,$$s,$$f,$$l){if($$f!==Null){print$$f;if($$l!==Null)print":$$l";print": ";}print"$$s\n";exit(1);});include($$argv[1]);' $(PHP_SCRIPT) $(RUNPIPE) # ----------------------------------------------------------------- # Version display diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index 003e283cb..946549a5b 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -71,9 +71,9 @@ missingtests: missingcpptests missingctests # found, runs testcase.php, except for multicpptests. run_testcase = \ if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ - $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_SCRIPT=$(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) RUNTOOL='$(RUNTOOL)' php_run; \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_EXTENSION=$(TARGETPREFIX)$*$(PHP_SO) PHP_SCRIPT=$(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) RUNTOOL='$(RUNTOOL)' php_run; \ elif [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*.php -a ! -f $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list ]; then \ - $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_SCRIPT=$(SCRIPTDIR)/$(SCRIPTPREFIX)$*.php RUNTOOL='$(RUNTOOL)' php_run; \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_EXTENSION=$(TARGETPREFIX)$*$(PHP_SO) PHP_SCRIPT=$(SCRIPTDIR)/$(SCRIPTPREFIX)$*.php RUNTOOL='$(RUNTOOL)' php_run; \ fi # Clean: remove the generated .php file diff --git a/Examples/test-suite/php/tests.php b/Examples/test-suite/php/tests.php index cbdb9e209..7491bf10b 100644 --- a/Examples/test-suite/php/tests.php +++ b/Examples/test-suite/php/tests.php @@ -175,7 +175,7 @@ class check { $extra=array_flip(check::get_extra_globals()); foreach ($globals as $glob) { if (self::GETSET) { - if (! isset($extra[$glob])) $missing[]=$glob; + if (! function_exists($glob . "_get") && ! function_exists($glob . "_set")) $missing[]=$glob; else unset($extra[$glob]); } else { if (! isset($GLOBALS[$glob])) $missing[]=$glob; diff --git a/Lib/php/const.i b/Lib/php/const.i index 9c65640db..79c6d2449 100644 --- a/Lib/php/const.i +++ b/Lib/php/const.i @@ -38,7 +38,10 @@ zend_declare_class_constant_string(SWIGTYPE_$class_ce, "$const_name", sizeof("$const_name") - 1, $value); %} -%typemap(classconsttab) SWIGTYPE *, +// This creates a zend_object to wrap the pointer, and we can't do that +// before the Zend runtime has been initialised so we delay it until +// RINIT. The downside is it then happens for every request. +%typemap(classconsttab,rinit=1) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] %{ @@ -79,7 +82,10 @@ const char [] "SWIG_STRING_CONSTANT($symname, $value);"; -%typemap(consttab) SWIGTYPE *, +// This creates a zend_object to wrap the pointer, and we can't do that +// before the Zend runtime has been initialised so we delay it until +// RINIT. The downside is it then happens for every request. +%typemap(consttab,rinit=1) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] { diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index b763867b5..05cb570a6 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -371,19 +371,6 @@ public: Swig_banner(f_phpcode); Printf(f_phpcode, "\n"); - Printf(f_phpcode, "// Try to load our extension if it's not already loaded.\n"); - Printf(f_phpcode, "if (!extension_loaded('%s')) {\n", module); - Printf(f_phpcode, " if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {\n"); - Printf(f_phpcode, " if (!dl('php_%s.dll')) return;\n", module); - Printf(f_phpcode, " } else {\n"); - Printf(f_phpcode, " // PHP_SHLIB_SUFFIX gives 'dylib' on MacOS X but modules are 'so'.\n"); - Printf(f_phpcode, " if (PHP_SHLIB_SUFFIX === 'dylib') {\n"); - Printf(f_phpcode, " if (!dl('%s.so')) return;\n", module); - Printf(f_phpcode, " } else {\n"); - Printf(f_phpcode, " if (!dl('%s.'.PHP_SHLIB_SUFFIX)) return;\n", module); - Printf(f_phpcode, " }\n"); - Printf(f_phpcode, " }\n"); - Printf(f_phpcode, "}\n\n"); /* sub-sections of the php file */ pragma_code = NewStringEmpty(); @@ -1493,7 +1480,11 @@ public: { tm = Swig_typemap_lookup("consttab", n, name, 0); Replaceall(tm, "$value", value); - Printf(s_cinit, "%s\n", tm); + if (Getattr(n, "tmap:consttab:rinit")) { + Printf(r_init, "%s\n", tm); + } else { + Printf(s_cinit, "%s\n", tm); + } } { @@ -1502,14 +1493,22 @@ public: Replaceall(tm, "$class", fake_class_name()); Replaceall(tm, "$const_name", iname); Replaceall(tm, "$value", value); - Printf(s_cinit, "%s\n", tm); + if (Getattr(n, "tmap:classconsttab:rinit")) { + Printf(r_init, "%s\n", tm); + } else { + Printf(s_cinit, "%s\n", tm); + } } } else { tm = Swig_typemap_lookup("classconsttab", n, name, 0); Replaceall(tm, "$class", class_name); Replaceall(tm, "$const_name", wrapping_member_constant); Replaceall(tm, "$value", value); - Printf(s_cinit, "%s\n", tm); + if (Getattr(n, "tmap:classconsttab:rinit")) { + Printf(r_init, "%s\n", tm); + } else { + Printf(s_cinit, "%s\n", tm); + } } wrapperType = standard; @@ -1653,6 +1652,9 @@ public: String *interfaces = Swig_typemap_lookup("phpinterfaces", node, "", 0); Replaceall(interfaces, " ", ""); if (interfaces) { + // It seems we need to wait until RINIT time to look up classes. + // The downside is that this then happens for every request. + Printf(r_init, "{\n"); List *interface_list = Split(interfaces, ',', -1); int num_interfaces = Len(interface_list); String *append_interface = NewStringEmpty(); @@ -1660,13 +1662,14 @@ public: String *interface = Getitem(interface_list, Iterator-1); String *interface_ce = NewStringEmpty(); Printf(interface_ce, "php_%s_interface_ce_%d" , class_name , Iterator); - Printf(s_oinit, " zend_class_entry *%s = zend_lookup_class(zend_string_init(\"%s\", sizeof(\"%s\") - 1, 0));\n", interface_ce, interface, interface); + Printf(r_init, " zend_class_entry *%s = zend_lookup_class(zend_string_init(\"%s\", sizeof(\"%s\") - 1, 0));\n", interface_ce, interface, interface); Append(append_interface, interface_ce); Append(append_interface, " "); } Chop(append_interface); Replaceall(append_interface, " ", ","); - Printf(s_oinit, " zend_class_implements(SWIGTYPE_%s_ce, %d, %s);\n", class_name, num_interfaces, append_interface); + Printf(r_init, " zend_class_implements(SWIGTYPE_%s_ce, %d, %s);\n", class_name, num_interfaces, append_interface); + Printf(r_init, "}\n"); } } |