UBB 解析类 <?php /************************************************************ * UBB 解析器 v1.0b * * 该解释器支持的是UBB的子集(标准集我也不知到啥样) * 需要其他的可以自行扩展, * 理论上支持任何[x=a,b,c]xxx[/x]结构的解析 * * 源代码由zy提供,在此思路上重写了大部分代码 * * 如果你有什么好的建议请联系 pazee@21cn.com * 正则表达式的用法得到 z_yong@163.com 的大力支持,在此表示感谢 * 耙子 2001/12/31 * http://www.fogsun.com * * $ 转载请完整保留此段文字 $ * * 使用说明 * 1.本代码未对html进行任何限制,仅增加了对UBB-〉Html的转换支持, * 如果需要请在调用本代码前自行过滤html标签, * 2.调用代码前请用 stripslashes 函数去掉转换内容中的冗余反斜杠, * 否则结果可能会出现问题 * 3.UBB 标签中不允许出现空格 *************************************************************/ define ("sVersion", "1.2.1.15 beta"); //ubbcode类 class ubbcode { var $nest; // 递归深度,for debug //可处理标签及处理函数表 var $tags = array( 'url' => '$this->url', 'email' => '$this->email', 'mail' => '$this->email', // 为了容错,[mail]和[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', 'fly' => '$this->fly', 'move' => '$this->move', 'glow' => '$this->CSSStyle', 'shadow' => '$this->CSSStyle', 'blur' => '$this->CSSStyle', 'wave' => '$this->CSSStyle', 'sub' => '$this->simple', 'sup' => '$this->simple', 'size' => '$this->size', 'face' => '$this->face', 'font' => '$this->face', // 为了容错,[font]和[face]等效 'color' => '$this->color' ); function ubbcode() { $this->$nest= 0; $this->$sLastModified= sprintf("%s", date("Y-m-j H:i", getlastmod())); } /*********************************************************************** * 对使用者输入的 E-Mail 作简单的检查, * 检查使用者的 E-Mail 字串是否有 @ 字元, * 在 @ 字元前有英文字母或数字,在之后有数节字串, * 最后的小数点后只能有二个或三个英文字母。 * super@mail.wilson.gs 就可以通过检查,super@mail.wilson 就不能通过检查 ************************************************************************/ function emailcheck($str) { if (eregi("^[_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3}$", $str)) return true; else return false; } /*********************************************************************** * 对使用者输入的 URL 作简单的检查, * 目前只能简单判断,不能自动检查fpt,finger等 ************************************************************************/ function checkURL($str) { $bValidURL= true; if (eregi("([a-z0-9-]+([\.][a-z0-9\-]+)+)", $str, $er_arr)) { /* printf ("0. %s <br>\n", $er_arr[0]); printf ("1. %s <br>\n", $er_arr[1]); printf ("2. %s <br>\n", $er_arr[2]); printf ("3. %s <br>\n", $er_arr[3]); printf ("4. %s <br>\n", $er_arr[4]); */ } else $bValidURL= false; return $bValidURL; } /*********************************************************************** * 对使用者输入的 图片URL 作简单的检查, * 目前只能简单判断结尾是否为图片文件 * 不支持由CGI动态生成的图片,比如计数器这类的 ************************************************************************/ function checkImgURL($str) { if ($this->checkURL($str)) { if(eregi("\.(jpeg|jpg|gif|bmp|png|pcx|tiff|tga|lwf)$", $str)) return true; else return false; } else return false; } /*********************************************************************** * 自动补全URL部分,主要是协议前缀, * 默认是htpp://,支持https://;ftp://;finger://;gopher://等 * 函数并不对URL的合法性作检查 ************************************************************************/ function formatURL($str) { if (!eregi("^(ftp|http|https|mms|gopher|finger|bbs|telnet):(\/\/|\\\\)", $str)) $str= 'http://'.$str; return $str; } //对$str进行UBB编码解析 function parse($str) { $nest ++; $parse = '.($str); $ret = '; while(true){ //查找[xx] 或者[xx=xx] , 但不包括[xx=] $eregi_ret=eregi("\[([a-z][a-z0-9]{0,7})(=[a-z0-9#.:/&@|\?,%=_\+\"\']+)?\]", $parse, $eregi_arr); if(!$eregi_ret) { $ret .= $parse; break; //如果没有,返回 } /* for Debug else { printf ("$. %s<br>", $eregi_ret); printf ("0. %s<br>", $eregi_arr[0]); printf ("1. %s<br>", $eregi_arr[1]); printf ("2. %s<br>", $eregi_arr[2]); printf ("3. %s<br>", $eregi_arr[3]); } */ $pos = @strpos($parse, $eregi_arr[0]); // 起始位置 $tag_start= $eregi_arr[1]; $tag= strtolower($eregi_arr[1]); $tag_param= $eregi_arr[2]; $parse2 = substr($parse, 0, $pos);//标记之前 $parse = substr($parse, $pos + $eregi_ret);//标记之后 if(!isset($this->tags[$tag])) { // echo "$tag.@133:不支持的标记<br>"; // for debug $ret .= $parse2.'['.$tag_start.']'; continue; //如果是不支持的标记 } //查找对应的结束标记 $eregi_ret=eregi("\[(/".$tag.")\]", $parse, $eregi_arr); if(!$eregi_ret) { // echo ('没有对应该的结束标记'.$rrr); //for debug $ret .= $parse2.'['.$tag_start.$tag_param.']'; continue;//没有对应该的结束标记 } $pos= strpos($parse, $eregi_arr[0]); $value= substr($parse, 0, $pos); //起止标记之间的内容 $tag_end= $eregi_arr[1]; $parse= substr($parse, $pos + $eregi_ret);//结束标记之后的内容 // 允许嵌套标记,递归分析 if (!(($tag == 'code') or ($tag=="url") or ($tag=="email") or ($tag=="img"))){ $value= $this->parse($value); } $ret.= $parse2; $parseFun= sprintf('$ret .= %s($tag_start, $tag_param, $tag_end, $value);', $this->tags[$tag]); eval($parseFun); } $nest --; return $ret; } /***************************************************** * 简单替换,类似[b]变为<b> * 标签内容不便,只是替代括号为<> *****************************************************/ function simple($start, $para, $end, $value){ if (strlen($para) > 0) return sprintf("[%s%s]%s[%s]", $start, $para, $value, $end); else return sprintf("<%s>%s<%s>", $start, $value, $end); /***************************************************** * 如下认为合法可以没有“http://”;ftp一定要自己加“ftp://” * [URL=http://www.fogsun.com]93611[/URL] * [URL=http://www.fogsun.com][/URL] * [URL]http://www.fogsun.com[/URL] *****************************************************/ function url($start, $para, $end, $value){ $sA= $value; $sURL= substr(trim($para), 1); if (strlen($sURL) > 0) { if (strlen($value) == 0) $sA= $sURL; } else { $sURL= trim($value); } $sURL= $this->formatURL($sURL); if($this->checkURL($sURL)) return "<a href=\"$sURL\">$sA</a>"; else { return sprintf("[%s%s]%s[%s]", $start, $para, $value, $end); } }
/***************************************************** * 如下认为合法可以没有“mailto:”头; * [email=pazee@21cn.com]pazee[/email] * [email=pazee@21cn.com][/email] * [email]pazee@21cn.com[/email] *****************************************************/ function email($start, $para, $end, $value){ $sA= $value; $sURL= substr(trim($para), 1); if (strlen($sURL) > 0) { if (strlen($value) == 0) $sA= $sURL; } else { $sURL= trim($value); } if (strtolower(substr($sURL, 0, 7)) != "mailto:") $sURL= "mailto:". $sURL; if($this->emailcheck(substr($sURL, 7))) return "<a href=\"$sURL\">$sA</a>"; else return sprintf("[%s%s]%s[%s]", $start, $para, $value, $end); } /***************************************************** * 显示图片;如下用法认为合法 * [img=www.21cn.com/title.jpg][/img] * [img]www.21cn.com/title.jpg[/img] *****************************************************/ function img($start, $para, $end, $value){ $sURL= substr(trim($para), 1); if (strlen($sURL) <= 0) $sURL= trim($value); $sURL= $this->formatURL($sURL); if ($this->checkImgURL($sURL)) return sprintf("<img src=\"%s\"></img>", $sURL); else return sprintf("[%s%s]%s[%s]", $start, $para, $value, $end); } /***************************************************** * 字符串从右向左循环移动 * 无参数 * 等效与html的<marquee> *****************************************************/ function fly($start, $para, $end, $value){ if (strlen($para)>0) // 有参数 return sprintf("[%s%s]%s[%s]", $start, $para, $value, $end); else return '<marquee behavior=alternate scrolldelay=100>'.$value.'</marquee>'; } /***************************************************** * 字符串来回移动 * 无参数 * 等效与html的<marquee> *****************************************************/ function move($start, $para, $end, $value) { if (strlen($para)>0) // 有参数 return sprintf("[%s%s]%s[%s]", $start, $para, $value, $end); else return '<marquee scrolldelay=100>'.$value.'</marquee>'; } /***************************************************** * 字符晕光效果包括 glow、shadow和blur * 字符晕光效果[glow=a,b,c]或者[shadow=a,b,c] * 3个参数允许缺省 * 实现文字阴影特效, * glow, shadow,blur 属性依次为颜色、宽度和边界大小 * wave 属性依次为变形频率、宽度和边界大小 *****************************************************/ function CSSStyle(&$start, &$para, &$end, &$value){ $rets= sprintf("[%s%s]%s[%s]", $start, $para, $value, $end); if (strlen($para)==0) { $para="=,,"; } if (eregi("^=([#]?[[:xdigit:]]{6}|[a-z0-9]*),([0-9]*),([0-9]*)", $para, $er_arr)) { $color= ($er_arr[1] != "") ? $er_arr[1] : red; // Default Color $width= ($er_arr[2] != "") ? $er_arr[2] : 400; // Default Width $border= ($er_arr[3] != "") ? $er_arr[3] : 5; // Default Border switch ($start) { case "glow": case "shadow": $rets= sprintf("<font style=\"FILTER: %s(Color =%s,Strength=%s); width:%s\">%s</font>", $start, $color, $border, $width, $value); break; case "blur"; $rets= sprintf("<font style=\"FILTER: %s(Strength=%s);color:%s; width:%s\">%s</font>", $start, $border, $color, $width, $value); break; case "wave": $color= ($er_arr[1] != "") ? $er_arr[1] : 4; // Default Color $border= ($er_arr[3] != "") ? $er_arr[3] : 2; // Default Border $rets= sprintf("<font style=\"FILTER: %s(Freq=%s, Strength=%s); width:%s\">%s</font>", $start, $color, $border, $width, $value); break; } } return $rets; }
/***************************************************** * 字体颜色 [color=n]xxx[/color] * n 可以是 #xxxxxx 或者 xxxxxx (6位16进制数) * red,greed,blue,black等颜色保留字也有效 * 等效与html的<font color=n>xxx</font> * [color]xxxx[/color]等效于 [color=red] *****************************************************/ function color($start, $para, $end, $value){ $cl= strtolower(substr($para, 1)); if ($cl == "") $cl= "red"; if (eregi("(^[#]?[[:xdigit:]]{6})|red|green|blue|yellow|blue|white|gray|brown" ,$cl)) return sprintf("<font color=%s>%s</font>",$cl, $value); else return sprintf("[%s%s]%s[%s]", $start, $para, $value, $end); } /***************************************************** * 字体大小 [size=n]xxx[/size] 1<= n <= 7; * 等效与html的<font size=n>xxx</font> *****************************************************/ function size($start, $para, $end, $value){ $size= substr($para, 1); if ($size >=1 && $size <=7 && (strlen($para) > 1)) return sprintf("<font size=%s>%s</font>",$size, $value); else return sprintf("[%s%s]%s[%s]", $start, $para, $value, $end); }
/***************************************************** * 字体名字 [face=n] n字体名称,不需要引号 * 等效与html的<font face=n>xxx</font> *****************************************************/ function face($start, $para, $end, $value){ $fn= substr($para, 1); if (!eregi("[[:punct:]]", $fn) && strlen($para) > 1) { switch (strtoupper($fn)) { case "ST": $fn= "宋体"; break; case "HT": $fn= "黑体"; break; case "KT": $fn= "楷体_GB2312"; break; case "FT": $fn= "仿宋_GB2312"; break; case "YY": $fn= "幼圆"; break; case "LS": $fn= "隶书"; break; } return sprintf("<font face=\"%s\">%s</font>",$fn, $value); } else return sprintf("[%s%s]%s[%s]", $start, $para, $value, $end); } /***************************************************** * 返回UBB解释器的版本和最后修改日期 *****************************************************/ function GetUBBVer(&$sVer, &$sLastMod) { $sVer= sVersion; $sLastMod= $this->$sLastModified; return $sVer; } }
/**************************** UPDATE LOG ********************************* 2001.12.31 实现基本完整的UBB标签支持功能 增加对若干标签的支持,比如face, size, color等 2001.01.04 增加了对图片URL的扩展名称检查,支持gif,bmp,pcx,tiff,png,jpg,jpeg,tga,lwf文件 增加了自动补全URL协议部分的函数,支持http,fpt,gopher,finger,bbs,telnet等等 允许\\和//的等效, 2002.01.07 修改了[face=]的显示错误,增加中文字体缩写 2002.01.08 完善了[glow]标签函数,增加了默认值,允许函数有缺省 增加了[shadow]标签,使用方法和[glow]类似,并允许叠加效果 2002.01.09 增加了[wave][blur]标签函数, 使用方法和[glow]类似,并允许叠加效果 2002.01.15 修改了正则表达式的匹配字符串,因为[URL=xxxx] 可能出现=_"'等这些字符, 但是使用[url]xxxxx[/url]就不会有问题,原来没考虑到; FormatURL增加了对mms协议的支持,现在media player的格式很多; 增加版本函数,可以返回UBB解释器的版本和最后修改日期 **************************************************************************/ ?>
<?php //测试 include ("./ubbcode.php"); printf("<html>\n"); echo "<head><title>UBB代码测试</title></head>\n"; echo "<body style =\"FONT-SIZE: 9pt; FONT-FAMILY: 宋体\">\n"; echo "<marquee scrolldelay=20>UBB表达式测试页</marquee>\n"; $ubbcode = new ubbcode(); $ubbcode->GetUBBVer($sVer, $sLastMod); printf("<br>\n 版本:%s<br>\n最后修订日期:%s<br>", $sVer, $sLastMod); echo "<form action=".($PATH_INFO)." method=post>\n"; echo "<textarea name=ubb style=\"width:95%; height:140px\">".stripslashes($ubb)."</textarea><br>\n"; echo "<input type=submit value=转换>\n"; echo "</form>\n"; if(isset($ubb)){ echo "<hr>\n".$ubbcode->parse(stripslashes(nl2br($ubb))); } echo "</body>\n"; echo "</html>\n"; ?> 大家可在这里测试效果 http://our93611.51.net/ubb/ubb.php 这里时说明 http://our93611.51.net/ubb/ubbintro.htm 按照写个规则,大家很容易写出来支持flash,mid,wma等等的新的ubb函数。 |