php strip_tags实现的c源码
函数声明:/php5/ext/stardard/php_string.h
函数原型:/php5/ext/stardard/string.c

/* {{{ proto string strip_tags(string str [, string allowable_tags])
   Strips HTML and PHP tags from a string */
PHP_FUNCTION(strip_tags)
{
char *buf;
zval **str, **allow=NULL;
char *allowed_tags=NULL;
int allowed_tags_len=0;
size_t retval_len;

switch (ZEND_NUM_ARGS()) {//参数判断
   case 1:
    if (zend_get_parameters_ex(1, &str) == FAILURE) {//若参数只有一个并且参数未取到,返回false
     RETURN_FALSE;
    }
    break;
   case 2:
    if (zend_get_parameters_ex(2, &str, &allow) == FAILURE){//若参数有二个并且参数未取到,返回false
     RETURN_FALSE;
    }
    convert_to_string_ex(allow); //将允许不被过滤的标签强转为字符串,
    allowed_tags = Z_STRVAL_PP(allow); //得到allow的内容
    allowed_tags_len = Z_STRLEN_PP(allow);//得到allow的长度 
    break;
   default:
    WRONG_PARAM_COUNT;
    break;
}
convert_to_string_ex(str);
buf = estrndup(Z_STRVAL_PP(str), Z_STRLEN_PP(str)); //就是拷贝了一个字符串
/***************************************************
estrndup() 用于替代strndup()。速度要快于 estrdup() 而且是二进制安全的。如果你在复制之前预先知道这个字符串的长度那就推荐你使用这个函数。 
Zend\zend_alloc.h(61): #define estrndup(s, length) _estrndup((s), (length) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)

ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
   char *p;

p = (char *) _emalloc(length+1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); 
   //封装了c的malloc函数,其功能就是申请一段内存,return malloc(size),函数原型 在zend_alloc.c的1859行
  
   if (!p) {
    return (char *)NULL;
   }
   memcpy(p, s, length);//完全拷贝s的前length长度的内容,和strcpy不同的是遇到\0也不停止
   p[length] = 0;将字符串的最后一个字符设置为结束符 0和'\0'一样,若字符串最后一个字符不是这个的话,再对这个字串进行操作的时候会导致内存溢出
   return p;
}
***************************************************/

retval_len = php_strip_tags_ex(buf, Z_STRLEN_PP(str), NULL, allowed_tags, allowed_tags_len, 0);

/****************************************************
函数原型string.c 4130行--4345行   可结合字符串"abc<a href="";看他的算法
基本流程是一个字符一个字符的去判断,遇到<改变状态为1,2,3等,以后字符不计入,遇到>后回归状态为0,字符重新开始计入返回串
PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow, int allow_len, zend_bool allow_tag_spaces)
{ //size_t是一种无符号的整型数,它的取值没有负数,在数组中也用不到负数,而它的取值范围是整型数的双倍。sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小。
   char *tbuf, *buf, *p, *tp, *rp, c, lc;
   int br, i=0, depth=0;
   int state = 0;//0表示正常字符,1表示html代码,2表示php代码 4表示js,css等

if (stateptr)
    state = *stateptr;//预定义去哪种标签

buf = estrndup(rbuf, len);//将rbuf(传进来的字符串)复制一份
   c = *buf; //c得到buf的起始地址,第一个字符
   lc = '\0';//lc是最后一个字符
   p = buf;//整个字符串,用来做循环用
   rp = rbuf;//初始为整个字符串,用来存放过滤后的字串
   br = 0;//括号的级数
   if (allow) {
    php_strtolower(allow, allow_len);//如果存在允许不被过滤的标签,全部转为小些
    tbuf = emalloc(PHP_TAG_BUF_SIZE+1);//申请一k内存空间,用来存放允许过滤的字符串 PHP_TAG_BUF_SIZE为1023
    tp = tbuf;
   } else {
    tbuf = tp = NULL;
   }

while (i < len) {
    switch (c) {
     case '\0'://若到结尾了,跳出
      break;
     case '<'://遇到<的字符 ,若下个字符是空格就当成正常字符跳到 正常处理的case 若不是,则将该字符计入到tp(存放<....>字符串的变量)中
      if (isspace(*(p + 1)) && !allow_tag_spaces) {
       goto reg_char;
      }
      if (state == 0) {
       lc = '<';
       state = 1;
       if (allow) {
        tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);//若马上要超出内存了,将指针再指向开头
        *(tp++) = '<';
       }
      } else if (state == 1) {
       depth++;
      }
      break;

case '('://遇到( 判断是否正在过滤代码,若不是,正常字符处理,如是,则计入到tp中
      if (state == 2) {
       if (lc != '"' && lc != '\'') {
        lc = '(';
        br++;
       }
      } else if (allow && state == 1) {
       tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
       *(tp++) = c;
      } else if (state == 0) {
       *(rp++) = c;
      }
      break;

case ')'://遇到( 判断是否正在过滤代码,若不是,正常字符处理,如是,则计入到tp中
      if (state == 2) {
       if (lc != '"' && lc != '\'') {
        lc = ')';
        br--;
       }
      } else if (allow && state == 1) {
       tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
       *(tp++) = c;
      } else if (state == 0) {
       *(rp++) = c;
      }
      break;

case '>':
      if (depth) {//若是 <<>> 这样的情况下,直接跳出
       depth--;
       break;
      }
    
      switch (state) {
       case 1: /* HTML/XML */
        lc = '>';
        state = 0;
        if (allow) {
         tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
         *(tp++) = '>';
         *tp='\0';
         if (php_tag_find(tbuf, tp-tbuf, allow)) {//查找下<>标签中的是否是存在允许的不过滤的标签中
          memcpy(rp, tbuf, tp-tbuf);//若果存在将这些标签加到返回字符串后面,即把tbuf前tp-tbuf个字符复制到rp指向的内存地址上
          rp += tp-tbuf;//把指针指向 目前所在的位置
         }
         tp = tbuf;//再次回归
        }
        break;
       
       case 2: /* PHP */
        if (!br && lc != '\"' && *(p-1) == '?') {
         state = 0;
         tp = tbuf;
        }
        break;
       
       case 3:
        state = 0;
        tp = tbuf;
        break;

case 4: /* JavaScript/CSS/etc... */
        if (p >= buf + 2 && *(p-1) == '-' && *(p-2) == '-') {
         state = 0;
         tp = tbuf;
        }
        break;

default:
        *(rp++) = c;
        break;
      }
      break;

