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?>