一个改进的UBB类

  1   
  2/*   
  3如有转载,请注明作者   
  4  
  5原作者: 何志强   
  6改进: SonyMusic[ [email protected] ]   
  7文件: ubb.php   
  8备注: 说是改进,其实核心函数parse()已经完全重写了,而且思路也是不一样的。   
  9不过仍是受何志强的例子的启发,而且测试的例子还有URLCHECK等几个函数也是沿用的何志强的程序,谢谢何志强。   
 10目前还没有颜色的功能,但我会加入的。   
 11如果在程序上有什么BUG或不便的地方,请给我MAIL。   
 12谢谢!   
 13改进功能:   
 14对字符串进行UBB编码,该类目前只支持下列几个简单且实用的编码:   
 151\. URL裢接   
 16[url] http://phpuser.com/ [/url]   
 17http://头可以不需要   
 18如[url]phpuser.com[/url]也是可以的。   
 192\. Email裢接   
 20[email] [email protected] [/email]   
 213\. 图片裢接   
 22[img] http://www.phpchina.com/images/logo.gif [/img]   
 23同URL链接一样,前面的http也可以不要。   
 244\. 文字方面   
 25[b]粗体字[/b]   
 26[i]斜体字[/i]   
 27[u]加下划线[/u]   
 28[h1]1号标题字[/h1] ... [h6]6号标题字[/h6]   
 29[sup][/sup]   
 30[sub][/sub]   
 31[tt][/tt]   
 32[s][/s]   
 33[strike][/strike]   
 34[em][/em]   
 35[strong][/strong]   
 36[code][/code]   
 37[samp][/samp]   
 38[kbd][/kbd]   
 39[var][/var]   
 40[dfn][/dfn]   
 41[cite][/cite]   
 42[small][/small]   
 43[big][/big]   
 44[blink][/blink]   
 45注意以下几点:   
 461\. url,email,img等标签是不分大小写的.   
 472\. 在标签中不允许有TAB键出现,但空格允许。   
 483\. 该类要调用htmlencode,htmlencode4textarea,emailcheck函数和urlcheck类.   
 494\. 修改后支持嵌套,但url,email,img这三个标签不是允许嵌套的。   
 50技术资料:   
 51Ultimate Bulletin Board   
 52http://www.ultimatebb.com/   
 53What is UBB Code   
 54http://www.scriptkeeper.com/ubb/ubbcode.html   
 55*/   
 56  
 57include("urlcheck.php");   
 58include("otherfunc.php"); //这两个文件的内容,附在最后。   
 59  
 60//ubbcode类   
 61class ubbcode{   
 62var $call_time=0;   
 63//可处理标签及处理函数对应表   
 64var $tags = array( //小写的标签 => 对应的处理函数   
 65'url' => '$this->url',   
 66'email' => '$this->email',   
 67'img' => '$this->img',   
 68'b' => '$this->simple',   
 69'i' => '$this->simple',   
 70'u' => '$this->simple',   
 71'tt' => '$this->simple',   
 72's' => '$this->simple',   
 73'strike' => '$this->simple',   
 74'h1' => '$this->simple',   
 75'h2' => '$this->simple',   
 76'h3' => '$this->simple',   
 77'h4' => '$this->simple',   
 78'h5' => '$this->simple',   
 79'h6' => '$this->simple',   
 80'sup' => '$this->simple',   
 81'sub' => '$this->simple',   
 82'em' => '$this->simple',   
 83'strong' => '$this->simple',   
 84'code' => '$this->simple',   
 85'samp' => '$this->simple',   
 86'kbd' => '$this->simple',   
 87'var' => '$this->simple',   
 88'dfn' => '$this->simple',   
 89'cite' => '$this->simple',   
 90'small' => '$this->simple',   
 91'big' => '$this->simple',   
 92'blink' => '$this->simple'   
 93);   
 94//url裢接属性   
 95var $attr_url;   
 96//url合法性检查对象   
 97var $urlcheck;   
 98  
 99function ubbcode($attr_url){   
100$this->attr_url = ''.$attr_url;   
101$this->urlcheck = new urlcheck();   
102}   
103  
104//对$str进行UBB编码解析   
105function parse($str){   
106$this->call_time++;   
107$parse = ''.htmlencode($str);   
108  
109$ret = '';   
110while(true){   
111$eregi_ret=eregi("[[#]{0,1}[[:alnum:]]{1,7}]",$parse,$eregi_arr); //查找[xx]   
112if(!$eregi_ret){   
113$ret .= $parse;   
114break; //如果没有,返回   
115}   
116$pos = @strpos ($parse,$eregi_arr[0]);   
117$tag_len=strlen($eregi_arr[0])-2;//标记长度   
118$tag_start=substr($eregi_arr[0],1,$tag_len);   
119$tag=strtolower($tag_start);   
120  
121if((($tag=="url") or ($tag=="email") or ($tag=="img")) and ($this->call_time>1)){   
122echo $this->call_time."

<br/>

1";   
2return $parse;//如果不能是不能嵌套的标记,直接返回   
3}   
4  
5$parse2 = substr($parse,0,$pos);//标记之前   
6$parse = substr($parse,$pos+$tag_len+2);//标记之后   
7if(!isset($this->tags[$tag])){   
8echo "$tag_start

<br/>

 1";   
 2$ret .= $parse2.'['.$tag_start.']';   
 3continue;//如果是不支持的标记   
 4}   
 5  
 6//查找对对应的结束标记   
 7$eregi_ret=eregi("[/".$tag."]",$parse,$eregi_arr);   
 8if(!$eregi_ret){   
 9$ret .= $parse2.'['.$tag_start.']';   
10continue;//如果没有对应该的结束标记   
11}   
12$pos=strpos($parse,$eregi_arr[0]);   
13$value=substr($parse,0,$pos);//这是起止标记之间的内容   
14$tag_end=substr($parse,$pos+2,$tag_len);   
15$parse=substr($parse,$pos+$tag_len+3);//结束标记之后的内容   
16  
17if(($tag!="url") and ($tag!="email") and ($tag!="img")){   
18$value=$this->parse($value);   
19}   
20  
21$ret .= $parse2;   
22eval('$ret .= '.$this->tags[$tag].'("'.$tag_start.'","'.$tag_end.'","'.$value.'");');   
23}   
24$this->call_time--;   
25return $ret;   
26}   
27  
28function simple($start,$end,$value){   
29return '<'.$start.'>'.$value.'
30<!--'.$end.'-->
31';   
32}   
33  
34function url($start,$end,$value){   
35$trim_value=trim($value);   
36if (strtolower(substr($trim_value,0,7))!="http://")   
37$trim_value="http://".$trim_value;   
38if($this->urlcheck->check($trim_value)) return '

<a '.$this-="" href="'.$trim_value.'">attr_url.'&gt;'.$value.'</a>

1';   
2else return '['.$start.']'.$value.'[/'.$end.']';   
3}   
4  
5function email($start,$end,$value){   
6if(emailcheck($value)) return '

<a href="mailto:'.$value.'">'.$value.'</a>

1';   
2else return '['.$start.']'.$value.'[/'.$end.']';   
3}   
4  
5function img($start,$end,$value){   
6$trim_value=trim($value);   
7if ((strtolower(substr($trim_value,0,7))!="http://") or ($this->urlcheck->check($trim_value)))   
8return '

<img src="'.$trim_value.'"/>

1';   
2else return '['.$start.']'.$value.'[/'.$end.']';   
3}   
4}   
5  
6//测试   
7echo '

