msgbartop
PHP语言, PHP扩展, Zend引擎相关的研究,技术,新闻分享 – 左手代码 右手诗
msgbarbottom

04 Apr 08 在PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究

最近在做一个PHP的安全模块,其中要在Module的函数中获取用户的Cookie,从而生成签名;今天找遍Baidu/Google,一点相关资料都 没有,不得已,只好给yahoo PHP dev mail list发了求救信。后来,偶然在Google上看到了一个变量 http_globals ,眼前一亮,虽然没有详细资料,但经过一顿试,N次Segmentation fault以后,终于成功!
接下来,我结合实例和大家分享:
假设要获取$_GET['c'];
首先,先介绍下http_globals;
1.http_globals,定义在php_globals.h中;
zval * http_globals[6];
其中的索引为:

#define TRACK_VARS_POST           0
#define TRACK_VARS_GET            1
#define TRACK_VARS_COOKIE         2
#define TRACK_VARS_SERVER         3
#define TRACK_VARS_ENV            4
#define TRACK_VARS_FILES          5
#define TRACK_VARS_REQUEST        6

就是不知道为什么,http_globals定义为6个元素,但是索引却定义了7个,猜测可能是因为REQUREST本来也就是GET和POST的 merge,并且存取都是通过宏来进行,所以可能最后宏中会处理TRACK_VARS_REQUEST为GET和POST的merge。
2.获取方法:

zval * arr;
zval ** temp;
char * key = "c", r_str;
int len = 2, r_len,duplicate=1;
arr = PG(http_globals)[TRACK_VARS_GET];
zend_hash_find(HASH_OF(arr), key, len, (void **)&temp);
r_str = Z_STRVAL_PP(temp);
r_len = Z_STRLEN_PP(temp);
ZVAL_STRINGL(return_value, r_str, r_len, duplicate)

3.分析
其中PG是一个宏,定义在php_globals.h中:
# define PG(v) TSRMG(core_globals_id, php_core_globals *, v)
TSRMG也是一个宏,定义在TSRM.h中:
#define TSRMG(id, type, element) (((type) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(id)])->element)
TSRM_UNSHUFFLE_RSRC_ID也是一个宏,也定义在TSRM.h中:
#define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1)

那么PG(http_globals)展开后就会成为:

PG(http_globals) =>;
TSRM(core_globals_id, php_core_globals *, http_globals);
=>;
((php_core_globals *)(*((void ***))tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(core_globals_id)])->http_globals);
=>;
((php_core_globals *)(*((void ***))tsrm_ls))[(core_globals_id-1)])->http_globals);

HASH_OF也是个宏,定义在zend_API.h中:

         #define HASH_OF(p) (Z_TYPE_P(p)==IS_ARRAY ? Z_ARRVAL_P(p) : ((Z_TYPE_P(p)==IS_OBJECT ? Z_OBJ_HT_P(p)->get_properties((p) TSRMLS_CC) : NULL)))

4.获取
根据测试的结果,可以认定PG(http_globals)[TRACK_VARS_GET]是一个hash table;
5.问题
有个问题就是,Zend中好像字符的len要计算结束符’\0′的,就是因为我定义len=1,导致crash N次。。郁闷。

6.再补充点关于return_value:

1. php.h:        #define PHP_FUNCTION                       ZEND_FUNCTION
2. zend_API.h: #define ZEND_FUNCTION(name)        ZEND_NAMED_FUNCTION(ZEND_FN(name))
3. zend_API.h: #define ZEND_FN(name)      zif_##name
4. zend_API.h: #define ZEND_NAMED_FUNCTION(name)       void name(INTERNAL_FUNCTION_PARAMETERS)
5. zend.h: #define INTERNAL_FUNCTION_PARAMETERS   int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC</blockquote>

这样一来,我们的函数PHP_FUNCTION(getGetParam)就会变成:
void zif_getGetParam( int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC);

