1<?php
2/**
3 * <text> tag that embeds plain text with linebreaks
4 */
5
6// must be run within Dokuwiki
7if(!defined('DOKU_INC')) die();
8
9/**
10 * All DokuWiki plugins to extend the parser/rendering mechanism
11 * need to inherit from this class
12 */
13class syntax_plugin_bbs extends DokuWiki_Syntax_Plugin {
14
15    function getType() { return 'protected';}
16    function getPType() { return 'normal';}
17    function getSort() { return 20; }
18
19    /**
20     * Connect pattern to lexer
21     */
22    function connectTo($mode) {
23        $this->Lexer->addSpecialPattern('<bbs>.*?</bbs>', $mode, 'plugin_bbs');
24    }
25
26    /**
27     * Handle the match
28     */
29    function handle($match, $state, $pos, &$handler){
30        return substr($match,5,-6);
31    }
32
33    /**
34     * Create output
35     */
36    function render($format, &$renderer, $data) {
37        if($format == 'xhtml'){
38            $data = trim( $renderer->_xmlEntities($data), "\n");
39            $data = $this->_parse_bbs($data);
40            $renderer->doc .= "<pre class=\"bbs\">".DOKU_LF;
41            $renderer->doc .= $data.DOKU_LF;
42            $renderer->doc .= "</pre>".DOKU_LF;
43            return true;
44        }else if($format == 'metadata'){
45            $data = $this->_parse_bbs_metadata($data);
46            $renderer->doc .= $data.DOKU_LF;
47            return true;
48        }
49        return false;
50    }
51
52    function _parse_bbs($s) {
53        $this->tags = array();
54        $s = preg_replace( "/\x1B/", '&#27;', $s);
55        // UAO to unicode
56        $s = preg_replace_callback( "/[\x{E024}-\x{F848}]/u", array($this,"_bbs_uao_to_unicode"), $s);
57        // Special formats: : text, > text, ※text
58        $s = preg_replace( "/^((?::|&gt;)(?: |&nbsp;).*)$/m", '&#27;[0;36m$1&#27;[m', $s );
59        $s = preg_replace( "/^(※.*)$/m", '&#27;[0;32m$1&#27;[m', $s );
60        // Control codes
61        $s = preg_replace_callback( "/&#27;\[([0-9;]*)(.)/", array($this,"_bbs_parse_tag"), $s );
62        // Links
63        $s = preg_replace_callback( "/(https?|ftp|telnet):\/\/(?:<.*?>|.)*?(?= |\n|$)/", array($this,"_bbs_parse_link"), $s );
64        return $s;
65    }
66
67    function _parse_bbs_metadata($s) {
68        $s = preg_replace( "/\x1B/", '&#27;', $s);
69        // UAO to unicode
70        $s = preg_replace_callback( "/[\x{E024}-\x{F848}]/u", array($this,"_bbs_uao_to_unicode"), $s);
71        // Control codes
72        $s = preg_replace( "/&#27;\[([0-9;]*)(.)/", "", $s );
73        return $s;
74    }
75
76    function _bbs_parse_tag($match) {
77        if ($match[2]!='m') return '';
78        $this->ret = '';
79        $args = explode(';',$match[1]);
80        if (empty($args)) {
81            $this->_bbs_close_tag();
82            return $this->ret;
83        }
84        for ($i=0,$I=count($args);$i<$I;++$i) {
85            $s = (int)$args[$i];
86            if ($s==0) {
87                $this->_bbs_add_tag();
88                $this->_bbs_close_tag();
89            }
90            else if ($s==1) {$this->tags[bright] = true;}
91            else if ($s==3) {$this->tags[italic] = true;}
92            else if ($s==5) {$this->tags[blink] = true;}
93            else if ($s==8) {$this->tags[hidden] = true;}
94            else if ($s>=30 && $s<=37) {$this->tags[fg] = $s;}
95            else if ($s>=40 && $s<=47) {$this->tags[bg] = $s;}
96        }
97        $this->_bbs_add_tag();
98        return $this->ret;
99    }
100
101    function _bbs_add_tag() {
102        $c = array();
103        if ($this->tags[fg]) $c[] = ($this->tags[bright]?'fgb':'fgd').$this->tags[fg];
104        if ($this->tags[bg]) $c[] = 'bg'.$this->tags[bg];
105        if ($this->tags[italic]) $c[] = 'italic';
106        if ($this->tags[blink]) $c[] = 'blink';
107        if ($this->tags[hidden]) $c[] = 'hidden';
108        if (!empty($c)) {
109            $this->ret .= '<span class="' . implode(' ', $c) . '">';
110            $this->tags[count]++;
111        }
112    }
113
114    function _bbs_close_tag() {
115        $count = $this->tags[count];
116        if ($count) $this->ret .= str_repeat( '</span>', $count+1 );
117        $this->tags = array();
118    }
119
120    function _bbs_parse_link($match) {
121        $url = preg_replace( "/<.*?>/", '', $match[0]);
122        return '<a class="' . $match[1] . '" href="' . $url . '">' . $match[0] . '</a>';
123    }
124
125    function _bbs_uao_to_unicode($match) {
126        require_once( dirname(__FILE__).'/'.'uao.php' );
127        global $uao_list;
128        $replaced = $uao_list[$match[0]];
129        if ($replaced) return $replaced;
130        return $match[0];
131    }
132}
133