|
New Includes Function -- spl_autoload()
author: ryat#www.wolvez.org team:http://www.80vul.com date:2009-04-13
一、描述
看看手册对这个函数的描述:
spl_autoload (PHP 5 >= 5.1.2)
spl_autoload — Default implementation for __autoload()
void spl_autoload ( string $class_name [, string $file_extensions= spl_autoload_extensions() ] )
This function is intended to be used as a default implementation for __autoload(). If nothing else is specified and autoload_register() is called without any parameters then this functions will be used for any later call to __autoload().
从描述中可以知道这个函数用来替代类中__autoload方法
二、代码分析
spl_autoload()的php源码:
// php_spl.c PHP_FUNCTION(spl_autoload) { ... char *class_name, *lc_name, *file_exts = SPL_G(autoload_extensions); int class_name_len, file_exts_len = SPL_G(autoload_extensions_len), found = 0; char *copy, *pos1, *pos2; ... if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &class_name, &class_name_len, &file_exts, &file_exts_len) == FAILURE) { RETURN_FALSE; } if (file_exts == NULL) { /* autoload_extensions is not intialzed, set to defaults */ copy = pos1 = estrndup(SPL_DEFAULT_FILE_EXTENSIONS, sizeof(SPL_DEFAULT_FILE_EXTENSIONS)-1); // 如果没有指定file_extensions参数,设定file_extensions为.inc或.php } else { copy = pos1 = estrndup(file_exts, file_exts_len); } lc_name = zend_str_tolower_dup(class_name, class_name_len); while(pos1 && *pos1 && !EG(exception)) { ... if (spl_autoload(class_name, lc_name, class_name_len, pos1 TSRMLS_CC)) { ... static int spl_autoload(const char *class_name, const char * lc_name, int class_name_len, const char * file_extension TSRMLS_DC) /* {{{ */ { ... class_file_len = spprintf(&class_file, 0, "%s%s", lc_name, file_extension); // 合并 class_name和file_extensions
ret = php_stream_open_for_zend_ex(class_file, &file_handle, ENFORCE_SAFE_MODE|USE_PATH|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC); // 打开指定文件 ... if (ret == SUCCESS) { if (!file_handle.opened_path) { file_handle.opened_path = estrndup(class_file, class_file_len); } if (zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL)==SUCCESS) { new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC); // 将文件编译成opcode ... } else { new_op_array = NULL; ... } if (new_op_array) { ... zend_execute(new_op_array TSRMLS_CC); // 执行opcode :) 可以看到,这个函数完全可以替代include/require函数的作用[当然如果你熟悉__autoload方法的使用方法的话,你可能很快就会意识到这点了:)]
三、测试代码
PoC:
// test.php <?php
spl_autoload('info', '.txt');
// info.txt <?php
phpinfo();
|