<html>';
echo '<head><title>测试</title></head>';
echo '<body>';
echo '<form action="'.str2url($PATH_INFO).'" method="post">';
echo '<textarea cols="100" name="ubb" rows="10">'.htmlencode4textarea($ubb).'</textarea><br/>';
echo '<input type="submit" value="转换"/>';
echo '</form>';

if(isset($ubb)){
$ubbcode = new ubbcode('target="_blank"');
echo '<hr/>'.$ubbcode-&gt;parse($ubb);
}

echo '</body>';
echo '</html>

1';   
2  

文件urlcheck.php的内容:

  1   
  2//urlcheck.php   
  3class urlcheck{   
  4var $regex = array(//协议名(注意在这里必须写成小写) => 对应的正则表达式   
  5'ftp' => '$this->ftpurl',   
  6'file' => '$this->fileurl',   
  7'http' => '$this->httpurl',   
  8'https' => '$this->httpurl',   
  9'gopher' => '$this->gopherurl',   
 10'news' => '$this->newsurl',   
 11'nntp' => '$this->nntpurl',   
 12'telnet' => '$this->telneturl',   
 13'wais' => '$this->waisurl'   
 14);   
 15  
 16var $lowalpha;   
 17var $hialpha;   
 18var $alpha;   
 19var $digit;   
 20var $safe;   
 21var $extra;   
 22var $national;   
 23var $punctuation;   
 24var $reserved;   
 25var $hex;   
 26var $escape;   
 27var $unreserved;   
 28var $uchar;   
 29var $xchar;   
 30var $digits;   
 31  
 32var $urlpath;   
 33var $password;   
 34var $user;   
 35var $port;   
 36var $hostnumber;   
 37var $alphadigit;   
 38var $toplabel;   
 39var $domainlabel;   
 40var $hostname;   
 41var $host;   
 42var $hostport;   
 43var $login;   
 44  
 45//ftp   
 46var $ftptype;   
 47var $fsegment;   
 48var $fpath;   
 49var $ftpurl;   
 50  
 51//file   
 52var $fileurl;   
 53  
 54//http,https   
 55var $search;   
 56var $hsegment;   
 57var $hpath;   
 58var $httpurl;   
 59  
 60//gopher   
 61var $gopher_string;   
 62var $selector;   
 63var $gtype;   
 64var $gopherurl;   
 65  
 66//news   
 67var $article;   
 68var $group;   
 69var $grouppart;   
 70var $newsurl;   
 71  
 72//nntp   
 73var $nntpurl;   
 74  
 75//telnet   
 76var $telneturl;   
 77  
 78//wais   
 79var $wpath;   
 80var $wtype;   
 81var $database;   
 82var $waisdoc;   
 83var $waisindex;   
 84var $waisdatabase;   
 85var $waisurl;   
 86  
 87function check($url){   
 88$pos = @strpos ($url,':',1);   
 89if($pos<1) return false;   
 90$prot = substr($url,0,$pos);   
 91if(!isset($this->regex[$prot])) return false;   
 92eval('$regex = '.$this->regex[$prot].';');   
 93return ereg('^'.$regex.'$',$url);   
 94}   
 95  
 96function urlcheck(){   
 97$this->lowalpha = '[a-z]';   
 98$this->hialpha = '[A-Z]';   
 99$this->alpha = '('.$this->lowalpha.'|'.$this->hialpha.')';   
100$this->digit = '[0-9]';   
101$this->safe = '[$.+_-]';   
102$this->extra = '[*()'!,]';   
103$this->national = '([{}|^~`]|\\[|\\])';   
104$this->punctuation = '[<>#%"]';   
105$this->reserved = '[?;/: @&= ]';   
106$this->hex = '('.$this->digit.'|[a-fA-F])';   
107$this->escape = '(%'.$this->hex.'{2})';   
108$this->unreserved = '('.$this->alpha.'|'.$this->digit.'|'.$this->safe.'|'.$this->extra.')';   
109$this->uchar = '('.$this->unreserved.'|'.$this->escape.')';   
110$this->xchar = '('.$this->unreserved.'|'.$this->reserved.'|'.$this->escape.')';   
111$this->digits = '('.$this->digit.'+)';   
112  
113$this->urlpath = '('.$this->xchar.'*)';   
114$this->password = '(('.$this->uchar.'|[?;&=]'.')*)';   
115$this->user = '(('.$this->uchar.'|[?;&=]'.')*)';   
116$this->port = $this->digits;   
117$this->hostnumber = '('.$this->digits.'.'.$this->digits.'.'.$this->digits.'.'.$this->digits.')';   
118$this->alphadigit = '('.$this->alpha.'|'.$this->digit.')';   
119$this->toplabel = '('.$this->alpha.'|('.$this->alpha.'('.$this->alphadigit.'|-)*'.$this->alphadigit.'))';   
120$this->domainlabel = '('.$this->alphadigit.'|('.$this->alphadigit.'('.$this->alphadigit.'|-)*'.$this->alphadigit.'))';   
121$this->hostname = '(('.$this->domainlabel.'\\.)*'.$this->toplabel.')';   
122$this->host = '('.$this->hostname.'|'.$this->hostnumber.')';   
123$this->hostport = '('.$this->host.'(:'.$this->port.')?)';   
124$this->login = '(('.$this->user.'(:'.$this->password.')?@)?'.$this->hostport.')';   
125  
126$this->ftptype = '[aidAID]';   
127$this->fsegment = '(('.$this->uchar.'|[?: @&= ])*)';   
128$this->fpath = '('.$this->fsegment.'(/'.$this->fsegment.')*)';   
129$this->ftpurl = '([fF][tT][pP]://'.$this->login.'(/'.$this->fpath.'(;[tT][yY][pP][eE]='.$this->ftptype.')?)?)';   
130  
131$this->fileurl = '([fF][iI][lL][eE]://('.$this->host.'|[lL][oO][cC][aA][lL][hH][oO][sS][tT])?/'.$this->fpath.')';   
132  
133$this->search = '(('.$this->uchar.'|[;: @&= ])*)';   
134$this->hsegment = '(('.$this->uchar.'|[;: @&= ])*)';   
135$this->hpath = '('.$this->hsegment.'(/'.$this->hsegment.')*)';   
136$this->httpurl = '([hH][tT][tT][pP][sS]?://'.$this->hostport.'(/'.$this->hpath.'([?]'.$this->search.')?)?)';   
137  
138$this->gopher_string = '('.$this->xchar.'*)';   
139$this->selector = '('.$this->xchar.'*)';   
140$this->gtype = $this->xchar;   
141$this->gopherurl = '([gG][oO][pP][hH][eE][rR]://'.$this->hostport.'(/('.$this->gtype.'('.$this->selector.'(%09'.$this->search.'(%09'.$this->gopher_string.')?)?)?)?)?)';   
142  
143$this->article = '(('.$this->uchar.'|[;/?:&=]) +@'.$this- >host.')';   
144$this->group = '('.$this->alpha.'('.$this->alpha.'|'.$this->digit.'|[-.+_])*)';   
145$this->grouppart = '([*]|'.$this->group.'|'.$this->article.')';   
146$this->newsurl = '([nN][eE][wW][sS]:'.$this->grouppart.')';   
147  
148$this->nntpurl = '([nN][nN][tT][pP]://'.$this->hostport.'/'.$this->group.'(/'.$this->digits.')?)';   
149  
150$this->telneturl = '([tT][eE][lL][nN][eE][tT]://'.$this->login.'/?)';   
151  
152$this->wpath = '('.$this->uchar.'*)';   
153$this->wtype = '('.$this->uchar.'*)';   
154$this->database = '('.$this->uchar.'*)';   
155$this->waisdoc = '([wW][aA][iI][sS]://'.$this->hostport.'/'.$this->database.'/'.$this->wtype.'/'.$this->wpath.')';   
156$this->waisindex = '([wW][aA][iI][sS]://'.$this->hostport.'/'.$this->database.'[?]'$this->search.')';   
157$this->waisdatabase = '([wW][aA][iI][sS]://'.$this->hostport.'/'.$this->database.')';   
158$this->waisurl = '('.$this->waisdatabase.'|'.$this->waisindex.'|'.$this->waisdoc.')';   
159}   
160}   
161  

文件otherfunc.php的内容:

 1   
 2//otherfunc.php   
 3function htmlencode($str){   
 4$str = (string)$str;   
 5  
 6$ret = '';   
 7$len = strlen($str);   
 8$nl = false;   
 9for($i=0;$i<$len;$i++){   
10$chr = $str[$i];   
11switch($chr){   
12case '<':   
13$ret .= '<';   
14$nl = false;   
15break;   
16case '>':   
17$ret .= '>';   
18$nl = false;   
19break;   
20case '"':   
21$ret .= '"';   
22$nl = false;   
23break;   
24case '&':   
25$ret .= '&';   
26$nl = false;   
27break;   
28/*   
29case ' ':   
30$ret .= ' ';   
31$nl = false;   
32break;   
33*/   
34case chr(9):   
35$ret .= '    ';   
36$nl = false;   
37break;   
38case chr(10):   
39if($nl) $nl = false;   
40else{   
41$ret .= '

<br/>

1';   
2$nl = true;   
3}   
4break;   
5case chr(13):   
6if($nl) $nl = false;   
7else{   
8$ret .= '

<br/>

 1';   
 2$nl = true;   
 3}   
 4break;   
 5default:   
 6$ret .= $chr;   
 7$nl = false;   
 8break;   
 9}   
10}   
11  
12return $ret;   
13}   
14  
15  
16function htmlencode4textarea($str){   
17$str = (string)$str;   
18  
19$ret = '';   
20$len = strlen($str);   
21for($i=0;$i<$len;$i++){   
22$chr = $str[$i];   
23switch($chr){   
24case '<':   
25$ret .= '<';   
26break;   
27case '>':   
28$ret .= '>';   
29break;   
30case '"':   
31$ret .= '"';   
32break;   
33case '&':   
34$ret .= '&';   
35break;   
36case ' ':   
37$ret .= ' ';   
38break;   
39case chr(9):   
40$ret .= '    ';   
41break;   
42default:   
43$ret .= $chr;   
44break;   
45}   
46}   
47  
48return $ret;   
49}   
50  
51function emailcheck($email){   
52$ret=false;   
53if(strstr($email, '@' ) && strstr($email, '.')){   
54if(eregi("^([_a-z0-9]+([\\._a-z0-9-]+)*)@([a-z0-9]{2,}(\\.[a-z0-9-]{2,})*\\.[a-z]{2,3})$", $email)){   
55$ret=true;   
56}   
57}   
58return $ret;   
59}   
60  
61function str2url($path){   
62return eregi_replace("%2f","/",urlencode($path));   
63}   
Published At
Categories with Web编程
Tagged with
comments powered by Disqus