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

31 篇文章 0 订阅

今天翻鸟哥的blog看这个转了一下,这是写扩展取变量值最基本的入门,但还有一方法,大家都不常用,通过hashtable去find这全局变量。有空再把方法贴上来


· 作者:laruence(http://www.laruence.com/)

· 本文地址: http://www.laruence.com/2008/04/04/17.html
· 转载请注明出处                                
       最近在做一个PHP的安全模块,其中要在Module的函数中获取用户的Cookie,从而生成签名;今天找遍Baidu/Google,一点相关资料都没有,不得已,只好给yahoo PHP dev mail list发了求救信。后来,偶然在Google上看到了一个变量http_globals ,眼前一亮,虽然没有详细资料,但经过一顿试,N次Segmentation fault以后,终于成功!
接下来,我结合实例和大家分享: 笑话365
假设要获取$_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 ** ) & amp ; 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 )] )-& gt ; http_globals );
=>;
(( php_core_globals * )( * ((void *** )) tsrm_ls ))[( core_globals_id - 1 )] )-& gt ; 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 ) -& gt ; 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);

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值