聚會時間公告: 因應COSCUP 2011, Kalug 8月份休會一次

六月 30, 2010

小惡魔AppleBOY
AppleBOY
小惡魔 – 電腦技術 – 工作筆記 – AppleBOY is about »

tag cloud

» [phpBB3] BBCode [url] Tag 支援中文網址

在 phpBB2 的時候就有發現這問題了,當時並沒有想去解決這問題,然而至今到了 phpBB3,依然出現這問題,不過我想這是因為中文網址的盛行,以及像 Wiki 之類都會有中文標籤,例如:一分鐘教室-userChrome.css,解決方法可以透過 urlencode 函式來處理掉網址編碼問題,在 phpBB 處理文章儲存,會先經過 bbcode 的處理,將 [b] [url] [img] 等標籤,加上一組 bbcode uid 來代表這篇文章所使用的全部 bbcode tag,整理文章處理過程如下

1. 開始找尋文章內容之 [b] [url] [img] … 等 Tag

$this->bbcodes = array(
    'code'          => array('bbcode_id' => 8,  'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#ise' => "\$this->bbcode_code('\$1', '\$2')")),
    'quote'         => array('bbcode_id' => 0,  'regexp' => array('#\[quote(?:="(.*?)")?\](.+)\[/quote\]#ise' => "\$this->bbcode_quote('\$0')")),
    'attachment'    => array('bbcode_id' => 12, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#ise' => "\$this->bbcode_attachment('\$1', '\$2')")),
    'b'             => array('bbcode_id' => 1,  'regexp' => array('#\[b\](.*?)\[/b\]#ise' => "\$this->bbcode_strong('\$1')")),
    'i'             => array('bbcode_id' => 2,  'regexp' => array('#\[i\](.*?)\[/i\]#ise' => "\$this->bbcode_italic('\$1')")),
    'url'           => array('bbcode_id' => 3,  'regexp' => array('#\[url(=(.*))?\](.*)\[/url\]#iUe' => "\$this->validate_url('\$2', '\$3')")),
    'img'           => array('bbcode_id' => 4,  'regexp' => array('#\[img\](.*)\[/img\]#iUe' => "\$this->bbcode_img('\$1')")),
    'size'          => array('bbcode_id' => 5,  'regexp' => array('#\[size=([\-\+]?\d+)\](.*?)\[/size\]#ise' => "\$this->bbcode_size('\$1', '\$2')")),
    'color'         => array('bbcode_id' => 6,  'regexp' => array('!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!ise' => "\$this->bbcode_color('\$1', '\$2')")),
    'u'             => array('bbcode_id' => 7,  'regexp' => array('#\[u\](.*?)\[/u\]#ise' => "\$this->bbcode_underline('\$1')")),
    'list'          => array('bbcode_id' => 9,  'regexp' => array('#\[list(?:=(?:[a-z0-9]|disc|circle|square))?].*\[/list]#ise' => "\$this->bbcode_parse_list('\$0')")),
    'email'         => array('bbcode_id' => 10, 'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#ise' => "\$this->validate_email('\$1', '\$2')")),
    'flash'         => array('bbcode_id' => 11, 'regexp' => array('#\[flash=([0-9]+),([0-9]+)\](.*?)\[/flash\]#ie' => "\$this->bbcode_flash('\$1', '\$2', '\$3')"))
);

2. 檢查 url, email, html 等驗證,並且轉換成 [url="xxxx":$bbcode_uid] … 等存入資料庫

function bbcode_specialchars($text)
function bbcode_color($stx, $in)
function bbcode_strong($in)
/**
* Parse i tag
*/

function bbcode_italic($in)

…. 等驗證,其中比較要注意的就是 url 驗證函式 function validate_url($var1, $var2),待會仔細祥解。
3. 讀取資料庫將 bbcode 轉換成 html 形式
先讀取 styles/XXXX/template/bbcode.html 檔案,比對文章內容正規語法:

