INI設定了 .
INI
某些设置如果可以在任何地方被修改就没有多大意义了, 比如safe_mode, 如果可以在任何地方去修改, 那么恶意脚本的作者就可以很简单的去禁用safe_mode, 接着去读或修改本不允许操作的文件.
类似的, 某些非安全相关的指令比如register_globals或magic_quotes_gpc, 在脚本中不能被修改, 因为, 在脚本执行时, 它所影响的事情已经发生过了.
这些指令的访问控制是通过PHP_INI_ENTRY()的第三个参数完成的. 在你前面例子中, 使用了PHP_INI_ALL, 它的定义是一个位域操作: PHP_INI_SYSTEM | PHP_INI_PERDIR | PHP_INI_USER.
对于register_globals和magic_quotes_gpc这样的指令, 定义的访问级别为PHP_INI_SYSTEM | PHP_INI_PERDIR. 排除了PHP_INI_USER将导致以这个名字调用ini_set()时最终会失败.
现在, 你可能已经猜到, safe_mode和open_basedir这样的指令应该仅被定义为PHP_INI_SYSTEM. 这样的设置就确保了只有系统管理员可以修改这些值, 因为只有它们可以访问修改php.ini或httpd.conf文件中的配置.
修改事件
当INI指令被修改时, 无论是通过ini_set()函数还是某个perdir指令的处理, 引擎都会为其测试OnModify回调. 修改处理器可以使用ZEND_INI_MH()宏定义, 并通过在OnModify参数上传递函数名附加到INI指令上:
ZEND_INI_MH(php_sample4_modify_greeting)
{
if (new_value_length == 0) {
return FAILURE;
}
return SUCCESS;
}
PHP_INI_BEGIN()
PHP_INI_ENTRY("sample4.greeting", "Hello World",
PHP_INI_ALL, php_sample4_modify_greeting)
PHP_INI_END() 登入後複製
通过在new_value_length为0时返回FAILURE, 这个修改处理器禁止将greeting设置为空字符串. ZEND_INI_MH()宏产生的整个原型如下:
int php_sample4_modify_greeting(zend_ini_entry *entry,
char *new_value, uint new_value_length,
void *mh_arg1, void *mh_arg2, void *mh_arg3,
int stage TSRMLS_DC); 登入後複製
各个参数的含义见下表:
参数名
含义
entry
指向引擎真實儲存的 INI 指令項 . 這個結構體提供了當前值 以及其他一些下面程式碼 (zend_ini_entry 結構體結構 ) 列出的資訊 . 如果處理器回傳 SUCCESS,
這個值將被設定到entry->value,同時如果 entry->orig_value
中 , 並設定中 , 並設定 entry->modified 標記 . 這個字串的長度透過 mh_arg1, 2 , 3
這 3 個指針對應 INI 指令定義時給出的資料指標 (zend_entry 指令定義時給出的資料指標 (zend_entry 實際上 , 這幾個值是引擎內部處理使用的 , 你不需要關心它們 . STAGE_ 系列的
5 個值之一:
STARTUP, SHUTDOWN, ACTIVATE, DEACTIVATE, RUNTIME. 這些常數對應於
MINIT, MSHUTDOWN, RINIT, RSHUTDOWN,以及活性腳本執行🜎🜎🎟
核心结构体: zend_ini_entry
struct _zend_ini_entry {
int module_number;
int modifiable;
char *name;
uint name_length;
ZEND_INI_MH((*on_modify));
void *mh_arg1;
void *mh_arg2;
void *mh_arg3;
char *value;
uint value_length;
char *orig_value;
uint orig_value_length;
int modified;
void ZEND_INI_DISP(*displayer);
}; 登入後複製
展示INI设置
在上一章, 你看到了MINFO函数以及相关的指令用于展示扩展的信息. 由于扩展暴露INI指令是很常见的, 因此引擎提供了一个公共的宏可以放置到PHP_MINFO_FUNCTION()中用于展示INI指令信息.
PHP_MINFO_FUNCTION(sample4)
{
DISPLAY_INI_ENTRIES();
} 登入後複製
这个宏将迭代PHP_INI_BEGIN()和PHP_INI_END()宏之间定义的INI指令集和, 在一个3列的表格中展示它们的INI指令名, 原始值(全局的), 以及当前值(经过PERDIR指令或ini_set()调用修改后)
默认情况下, 所有的指令都直接以其字符串形式输出. 对于某些指令, 比如布尔值以及用于语法高亮的颜色值, 则在展示处理时应用了其他格式. 这些格式是通过每个INI设置的显示处理器处理的, 它和你看到的OnModify一样是一个动态的回调函数指针.
显示处理器可以使用PHP_INI_ENTRY()宏的扩展版指定, 它接受一个额外的参数. 如果设置为NULL, 则使用展示字符串值的处理器作为默认处理器:
PHP_INI_ENTRY_EX("sample4.greeting", "Hello World", PHP_INI_ALL,
php_sample4_modify_greeting, php_sample4_display_greeting) 登入後複製
显然, 需要在INI设置定义之前声明这个函数. 和OnModify回调函数一样, 这可以通过一个包装宏以及少量编码完成:
#include "SAPI.h" /* needed for sapi_module */
PHP_INI_DISP(php_sample4_display_greeting)
{
const char *value = ini_entry->value;
/* 选择合适的当前值或原始值 */
if (type == ZEND_INI_DISPLAY_ORIG &&
ini_entry->modified) {
value = ini_entry->orig_value;
}
/* 使得打招呼的字符串粗体显示(当以HTML方式输出时) */
if (sapi_module.phpinfo_as_text) {
php_printf("%s", value);
} else {
php_printf("<b>%s</b>", value);
}
} 登入後複製
绑定到扩展的全局空间
所有的INI指令都在Zend引擎内有一块存储空间, 可以用以跟踪脚本内的变更并进行请求外部的全局设置维护. 在这块存储空间中, 所有的INI指令都以字符串值存储. 你已经知道了, 这些值可以使用INI_INT(), INI_FLT(), INI_BOOL()等宏函数, 很简单的翻译成其他的标量类型.
这个查找和转换过程由于两个原因非常低效: 首先, 每次一个INI的值在获取时, 它必须通过名字在一个HashTable中进行定位. 这种查找方式对于仅在运行时编译的用户空间脚本而言是没有问题的, 但是对于已编译的机器代码源, 运行时做这个工作就毫无意义.
每次请求标量值的时候都需要将底层的字符串值转换到标量值是非常低效的. 因此我们使用你已经学习过的线程安全全局空间作为存储媒介, 每次INI指令值变更时更新它即可. 这样, 所有访问INI指令的代码都只需要查找你的线程安全全局空间结构体中的某个指针即可, 这样就获得了编译期优化的优点.
在你的php_sample4.h文件MODULE_GLOBALS结构体中增加const char *greeting; 接着更新sample4.c中的下面两个方法:
ZEND_INI_MH(php_sample4_modify_greeting)
{
/* Disallow empty greetings */
if (new_value_length == 0) {
return FAILURE;
}
SAMPLE4_G(greeting) = new_value;
return SUCCESS;
}
PHP_FUNCTION(sample4_hello_world)
{
php_printf("%s\n", SAMPLE4_G(greeting));
} 登入後複製
由于这是对INI访问的一种非常常见的优化方式, 因此引擎暴露了一组专门处理INI指令到全局变量的绑定宏:
STD_PHP_INI_ENTRY_EX("sample4.greeting", "Hello World",
PHP_INI_ALL, OnUpdateStringUnempty, greeting,
zend_sample4_globals, sample4_globals,
php_sample4_display_greeting) 登入後複製
这个宏执行和上面你自己的php_sample4_modify_greeting相同的工作, 但它不需要OnModify回调. 取而代之的是, 它使用了一个泛化的修改回调OnUpdateStringUnempty, 以及信息应该存储的空间. 如果要允许空的greeting指令值, 你可以直接指定OnUpdateString替代OnUpdateStringUnempty.
类似的, INI指令也可以绑定long, double, zend_bool的标量值. 在你的php_sample4.h中MODULE_GLOBALS结构体上增加几个字段:
long mylong;
double mydouble;
zend_bool mybool; 登入後複製
现在在你的PHP_INI_BEGIN()/PHP_INI_END()代码块中使用STD_PHP_INI_ENTRY()宏创建新的INI指令, 它和对应的_EX版本的宏的区别只是显示处理器以及绑定到的值不同.
STD_PHP_INI_ENTRY("sample4.longval", "123",
PHP_INI_ALL, OnUpdateLong, mylong,
zend_sample4_globals, sample4_globals)
STD_PHP_INI_ENTRY("sample4.doubleval", "123.456",
PHP_INI_ALL, OnUpdateDouble, mydouble,
zend_sample4_globals, sample4_globals)
STD_PHP_INI_ENTRY("sample4.boolval", "1",
PHP_INI_ALL, OnUpdateBool, mybool,
zend_sample4_globals, sample4_globals) 登入後複製
这里要注意, 如果调用了DISPLAY_INI_ENTRIES(), 布尔类型的INI指令"sample4.boolval"将和其他设置一样, 被显示为它的字符串值; 然而, 首选的布尔值指令应该被显示为"on"或"off". 要使用这些更加表意的显示, 你可以使用STD_PHP_INI_ENTRY_EX()宏并创建显示处理器, 或者使用另外一个宏:
STD_PHP_INI_BOOLEAN("sample4.boolval", "1",
PHP_INI_ALL, OnUpdateBool, mybool,
zend_sample4_globals *, sample4_globals) 登入後複製
这个特定类型的宏是布尔类型特有的, 它提供的是将布尔值转换为"on"/"off"值的显示处理器.
小结
在本章, 你了解了php语言中最古老的特性之一的实现, 它也是阻碍php可移植的罪魁. 对于每个新的INI设置, 都会使得编写可移植代码变得更加复杂. 使用这些特性要非常慎重, 因为扩展以后时钟都要使用它了. 并且, 在使用时要注意不同系统间的行为一致性, 以免在维护时出现不可预期的状况.
接下来的三张, 我们将深入到流API, 开始使用流的实现层和包装操作, 上下文, 过滤器等.
以上就是[翻译][php扩展开发和嵌入式]第13章-php的INI设置 的内容,更多相关内容请关注PHP中文网(www.php.cn)!
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
您如何在PHP中解析和處理HTML/XML?
Feb 07, 2025 am 11:57 AM
本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲
在PHP API中說明JSON Web令牌(JWT)及其用例。
Apr 05, 2025 am 12:04 AM
JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、
php程序在字符串中計數元音
Feb 07, 2025 pm 12:12 PM
字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。
什麼是元音?
元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫:
a, e, i, o, u
示例 1
輸入:字符串 = "Tutorialspoint"
輸出:6
解釋
字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元
解釋PHP中的晚期靜態綁定(靜態::)。
Apr 03, 2025 am 12:04 AM
靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。
See all articles