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
基本流程是一个字符一个字符的去判断,遇到后回归状态为0,字符重新开始计入返回串
char *tbuf, *buf, *p, *tp, *rp, c, lc;
int state = 0;//0表示正常字符,1表示html代码,2表示php代码 4表示js,css等
buf = estrndup(rbuf, len);//将rbuf(传进来的字符串)复制一份
rp = rbuf;//初始为整个字符串,用来存放过滤后的字串
php_strtolower(allow, allow_len);//如果存在允许不被过滤的标签,全部转为小些
tbuf = emalloc(PHP_TAG_BUF_SIZE+1);//申请一k内存空间,用来存放允许过滤的字符串 PHP_TAG_BUF_SIZE为1023
if (isspace(*(p + 1)) && !allow_tag_spaces) {
tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);//若马上要超出内存了,将指针再指向开头
case '('://遇到( 判断是否正在过滤代码,若不是,正常字符处理,如是,则计入到tp中
if (lc != '"' && lc != '\'') {
} else if (allow && state == 1) {
tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
case ')'://遇到( 判断是否正在过滤代码,若不是,正常字符处理,如是,则计入到tp中
if (lc != '"' && lc != '\'') {
} else if (allow && state == 1) {
tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
if (depth) {//若是 <<>> 这样的情况下,直接跳出
tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
if (php_tag_find(tbuf, tp-tbuf, allow)) {//查找下<>标签中的是否是存在允许的不过滤的标签中
memcpy(rp, tbuf, tp-tbuf);//若果存在将这些标签加到返回字符串后面,即把tbuf前tp-tbuf个字符复制到rp指向的内存地址上
if (!br && lc != '\"' && *(p-1) == '?') {
case 4: /* JavaScript/CSS/etc... */
if (p >= buf + 2 && *(p-1) == '-' && *(p-2) == '-') {
if (state == 2 && *(p-1) != '\\') {//如果是要过滤php代码 并且 前一个字符是 \ 将最后一个字符lc设置为 当前字符或者 \0
} else if (state == 0) {//如果是正常字符,正常处理
} else if (allow && state == 1) {//如果是html代码中的,则将该字符添加到 允许不被过滤的字符串中去
tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
/* JavaScript & Other HTML scripting languages */
} else if (allow && state == 1) {
tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
case '-': //如果钱几个字符是!--则将状态3置为4,否则以正常字符算
if (state == 3 && p >= buf + 2 && *(p-1) == '-' && *(p-2) == '!') {
case 'e'://如果是doctype 则将状态置为1,即过滤html
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长度的字符串 }