<?php /* 如有转载,请注明作者 原作者: 何志强 改进: SonyMusic[ sonymusic@163.net ] 文件: ubb.php 备注: 说是改进,其实核心函数parse()已经完全重写了,而且思路也是不一样的。 不过仍是受何志强的例子的启发,而且测试的例子还有URLCHECK等几个函数也是沿用的何志强的程序,谢谢何志强。 目前还没有颜色的功能,但我会加入的。 如果在程序上有什么BUG或不便的地方,请给我MAIL。 谢谢! 改进功能: 对字符串进行UBB编码,该类目前只支持下列几个简单且实用的编码: 1. URL裢接 [url] http://phpuser.com/ [/url] http://头可以不需要 如[url]phpuser.com[/url]也是可以的。 2. Email裢接 [email] sonymusic@163.net [/email] 3. 图片裢接 [img] http://www.phpchina.com/images/logo.gif [/img] 同URL链接一样,前面的http也可以不要。 4. 文字方面 [b]粗体字[/b] [i]斜体字[/i] [u]加下划线[/u] [h1]1号标题字[/h1] ... [h6]6号标题字[/h6] [sup][/sup] [sub][/sub] [tt][/tt] [s][/s] [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)); } ?>