switch ($bbcode_id)
{
    case 0:
        $this->bbcode_cache[$bbcode_id] = array(
            'str' => array(
                '[/quote:$uid]' => $this->bbcode_tpl('quote_close', $bbcode_id)
            ),
            'preg' => array(
                '#\[quote(?:="(.*?)")?:$uid\]((?!\[quote(?:=".*?")?:$uid\]).)?#ise' => "\$this->bbcode_second_pass_quote('\$1', '\$2')"
            )
        );
    break;

    case 1:
        $this->bbcode_cache[$bbcode_id] = array(
            'str' => array(
                '[b:$uid]'  => $this->bbcode_tpl('b_open', $bbcode_id),
                '[/b:$uid]' => $this->bbcode_tpl('b_close', $bbcode_id),
            )
        );
    break;

    case 2:
        $this->bbcode_cache[$bbcode_id] = array(
            'str' => array(
                '[i:$uid]'  => $this->bbcode_tpl('i_open', $bbcode_id),
                '[/i:$uid]' => $this->bbcode_tpl('i_close', $bbcode_id),
            )
        );
    break;

    case 3:
        $this->bbcode_cache[$bbcode_id] = array(
            'preg' => array(
                '#\[url:$uid\]((.*?))\[/url:$uid\]#s'           => $this->bbcode_tpl('url', $bbcode_id),
                '#\[url=([^\[]+?):$uid\](.*?)\[/url:$uid\]#s'   => $this->bbcode_tpl('url', $bbcode_id),
            )
        );
    break;

    case 4:
        if ($user->optionget('viewimg'))
        {
            $this->bbcode_cache[$bbcode_id] = array(
                'preg' => array(
                    '#\[img:$uid\](.*?)\[/img:$uid\]#s'     => $this->bbcode_tpl('img', $bbcode_id),
                )
            );
        }
        else
        {
            $this->bbcode_cache[$bbcode_id] = array(
                'preg' => array(
                    '#\[img:$uid\](.*?)\[/img:$uid\]#s'     => str_replace('$2', '[ img ]', $this->bbcode_tpl('url', $bbcode_id, true)),
                )
            );
        }
    break;

    case 5:
        $this->bbcode_cache[$bbcode_id] = array(
            'preg' => array(
                '#\[size=([\-\+]?\d+):$uid\](.*?)\[/size:$uid\]#s'  => $this->bbcode_tpl('size', $bbcode_id),
            )
        );
    break;

    case 6:
        $this->bbcode_cache[$bbcode_id] = array(
            'preg' => array(
                '!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!is'   => $this->bbcode_tpl('color', $bbcode_id),
            )
        );
    break;

    case 7:
        $this->bbcode_cache[$bbcode_id] = array(
            'str' => array(
                '[u:$uid]'  => $this->bbcode_tpl('u_open', $bbcode_id),
                '[/u:$uid]' => $this->bbcode_tpl('u_close', $bbcode_id),
            )
        );
    break;

    case 8:
        $this->bbcode_cache[$bbcode_id] = array(
            'preg' => array(
                '#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#ise'   => "\$this->bbcode_second_pass_code('\$1', '\$2')",
            )
        );
    break;

    case 9:
        $this->bbcode_cache[$bbcode_id] = array(
            'preg' => array(
                '#(\[\/?(list|\*):[mou]?:?$uid\])[\n]{1}#'  => "\$1",
                '#(\[list=([^\[]+):$uid\])[\n]{1}#'         => "\$1",
                '#\[list=([^\[]+):$uid\]#e'                 => "\$this->bbcode_list('\$1')",
            ),
            'str' => array(
                '[list:$uid]'       => $this->bbcode_tpl('ulist_open_default', $bbcode_id),
                '[/list:u:$uid]'    => $this->bbcode_tpl('ulist_close', $bbcode_id),
                '[/list:o:$uid]'    => $this->bbcode_tpl('olist_close', $bbcode_id),
                '[*:$uid]'          => $this->bbcode_tpl('listitem', $bbcode_id),
                '[/*:$uid]'         => $this->bbcode_tpl('listitem_close', $bbcode_id),
                '[/*:m:$uid]'       => $this->bbcode_tpl('listitem_close', $bbcode_id)
            ),
        );
    break;

    case 10:
        $this->bbcode_cache[$bbcode_id] = array(
            'preg' => array(
                '#\[email:$uid\]((.*?))\[/email:$uid\]#is'          => $this->bbcode_tpl('email', $bbcode_id),
                '#\[email=([^\[]+):$uid\](.*?)\[/email:$uid\]#is'   => $this->bbcode_tpl('email', $bbcode_id)
            )
        );
    break;

    case 11:
        if ($user->optionget('viewflash'))
        {
            $this->bbcode_cache[$bbcode_id] = array(
                'preg' => array(
                    '#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#'    => $this->bbcode_tpl('flash', $bbcode_id),
                )
            );
        }
        else
        {
            $this->bbcode_cache[$bbcode_id] = array(
                'preg' => array(
                    '#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#'    => str_replace('$1', '$3', str_replace('$2', '[ flash ]', $this->bbcode_tpl('url', $bbcode_id, true)))
                )
            );
        }
    break;

    case 12:
        $this->bbcode_cache[$bbcode_id] = array(
            'str'   => array(
                '[/attachment:$uid]'    => $this->bbcode_tpl('inline_attachment_close', $bbcode_id)
            ),
            'preg'  => array(
                '#\[attachment=([0-9]+):$uid\]#'    => $this->bbcode_tpl('inline_attachment_open', $bbcode_id)
            )
        );
    break;

    default:
        if (isset($rowset[$bbcode_id]))
        {
            if ($this->template_bitfield->get($bbcode_id))
            {
                // The bbcode requires a custom template to be loaded
                if (!$bbcode_tpl = $this->bbcode_tpl($rowset[$bbcode_id]['bbcode_tag'], $bbcode_id))
                {
                    // For some reason, the required template seems not to be available, use the default template
                    $bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl'];
                }
                else
                {
                    // In order to use templates with custom bbcodes we need
                    // to replace all {VARS} to corresponding backreferences
                    // Note that backreferences are numbered from bbcode_match
                    if (preg_match_all('/\{(URL|LOCAL_URL|EMAIL|TEXT|SIMPLETEXT|INTTEXT|IDENTIFIER|COLOR|NUMBER)[0-9]*\}/', $rowset[$bbcode_id]['bbcode_match'], $m))
                    {
                        foreach ($m[0] as $i => $tok)
                        {
                            $bbcode_tpl = str_replace($tok, '$' . ($i + 1), $bbcode_tpl);
                        }
                    }
                }
            }
            else
            {
                // Default template
                $bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl'];
            }

            // Replace {L_*} lang strings
            $bbcode_tpl = preg_replace('/{L_([A-Z_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $bbcode_tpl);

            if (!empty($rowset[$bbcode_id]['second_pass_replace']))
            {
                // The custom BBCode requires second-pass pattern replacements
                $this->bbcode_cache[$bbcode_id] = array(
                    'preg' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl)
                );
            }
            else
            {
                $this->bbcode_cache[$bbcode_id] = array(
                    'str' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl)
                );
            }
        }
        else
        {
            $this->bbcode_cache[$bbcode_id] = false;
        }
    break;
}

