]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/SyntaxHighlighter.php
renamed global $Theme to $WikiTheme (gforge nameclash)
[SourceForge/phpwiki.git] / lib / plugin / SyntaxHighlighter.php
1 <?php // -*-php-*-
2 rcs_id('$Id: SyntaxHighlighter.php,v 1.5 2004-06-14 11:31:39 rurban Exp $');
3 /**
4  Copyright 2004 $ThePhpWikiProgrammingTeam
5
6  This file is part of PhpWiki.
7
8  PhpWiki is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12
13  PhpWiki is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with PhpWiki; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 /**
24  * The SyntaxHighlighter plugin passes all its arguments through a C++ 
25  * highlighter called "highlight" (available at http://www.andre-simon.de/).
26  *
27  * @author: alecthomas
28  * 
29  * syntax: See http://www.andre-simon.de/doku/highlight/highlight.html
30  * style = ["ansi", "gnu", "kr", "java", "linux"]
31  
32 <?plugin SyntaxHighlighter syntax=c style=kr color=emacs
33  #include <stdio.h>
34  
35  int main() {
36  printf("Lalala\n");
37  }
38 ?>
39
40  I did not use beautifier, because it used up more than 8M of memory on
41  my system and PHP killed it. I'm not sure whether this is a problem
42  with my integration, or with beautifier itself.
43
44 Fixes by Reini Urban:
45   support options: syntax, style, color.
46   php version switch
47   HIGHLIGHT_DATA_DIR, HIGHLIGHT_EXE
48 */
49
50 define('HIGHLIGHT_EXE','highlight');
51 //define('HIGHLIGHT_EXE','/usr/local/bin/highlight');
52
53 // highlight requires two subdirs themes and langDefs somewhere.
54 // Best by highlight.conf in $HOME, but the webserver user usually 
55 // doesn't have a $HOME
56 if (isWindows())
57     define('HIGHLIGHT_DATA_DIR','f:\cygnus\usr\local\share\highlight');
58 else
59     define('HIGHLIGHT_DATA_DIR','/usr/share/highlight');
60
61 class WikiPlugin_SyntaxHighlighter
62 extends WikiPlugin
63 {
64     function getName () {
65         return _("SyntaxHighlighter");
66     }
67     function getDescription () {
68         return _("Source code syntax highlighter (via http://www.andre-simon.de)");
69     }
70     function managesValidators() {
71         return true;
72     }
73     function getVersion() {
74         return preg_replace("/[Revision: $]/", '',
75                             "\$Revision: 1.5 $");
76     }
77     function getDefaultArguments() {
78         return array(
79                      'syntax' => null, // required argument
80                      'style'  => null, // optional argument ["ansi", "gnu", "kr", "java", "linux"]
81                      'color'  => null, // optional, see highlight/themes
82                      'number' => 0,
83                      'wrap'   => 0,
84                      );
85     }
86     function handle_plugin_args_cruft(&$argstr, &$args) {
87         $this->source = $argstr;
88     }
89
90     function newFilterThroughCmd($input, $commandLine) {
91         $descriptorspec = array(
92                0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
93                1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
94                2 => array("pipe", "w"),  // stdout is a pipe that the child will write to
95         );
96
97         $process = proc_open("$commandLine", $descriptorspec, $pipes);
98         if (is_resource($process)) {
99             // $pipes now looks like this:
100             // 0 => writeable handle connected to child stdin
101             // 1 => readable  handle connected to child stdout
102             // 2 => readable  handle connected to child stderr
103             fwrite($pipes[0], $input);
104             fclose($pipes[0]);
105             $buf = "";
106             while(!feof($pipes[1])) {
107                 $buf .= fgets($pipes[1], 1024);
108             }
109             fclose($pipes[1]);
110             $stderr = '';
111             while(!feof($pipes[2])) {
112                 $stderr .= fgets($pipes[2], 1024);
113             }
114             fclose($pipes[2]);
115             // It is important that you close any pipes before calling
116             // proc_close in order to avoid a deadlock
117             $return_value = proc_close($process);
118             if (empty($buf)) printXML($this->error($stderr));
119             return $buf;
120         }
121     }
122
123     /* PHP versions < 4.3
124      * TODO: via temp file looks more promising
125      */
126     function OldFilterThroughCmd($input, $commandLine) {
127          $input = str_replace ("\\", "\\\\", $input);
128          $input = str_replace ("\"", "\\\"", $input);
129          $input = str_replace ("\$", "\\\$", $input);
130          $input = str_replace ("`", "\`", $input);
131          $input = str_replace ("'", "\'", $input);
132          //$input = str_replace (";", "\;", $input);
133
134          $pipe = popen("echo \"$input\"|$commandLine", 'r');
135          if (!$pipe) {
136             print "pipe failed.";
137             return "";
138          }
139          $output = '';
140          while (!feof($pipe)) {
141             $output .= fread($pipe, 1024);
142          }
143          pclose($pipe);
144          return $output;
145     }
146
147     function run($dbi, $argstr, $request) {
148         extract($this->getArgs($argstr, $request));
149         $source =& $this->source;
150         if (empty($syntax)) return $this->error(_("Syntax language not specified."));
151         if (!empty($source)) {
152             $args = "";
153             if (defined('HIGHLIGHT_DATA_DIR'))
154                 $args .= " --data-dir " . HIGHLIGHT_DATA_DIR;
155             if ($number != 0) $args .= " -l";
156             if ($wrap != 0)   $args .= " -V";
157             $html = HTML();
158             if (!empty($color) and !preg_match('/^[\w-]+$/',$color)) {
159                 $html->pushContent($this->error(fmt("invalid %s ignored",'color')));
160                 $color = false;
161             }
162             if (!empty($color)) $args .= " --style $color -c ".FindFile("uploads")."/highlight-$color.css";
163             if (!empty($style)) $args .= " -F $style";
164             $commandLine = HIGHLIGHT_EXE . "$args -q -X -f -S $syntax";
165             if (check_php_version(4,3,0))
166                 $code = $this->newFilterThroughCmd($source, $commandLine);
167             else 
168                 $code = $this->oldFilterThroughCmd($source, $commandLine);
169             if (empty($code))
170                 return $this->error(fmt("Couldn't start commandline '%s'",$commandLine));
171             $pre = HTML::pre(HTML::raw($code));
172             $pre->setAttr('class','tightenable top bottom');
173             $html->pushContent($pre);
174             $css = $GLOBALS['WikiTheme']->_CSSlink('',empty($color) ? 'highlight.css' : "uploads/highlight-$color.css",'');
175             return HTML($css,$html);
176         } else {
177             return $this->error(fmt("empty source"));
178         }
179     }
180 };
181
182 // $Log: not supported by cvs2svn $
183 // Revision 1.4  2004/05/18 14:49:52  rurban
184 // Simplified strings for easier translation
185 //
186 // Revision 1.3  2004/05/14 17:33:12  rurban
187 // new plugin RecentChanges
188 //
189 // Revision 1.2  2004/05/14 15:56:16  rurban
190 // protect color argument, more error handling, added default css
191 //
192 // Revision 1.1  2004/05/14 14:55:52  rurban
193 // Alec Thomas original plugin, which comes with highlight http://www.andre-simon.de/,
194 // plus some extensions by Reini Urban
195 //
196 //
197
198 // For emacs users
199 // Local Variables:
200 // mode: php
201 // tab-width: 8
202 // c-basic-offset: 4
203 // c-hanging-comment-ender-p: nil
204 // indent-tabs-mode: nil
205 // End:
206 ?>