1<?php
2
3/**
4 * Plugin xssnipper: provides rendered code snippeds from files to be displayed in a code block
5 *
6 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
7 * @author     Taggic <taggic@t-online.de>
8 */
9
10if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
11if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
12if(!defined('DOKU_DATA')) define('DOKU_DATA',DOKU_INC.'data/pages/');
13require_once(DOKU_PLUGIN.'syntax.php');
14require_once(DOKU_INC.'inc/parser/xhtml.php');
15require_once(DOKU_INC.'inc/parser/renderer.php');
16
17
18include_once(DOKU_INC.'inc/geshi.php');
19
20/**
21 * All DokuWiki plugins to extend the parser/rendering mechanism
22 * need to inherit from this class
23 */
24class syntax_plugin_xssnipper extends DokuWiki_Syntax_Plugin {
25
26/******************************************************************************/
27/* return some info
28*/
29    function getInfo(){
30        return confToHash(dirname(__FILE__).'/plugin.info.txt');
31    }
32
33    function getType(){ return 'substition';}
34    function getPType(){ return 'block';}
35    function getSort(){ return 999;}
36
37/******************************************************************************/
38/* Connect pattern to lexer
39*/
40    function connectTo($mode){
41        $this->Lexer->addSpecialPattern('\{\(xssnipper\>.*?\)\}',$mode,'plugin_xssnipper');
42    }
43
44/******************************************************************************/
45/* handle the match
46*/
47    function handle($match, $state, $pos, Doku_Handler &$handler) {
48        global $ID;
49        $match = substr($match,strlen('{(xssnipper>'),-2); //strip markup from start and end
50
51        //handle params
52        $data = array();
53    /******************************************************************************/
54    /*      parameters can be:
55            {(xssnipper>[file path],[from line],[to line],[type])}
56            [file path]   ... path to the file (either it is in DokuWiki media directory or windows fileshare, etc.)
57            [from line]   ... the first line, which should be displayed
58            [to line]     ... the last line, which should be displayed
59            [type] [file] ... the type of content to tell the syntax higlighter how to interprete and set colors
60                              and pass a file for download the code block
61    /******************************************************************************/
62
63        $params = explode(",",$match);  // if you will have more parameters and choose ',' to delim them
64
65
66        if (!$params) {
67          msg('Syntax of xssnipper detected but parameter missing.', -1);
68        }
69        elseif($params[0] == ''){
70          //             0      1            2              3
71          // {(xssnipper>,[start line],[type] [file],<c>[content]</c>)}
72          $params = explode(",",$match,4);
73          $xssnipper                = array();
74          $xssnipper['filepath']    = '';
75          $xssnipper['from']        = $params[1];
76          $alpha                    = explode(' ',$params[2]);
77          $xssnipper['type']        = $alpha[0];
78          $xssnipper['file']        = $alpha[1];
79          $xssnipper['block']       = $alpha[2];
80          $xssnipper['code']        = $params[3];
81        }
82        else {
83          // Values
84          $xssnipper                = array();
85          $xssnipper['filepath']    = $params[0];
86          $xssnipper['from']        = $params[1];
87          $xssnipper['until']       = $params[2];
88          $alpha                    = explode(' ',$params[3]);
89          $xssnipper['type']        = $alpha[0];
90          $xssnipper['file']        = $alpha[1];
91          $xssnipper['block']       = $alpha[2];
92        }
93        return $xssnipper;
94     }
95/******************************************************************************/
96/* render output
97* @author Taggic <taggic@t-online.de>
98*/
99    function render($mode, Doku_Renderer &$renderer, $xssnipper) {
100        global $ID;
101        if(!$xssnipper['type'])  $xssnipper['type']='txt';
102        if($this->_codeblock<1)  $this->_codeblock=1;
103
104        if($xssnipper['filepath']=='') {
105           $code_lines = $xssnipper['code'];
106        }
107        else {
108          if(!$xssnipper['file'])  $xssnipper['file']= basename($xssnipper['filepath']);
109          if(!$xssnipper['file'])  $xssnipper['file']='snippet.'.$xssnipper['type'];
110
111      // 1. check if $xssnipper['filepath'] exist, else error message
112          if(!file_exists($xssnipper['filepath'])) {
113            msg('file '.$xssnipper['filepath'].' not found',-1);
114            return false;
115          }
116
117      // 2. open the file in read mode
118          $records    = file($xssnipper['filepath']);
119
120      // 3. load the file content from line = $xssnipper['from'] , to line = $xssnipper['until']  into $code_lines
121          if(!$xssnipper['until']) $xssnipper['until']=count($records);
122          foreach ($records as $line_num => $line) {
123              if(($line_num>=$xssnipper['from']-1) && ($line_num<=$xssnipper['until']-2))
124                  $code_lines .= $line;
125              if ($line_num>$xssnipper['until']) break;
126          }
127      }
128      $geshi = new GeSHi($code_lines, $xssnipper['type']);
129      $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
130      $geshi->set_overall_class('xssnipper');
131      $geshi->set_header_type(GESHI_HEADER_DIV);
132      //        $geshi->set_header_type(GESHI_HEADER_PRE_TABLE);
133      $geshi->start_line_numbers_at($xssnipper['from']);
134
135      $xs_path = '?do=export_code&id='.$ID;
136      $text = $geshi->parse_code();
137
138      $code_block .= NL.NL.'
139      <dl class="code">
140        <dt>
141          <a href="'.$xs_path.'&codeblock='.$this->_codeblock.'" title="Download Snippet" class="mediafile mf_'.$xssnipper['type'].'">'.$xssnipper['file'].'</a>
142        </dt>';
143
144        // returns the javascript function for clip-clap of block if downloadblock is used
145        $clipclap_flag = false;
146        if($xssnipper['block']) {
147            $code_block .= '<br />'.$this->__scripts_html();
148            $clipclap_id   = microtime();
149            $img_ID        = 'img_'.$clipclap_id;
150            $clipclap_img .= '<img id="'.$img_ID.'"
151                                   src="'.DOKU_BASE.'lib/plugins/xssnipper/images/enfold.png"
152                                   alt="show"  />'.NL;
153
154            $code_block .= '<span id="'.$clipclap_id.'" style="display : none;">'.NL;
155            $clipclap_flag = true;
156        }
157
158        $code_block .= '<dd style="display : none;">'.$code_lines.'</dd>'.$text.NL;
159
160        if($clipclap_flag == true) {
161            $code_block .= '</span>'.NL;
162            $code_block .= '<div class="img_clipclap" title="view code" id="'.$clipclap_id.'2" onClick="span_open(\''.$clipclap_id.'\',\''.$img_ID.'\')"></div>'.NL;
163        }
164      $code_block .= '</dl>'.NL;
165
166      $renderer->doc .= $code_block;
167
168      if($this->_codeblock == $_REQUEST['codeblock']){
169        header("Content-Type: text/plain; charset=utf-8");
170        header("Content-Disposition: attachment; filename=".trim($xssnipper['file']));
171        header("X-Robots-Tag: noindex");
172        header("Pragma: public");
173        echo trim($code_lines,"\r\n");
174        exit;
175      }
176      $this->_codeblock++;
177
178    }
179/******************************************************************************/
180    function __scripts_html()  {
181        $ret .=  '<span><script>
182             function span_open(blink_id, img_id)
183              {   if (document.getElementById(blink_id).style.display == "block")
184                  {   document.getElementById(blink_id).style.display = "none";
185                      document.getElementById(img_id).style.backgroundPosition = "0px 0px";
186                  }
187                  else
188                  {   document.getElementById(blink_id).style.display = "block";
189                      document.getElementById(img_id).style.backgroundPosition = "0px -19px";
190                  }
191              }
192        </script></span>'.NL;
193        return $ret;
194    }
195}
196?>