接下來將 bbcode 轉換成 html,用 bbcode_tpl() 函式即可,這樣就可以完整顯示出文章。

=========== 正文開始 ===========

在驗證文章內容全部 [url(=$var1)]$var2[/url] 標籤,會經過 get_preg_expression(’url’) 這函式的驗證,看 url 是否合法,當然如果網址列有中文就不可能通過,所以必須在網址驗證之前,把網址編碼過,通過驗證之後再把網址解碼,這樣就沒問題了,底下為安裝步驟

打開 includes/message_parser.php

找尋

function validate_url($var1, $var2)

前面加入

/**
*  url encode
*
* @param string $string http url
*/


function encode_url($string)
{
    $entities = array('%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D', '%2B', '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D');
    $replacements = array('!', '*', "'", "(", ")", ";", ":", "@", "&", "=", "+", "$", ",", "/", "?", "%", "#", "[", "]");
    return str_replace($entities, $replacements, urlencode($string));
}

找尋 validate_url 函式

$url = ($var1) ? $var1 : $var2;

後面加入

// encode url
$url = $this->encode_url($url);

找尋

return ($var1) ? '[url=' . $this->bbcode_specialchars($url) . ':' . $this->bbcode_uid . ']' . $var2 . '[/url:' . $this->bbcode_uid . ']' : '[url:' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($url) . '[/url:' . $this->bbcode_uid . ']';

