您的位置:首页 > 编程语言 > PHP开发

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

2011-10-30 13:02 585 查看
今天翻鸟哥的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
**)&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<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);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: