php 魔法引用magic_quotes_gpc()函数用法

 更新时间:2016年11月25日 16:45  点击:2080
magic_quotes_gpc是用来判断我们apache是不是开启了自动转译功能了,为了让各位更好的理解魔法引用magic_quotes_gpc()函数用法下面来给各位总结与举一些例子。

magic_quotes_gpc的设定值将会影响通过Get/Post/Cookies获得的数据


这两天接入百度SDK处理支付回调时碰到了签名通不过的情况,签名规则很简单,md5(transdata + appkey) 和 接受到的sign比较,请求方式为POST。

于是乎通过php://input记录下了原始数据和记录下了POST数据,通过日志查看到结果类似如下:

//原始数据
transdata={"exorderno":"2014031223","transid":"05514312314566",
"waresid":1,"appid":"1","feetype":0,"money":1,"count":1,"result":0,
"transtype":0,"transtime":"2014-03-12 15:33:19","paytype":401}&sign=xxxx
 
//post数据
[transdata] => {\"exorderno\":\"2014031223452345234\",\"transid\":
\"05514031215312314566\",\"waresid\":1,\"appid\":\"1\",\"feetype\":0,
\"money\":1,\"count\":1,\"result\":0,\"transtype\":0,
\"transtime\":\"2014-03-12 15:33:19\",\"paytype\":401}
[sign] => xxxx

可见接收到post数据时引号自动转义了,而程序上未做到该操作,很容易就联想到服务器的魔法引用打开了,查看
php版本

PHP 5.2.14 (cli) (built: Jun 7 2012 20:39:40)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies

例子说明:

$data1 = $_POST['aaa']; 

 $data2 = implode(file('1.txt')); 

 if(get_magic_quotes_gpc()){ 

    //把数据$data1直接写入数据库 (自动转译) 

 }else{ 

    $data1 = addslashes($data1); 

    //把数据$data1写入数据库,用函数(addslashes()转译) 

 } 

 if(get_magic_quotes_runtime()){ 

    //把数据$data2直接写入数据库(自动转译) 

 //从数据库读出的数据要经过一次stripslashes()之后输出,stripslashes()的作用是去掉:\ ,和addslashes()作用相反 

 }else{ 

    $data2 = addslashes($data2); 

     //把数据$data2写入数据库 

   

 //从数据库读出的数据直接输出 

}

最关键的区别是就是上面提到的2点:他们针对的处理对象不同

magic_quotes_gpc的设定值将会影响通过Get/Post/Cookies获得的数据

注意的是没有 set_magic_quotes_gpc()这个函数,就是不能在程序里面设置magic_quotes_gpc的值。

魔法引用5.4才删掉的,那极有可能这里打开在,查看配置文件确实如此,根据条件开关strip一下即可。

问题很快就解决了,但如果不熟悉这块可能还需要点时间,之前在CI的全局参数xss设置中有类似的地方,当进行全局处理之后对于这种接口、密钥可能会带来一些影响,所以全局参数过滤需要注意点。

矛盾可分为主要矛盾和次要矛盾,我们在程序设计中也常有这种思想,改最少的地方,过滤大部分参数,少数特殊处理。php中把它去掉了并不说明它没有存在的价值,有了魔法引用少了很多注入,但同时也让一些东西变得混乱,哪里需要转义,要怎么转义,通过什么方式来转义等等。客观看待,汲取中间有用的部分

前段时间头一次听说浅复制与深复制了,当时就是看的java例子,下文我来为各位分享一些小编总结的php中浅复制与深复制的例子供各位学习


周末闲来无事看到了原型模式,其中谈到了浅复制和深复制,想到PHP中的对应赋值、克隆以及克隆是浅复制还是深复制。

先来看看赋值,例如有一个简历类,有身高和体重两个属性:

class Resume 

{

    public $height;

    public $weight;

 

    public $workExperience;

}

$ResumeA = new Resume();

$ResumeB = $ResumeA;

此时实例化了一个Resume类并赋值给了$ResumeA变量,然后将$ResumeA变量赋值给$ResumeB。PHP手册上有说:

自PHP5起,new运算符自动返回一个引用,一个对象变量已经不再保存整个对象的值。只是保存一个标识符来访问真正的对象内容。 当对象作为参数传递,作为结果返回,或者赋值给另外一个变量,另外一个变量跟原来的不是引用的关系,只是他们都保存着同一个标识符的拷贝,这个标识符指向同一个对象的真正内容。

所以若通过$ResumeB修改height属性,则$ResumeA也会跟着变。如果想要复制一个全新的对象,则可以通过clone来实现,如:

$ResumeB = clone $ResumeA;

此时将$ResumeA的值拷贝到新的变量$ResumeB中,改变其中一个不影响另一个,修改$ResumeB中height属性,$ResumeA不会跟着改变。
但如果该类引用了其他对象,则所有的引用仍然指向到原来的对象。clone的这种复制方式就是浅复制。被赋值对象的所有变量都还有与原来对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。

如果上面类中workExperience为WorkExperience类的引用,当克隆的时候,克隆前后的workExperience属性还是指向到同一个对象内容。

与浅复制对应的是深复制,深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。

PHP中可以通过两种方式来实现深复制。第一种是__clone魔术方法:

public function __clone()

{

    $this->workExperience = new WorkExperience();

}

深复制涉及深的层次,通过clone魔术方法实现需要知道有几层然后对每一层依次实现。还有一种是可以通过序列化对象的方式,先将对象序列化之后再反序列化,如:

$ResumeB = unserialize(serialize($ResumeA));

clone还算常用的拷贝方式,整理的目的只是为了记录一下clone是浅复制,需要注意一下对象的引用

我们再举一个更实用的例子来说明一下PHP clone这种浅拷贝带来的后果:

class testClass
{
   public $str_data;
   public $obj_data;
}
$dateTimeObj = new DateTime("2014-07-05", new DateTimeZone("UTC"));
$obj1 = new testClass();
$obj1->str_data ="aaa";
$obj1->obj_data = $dateTimeObj;
$obj2 = clone $obj1;
var_dump($obj1);    // str_data:"aaa"  obj_data:"2014-07-05 00:00:00"
var_dump($obj2);    // str_data:"aaa"  obj_data:"2014-07-05 00:00:00"
$obj2->str_data ="bbb";
$obj2->obj_data->add(new DateInterval('P10D'));      //给$obj2->obj_date 的时间增加了10天
var_dump($obj1);     // str_data:"aaa"   obj_data:"2014-07-15 00:00:00"  !!!!
var_dump($obj2);     // str_data:"bbb"   obj_data:"2014-07-15 00:00:00"
var_dump($dateTimeObj)  // 2014-07-15 00:00:00"


这一下可以更加清楚的看到问题了吧。 一般来讲,你用clone来复制对象,希望是把两个对象彻底分开,不希望他们之间有任何关联, 但由于clone的shallow copy的特性, 有时候会出现非你期望的结果,上面的例子中,
1) $obj1->obj_data =$dateTimeObj 这句话实际上是个引用类型的赋值. 还记得前面提到的PHP中对象直接的赋值是引用操作么?除非你用$obj1->obj_dat = clone $dataTimeObj!

2) $obj2 = clone $obj1 这句话生成了一个obj1对象的浅拷贝对象,并赋给obj2. 由于是浅拷贝,obj2中的obj_data也是对$dateTimeObj的引用!

3)$dateTimeObj, $obj1->obj_data, $obj2->obj_data 实际上是同一个内存区对象数据的引用,因此修改其中任何一个都会影响其他两个!

 

如何解决这个问题呢? 采用PHP中的 __clone方法 把浅拷贝转换为深拷贝(这个方法给C++中的copy constructor概念上有些相似,但执行流程并不一样)

class testClass
{
 public $str_data;
 public $obj_data;
 public function __clone() {
   $this->obj_data = clone $this->obj_data;
}
$dateTimeObj = new DateTime("2014-07-05", new DateTimeZone("UTC"));
$obj1 = new testClass();
$obj1->str_data ="aaa";
$obj1->obj_data = $dateTimeObj;
$obj2 = clone $obj1;
var_dump($obj1);  // str_data:"aaa"  obj_data:"2014-07-05 00:00:00"
var_dump($obj2);  // str_data:"aaa"  obj_data:"2014-07-05 00:00:00"
$obj2->str_data ="bbb";
$obj2->obj_data->add(new DateInterval('P10D'));
var_dump($obj1);  // str_data:"aaa"  obj_data:"2014-07-05 00:00:00"
var_dump($obj2);  // str_data:"aaa"  obj_data:"2014-07-15 00:00:00"
var_dump($dateTimeObj);  //"2014-07-05 00:00:00"


关于 __clone() , PHP官方的文档: Once the cloing is complete, if a __clone() method is defined, then the newly created object’s __clone() method will be called, to allow any necessary properties that need to be changed.

按照这个定义,事实上__clone方法可以做很多事情,但我目前能想到的就只有把 浅拷贝变成深拷贝 这个场景的应用了, 如果有其他用法,欢迎大家提出来

file_get_contents函数我们通常是拿来对文件操作了,下面一起来看看file_get_contents函数的高级使用方法吧.


首先解决file_get_contents的超时问题,在超时返回错误后就象js中的settimeout那样进行一次尝试,错误超过3次或者5次后就确认为无法连线伺服器而彻底放弃。
这?就简单介绍两种解决方法:

一、增加超时的时间限制

注意:set_time_limit只是设定你的PHP程式的超时时间,而不是file_get_contents函数读取URL的超时时间。
我一开始以为set_time_limit也能影响到file_get_contents,后来经测试是无效的。真正的修改file_get_contents延时可以用resource $context的timeout参数:
PHP程式码

    $opts = array(
        'http'=>array(
            'method'=>"GET",
            'timeout'=>60,
        )
    );

    $context = stream_context_create($opts);

    $html =file_get_contents('http://www.111cn.net', false, $context);
    fpassthru($fp);

二、多次尝试

PHP程式码
    $cnt=0;
    while($cnt < 3 && ($str=@file_get_contents('http...'))===FALSE){
      $cnt++;
    }

以上方法对付超时已经OK了。接下来演示一下用file_get_contents实现Post,如下:
PHP程式码

    function Post($url, $post = null){
        $context = array();
        if (is_array($post)) {
            ksort($post);

            $context['http'] = array (
                'timeout'=>60,
                'method' => 'POST',
                'content' => http_build_query($post, '', '&'),
             );
        }

        return file_get_contents($url, false, stream_context_create($context));
    }

    $data = array (
        'name' => 'test',
        'email' => 'test@gmail.com',
        'submit' => 'submit',
     );

     echo Post('http://www.111cn.net', $data);

注意档案头的Set_time_out否则整个档案都得超时了

提取链接是一个很简单的做法了,下面这个例子相对来讲是比较全面了,下面我们一起来看看这个php curl采集页面内容并提取所有的链接例子.

本文承接上面两篇,本篇中的示例要调用到前两篇中的函数,做一个简单的URL采集。一般php采集网络数据会用file_get_contents、file和cURL。不过据说cURL会比file_get_contents、file更快更专业,更适合采集。今天就试试用cURL来获取网页上的所有链接。示例如下:


<?php
/*
 * 使用curl 采集111cn.net下的所有链接。
 */
include_once('function.php');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.111cn.net/');
// 只需返回HTTP header
curl_setopt($ch, CURLOPT_HEADER, 1);
// 页面内容我们并不需要
// curl_setopt($ch, CURLOPT_NOBODY, 1);
// 返回结果,而不是输出它
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$html = curl_exec($ch);
$info = curl_getinfo($ch);
if ($html === false) {
 echo "cURL Error: " . curl_error($ch);
}
curl_close($ch);
$linkarr = _striplinks($html);
// 主机部分,补全用
$host = 'http://www.111cn.net/';
if (is_array($linkarr)) {
 foreach ($linkarr as $k => $v) {
  $linkresult[$k] = _expandlinks($v, $host);
 }
}
printf("<p>此页面的所有链接为:</p><pre>%s</pre>n", var_export($linkresult , true));
?>


function.php内容如下(即为上两篇中两个函数的合集):

<?php
function _striplinks($document) {
 preg_match_all("'<s*as.*?hrefs*=s*(["'])?(?(1) (.*?)\1 | ([^s>]+))'isx", $document, $links);
 // catenate the non-empty matches from the conditional subpattern
 while (list($key, $val) = each($links[2])) {
  if (!empty($val))
   $match[] = $val;
 } while (list($key, $val) = each($links[3])) {
  if (!empty($val))
   $match[] = $val;
 }
 // return the links
 return $match;
}
/*===================================================================*
 Function: _expandlinks
 Purpose: expand each link into a fully qualified URL
 Input:  $links   the links to qualify
    $URI   the full URI to get the base from
 Output:  $expandedLinks the expanded links
*===================================================================*/
function _expandlinks($links,$URI)
{
 $URI_PARTS = parse_url($URI);
 $host = $URI_PARTS["host"];
 preg_match("/^[^?]+/",$URI,$match);
 $match = preg_replace("|/[^/.]+.[^/.]+$|","",$match[0]);
 $match = preg_replace("|/$|","",$match);
 $match_part = parse_url($match);
 $match_root =
 $match_part["scheme"]."://".$match_part["host"];
 $search = array(  "|^http://".preg_quote($host)."|i",
      "|^(/)|i",
      "|^(?!http://)(?!mailto:)|i",
      "|/./|",
      "|/[^/]+/../|"
     );
 $replace = array( "",
      $match_root."/",
      $match."/",
      "/",
      "/"
     );
 $expandedLinks = preg_replace($search,$replace,$links);
 return $expandedLinks;
}
?>


具体想要和file_get_contents做一个比较的话,可以利用linux下的time命令查看两者执行各需多长时间。据目前测试看是CURL更快一些。最后链接下上面两个函数相关介绍。

匹配链接函数: function _striplinks()

相对路径转绝对:function _expandlinks()

在做文件上传时有一个非常必须要做的功能就是上传文件会按日期生成目录并把文件保存在目录下了,下面我来为各位介绍一段php自动创建目录并保存文件函数

php保存文件,还可以根据文件路径自动连续创建目录,代码如下(注:PHP要版本5以上):

<?php
 /**
  * 保存文件
  *
  * @param string $fileName 文件名(含相对路径)
  * @param string $text 文件内容
  * @return boolean
  */
 function saveFile($fileName, $text) {
  if (!$fileName || !$text)
   return false;
  if (makeDir(dirname($fileName))) {
   if ($fp = fopen($fileName, "w")) {
    if (@fwrite($fp, $text)) {
     fclose($fp);
     return true;
    } else {
     fclose($fp);
     return false;
    }
   }
  }
  return false;
 }
 /**
  * 连续创建目录
  *
  * @param string $dir 目录字符串
  * @param int $mode 权限数字
  * @return boolean
  */
 function makeDir($dir, $mode=0755) {
   /*function makeDir($dir, $mode="0777") { 此外0777不能加单引号和双引号,
  加了以后,"0400" = 600权限,处以为会这样,我也想不通*/
  if (!dir) return false;
  if(!file_exists($dir)) {
   return mkdir($dir,$mode,true);
  } else {
   return true;
  }
 }
?>
//以下是测试内容,并调用上面的函数
<?php
 $content = '这里是测试内容';
 if(saveFile('dir/test.txt',$content)){
  echo '写入成功';
 }else{
  echo '写入失败';
 }
?>

注意:makeDir就是一个目录创建函数,我们使用的是递归创建了.

[!--infotagslink--]

相关文章

  • php正确禁用eval函数与误区介绍

    eval函数在php中是一个函数并不是系统组件函数,我们在php.ini中的disable_functions是无法禁止它的,因这他不是一个php_function哦。 eval()针对php安全来说具有很...2016-11-25
  • php中eval()函数操作数组的方法

    在php中eval是一个函数并且不能直接禁用了,但eval函数又相当的危险了经常会出现一些问题了,今天我们就一起来看看eval函数对数组的操作 例子, <?php $data="array...2016-11-25
  • Python astype(np.float)函数使用方法解析

    这篇文章主要介绍了Python astype(np.float)函数使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-08
  • Python中的imread()函数用法说明

    这篇文章主要介绍了Python中的imread()函数用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-16
  • C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
  • C#学习笔记- 随机函数Random()的用法详解

    下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#中using的三种用法

    using 指令有两个用途: 允许在命名空间中使用类型,以便您不必限定在该命名空间中使用的类型。 为命名空间创建别名。 using 关键字还用来创建 using 语句 定义一个范围,将在此...2020-06-25
  • 金额阿拉伯数字转换为中文的自定义函数

    CREATE FUNCTION ChangeBigSmall (@ChangeMoney money) RETURNS VarChar(100) AS BEGIN Declare @String1 char(20) Declare @String2 char...2016-11-25
  • Android开发中findViewById()函数用法与简化

    findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20
  • C++中 Sort函数详细解析

    这篇文章主要介绍了C++中Sort函数详细解析,sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变...2022-08-18
  • PHP用strstr()函数阻止垃圾评论(通过判断a标记)

    strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。该函数返回字符串的其余部分(从匹配点)。如果未找到所搜索的字符串,则返回 false。语法:strstr(string,search)参数string,必需。规定被搜索的字符串。 参数sea...2013-10-04
  • PHP函数分享之curl方式取得数据、模拟登陆、POST数据

    废话不多说直接上代码复制代码 代码如下:/********************** curl 系列 ***********************///直接通过curl方式取得数据(包含POST、HEADER等)/* * $url: 如果非数组,则为http;如是数组,则为https * $header:...2014-06-07
  • php中的foreach函数的2种用法

    Foreach 函数(PHP4/PHP5)foreach 语法结构提供了遍历数组的简单方式。foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息。...2013-09-28
  • C语言中free函数的使用详解

    free函数是释放之前某一次malloc函数申请的空间,而且只是释放空间,并不改变指针的值。下面我们就来详细探讨下...2020-04-25
  • PHP函数strip_tags的一个bug浅析

    PHP 函数 strip_tags 提供了从字符串中去除 HTML 和 PHP 标记的功能,该函数尝试返回给定的字符串 str 去除空字符、HTML 和 PHP 标记后的结果。由于 strip_tags() 无法实际验证 HTML,不完整或者破损标签将导致更多的数...2014-05-31
  • SQL Server中row_number函数的常见用法示例详解

    这篇文章主要给大家介绍了关于SQL Server中row_number函数的常见用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-12-08
  • PHP加密解密函数详解

    分享一个PHP加密解密的函数,此函数实现了对部分变量值的加密的功能。 加密代码如下: /* *功能:对字符串进行加密处理 *参数一:需要加密的内容 *参数二:密钥 */ function passport_encrypt($str,$key){ //加密函数 srand(...2015-10-30
  • php的mail函数发送UTF-8编码中文邮件时标题乱码的解决办法

    最近遇到一个问题,就是在使用php的mail函数发送utf-8编码的中文邮件时标题出现乱码现象,而邮件正文却是正确的。最初以为是页面编码的问题,发现页面编码utf-8没有问题啊,找了半天原因,最后找到了问题所在。 1.使用 PEAR 的...2015-10-21
  • C#中加载dll并调用其函数的实现方法

    下面小编就为大家带来一篇C#中加载dll并调用其函数的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#虚函数用法实例分析

    这篇文章主要介绍了C#虚函数用法,实例分析了C#中虚函数的功能与基本使用技巧,需要的朋友可以参考下...2020-06-25