|
<?php /* 如有转载,请注明作者
原作者: 何志强 改进: SonyMusic[ sonymusic@163.net ] 文件: ubb.php 备注: 说是改进,其实核心函数parse()已经完全重写了,而且思路也是不一样的。 不过仍是受何志强的例子的启发,而且测试的例子还有URLCHECK等几个函数也是沿用的何志强的程序,谢谢何志强。 目前还没有颜色的功能,但我会加入的。 如果在程序上有什么BUG或不便的地方,请给我MAIL。 谢谢! 改进功能: 对字符串进行UBB编码,该类目前只支持下列几个简单且实用的编码: 1. URL裢接 http://phpuser.com/ http://头可以不需要 如phpuser.com也是可以的。 2. Email裢接 sonymusic@163.net 3. 图片裢接 同URL链接一样,前面的http也可以不要。 4. 文字方面 粗体字 斜体字 加下划线 [h1]1号标题字[/h1] ... [h6]6号标题字[/h6] [sup][/sup] [sub][/sub] [tt][/tt]
[strike][/strike] [em][/em] [strong][/strong] [code][/code] [samp][/samp] [kbd][/kbd] [var][/var] [dfn][/dfn] [cite][/cite] [small][/small] [big][/big] [blink][/blink] 注意以下几点: 1. url,email,img等标签是不分大小写的. 2. 在标签中不允许有TAB键出现,但空格允许。 3. 该类要调用htmlencode,htmlencode4textarea,emailcheck函数和urlcheck类. 4. 修改后支持嵌套,但url,email,img这三个标签不是允许嵌套的。 技术资料: Ultimate Bulletin Board http://www.ultimatebb.com/ What is UBB Code http://www.scriptkeeper.com/ubb/ubbcode.html */
include("urlcheck.php"); include("otherfunc.php"); //这两个文件的内容,附在最后。
//ubbcode类 class ubbcode{ var $call_time=0; //可处理标签及处理函数对应表 var $tags = array( //小写的标签 => 对应的处理函数 'url' => '$this->url', 'email' => '$this->email', 'img' => '$this->img', 'b' => '$this->simple', 'i' => '$this->simple', 'u' => '$this->simple', 'tt' => '$this->simple', 's' => '$this->simple', 'strike' => '$this->simple', 'h1' => '$this->simple', 'h2' => '$this->simple', 'h3' => '$this->simple', 'h4' => '$this->simple', 'h5' => '$this->simple', 'h6' => '$this->simple', 'sup' => '$this->simple', 'sub' => '$this->simple', 'em' => '$this->simple', 'strong' => '$this->simple', 'code' => '$this->simple', 'samp' => '$this->simple', 'kbd' => '$this->simple', 'var' => '$this->simple', 'dfn' => '$this->simple', 'cite' => '$this->simple', 'small' => '$this->simple', 'big' => '$this->simple', 'blink' => '$this->simple' ); //url裢接属性 var $attr_url; //url合法性检查对象 var $urlcheck;
function ubbcode($attr_url){ $this->attr_url = ''.$attr_url; $this->urlcheck = new urlcheck(); }
//对$str进行UBB编码解析 function parse($str){ $this->call_time++; $parse = ''.htmlencode($str);
$ret = ''; while(true){ $eregi_ret=eregi("[[#]{0,1}[[:alnum:]]{1,7}]",$parse,$eregi_arr); //查找[xx] if(!$eregi_ret){ $ret .= $parse; break; //如果没有,返回 } $pos = @strpos ($parse,$eregi_arr[0]); $tag_len=strlen($eregi_arr[0])-2;//标记长度 $tag_start=substr($eregi_arr[0],1,$tag_len); $tag=strtolower($tag_start);
if((($tag=="url") or ($tag=="email") or ($tag=="img")) and ($this->call_time>1)){ echo $this->call_time."<br>"; return $parse;//如果不能是不能嵌套的标记,直接返回 }
$parse2 = substr($parse,0,$pos);//标记之前 $parse = substr($parse,$pos+$tag_len+2);//标记之后 if(!isset($this->tags[$tag])){ echo "$tag_start<br>"; $ret .= $parse2.'['.$tag_start.']'; continue;//如果是不支持的标记 }
//查找对对应的结束标记 $eregi_ret=eregi("[/".$tag."]",$parse,$eregi_arr); if(!$eregi_ret){ $ret .= $parse2.'['.$tag_start.']'; continue;//如果没有对应该的结束标记 } $pos=strpos($parse,$eregi_arr[0]); $value=substr($parse,0,$pos);//这是起止标记之间的内容 $tag_end=substr($parse,$pos+2,$tag_len); $parse=substr($parse,$pos+$tag_len+3);//结束标记之后的内容
if(($tag!="url") and ($tag!="email") and ($tag!="img")){ $value=$this->parse($value); }
$ret .= $parse2; eval('$ret .= '.$this->tags[$tag].'("'.$tag_start.'","'.$tag_end.'","'.$value.'");'); } $this->call_time--; return $ret; }
function simple($start,$end,$value){ return '<'.$start.'>'.$value.'</'.$end.'>'; }
function url($start,$end,$value){ $trim_value=trim($value); if (strtolower(substr($trim_value,0,7))!="http://") $trim_value="http://".$trim_value; if($this->urlcheck->check($trim_value)) return '<a href="'.$trim_value.'" '.$this->attr_url.'>'.$value.'</a>'; else return '['.$start.']'.$value.'[/'.$end.']'; }
function email($start,$end,$value){ if(emailcheck($value)) return '<a href="mailto:'.$value.'">'.$value.'</a>'; else return '['.$start.']'.$value.'[/'.$end.']'; }
function img($start,$end,$value){ $trim_value=trim($value); if ((strtolower(substr($trim_value,0,7))!="http://") or ($this->urlcheck->check($trim_value))) return '<img src="'.$trim_value.'"></img>'; else return '['.$start.']'.$value.'[/'.$end.']'; } }
//测试 echo '<html>'; echo '<head><title>测试</title></head>'; echo '<body>'; echo '<form action="'.str2url($PATH_INFO).'" method="post">'; echo '<textarea cols="100" rows="10" name="ubb">'.htmlencode4textarea($ubb).'</textarea><br>'; echo '<input type="submit" value="转换">'; echo '</form>';
if(isset($ubb)){ $ubbcode = new ubbcode('target="_blank"'); echo '<hr>'.$ubbcode->parse($ubb); }
echo '</body>'; echo '</html>';
?>
文件urlcheck.php的内容: <?php //urlcheck.php class urlcheck{ var $regex = array(//协议名(注意在这里必须写成小写) => 对应的正则表达式 'ftp' => '$this->ftpurl', 'file' => '$this->fileurl', 'http' => '$this->httpurl', 'https' => '$this->httpurl', 'gopher' => '$this->gopherurl', 'news' => '$this->newsurl', 'nntp' => '$this->nntpurl', 'telnet' => '$this->telneturl', 'wais' => '$this->waisurl' );
var $lowalpha; var $hialpha; var $alpha; var $digit; var $safe; var $extra; var $national; var $punctuation; var $reserved; var $hex; var $escape; var $unreserved; var $uchar; var $xchar; var $digits;
var $urlpath; var $password; var $user; var $port; var $hostnumber; var $alphadigit; var $toplabel; var $domainlabel; var $hostname; var $host; var $hostport; var $login;
//ftp var $ftptype; var $fsegment; var $fpath; var $ftpurl;
//file var $fileurl;
//http,https var $search; var $hsegment; var $hpath; var $httpurl;
//gopher var $gopher_string; var $selector; var $gtype; var $gopherurl;
//news var $article; var $group; var $grouppart; var $newsurl;
//nntp var $nntpurl;
//telnet var $telneturl;
//wais var $wpath; var $wtype; var $database; var $waisdoc; var $waisindex; var $waisdatabase; var $waisurl;
function check($url){ $pos = @strpos ($url,':',1); if($pos<1) return false; $prot = substr($url,0,$pos); if(!isset($this->regex[$prot])) return false; eval('$regex = '.$this->regex[$prot].';'); return ereg('^'.$regex.'$',$url); }
function urlcheck(){ $this->lowalpha = '[a-z]'; $this->hialpha = '[A-Z]'; $this->alpha = '('.$this->lowalpha.'|'.$this->hialpha.')'; $this->digit = '[0-9]'; $this->safe = '[$.+_-]'; $this->extra = '[*()'!,]'; $this->national = '([{}|^~`]|\[|\])'; $this->punctuation = '[<>#%"]'; $this->reserved = '[?;/: @&= ]'; $this->hex = '('.$this->digit.'|[a-fA-F])'; $this->escape = '(%'.$this->hex.'{2})'; $this->unreserved = '('.$this->alpha.'|'.$this->digit.'|'.$this->safe.'|'.$this->extra.')'; $this->uchar = '('.$this->unreserved.'|'.$this->escape.')'; $this->xchar = '('.$this->unreserved.'|'.$this->reserved.'|'.$this->escape.')'; $this->digits = '('.$this->digit.'+)';
$this->urlpath = '('.$this->xchar.'*)'; $this->password = '(('.$this->uchar.'|[?;&=]'.')*)'; $this->user = '(('.$this->uchar.'|[?;&=]'.')*)'; $this->port = $this->digits; $this->hostnumber = '('.$this->digits.'.'.$this->digits.'.'.$this->digits.'.'.$this->digits.')'; $this->alphadigit = '('.$this->alpha.'|'.$this->digit.')'; $this->toplabel = '('.$this->alpha.'|('.$this->alpha.'('.$this->alphadigit.'|-)*'.$this->alphadigit.'))'; $this->domainlabel = '('.$this->alphadigit.'|('.$this->alphadigit.'('.$this->alphadigit.'|-)*'.$this->alphadigit.'))'; $this->hostname = '(('.$this->domainlabel.'\.)*'.$this->toplabel.')'; $this->host = '('.$this->hostname.'|'.$this->hostnumber.')'; $this->hostport = '('.$this->host.'(:'.$this->port.')?)'; $this->login = '(('.$this->user.'(:'.$this->password.')?@)?'.$this->hostport.')';
$this->ftptype = '[aidAID]'; $this->fsegment = '(('.$this->uchar.'|[?: @&= ])*)'; $this->fpath = '('.$this->fsegment.'(/'.$this->fsegment.')*)'; $this->ftpurl = '([fF][tT][pP]://'.$this->login.'(/'.$this->fpath.'(;[tT][yY][pP][eE]='.$this->ftptype.')?)?)';
$this->fileurl = '([fF][iI][lL][eE]://('.$this->host.'|[lL][oO][cC][aA][lL][hH][oO][sS][tT])?/'.$this->fpath.')';
$this->search = '(('.$this->uchar.'|[;: @&= ])*)'; $this->hsegment = '(('.$this->uchar.'|[;: @&= ])*)'; $this->hpath = '('.$this->hsegment.'(/'.$this->hsegment.')*)'; $this->httpurl = '([hH][tT][tT][pP][sS]?://'.$this->hostport.'(/'.$this->hpath.'([?]'.$this->search.')?)?)';
$this->gopher_string = '('.$this->xchar.'*)'; $this->selector = '('.$this->xchar.'*)'; $this->gtype = $this->xchar; $this->gopherurl = '([gG][oO][pP][hH][eE][rR]://'.$this->hostport.'(/('.$this->gtype.'('.$this->selector.'(%09'.$this->search.'(%09'.$this->gopher_string.')?)?)?)?)?)';
$this->article = '(('.$this->uchar.'|[;/?:&=]) +@'.$this- >host.')'; $this->group = '('.$this->alpha.'('.$this->alpha.'|'.$this->digit.'|[-.+_])*)'; $this->grouppart = '(|'.$this->group.'|'.$this->article.')'; $this->newsurl = '([nN][eE][wW][sS]:'.$this->grouppart.')';
$this->nntpurl = '([nN][nN][tT][pP]://'.$this->hostport.'/'.$this->group.'(/'.$this->digits.')?)';
$this->telneturl = '([tT][eE][lL][nN][eE][tT]://'.$this->login.'/?)';
$this->wpath = '('.$this->uchar.'*)'; $this->wtype = '('.$this->uchar.'*)'; $this->database = '('.$this->uchar.'*)'; $this->waisdoc = '([wW][aA][iI][sS]://'.$this->hostport.'/'.$this->database.'/'.$this->wtype.'/'.$this->wpath.')'; $this->waisindex = '([wW][aA][iI][sS]://'.$this->hostport.'/'.$this->database.'[?]'$this->search.')'; $this->waisdatabase = '([wW][aA][iI][sS]://'.$this->hostport.'/'.$this->database.')'; $this->waisurl = '('.$this->waisdatabase.'|'.$this->waisindex.'|'.$this->waisdoc.')'; } }
?>
文件otherfunc.php的内容: <?php //otherfunc.php function htmlencode($str){ $str = (string)$str;
$ret = ''; $len = strlen($str); $nl = false; for($i=0;$i<$len;$i++){ $chr = $str[$i]; switch($chr){ case '<': $ret .= '<'; $nl = false; break; case '>': $ret .= '>'; $nl = false; break; case '"': $ret .= '"'; $nl = false; break; case '&': $ret .= '&'; $nl = false; break; /* case ' ': $ret .= ' '; $nl = false; break; */ case chr(9): $ret .= ' '; $nl = false; break; case chr(10): if($nl) $nl = false; else{ $ret .= '<br>'; $nl = true; } break; case chr(13): if($nl) $nl = false; else{ $ret .= '<br>'; $nl = true; } break; default: $ret .= $chr; $nl = false; break; } }
return $ret; }
function htmlencode4textarea($str){ $str = (string)$str;
$ret = ''; $len = strlen($str); for($i=0;$i<$len;$i++){ $chr = $str[$i]; switch($chr){ case '<': $ret .= '<'; break; case '>': $ret .= '>'; break; case '"': $ret .= '"'; break; case '&': $ret .= '&'; break; case ' ': $ret .= ' '; break; case chr(9): $ret .= ' '; break; default: $ret .= $chr; break; } }
return $ret; }
function emailcheck($email){ $ret=false; if(strstr($email, '@' ) && strstr($email, '.')){ if(eregi("^([_a-z0-9]+([\._a-z0-9-]+)*)@([a-z0-9]{2,}(\.[a-z0-9-]{2,})*\.[a-z]{2,3})$", $email)){ $ret=true; } } return $ret; }
function str2url($path){ return eregi_replace("%2f","/",urlencode($path)); } ?>
|
|