网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > PHP技巧
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
本月文章推荐
.正则表达式中的特殊字符一览.
.几种显示数据的方法的比较.
.使用php4加速网络传输 .
.有关在Windows下配置PHP+Apache+.
.不需要mod_rewrite直接使用php实.
.攻克CakePHP系列一 连接MySQL数据.
.使用php+xslt在windows平台上.
.利用ObjMap将多维数组转换成Obje.
.用PHP自动把纯文本转换成Web页面.
.PHPUnit袖珍指南之PHPUnit的目的.
.PHP一些常用的正则表达式.
.用函数读出数据表内容放入二维数.
.[GD]生成bmp格式的图片(imagebmp).
.PHP采集程序中常用的函数.
.php生成EXCEL的东东.
.关于unserialize的问题.
.利用PHP的OOP特性实现数据保护.
.PHP伪造referer实例代码.
.PHP中路径问题的解决方案.
.addslashes和mysql_real_escape_.

PHP的GET/POST等大变量生成过程

发表日期:2008-12-16


· 作者:laruence(http://www.laruence.com/)
· 本文地址:http://www.laruence.com/2008/11/07/581.html
· 转载请注明出处                                                  
主要探讨了PHP的大变量的生成过程。另外如果你注意到, 当在表单中提交的input的name中如果有点号的时候, 在PHP中会自动把点号处理成下划线。并且你很想知道这是为什么,在什么时候发生的? 呵呵,本文也就这个问题做了回答。
首先明确一个问题,PHP的变量名中是不能包含点号的。 但是为了处理表单中的点号命名,PHP就会自动把点号(.)转换成下划线(_)。
      要知道PHP是怎么处理的,首先我们要了解,$_GET, $_POST, $_COOKIE等变量的构造过程。
在每个请求到来以后,apache处理到response阶段的时候, 会将控制权交给PHP模块, PHP模块会在处理请求之前首先间接调用php_request_startup (具体调用序列是send_php -> apache_php_module_main ->php_request_startup, 关于这部门可以参看我前面的文章(PHP Life Cycle) , 在php_request_startup中:
int
php_request_startup(TSRMLS_D)
{
int
retval=SUCCESS;

#if PHP_SIGCHILD
signal(SIGCHLD,sigchld_handler);
#endif
if
(php_start_sapi()==FAILURE)
{
return
FAILURE;
   }
php_output_activate(TSRMLS_C);
   sapi_activate(TSRMLS_C);
   php_hash_environment(TSRMLS_C);

   zend_try
{
PG(during_request_startup)=1;
        php_output_activate(TSRMLS_C);
        if
(PG(expose_php))
{
sapi_add_header(SAPI_PHP_VERSION_HEADER,sizeof(SAPI_PHP_VERSION_HEADER)-1,1);
        }
}
zend_catch
{
retval=FAILURE;
   }
zend_end_try();

   return
retval;
}


   注意其中的php_hash_environment(TSRMLS_C)函数调用 , 这个函数就是在请求处理前, 初始化请求相关的变量的函数。
  这个函数定义在: main/php_variables.c中 , 有兴趣的可以看看:
int
php_hash_environment(TSRMLS_D)
{
char*p;
        unsigned
char
_gpc_flags[5]={0,0,0,0,0};
        zend_bool
jit_initialization=(PG(auto_globals_jit)&& !PG(register_globals)&& !PG(register_long_arrays));
        struct
auto_global_record
{
char*name;
               uint
name_len;
               char*long_name;
               uint
long_name_len;
               zend_bool
jit_initialization;
        }
auto_global_records[]={
{
"_POST",sizeof("_POST"),"HTTP_POST_VARS",sizeof("HTTP_POST_VARS"),0
},
               {
"_GET",sizeof("_GET"),"HTTP_GET_VARS",sizeof("HTTP_GET_VARS"),0
},
               {
"_COOKIE",sizeof("_COOKIE"),"HTTP_COOKIE_VARS",sizeof("HTTP_COOKIE_VARS"),0
},
               {
"_SERVER",sizeof("_SERVER"),"HTTP_SERVER_VARS",sizeof("HTTP_SERVER_VARS"),1
},
               {
"_ENV",sizeof("_ENV"),"HTTP_ENV_VARS",sizeof("HTTP_ENV_VARS"),1
},
               {
"_FILES",sizeof("_FILES"),"HTTP_POST_FILES",sizeof("HTTP_POST_FILES"),0
},
        };
        size_t
num_track_vars=sizeof(auto_global_records)/sizeof(struct
auto_global_record);
        size_t
i;

        /* jit_initialization = 0; */
for
(i=0;i<num_track_vars;i++)
{
PG(http_globals)[i]=NULL;
        }
for
(p=PG(variables_order);p&& *p;p++)
{
switch(*p)
{
case
'p':
                        case
'P':
                                if
(!_gpc_flags[0]&& !SG(headers_sent)&&SG(request_info).request_method&& !strcasecmp(SG(request_info).request_method,"POST"))
{
sapi_module.treat_data(PARSE_POST,NULL,NULL
TSRMLS_CC);      /* POST Data */
_gpc_flags[0]=1;
                                       if
(PG(register_globals))
{
php_autoglobal_merge(&EG(symbol_table),Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_POST])
TSRMLS_CC);
                                       }
}
break;
                   ....以下省略,www.devdao.com:
}}}


   到了这里说个题外话, 就是在php.ini中, 可以使用variables_order来控制PHP是否生成某个大变量,已经大变量的生成顺序。
   关于顺序,就是说, 如果打开了auto_register_globals的情况下, 如果先处理p,后处理g,那么$_GET['a'],就会覆盖$_POST['a'];
   可以看到,离成功不远了,sapi_module.treat_data 也就是php_default_treat_data,
   在php_default_treat_data中,对于变量,都调用php_register_variable_safe来注册变量, 而php_register_variable_safe最终会调用php_register_variable_ex:
PHPAPI
void
php_register_variable_ex(char*var,zval*val,zval*track_vars_array
TSRMLS_DC)
{
char*p=NULL;
   char*ip;      /* index pointer */
char*index, *escaped_index=NULL;
   int
var_len,index_len;
   zval*gpc_element, **gpc_element_p;
   zend_bool
is_array=0;
   HashTable*symtable1=NULL;

   assert(var!=NULL);

   if
(track_vars_array)
{
symtable1=Z_ARRVAL_P(track_vars_array);
   }
else
if
(PG(register_globals))
{
symtable1=EG(active_symbol_table);
   }
if
(!symtable1)
{
/* Nothing to do */
zval_dtor(val);
        return;
   }
/*
     * Prepare variable name
     */
/* ignore leading spaces in the variable name */
while
(*var&& *var=='
')
{
var++;
   }
/* ensure that we don't have spaces or dots in the variable name (not binary safe) */
//特别注意以下这段。。。。
for
(p=var; *p;p++)
{
if
(*p=='
'|| *p=='.')
{
            *p='_';
        }
else
if
(*p=='[')
{
is_array=1;
            ip=p;
            *p=0;
            break;
        }
  ....以下省略

   呵呵,问题的原因找到了, 就是在php_register_variable的时候,会将(.)转换成(_).
最后,再介绍下$_REQUEST变量的生成, 其实很简单, 在php_hash_environment中的最后, 会调用php_auto_globals_create_request(”_REQUEST”, sizeof(”_REQUEST”)-1TSRMLS_CC)来注册_REQUEST大变量, 在php_auto_globals_create_request(”_REQUEST”,sizeof(”_REQUEST”)-1 TSRMLS_CC)中,只是简单的将$_GET, $_POST, $_COOKIEmerge起来(G(http_globals)[TRACK_VARS_COOKIE]这部分,可以参看我较早前的在PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究) :
static
zend_bool
php_auto_globals_create_request(char*name,uint
name_len
TSRMLS_DC)
{
zval*form_variables;
   unsigned
char
_gpc_flags[3]={0,0,0};
   char*p;

   ALLOC_ZVAL(form_variables);
   array_init(form_variables);
   INIT_PZVAL(form_variables);

   for
(p=PG(variables_order);p&& *p;p++)
{
switch
(*p)
{
case'g':
            case'G':
               if
(!_gpc_flags[0])
{
php_autoglobal_merge(Z_ARRVAL_P(form_variables),Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET])
TSRMLS_CC);
                    _gpc_flags[0]=1;
               }
break;                                                                                                                    case'p':
            case'P':
               if
(!_gpc_flags[1])
{
php_autoglobal_merge(Z_ARRVAL_P(form_variables),Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_POST])
TSRMLS_CC);
                    _gpc_flags[1]=1;
               }
break;
            case'c':
            case'C':                                                                                                                        if
(!_gpc_flags[2])
{
php_autoglobal_merge(Z_ARRVAL_P(form_variables),Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE])
TSRMLS_CC);
                    _gpc_flags[2]=1;
               }
break;
        }
}
zend_hash_update(&EG(symbol_table),"_REQUEST",sizeof("_REQUEST"), &form_variables,sizeof(zval*),NULL);
   return
0;
}

上一篇:phpmailer所有对象和属性 中文 人气:40
下一篇:PHP性能优化的技巧 人气:66
浏览全部PHP的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