case '"':
     case '\'':
      if (state == 2 && *(p-1) != '\\') {//如果是要过滤php代码 并且 前一个字符是 \ 将最后一个字符lc设置为 当前字符或者 \0
       if (lc == c) {
        lc = '\0';
       } else if (lc != '\\') {
        lc = c;
       }
      } else if (state == 0) {//如果是正常字符,正常处理
       *(rp++) = c;
      } else if (allow && state == 1) {//如果是html代码中的,则将该字符添加到 允许不被过滤的字符串中去
       tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
       *(tp++) = c;
      }
      break;
    
     case '!': 
      /* JavaScript & Other HTML scripting languages */
      if (state == 1 && *(p-1) == '<') { 
       state = 3;
       lc = c;
      } else {
       if (state == 0) {
        *(rp++) = c;
       } else if (allow && state == 1) {
        tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
        *(tp++) = c;
       }
      }
      break;

case '-': //如果钱几个字符是!--则将状态3置为4,否则以正常字符算
      if (state == 3 && p >= buf + 2 && *(p-1) == '-' && *(p-2) == '!') {
       state = 4;
      } else {
       goto reg_char;
      }
      break;

case '?'://如果前个字符是<并state=1,则将状态变为2即过滤php代码

if (state == 1 && *(p-1) == '<') { 
       br=0;
       state=2;
       break;
      }

case 'E':
     case 'e'://如果是doctype 则将状态置为1,即过滤html
      /* !DOCTYPE exception */
      if (state==3 && p > buf+6
            && tolower(*(p-1)) == 'p'
               && tolower(*(p-2)) == 'y'
            && tolower(*(p-3)) == 't'
            && tolower(*(p-4)) == 'c'
            && tolower(*(p-5)) == 'o'
            && tolower(*(p-6)) == 'd') {
       state = 1;
       break;
      }
      /* fall-through */

case 'l'://如果状态是过滤php,且是前几个字符是xml,则将状态置为过滤html

/* swm: If we encounter '<?xml' then we shouldn't be in
      * state == 2 (PHP). Switch back to HTML.
      */

if (state == 2 && p > buf+2 && *(p-1) == 'm' && *(p-2) == 'x') {
       state = 1;
       break;
      }

/* fall-through */
     default:
reg_char:
      if (state == 0) {
       *(rp++) = c;
      } else if (allow && state == 1) {
       tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
       *(tp++) = c;
      } 
      break;
    }
    c = *(++p);
    i++;
   } 
   if (rp < rbuf + len) {
    *rp = '\0';
   }
   efree(buf);//封装内存释放函数void free(void *ptr);的函数
   if (allow)
    efree(tbuf);
   if (stateptr)
    *stateptr = state;

return (size_t)(rp - rbuf);//返回过滤后的长度
}
****************************************************/

RETURN_STRINGL(buf, retval_len, 0);//返回retval_len长度的字符串
}