取代

return ($var1) ? '[url=' . $this->bbcode_specialchars($url) . ':' . $this->bbcode_uid . ']' . $var2 . '[/url:' . $this->bbcode_uid . ']' : '[url:' . $this->bbcode_uid . ']' . urldecode($this->bbcode_specialchars($url)) . '[/url:' . $this->bbcode_uid . ']';

測試結果,請參考此網址:Re: 討論區判斷含中文鏈結的 bug

Related View

六月 13, 2010

小惡魔AppleBOY
AppleBOY
小惡魔 – 電腦技術 – 工作筆記 – AppleBOY is about »

tag cloud

» [phpBB3 外掛] 根據使用者文章數目限制簽名檔顯示

前一篇提到:『[教學] phpBB3 使用者簽名檔 url 連結加上 rel=”nofollow”』,本篇會將其做成後台,方便管理者可以從後台管理,這次加上一個新功能:『限制使用者顯示簽名檔』,根據使用者文章數量來決定是否顯示簽名檔,可以避免想要來打廣告的新註冊使用者,限制文章數量是一種方式,但是也不是最好的方式,phpBB3 本身可以在後台限制是否顯示使用者簽名檔,不過我想各大站長都會開放此功能,好讓使用者可以放個人網站或者是部落格,底下是外掛安裝方式:

安裝

打開 includes/acp/acp_board.php

找尋

