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


    假设要获取$_GET['c']; 首先,先介绍下http_globals;

    1.http_globals,定义在php_globals.h中; zval * http_globals[6]; 其中的索引为:

    1 #defineTRACK_VARS_POST 0
    2 #defineTRACK_VARS_GET 1
    3 #defineTRACK_VARS_COOKIE 2
    4 #defineTRACK_VARS_SERVER 3
    5 #defineTRACK_VARS_ENV 4
    6 #defineTRACK_VARS_FILES 5
    7 #defineTRACK_VARS_REQUEST 6

     

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

    2.获取方法:

    1 zval * arr;
    2 zval ** temp;
    3 char * key = "c", r_str;
    4 int len = 2, r_len,duplicate=1;
    5 arr = PG(http_globals)[TRACK_VARS_GET];
    6 zend_hash_find(HASH_OF(arr), key, len, (void **)&temp);
    7 r_str = Z_STRVAL_PP(temp);
    8 r_len = Z_STRLEN_PP(temp);
    9 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)展开后就会成为:

    1. 1 PG(http_globals) =>;
      2 TSRM(core_globals_id, php_core_globals *, http_globals);
      3 =>;
      4 ((php_core_globals *)(*((void ***))tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(core_globals_id)])->http_globals);
      5 =>;
      6 ((php_core_globals *)(*((void ***))tsrm_ls))[(core_globals_id-1)])->http_globals);

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

    1. 1 #defineHASH_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要计算结束符’′的,就是因为我定义len=1,导致crash N次。。郁闷。

    6.再补充点关于return_value:

     

    1 php.h: #definePHP_FUNCTIONZEND_FUNCTION
    2 zend_API.h: #defineZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name))
    3 zend_API.h: #defineZEND_FN(name) zif_##name
    4 zend_API.h: #defineZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS)
    5 zend.h: #defineINTERNAL_FUNCTION_PARAMETERS int ht, zval*return_value, zval**return_value_ptr, zval*this_ptr, int return_value_usedTSRMLS_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.原代码:

     

     1 PHP_FUNCTION(confirm_getCookie_compiled){
     2      char *arg = NULL;
     3      int arg_len, len;
     4      ulongikey;
     5      char * strg, * skey;
     6      zval * arr;
     7      zval**data;
     8      HashTable* h;
     9      if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
    10           WRONG_PARAM_COUNT;
    11      }
    12      arr = PG(http_globals)[TRACK_VARS_GET];
    13      h = HASH_OF(arr);
    14      array_init(return_value);
    15      zend_hash_internal_pointer_reset(h);
    16      int count = zend_hash_num_elements(h);
    17      for(int i=0 ; i&lt;count; i++){
    18           zend_hash_get_current_data(h, (void**)&data);
    19           zend_hash_get_current_key(h, &skey, &ikey, 0);
    20           add_assoc_stringl(return_value, skey, Z_STRVAL_PP(data), Z_STRLEN_PP(data), 1);
    21           zend_hash_move_forward(h);
    22      }
    23      return;
    24      // RETURN_STRINGL(strg, len, 0);
    25      //ZVAL_STRINGL(return_value, strg, len, 0);
    26 }

     

    文章出处: http://www.laruence.com/2008/04/04/17.html

  • 相关阅读:
    WSL 修改默认登录用户为root
    WSL ssh服务自启动
    odoo 获取model的所有字段
    C++类型父类与子类的转换--dynamic_cast(转)
    开源软件/镜像库
    C/C++编译器gcc的windows版本MinGW-w64安装教程(转)
    msys2 环境搭建
    Windows下利用Cygwin搭建C/C++开发环境GCC(转)
    模板类中子类访问父类中的成员需要通过this指针
    C++ 构造函数与this指针
  • 原文地址:https://www.cnblogs.com/liangle/p/3173451.html
Copyright © 2020-2023  润新知