php源码之strip_tags相关推荐

  1. Thinkphp 源码分析

    Thinkphp 源码分析 ThinkPHP是国内非常火的一个轻量级框架,采用MVC模式,结构写的非常好,今天 大象 带大家走一下ThinkPHP框架系统运行流程,我将跟随ThinkPHP的执行进行代 ...

  2. PHP百度收录量查询接口源码,百度收录量API查询PHP源码

    百度收录量API查询PHP源码 /* Plugin Name:百度收录量 Version:1.0 Description:根据域名返回百度收录量 Author:绿游 Author URL:http:/ ...

  3. PHP开发h5棋牌源码curl用法

    PHP开发h5棋牌源码curl用法(aqiulian.com),更多PHPcurl用法咨询Q:212303635.curl 是使用URL语法的传送文件工具,支持FTP.FTPS.HTTP HTPPS ...

  4. PHP万能小偷程序源码

    PHP万能小偷程序源码 源码,发出来大家共享一下,下面是采集车的官方介绍信息: 1.完全免费 采集车是一款完全免费的信息收集工具,我们本着团结共享的精神,尽量压缩建站成本. 2.高通用性 无论您是使用 ...

  5. ecshop源码分析:smarty模板类

    花了差不多3天半的时间,基本上把ecshop1400多行的模板类源码阅读完毕.从构造函数一行一行的阅读下去,遇到方法的调用便进去,遇到返回值又回到调用它的地方,这样来回不知道多少遍,每次阅读都让我心奋 ...

  6. 2023最新聚合热搜热榜PHP接口API源码

    聚合热搜热榜PHP接口API源码,本源码接口均抓取采集各大官网数据. PHP环境为5.6或以上,解压压缩包里面的hotlist.php文件到网站目录 然后输入参数输入?type 参数内容: zhihu ...

  7. 项目部署--我爱起名网平台搭建学习研究(含php源码,亲测有效)

    30年八字起名经验,起名专业权威,已为近十万名宝宝起名,好评率高达99.9%平台的搭建 只能用来学习研究使用,切勿商用或牟利,请大家遵守好这个规则,如果侵犯了你,请联系小编立即删除 本文涉及到的知识点 ...

  8. 聚合热搜热榜PHP接口API源码

    API说明 聚合热搜热榜PHP接口API源码,本源码接口均抓取采集各大官网数据. PHP环境为5.6或以上,解压压缩包里面的hotlist.php文件到网站目录 然后输入参数输入?type 参数内容: ...

  9. 火车头采集器双标题插件【完整php源码】

    最近比较流行的一种伪原创方式,火车头采集器双标题插件,功能主要如下: 1.原文标题伪原创,实现标题相关双标题: 2.文章内容伪原创,提高文章的原创度: 3.文章内容摘要提取. 废话就不多说,插件是用p ...

最新文章

  1. python导入matplotlib出错_解决导入matplotlib的RuntimeError: Python is not installed as a framework....
  2. 基于OpenCV的车辆变道检测
  3. 编译小米android系统软件,为Android加入busybox工具之小米(开发版本)
  4. 操作系统:基本分段存储管理方式
  5. 1.逐帧动画shader
  6. spring版本 jdk8_从JDK8升级到JDK11,看这篇就足够了
  7. api 创建zookeeper客户端_一文了解 Zookeeper 基本原理与应用场景
  8. Java代码中换行符怎么用
  9. 关于java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to 实体类
  10. Linux 内核第一宏
  11. Oracle的sql条件带有,oraclesql语句的if
  12. 仿小米商城html网页源码
  13. 房地产“产权分割制”是什么大杀器?
  14. hrbust/哈理工oj 1787 New Fibonacci Number【欧拉降幂+矩阵快速幂】
  15. matlab仿真下载,MATLAB仿真 关于MATLAB建模仿真源程序 - 下载 - 搜珍网
  16. 计算机的发展共经历了哪几个阶段,1. 计算机的发展经历了哪几个阶段?各阶段的主要特征是什么,计算机的发展经历了哪些阶段?...
  17. 机器学习(四):决策树绘画(基础篇)
  18. 撸羊毛之殇系列——之抖音极速版
  19. c语言霍夫变换圆检测,Hough Transform(霍夫变换)检测Circle(圆)的几种方法
  20. 2021年电工(初级)考试题库及电工(初级)考试内容

热门文章

  1. 事务的四个特性以及四个隔离级别
  2. Spark综合学习笔记(三)搜狗搜索日志分析
  3. python语法错误修改病句_高考语文病句类型及改错方法 病句改错(请先说出是什么语法错误) 天安...
  4. 电路的升压(boost)5-12v,降压(buck)和电荷泵
  5. Bookpedia for Mac(图书收藏管理软件)
  6. 宇宙久维了之1900电磁DC字母哥谭
  7. Chrome 升级成最新v33 造成开发上面诸多不便,赶紧回滚v32
  8. 应届生的身份有什么好处
  9. “元宇宙”虚拟世界的营销法则 “品牌元宇宙空间”算什么?
  10. 大红喜庆版UI猜灯谜又叫猜字谜微信小程序源码下载