可见,return_value是默认就定义的,是返回值的载体。

呵呵,就写这么多,有时间再补充。

7.原代码:

PHP_FUNCTION(confirm_getCookie_compiled){
	char *arg = NULL;
	int arg_len, len;
	ulong ikey;
	char * strg, * skey;
	zval * arr;
	zval **data;
	HashTable* h;
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
		WRONG_PARAM_COUNT;
	}
	arr = PG(http_globals)[TRACK_VARS_GET];
	h  = HASH_OF(arr);
	array_init(return_value);
	zend_hash_internal_pointer_reset(h);
	int count = zend_hash_num_elements(h);
	for(int i=0 ; i&lt;count; i++){
		zend_hash_get_current_data(h, (void**)&data);
		zend_hash_get_current_key(h, &skey, &ikey, 0);
		add_assoc_stringl(return_value, skey, Z_STRVAL_PP(data), Z_STRLEN_PP(data), 1);
		zend_hash_move_forward(h);
	}
	return;
	//      RETURN_STRINGL(strg, len, 0);
	//ZVAL_STRINGL(return_value, strg, len, 0);
}


分享到:



Related Posts:

Tags: , , , ,

17 Responses to “在PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究”

  1. Georgerip |

    Georgerip

  2. HarryJes |

    HarryJesPM

  3. Randy.Lin |

    zend_hash_find(HASH_OF(arr), key, len, (void **)&temp);

    最后的&被转义了吧

  4. grosir baju murah tanah abang |

    There are plenty of different fashion wholesalers to choose from who caan supply yyou
    with the latest women’s summer fashion but choosing the right one for your company isn’t always easy.
    The pieces easily fit together but when finished they
    look like a traditioinal hardwood floor. The key to sich a business would be
    to procure the clothing at very cheap rices so as to offer them to customers for an affordable price.

  5. 风雪之隅-鸟哥文章汇总 | 互联网菜鸟 |

    [...] 21 Apr 08 关于PHP你可能不知道的-PHP的事件驱动化设计 17 Apr 08 页面乱码问题根源浅析 14 Apr 08 PHP实现异步调用方法研究 04 Apr 08 在PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究 [...]

  6. PHP源码分析文章整理 | 牛腩五花肉的博客-linux系统编程 |

    [...] 在PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究 [...]

  7. john |

    那个c函数里面的那个for循环没看懂,请博主解释下,谢谢

  8. PHP5.4的新特性 — 见贤思齐 |

    [...] 在PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究 [...]

  9. 雪候鸟 |

    @软件工程师李飛 恩, 这个文章是08年的,那个时候还没弄清楚这个问题, 呵呵, anyway, thanks

  10. 软件工程师李飛 |

    就是不知道为什么,http_globals定义为6个元素,但是索引却定义了7个,猜测可能是因为REQUREST本来也就是GET和POST的 merge,并且存取都是通过宏来进行,所以可能最后宏中会处理TRACK_VARS_REQUEST为GET和POST的merge。

    REQUEST直接加到symbol_table了

  11. 在PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究 | 万维网黑客联盟 |

    [...] 本文地址: http://www.laruence.com/2008/04/04/17.html [...]

  12. 雪候鸟 |

    @chance vim grep

  13. chance |

    请问博主用什么工具或者方法追踪某一个宏或者函数它们所在的具体文件?

  14. comidy |

    学习!

  15. 深入理解PHP原理之文件上传 | 风雪之隅 |

    [...] 注1:参看 在PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究 [main/rfc1867.h]       #define MULTIPART_CONTENT_TYPE [...]

  16. PHP的GET/POST等大变量生成过程 | 风雪之隅 |

    [...] $_POST, $_COOKIE merge起来(G(http_globals)[TRACK_VARS_COOKIE]这部分,可以参看我较早前的 ) : static zend_bool php_auto_globals_create_request(char *name, uint name_len [...]

  17. Anonymous |

    nice

Leave a Reply

*