php實現(xiàn)文件下載代碼繼續(xù)執(zhí)行php原始的執(zhí)行函數(shù)測試代碼打造php自己的鏈路追蹤和性能監(jiān)控 php評論功能實現(xiàn)代碼
2023-01-20
最近看php源碼網(wǎng)站模板,為了驗證效果網(wǎng)站制作,寫了一個php擴(kuò)展php實現(xiàn)文件下載代碼,主要功能是創(chuàng)建php自己的鏈接跟蹤和性能監(jiān)控
首先從下載源代碼
編譯安裝使用
現(xiàn)在只是一個基本功能,以后會逐步完善
核心功能是重寫PHP的執(zhí)行函數(shù),也就是經(jīng)常寫的
PHP_MINIT_FUNCTION(pid)
{
REGISTER_INI_ENTRIES();
ori_execute_ex = zend_execute_ex;
zend_execute_ex = pid_execute_ex;
ori_execute_internal = zend_execute_internal;
zend_execute_internal = pid_execute_internal;
return SUCCESS;
}
執(zhí)行過程中發(fā)現(xiàn)是要攔截的函數(shù)時,會獲取函數(shù)的參數(shù)返回值并記錄日志php實現(xiàn)文件下載代碼,繼續(xù)執(zhí)行PHP原來的執(zhí)行函數(shù)
ZEND_API void pid_execute_core(int internal, zend_execute_data *execute_data, zval *return_value)
{
char *logs_dir = {0};
char *re_func = {0};
char *file_log = "trace.log";
//從php.ini文件讀取攔截函數(shù)和日志目錄
logs_dir = INI_STR("pid.log_path");
re_func = INI_STR("pid.function");
char *name = (char *) malloc(strlen(logs_dir) + strlen(file_log));
sprintf(name, "%s%s", logs_dir, file_log);
FILE *fp;
if((fp = fopen(name, "a+")) == NULL){
printf("file cannot open \n");
}
zend_function *zf = obtain_zend_function(execute_data);
int flag = 0;
char str_1[512] = {0};
char *token;
const char s[2] = ",";
if (zf->common.function_name != NULL){
sprintf(str_1, ZSTR_VAL(zf->common.function_name));
/* 獲取第一個子字符串 */
token = strtok(re_func, s);
/* 繼續(xù)獲取其他的子字符串 */
while( token != NULL ) {
printf( "%s\n", token );
if(strcmp(str_1, token) == 0){
flag = 1;
fputs("\n執(zhí)行函數(shù)的名字:", fp);
fputs( str_1, fp);
break;
}else{
flag = 0;
}
token = strtok(NULL, s);
}
}
int arg_count = 0;
arg_count = ZEND_CALL_NUM_ARGS(execute_data);
smart_str res = {0};
smart_str buf = {0};
if (arg_count) {
zval *p = ZEND_CALL_ARG(execute_data, 1);
if (execute_data->func->type == ZEND_USER_FUNCTION) {
uint32_t first_extra_arg = execute_data->func->op_array.num_args;
if (first_extra_arg && arg_count > first_extra_arg) {
p = ZEND_CALL_VAR_NUM(execute_data, execute_data->func->op_array.last_var + execute_data->func->op_array.T);
}
}
int i;
for (i = 0; i < arg_count; i++) {
php_var_export_ex(p, 2, &buf);
p++;
}
if(flag == 1){
fputs(";執(zhí)行函數(shù)的參數(shù):", fp);
fputs( ZSTR_VAL(buf.s), fp);
//printf("執(zhí)行函數(shù)的參數(shù) %s ......\n", ZSTR_VAL(buf.s));
}
}
if (internal) {
if (ori_execute_internal) {
ori_execute_internal(execute_data, return_value);
} else {
execute_internal(execute_data, return_value);
}
} else {
ori_execute_ex(execute_data);
}
if (return_value) { /* internal */
php_var_export_ex(return_value, 2, &res);
if(flag == 1){
fputs(";執(zhí)行函數(shù)的返回結(jié)果:", fp);
fputs( ZSTR_VAL(res.s), fp);
//printf("內(nèi)部函數(shù)返回的結(jié)果 %s === \n", ZSTR_VAL(res.s));
}
} else if (execute_data->return_value) { /* user function */
php_var_export_ex(execute_data->return_value, 2, &res);
if(flag == 1){
fputs(";執(zhí)行函數(shù)的返回結(jié)果:", fp);
fputs( ZSTR_VAL(res.s), fp);
//printf("自定義函數(shù)返回結(jié)果 %s ===\n", ZSTR_VAL(res.s));
}
}
fclose(fp);
}
測試代碼
執(zhí)行函數(shù)的名字:aa;執(zhí)行函數(shù)的參數(shù):'nihao'111
array (
0 => 1,
1 => 'yy',
2 => 66,
);執(zhí)行函數(shù)的返回結(jié)果:8888
執(zhí)行函數(shù)的名字:date;執(zhí)行函數(shù)的參數(shù):'Y-m-d';執(zhí)行函數(shù)的返回結(jié)果:'2021-07-17'
執(zhí)行函數(shù)的名字:aa;執(zhí)行函數(shù)的參數(shù):'nihao'111
array (
0 => 1,
1 => 'yy',
2 => 66,
);執(zhí)行函數(shù)的返回結(jié)果:8888
執(zhí)行函數(shù)的名字:date;執(zhí)行函數(shù)的參數(shù):'Y-m-d';執(zhí)行函數(shù)的返回結(jié)果:'2021-07-17'