Overriding INI_SYSTEM and INI_PERDIR Options

In the last chapter, you used zend_alter_ini_setting() to modify some PHP INI options. Because sapi/embed thrusts your script directly into runtime mode, most of the more important INI options are unmodifiable after control has been returned to your application. To change these values, it's necessary to be able to execute code after the main engine startup so that space for these variables is available, yet before the request startup.

One approach might be to copy and paste the contents of php_embed_init() into your application, make the necessary changes in your local copy, and then use that method instead. Of course, this approach presents some problems.

First and foremost, you've effectively forked a portion of code someone else was already busily putting the work in on maintaining. Now, instead of just maintaining your application, you've got to keep up with a random bit of forked code someone else wrote as well. Fortunately, there are a few much simpler methods.

Overriding the Default php.ini File

Because embed is a sapi just like any other PHP sapi implementation, it's hooked into the engine by way of a sapi_module_struct. The embed SAPI declares and populates an instance of this structure that your application has access to even before calling php_embed_init().

In this structure is a simple char* field named php_ini_path_override. To request that embedand by extension PHP and Zenduse your alternate file, just populate this field with a NULL-terminated string prior to calling php_embed_init() as in the following modified startup_php() function in embed4.c.

static void startup_php(void) { /* Create "dummy" argc/argv to hide the arguments * meant for our actual application */ int argc = 1; char *argv[2] = { "embed4", NULL }; php_embed_module.php_ini_path_override = "/etc/php_embed4.ini"; php_embed_init(argc, argv PTSRMLS_CC); }

This allows each application using the embed library to remain customizable, without imposing their configurations on each other. Conversely, if you'd rather prevent your application from using php.ini at all, simply set the php_ini_ignore field in php_embed_module and all settings will default to their built-in values unless specifically modified by your application.

Overriding Embed Startup

The sapi_module_struct also contains several callback functions, four of which are of interest for periodically taking back control during PHP startup and shutdown.

/* From main/SAPI.h */ typedef struct _sapi_module_struct { ... int (*startup)(struct _sapi_module_struct *sapi_module); int (*shutdown)(struct _sapi_module_struct *sapi_module); int (*activate)(TSRMLS_D); int (*deactivate)(TSRMLS_D); ... } sapi_module_struct;

Do these method names ring a bell? They shouldthey correspond to an extension's MINIT, MSHUTDOWN, RINIT, and RSHUTDOWN methods and trigger during the same cycles as they do for extensions. To take advantage of these hooks, modify startup_php() in embed4 to the following version along with the additional code provided:

static int (*original_embed_startup)(struct _sapi_module_struct *sapi_module); static int embed4_startup_callback(struct _sapi_module_struct *sapi_module) { /* Call original startup callback first, * otherwise the environment won't be ready */ if (original_embed_startup(sapi_module) == FAILURE) { /* Application failure handling may occur here */ return FAILURE; } /* Calling the original embed_startup actually places us * in the ACTIVATE stage rather than the STARTUP stage, but * we can still alter most INI_SYSTEM and INI_PERDIR entries anyhow */ zend_alter_ini_entry("max_execution_time", sizeof("max_execution_time"), "15", sizeof("15") - 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); zend_alter_ini_entry("safe_mode", sizeof("safe_mode"), "1", sizeof("1") - 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); return SUCCESS; } static void startup_php(void) { /* Create "dummy" argc/argv to hide the arguments * meant for our actual application */ int argc = 1; char *argv[2] = { "embed4", NULL }; /* Override the standard startup method with our own * but save the original so that it can still be invoked. */ original_embed_startup = php_embed_module.startup; php_embed_module.startup = embed4_startup_callback; php_embed_init(argc, argv PTSRMLS_CC); }

Using options like safe_mode, open_basedir, and others will help limit what individuals scripting behavior into your application can do and should help ensure a safer, more reliable application.

Категории