]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/SyntaxHighlighter.php
rcs_id no longer makes sense with Subversion global version number
[SourceForge/phpwiki.git] / lib / plugin / SyntaxHighlighter.php
1 <?php // -*-php-*-
2 // rcs_id('$Id$');
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 if (!defined('HIGHLIGHT_EXE'))
50     define('HIGHLIGHT_EXE','highlight');
51 //define('HIGHLIGHT_EXE','/usr/local/bin/highlight');
52 //define('HIGHLIGHT_EXE','/home/groups/p/ph/phpwiki/bin/highlight');
53
54 // highlight requires two subdirs themes and langDefs somewhere.
55 // Best by highlight.conf in $HOME, but the webserver user usually
56 // doesn't have a $HOME
57 if (!defined('HIGHLIGHT_DATA_DIR'))
58     if (isWindows())
59         define('HIGHLIGHT_DATA_DIR','f:\cygnus\usr\local\share\highlight');
60     else
61         define('HIGHLIGHT_DATA_DIR','/usr/share/highlight');
62         //define('HIGHLIGHT_DATA_DIR','/home/groups/p/ph/phpwiki/share/highlight');
63
64 class WikiPlugin_SyntaxHighlighter
65 extends WikiPlugin
66 {
67     function getName () {
68         return _("SyntaxHighlighter");
69     }
70     function getDescription () {
71         return _("Source code syntax highlighter (via http://www.andre-simon.de)");
72     }
73     function managesValidators() {
74         return true;
75     }
76     function getDefaultArguments() {
77         return array(
78                      'syntax' => null, // required argument
79                      'style'  => null, // optional argument ["ansi", "gnu", "kr", "java", "linux"]
80                      'color'  => null, // optional, see highlight/themes
81                      'number' => 0,
82                      'wrap'   => 0,
83                      );
84     }
85     function handle_plugin_args_cruft(&$argstr, &$args) {
86         $this->source = $argstr;
87     }
88
89     function newFilterThroughCmd($input, $commandLine) {
90         $descriptorspec = array(
91                0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
92                1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
93                2 => array("pipe", "w"),  // stdout is a pipe that the child will write to
94         );
95
96         $process = proc_open("$commandLine", $descriptorspec, $pipes);
97         if (is_resource($process)) {
98             // $pipes now looks like this:
99             // 0 => writeable handle connected to child stdin
100             // 1 => readable  handle connected to child stdout
101             // 2 => readable  handle connected to child stderr
102             fwrite($pipes[0], $input);
103             fclose($pipes[0]);
104             $buf = "";
105             while(!feof($pipes[1])) {
106                 $buf .= fgets($pipes[1], 1024);
107             }
108             fclose($pipes[1]);
109             $stderr = '';
110             while(!feof($pipes[2])) {
111                 $stderr .= fgets($pipes[2], 1024);
112             }
113             fclose($pipes[2]);
114             // It is important that you close any pipes before calling
115             // proc_close in order to avoid a deadlock
116             $return_value = proc_close($process);
117             if (empty($buf)) printXML($this->error($stderr));
118             return $buf;
119         }
120     }
121
122     /* PHP versions < 4.3
123      * TODO: via temp file looks more promising
124      */
125     function OldFilterThroughCmd($input, $commandLine) {
126          $input = str_replace ("\\", "\\\\", $input);
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
133          $pipe = popen("echo \"$input\"|$commandLine", 'r');
134          if (!$pipe) {
135             print "pipe failed.";
136             return "";
137          }
138          $output = '';
139          while (!feof($pipe)) {
140             $output .= fread($pipe, 1024);
141          }
142          pclose($pipe);
143          return $output;
144     }
145
146     function run($dbi, $argstr, &$request, $basepage) {
147         extract($this->getArgs($argstr, $request));
148         $source =& $this->source;
149         if (empty($syntax)) return $this->error(_("Syntax language not specified."));
150         if (!empty($source)) {
151             $args = "";
152             if (defined('HIGHLIGHT_DATA_DIR'))
153                 $args .= " --data-dir " . HIGHLIGHT_DATA_DIR;
154             if ($number != 0) $args .= " -l";
155             if ($wrap != 0)   $args .= " -V";
156             $html = HTML();
157             if (!empty($color) and !preg_match('/^[\w-]+$/',$color)) {
158                 $html->pushContent($this->error(fmt("invalid %s ignored",'color')));
159                 $color = false;
160             }
161             if (!empty($color)) $args .= " --style $color --inline-css";
162             if (!empty($style)) $args .= " -F $style";
163             $commandLine = HIGHLIGHT_EXE . "$args -q -X -f -S $syntax";
164             if (check_php_version(4,3,0))
165                 $code = $this->newFilterThroughCmd($source, $commandLine);
166             else
167                 $code = $this->oldFilterThroughCmd($source, $commandLine);
168             if (empty($code))
169                 return $this->error(fmt("Couldn't start commandline '%s'",$commandLine));
170             $pre = HTML::pre(HTML::raw($code));
171             $html->pushContent($pre);
172             return HTML($html);
173         } else {
174             return $this->error(fmt("empty source"));
175         }
176     }
177 };
178
179 // For emacs users
180 // Local Variables:
181 // mode: php
182 // tab-width: 8
183 // c-basic-offset: 4
184 // c-hanging-comment-ender-p: nil
185 // indent-tabs-mode: nil
186 // End:
187 ?>