#
# Find
#
'max_sig_img_height' => array('lang' => 'MAX_SIG_IMG_HEIGHT',        'validate' => 'int:0',  'type' =>    'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),

後面加上

#
# after add
#
'max_sig_post_count_limit' => array('lang' => 'MAX_SIG_POSTS_LIMIT',   'validate' => 'int:0',  'type' =>    'text:5:4', 'explain' => true),

打開 viewtopic.php

找尋

#
# Find
#
if ($row['user_sig'] && $config['allow_sig'] && $user->optionget('viewsigs'))

取代

#
# Replace
#
if (($row['user_sig'] && $config['allow_sig'] && $user->optionget('viewsigs') && $row['user_posts'] >=                               $config['max_sig_post_count_limit']) || (isset($user->data['session_admin']) && $user->data['session_admin']))

中文化

打開 language/zh_cmn_hant/acp/board.php

找尋

#
# Find
#
'MAX_SIG_URLS_EXPLAIN' => '會員簽名檔中允許的最多連結數量。設定為 0,表示沒有限制。',

後面加上

#
# after add
#
'MAX_SIG_POSTS_LIMIT' => '簽名檔顯示與否',
'MAX_SIG_POSTS_LIMIT_EXPLAIN' => '會員文章數量超過多少才會顯示。設定為 0,表示沒有限制。',

請先參考 [教學] phpBB3 使用者簽名檔 url 連結加上 rel=”nofollow”,在依照底下安裝改成後台

安裝

打開 includes/acp/acp_board.php

找尋

#
# Find
#
'allow_sig_links' => array('lang' => 'ALLOW_SIG_LINKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),

後面加上

#
# after add
#
'allow_sig_nofollow' => array('lang' => 'ALLOW_SIG_NOFOLLOW', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),

打開 viewtopic.php

找尋

#
# Find
#
$bbcode->bbcode_second_pass($user_cache[$poster_id]['sig'], $user_cache[$poster_id]['sig_bbcode_uid'], $user_cache[$poster_id]['sig_bbcode_bitfield'], true);

取代

#
# Replace
#
$check = ($config['allow_sig_nofollow']) ? true : false;
$bbcode->bbcode_second_pass($user_cache[$poster_id]['sig'], $user_cache[$poster_id]['sig_bbcode_uid'], $user_cache[$poster_id]['sig_bbcode_bitfield'], $check);

中文化

打開 language/zh_cmn_hant/acp/board.php

找尋

#
# Find
#
'ALLOW_SIG_SMILIES' => '允許在會員簽名檔中使用表情符號',

後面加上

#
# after add
#
'ALLOW_SIG_NOFOLLOW' => '增加會員簽名檔中網址連結設定 rel="nofollow"',

展示圖:
phpBB3_02
phpBB3_01
phpBB3_03

Related View

六月 10, 2010

小惡魔AppleBOY
AppleBOY
小惡魔 – 電腦技術 – 工作筆記 – AppleBOY is about »

tag cloud

» [教學] phpBB3 使用者簽名檔 url 連結加上 rel=”nofollow”

基於 Moztw 討論區 有大陸使用者註冊之後,在簽名檔加入一些廣告連結,為了降低 Google Page Rank,所以我們必須指示搜尋引擎「不要前往此網頁上的連結」或是「不要前往此連結」,可以參考 關於 rel=”nofollow”phpBB3 編輯三個檔案就可以了,此修改不影響文章內容,只有針對簽名檔作用,底下是 patch 程式碼,可以參考看看

includes/bbcode.php

--- phpBB3/includes/bbcode.php  2010-03-06 04:37:23.000000000 +0800
+++ www/includes/bbcode.php     2010-06-10 20:58:02.000000000 +0800
@@ -2,7 +2,8 @@
 /**
 *
 * @package phpBB3
-* @version $Id$
+* @version $Id: bbcode.php 9461 2009-04-17 15:23:17Z acydburn $
+* @log 2010-06-10 appleboy $
 * @copyright (c) 2005 phpBB Group
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 *
@@ -48,7 +49,7 @@
        /**
        * Second pass bbcodes
        */
-       function bbcode_second_pass(&$message, $bbcode_uid = '', $bbcode_bitfield = false)
+       function bbcode_second_pass(&$message, $bbcode_uid = '', $bbcode_bitfield = false, $bbcode_is_sig = false)
        {
                if ($bbcode_uid)
                {
@@ -110,6 +111,13 @@
                                                }

                                                $message = preg_replace($preg['search'], $preg['replace'], $message);
+
+                                               /*
+                                                * 2010.06.10 add search nofollow module by appleboy
+                                                */
+                                               $replace = ($bbcode_is_sig === true) ? 'rel="external nofollow"' : '';
+                                               $message = preg_replace("/\{NOFOLLOW\}/i", $replace, $message);
+
                                                $preg = array('search' => array(), 'replace' => array());
                                        }
                                }

styles/Moztw-2009-1.0.6/template/bbcode.html

--- phpBB3/styles/subsilver2/template/bbcode.html       2010-03-06 04:37:24.000000000 +0800
+++ www/styles/Moztw-2009-1.0.6/template/bbcode.html    2010-06-10 17:20:32.000000000 +0800
@@ -52,7 +52,7 @@

 <!-- BEGIN img --><img src="{URL}" alt="{L_IMAGE}" /><!-- END img -->

-<!-- BEGIN url --><a href="{URL}" class="postlink">{DESCRIPTION}</a><!-- END url -->
+<!-- BEGIN url --><a href="{URL}" class="postlink" {NOFOLLOW}>{DESCRIPTION}</a><!-- END url -->

 <!-- BEGIN email --><a href="mailto:{EMAIL}">{DESCRIPTION}</a><!-- END email -->

www/viewtopic.php

--- phpBB3/viewtopic.php        2010-03-06 04:37:23.000000000 +0800
+++ www/viewtopic.php   2010-06-10 20:27:06.000000000 +0800
@@ -1342,7 +1278,8 @@

                if ($user_cache[$poster_id]['sig_bbcode_bitfield'])
                {
-                       $bbcode->bbcode_second_pass($user_cache[$poster_id]['sig'], $user_cache[$poster_id]['sig_bbcode_uid'], $user_cache[$pos
ter_id]['sig_bbcode_bitfield']);
+                       // 2010.06.10 add search nofollow module by appleboy
+                       $bbcode->bbcode_second_pass($user_cache[$poster_id]['sig'], $user_cache[$poster_id]['sig_bbcode_uid'], $user_cache[$pos
ter_id]['sig_bbcode_bitfield'], true);
                }

                $user_cache[$poster_id]['sig'] = bbcode_nl2br($user_cache[$poster_id]['sig']);

Related View

support:

biggo.com.tw

A Django site.