Recent Topics

1 Aug 31, 2005 00:35    

This plugin (implemented as a renderer plugin) will highlight source code for different programming languages. It uses [url=http://qbnz.com/highlighter]GeSHi[/url], the Generic Syntax Highlighter, a simple but powerful highlighting class that supports a wide range of popular languages.

To install the plugin, create a file named _syntax_highlight.renderer.php and place it under the plugins/renderers directory of your b2evolution installation. Here are the contents of this file:

<?php
/*
 * Plugin Name: Syntax Highlight, Version: 1.1
 *
 * Author: Mariano Iglesias - http://www.marianoiglesias.com.ar
 *
 * STEP ONE: Save this as _syntax_highlight.renderer.php and upload it to your
 * plugins/renderers folder
 *
 * STEP TWO: Download GeSHi from http://qbnz.com/highlighter and unzip inside
 * your plugins/renderers folder
 *
 * Within your b2evolution posts, place any sourcecode that you wish to have
 * highlighted within the following tags:
 *
 * <pre lang="LANGUAGE">
 * </pre>
 *
 * Where LANGUAGE is any of the available GeSHi languages. For example:
 *
 * <pre lang="php">$my_variable = 'Hello b2evo!';</pre>
 *
 * <pre> tags without lang attribute will not be parsed by GeSHi and will
 * remain as they are.
 */
if( !defined('DB_USER') ) die( 'Please, do not access this page directly.' );

/**
 * Configuration for this plugin
 */

define ('PATH_TO_GESHI', dirname(__FILE__) . '/geshi');
define ('INCLUDE_LINE_NUMBERS', false);

/**
 * Includes:
 */
require_once dirname(__FILE__).'/../renderer.class.php';
require_once PATH_TO_GESHI.'/geshi.php';

/**
 * @package plugins
 */
class syntax_highlight_Rendererplugin extends RendererPlugin
{
	var $code = 'syntax_highlight';
	var $name = 'Syntax Highlighter';
	var $priority = 1;
	var $apply_when = 'always';
	var $apply_to_html = true;
	var $apply_to_xml = false;
	var $short_desc = 'formats source code with highlight';
	var $long_desc = 'This plugin uses Geshi to highlight a piece of generic sourcecode with style.';
	var $include_line_numbers = INCLUDE_LINE_NUMBERS;

	/**
	 * Constructor
	 *
	 * {@internal syntax_highlight_Rendererplugin::syntax_highlight_Rendererplugin(-)}}
	 */
	function syntax_highlight_Rendererplugin()
	{
		$this->short_desc = T_('formats source code with highlight');
		$this->long_desc = T_('This plugin uses Geshi to highlight a piece of generic sourcecode with style.');
	}

	function render( & $content, $format )
	{
		if( ! parent::render( $content, $format ) )
		{
			return false;
		}
		else
		{
			// Search for code to be highlighted

			$pattern = "/(<\/?pre(\s+lang=\"(.*?)\")?>)/";
			$content_parts = preg_split($pattern, $content, -1, PREG_SPLIT_DELIM_CAPTURE);

			$modified_content = '';
			$code_line = null;
			$code_language = null;
			
			for ($i=0, $limiti = count($content_parts); $i < $limiti; $i++ )
			{
				$element = $content_parts[$i];
			
				if (preg_match($pattern, $element))
				{
					if (!isset($code_line) && strpos(strtolower($element), 'lang') !== false)
					{
						$code_line = 0;
						$code_language = null;
					}
					else if (strpos(strtolower($element), 'lang') === false && strpos(strtolower($element), '/pre') === false)
					{
						$code_line = -1;
					}
					else
					{
						$code_line = null;
					}
				}
				else if (isset($code_line) && $code_line >= 0)
				{
					$code_line++;
					
					if ($code_line == 2)
					{
						$code_language = $element;
					}
					else if ($code_line > 2 && isset($code_language))
					{
						$element = str_replace('&amp;', '&', $element);
						$element = str_replace('&lt;', '<', $element);
						$element = str_replace('&gt;', '>', $element);
					
						$modified_content .= '<div class="code">';
						$modified_content .= $this->highlight($element, $code_language);
						$modified_content .= '</div>';
					}
				}
				else
				{
					$modified_content .= ($code_line === -1 ? '<pre>' : '') . $element . ($code_line === -1 ? '</pre>' : '');
				}
			}

			$content = $modified_content;
		}

		return true;
	}
   
	function highlight($source, $language = 'php')
	{
		$geshi =& new GeSHi(str_replace('\"', '"', $source), $language, PATH_TO_GESHI . '/geshi');

		$geshi->set_header_type(GESHI_HEADER_DIV);
		
		if ($this->include_line_numbers)
		{
			$geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
		}

		return $geshi->parse_code();
	}
}

// Register the plugin

$this->register( new syntax_highlight_Rendererplugin() );

?>

You will also have to download GeSHi and place it somewhere that it can be found by the plugin. Download GeSHi from its SourceForge download page located at http://sourceforge.net/project/showfiles.php?group_id=114997 and unzip the package into the plugins/renderers directory of your b2evolution installation. If you decide to copy it somewhere else, remember to reflect this change on the following line within the _syntax_highlight.renderer.php file:

define ('PATH_TO_GESHI', dirname(__FILE__) . '/geshi');

To use it within your b2evolution posts, place any sourcecode that you wish to have highlighted within the tags <pre> and </pre>, and use the attribute lang within the pre tag to specify which GeSHi language should be used when parsing. For example:

<pre lang="php">
if (1 == 1)
{
	echo 'Hello b2evo!';
}
</pre>

If you want pre tags within your post and do not wish them to be handled by this plugin, just ommit the lang attribute. Therefore, all pre tags that wish to be highlighted MUST contain a lang attribute.

Due to b2evolution HTML checking you cannot insert HTML tags within your source code. Instead, use the &lt; and &gt; entities for specifying < and >. They will be converted before passing the code to GeSHi. This also applies for the &amp; entity.

For example, to have the following HTML code highlighted within your b2evo post:

<select name="myselect">
    <option value="1">My Option</option>
</select>

You will have to do the following:

<pre lang="html">
&lt;select name="myselect"&gt;
    &lt;option value="1"&gt;My Option&lt;/option&gt;
&lt;/select&gt;
</pre>

You can see a preview of how this plugin works at [url=http://cricava.com/blogs/index.php?blog=6&title=get_a_taste_of_ajax_with_php&more=1&c=1&tb=1&pb=1]this post in my blog[/url].

2 Aug 31, 2005 01:26

This is cool, but there must be a way around the html checker. I don't think I could stand to type out all of those codes to display > and stuff.

3 Aug 31, 2005 01:34

personman wrote:

This is cool, but there must be a way around the html checker. I don't think I could stand to type out all of those codes to display > and stuff.

Well, there's. Open the file conf\_formatting.php within your b2evo installation and look for the following lines:

$use_html_checker = 1;
$use_security_checker = 0;

change them as follows:

$use_html_checker = 0;
$use_security_checker = 1;

This will disable the HTML checking, and enable the security checking (having them both disabled is definitely NOT recommended.)

Hope that helps.

4 Aug 31, 2005 01:58

I bookmarked this thread because I want to remember to come back to it. I'm kinda too busy to get another hack project going right now, but that's not why I'm posting.

<ramble>I'm thinking *maybe* we could mix some stuff together here. For example the existing 'code' button could make the <pre lang=""> tag if we take the javascript bit from the existing 'link' that lets you plug in your URL. That way you click 'code' and get a popup where you type php or html or whatever then click okay. Bam - instant language tag. Next step is even harder - the html issue. Actually even php is tough if you are posting hacks for b2evolution because html is sprinkled here and there in the php. Whatever - suppose someone smart took my 'insert code' thing and put a few options on it. Pick a radio button for "GeSHi PHP" or "GeSHi HTML" and so on. You then paste in your code and away it goes (unless it stalls...), knowing to convert <s and >s for you if you are doing a GeSHi HTML job. In fact you wouldn't even need to tweak the code button this way. Just let upcode figure out exactly what tags to wrap the code in and what converting to do if any. Drawback: it is not a straight plugin that way. I suppose if I thought more about it I could have probably made a new toolbar - ! So instead of clicking upcode then selecting which GeSHi-job you want how about another toolbar above the post textarea with the options listed there. Still do a popup window for the occasions you need conversions, but it can be implemented as a plugin with maybe an extra file driving the popup.</ramble>

I'm posting so's when I get back here I'll remember what I'm thinking now ;)

6 Aug 31, 2005 02:13

EdB wrote:

I bookmarked this thread because I want to remember to come back to it. I'm kinda too busy to get another hack project going right now, but that's not why I'm posting.

<ramble>I'm thinking *maybe* we could mix some stuff together here. For example the existing 'code' button could make the <pre lang=""> tag if we take the javascript bit from the existing 'link' that lets you plug in your URL. That way you click 'code' and get a popup where you type php or html or whatever then click okay. Bam - instant language tag. Next step is even harder - the html issue. Actually even php is tough if you are posting hacks for b2evolution because html is sprinkled here and there in the php. Whatever - suppose someone smart took my 'insert code' thing and put a few options on it. Pick a radio button for "GeSHi PHP" or "GeSHi HTML" and so on. You then paste in your code and away it goes (unless it stalls...), knowing to convert <s and >s for you if you are doing a GeSHi HTML job. In fact you wouldn't even need to tweak the code button this way. Just let upcode figure out exactly what tags to wrap the code in and what converting to do if any. Drawback: it is not a straight plugin that way. I suppose if I thought more about it I could have probably made a new toolbar - ! So instead of clicking upcode then selecting which GeSHi-job you want how about another toolbar above the post textarea with the options listed there. Still do a popup window for the occasions you need conversions, but it can be implemented as a plugin with maybe an extra file driving the popup.</ramble>

I'm posting so's when I get back here I'll remember what I'm thinking now ;)

The truth is that the way to go would be to talk with the b2evo guys and have them add a third option to the formatting options, something like:

$use_html_checker_within_pre=0;

Then, we can grab the SafeHtmlChecker class (located at b2evocore/_class_htmlchecker.php) and let it only check HTML code within a PRE tag if

$use_html_checker_within_pre == 1;

This way, one can disable HTML checking within a PRE without having to disable HTML checking alltogether.

As to your ideas, probably after poping up the window and giving the user the possibility to add their source code, just before adding it to the textarea have a javascript do the necessary substitutions (< for &lt; > for &gt; and so on...)

However, this falls more into the hack arena and I was quite into making it more of a plugin so version upgrades would not impact so heavily on this functionality.

Let's see how we can continue.

7 Aug 31, 2005 10:04

The truth is that the way to go would be to talk with the b2evo guys and have them add a third option to the formatting options, something like:

Code:
$use_html_checker_within_pre=0;

Then, we can grab the SafeHtmlChecker class (located at b2evocore/_class_htmlchecker.php) and let it only check HTML code within a PRE tag if
Code:
$use_html_checker_within_pre == 1;

This way, one can disable HTML checking within a PRE without having to disable HTML checking alltogether.

I like this idea and we can ask to add it to next b2evolution version.

8 Aug 31, 2005 18:49

slamp wrote:

I like this idea and we can ask to add it to next b2evolution version.

Well, I kind of did it and test it to see what to say particularly to the b2evo guys. For those of you who want to test this feature (disabling HTML checking within a PRE tag without having to disable HTML checking alltogether), here's what you should do.

STEP 1 - Open the file b2evocore/_class_htmlchecker.php and look for function tag_open() (in my b2evo 0.9.0.12 is on line 119). Just after the function has opened, add the following lines:

		/* START MODIFICATION BY Mariano Iglesias - http://www.marianoiglesias.com.ar */
		global $use_html_checker_within_pre;
		
		if ($this->ignore_checking == true)
		{
			if ($tag == 'pre')
			{
				// Set previous, used for checking nesting context rules
				$this->stack[] = $tag;
			}
		
			return;
		}
		
		/* END MODIFICATION BY Mariano Iglesias - http://www.marianoiglesias.com.ar */

STEP 2 - In the same function, look for the following line (after adding the above lines that should be line 147):

$previous = $this->stack[count($this->stack)-1];

Add the following lines just below that line:

		/* START MODIFICATION BY Mariano Iglesias - http://www.marianoiglesias.com.ar */
		
		if (	$tag == 'pre' && 
			(!isset($use_html_checker_within_pre) || $use_html_checker_within_pre == 0) && 
			(!isset($previous) || $previous != 'pre') &&
			isset($attrs) && is_array($attrs) && isset($attrs['lang'])
		)
		{
			// Set ignore checking
			
			$this->ignore_checking = true;
			
			// Set previous, used for checking nesting context rules
			$this->stack[] = $tag;
		
			return;
		}
		
		/* END MODIFICATION BY Mariano Iglesias - http://www.marianoiglesias.com.ar */

STEP 3 - Look for function tag_close() (after adding all set of above lines that should be line 234), and right after the function was declared (inside the function) add the following lines:

		/* START MODIFICATION BY Mariano Iglesias - http://www.marianoiglesias.com.ar */
		
		if ($this->ignore_checking == true)
		{
			if ($tag == 'pre')
			{
				array_pop($this->stack);
				
				$previous = $this->stack[count($this->stack)-1];
				
				if ($previous != 'pre')
				{
					$this->ignore_checking = false;
				}
			}
		
			return;
		}
		
		/* END MODIFICATION BY Mariano Iglesias - http://www.marianoiglesias.com.ar */

So basically you would end up with the following source for file b2evocore/_class_htmlchecker.php:

<?php
/**
 * SafeHtmlChecker
 *
 * checks HTML against a subset of elements to ensure safety and XHTML validation.
 *
 * b2evolution - {@link http://b2evolution.net/}
 * Released under GNU GPL License - {@link http://b2evolution.net/about/license.html}
 * @copyright (c)2003-2004 by Francois PLANQUE - {@link http://fplanque.net/}
 *
 * @package evocore
 * @author Simon Willison, 23rd Feb 2003, modified by fplanque, sakichan
 */
if( !defined('DB_USER') ) die( 'Please, do not access this page directly.' );

/**
 * SafeHtmlChecker
 *
 * checks HTML against a subset of elements to ensure safety and XHTML validation.
 *
 * @package evocore
 */
class SafeHtmlChecker
{
	var $tags;      // Array showing allowed attributes for tags
	var $tagattrs;  // Array showing URI attributes
	var $uri_attrs;
	var $allowed_uri_scheme;

	// Internal variables
	var $parser;
	var $stack = array();
	var $last_checked_pos;
	var $error;

	/**
	 * SafeHtmlChecker(-)
	 */
	function SafeHtmlChecker( & $allowed_tags, & $allowed_attribues, & $uri_attrs, & $allowed_uri_scheme, $encoding = 'ISO-8859-1' )
	{
		$this->tags = & $allowed_tags;
		$this->tagattrs = & $allowed_attribues;
		$this->uri_attrs = & $uri_attrs;
		$this->allowed_uri_scheme = & $allowed_uri_scheme;
		$this->encoding = $encoding;
		$this->parser = xml_parser_create( $this->encoding );
		$this->last_checked_pos = 0;
		$this->error = false;

		// Creates the parser
		xml_set_object( $this->parser, $this);

		// set functions to call when a start or end tag is encountered
		xml_set_element_handler($this->parser, 'tag_open', 'tag_close');
		// set function to call for the actual data
		xml_set_character_data_handler($this->parser, 'cdata');

		xml_set_default_handler($this->parser, 'default_handler');
		xml_set_external_entity_ref_handler($this->parser, 'external_entity');
		xml_set_unparsed_entity_decl_handler($this->parser, 'unparsed_entity');

		xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
	}

	function default_handler( $parser, $data)
	{
		// echo 'default handler: '.$data.'<br />';
	}

	function external_entity( $parser, $open_entity_names, $base, $system_id, $public_id)
	{
		// echo 'external_entity<br />';
	}


	function unparsed_entity( $parser, $entity_name, $base, $system_id, $public_id, $notation_name)
	{
		// echo 'unparsed_entity<br />';
	}


	/**
	 * check(-)
	 */
	function check($xhtml)
	{
		// Open comments or '<![CDATA[' are dangerous
		$xhtml = str_replace('<!', '', $xhtml);

		// Convert isolated & chars
		$xhtml = preg_replace( '#(\s)&(\s)#', '\\1&amp;\\2', $xhtml );

		$xhtml = '<?xml version="1.0" encoding="'.$this->encoding.'"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
				.'<body>'.$xhtml.'</body>';

		if( isset($use_html_checker_within_pre) && $use_html_checker_within_pre == 1 && !xml_parse($this->parser, $xhtml) )
		{
			$xml_error_code = xml_get_error_code( $this->parser );
			$xml_error_string = xml_error_string( $xml_error_code );
			switch( $xml_error_code )
			{
				case XML_ERROR_TAG_MISMATCH:
					$xml_error_string .= ': <code>'.$this->stack[count($this->stack)-1].'</code>';
					break;
			}
			$pos = xml_get_current_byte_index($this->parser);
			$xml_error_string .= ' near <code>'.htmlspecialchars( substr( $xhtml, $this->last_checked_pos, $pos-$this->last_checked_pos+20 ) ).'</code>';
	
			$this->html_error( T_('Parser error: ').$xml_error_string );

		}
	}

	/**
	 * tag_open(-)
	 *
	 * Called when the parser finds an opening tag
	 */
	function tag_open($parser, $tag, $attrs)
	{
		/* START MODIFICATION BY Mariano Iglesias - http://www.marianoiglesias.com.ar */

		global $use_html_checker_within_pre;
		
		if ($this->ignore_checking == true)
		{
			if ($tag == 'pre')
			{
				// Set previous, used for checking nesting context rules
				$this->stack[] = $tag;
			}
		
			return;
		}
		
		/* END MODIFICATION BY Mariano Iglesias - http://www.marianoiglesias.com.ar */
	
		// echo "processing tag: $tag <br />\n";
		$this->last_checked_pos = xml_get_current_byte_index($this->parser);

		if ($tag == 'body')
		{
			if( count($this->stack) > 0 )
				$this->html_error( T_('Tag <code>body</code> can only be used once!') );
			$this->stack[] = $tag;
			return;
		}
		
		$previous = $this->stack[count($this->stack)-1];
		
		/* START MODIFICATION BY Mariano Iglesias - http://www.marianoiglesias.com.ar */
		
		if (	$tag == 'pre' && 
			(!isset($use_html_checker_within_pre) || $use_html_checker_within_pre == 0) && 
			(!isset($previous) || $previous != 'pre') &&
			isset($attrs) && is_array($attrs) && isset($attrs['lang'])
		)
		{
			// Set ignore checking
			
			$this->ignore_checking = true;
			
			// Set previous, used for checking nesting context rules
			$this->stack[] = $tag;
		
			return;
		}
		
		/* END MODIFICATION BY Mariano Iglesias - http://www.marianoiglesias.com.ar */

		// If previous tag is illegal, no point in running tests
		if (!in_array($previous, array_keys($this->tags))) {
			$this->stack[] = $tag;
			return;
		}
		// Is tag a legal tag?
		if (!in_array($tag, array_keys($this->tags))) {
			$this->html_error( T_('Illegal tag'). ": <code>$tag</code>" );
			$this->stack[] = $tag;
			return;
		}
		// Is tag allowed in the current context?
		if (!in_array($tag, explode(' ', $this->tags[$previous]))) {
			if ($previous == 'body') {
				$this->html_error(	sprintf( T_('Tag %s must occur inside another tag'), '<code>'.$tag.'</code>' ) );
			} else {
				$this->html_error(	sprintf( T_('Tag %s is not allowed within tag %s'), '<code>'.$tag.'</code>', '<code>'.$previous.'</code>') );
			}
		}
		// Are tag attributes valid?
		foreach( $attrs as $attr => $value )
		{
			if (!isset($this->tagattrs[$tag]) || !in_array($attr, explode(' ', $this->tagattrs[$tag])))
			{
				$this->html_error( sprintf( T_('Tag %s may not have attribute %s'), '<code>'.$tag.'</code>', '<code>'.$attr.'</code>' ) );
			}
			if (in_array($attr, $this->uri_attrs))
			{ // Must this attribute be checked for URIs
				$matches = array();
				$value = trim($value);
				if( $error = validate_url( $value, $this->allowed_uri_scheme ) )
				{
					$this->html_error( T_('Found invalid URL: ').$error );
				}
			}
		}
		// Set previous, used for checking nesting context rules
		$this->stack[] = $tag;
	}

	/**
	 * cdata(-)
	 */
	function cdata($parser, $cdata)
	{
		$this->last_checked_pos = xml_get_current_byte_index($this->parser);

		// Simply check that the 'previous' tag allows CDATA
		$previous = $this->stack[count($this->stack)-1];
		// If previous tag is illegal, no point in running test
		if (!in_array($previous, array_keys($this->tags))) {
			return;
		}
		if (trim($cdata) != '') {
			if (!in_array('#PCDATA', explode(' ', $this->tags[$previous]))) {
				$this->html_error(	sprintf( T_('Tag %s may not contain raw character data'), '<code>'.$previous.'</code>' ) );
			}
		}
	}

	/**
	 * tag_close(-)
	 */
	function tag_close($parser, $tag)
	{
		/* START MODIFICATION BY Mariano Iglesias - http://www.marianoiglesias.com.ar */
		
		if ($this->ignore_checking == true)
		{
			if ($tag == 'pre')
			{
				array_pop($this->stack);
				
				$previous = $this->stack[count($this->stack)-1];
				
				if ($previous != 'pre')
				{
					$this->ignore_checking = false;
				}
			}
		
			return;
		}
		
		/* END MODIFICATION BY Mariano Iglesias - http://www.marianoiglesias.com.ar */
	
		$this->last_checked_pos = xml_get_current_byte_index($this->parser);

		// Move back one up the stack
		array_pop($this->stack);
	}

	function html_error( $string )
	{
		$this->error = true;
		errors_add( $string );
	}

	/**
	 * isOK(-)
	 */
	function isOK()
	{
		return ! $this->error;
	}

}

?>

Now, what this does (if you take a look at the source) is to expect a global variable called $use_html_checker_within_pre. If this variable IS SET and has been set to the value 1, then b2evo will do its checking as it did before. If that variable is NOT SET or has a value of 0, then for any PRE tag that has the attribute lang set, HTML checking will be ignored.

Please tell me what you think.

Also, does anybody know where could we get in contact with the b2evo guys to propose this change?

9 Aug 31, 2005 19:06

I'd love to test it but I've got a fly-in to go to. Hopefully someone else will eh? I think at the forum level you should post a thread in the "Features Request" forum and reference this thread. I'm pretty sure some of the dev team pops in there from time to time. Also Francois' web is linked at the bottom of the main b2evolution.net page - he's The Man for b2evo stuff.

10 Aug 31, 2005 20:56

For the above modification to the file b2evocore/_class_htmlchecker, I forgot one more modification.

Go to line 96, and change the following line:

if( !xml_parse($this->parser, $xhtml) )

into this:

if( isset($use_html_checker_within_pre) && $use_html_checker_within_pre == 1 && !xml_parse($this->parser, $xhtml) )

this will avoid normal XML tag mismatch checking.

11 Aug 31, 2005 21:12

EdB wrote:

I'd love to test it but I've got a fly-in to go to. Hopefully someone else will eh? I think at the forum level you should post a thread in the "Features Request" forum and reference this thread. I'm pretty sure some of the dev team pops in there from time to time. Also Francois' web is linked at the bottom of the main b2evolution.net page - he's The Man for b2evo stuff.

Testing could be a good idea. I did some testing in my b2evo 0.9.0.12 installation, and it worked fine.

Also, I just added a thread at the Features Request forum as you suggested. The thread [url=http://forums.b2evolution.net/viewtopic.php?p=24937]is here[/url]. Hope someone will consider it, otherwise another route should be taken. I haven't write to Francois yet, since I want to see if that forum post gets any attention. If it does not, then we should look into how to get this post to the b2evo developers' mailbox.

12 Sep 02, 2005 16:44

it works. Anyway I have some question: When I post the following code:

<?php
if (1 == 1)
{
   echo 'Hello b2evo!';
}
?>


I got a space betwwen the first < and ?. I also got </> at the end of code.

< ?php
if (1 == 1)
{
   echo 'Hello b2evo!';
}
?>
</>


Do you know why ?

The code bellow is not hightlight even if I use &lg; and &lt;


<pre lang="html">
<select name="myselect">
    <option value="1">My Option</option>
</select>
</pre>

the behaviour is the same even if $use_html_checker_within_pre is set to 0 or to 1.

Slamp
PS: It will be great if php highlighter could be add to phpbb :)

13 Sep 03, 2005 03:38

slamp wrote:

it works. Anyway I have some question: When I post the following code:

<?php
if (1 == 1)
{
   echo 'Hello b2evo!';
}
?>


I got a space betwwen the first < and ?. I also got </> at the end of code.
Do you know why ?

Did you use the variable to deactivate html checking?

The code bellow is not hightlight even if I use &lg; and &lt;


<pre lang="html">
<select name="myselect">
    <option value="1">My Option</option>
</select>
</pre>

Try using html4strict instead of html in the lang attribute for the pre tag. That is the code I saw in GeSHi.

PS: It will be great if php highlighter could be add to phpbb :)

Yes, it would. Let's see what we can do.

14 Sep 05, 2005 15:03

Did you use the variable to deactivate html checking?

Here is my configuration:

$use_html_checker = 1;
$use_security_checker = 0;
$use_html_checker_within_pre = 0;

It works with html4strict. Great !

15 Sep 30, 2005 10:01

those that have installed this might want to go grab the latest update to geshi..

http://www.frsirt.com/english/advisories/2005/1813

funny, that advisory doesnt make it out to be the threat it is -- esentially, if someone knows your path to geshi, they can read your configuration files as well.

http://securityreason.com/achievement_securityalert/23

I like this idea and we can ask to add it to next b2evolution version.

One more reason why adding "things" to core features is a bad idea.

16 Sep 30, 2005 10:42

http://securityreason.com/achievement_securityalert/23

the security hole is important but based on a contrib file which do not need to be installed when using this plugin. It's in ./contrib/example.php

I like this idea and we can ask to add it to next b2evolution version.

One more reason why adding "things" to core features is a bad idea.

I agree.

17 Sep 30, 2005 18:26

i understood where the problem was when I posted.. that said, neither of us have any idea whether or not someone using this installed that .. a heads up is better than a compromised site :)

18 Oct 25, 2005 18:22

mariano.iglesias wrote:

To install the plugin, create a file named _syntax_highlight.renderer.php and place it under the plugins/renderers directory of your b2evolution installation.

I tried to install the plugin but nothing happens :(

Don't I need to install the plugin in the admin? I can't see it listed in the available plugins. When I enter php-code with the pre-tag and lang="php" nothing happens. The Tag will be displayed unchanged. It seems that the plugin is not recognized by b2evolution.

Marian

19 Oct 25, 2005 19:02

Which version of b2evolution are you using ?

20 Oct 25, 2005 19:12

slamp wrote:

Which version of b2evolution are you using ?

:oops: Okay I see, It's my fault. I'm using the latest CVS-Version and it seems that the plugin-handling has been changed there.

I will ask in the developer mailinglist, how I could adopt it to the next version.

Regards
Marian

21 Nov 08, 2006 19:35

I also require syntax highlighting capabilities in my blog, so I was wondering whether this modification is known to still work with 1.8+ ?

Thanks

22 Feb 02, 2007 08:55

Don't know if this is relevant now, but I adapted the plugin for 1.8.x+. I also changed the code container to be pre instead of div, as div resulted in a lot of additional newlines in the highlighted code.

Here's the code:


<?php
/*
 * Plugin Name: Syntax Highlight, Version: 1.1
 *
 * Author: Mariano Iglesias - http://www.marianoiglesias.com.ar
 *
 * Modified for b2evolution 1.8.x+ by Per Jönsson (http://www.pjd.nu)
 *
 * STEP ONE: Save this as _syntax_highlight.plugin.php and upload it to your
 * plugins folder
 *
 * STEP TWO: Download GeSHi from http://qbnz.com/highlighter and unzip inside
 * your plugins folder
 *
 * Within your b2evolution posts, place any sourcecode that you wish to have
 * highlighted within the following tags:
 *
 * <pre lang="LANGUAGE">
 * </pre>
 *
 * Where LANGUAGE is any of the available GeSHi languages. For example:
 *
 * <pre lang="php">$my_variable = 'Hello b2evo!';</pre>
 *
 * <pre> tags without lang attribute will not be parsed by GeSHi and will
 * remain as they are.
 */
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );

/**
 * Configuration for this plugin
 */

define ('PATH_TO_GESHI', dirname(__FILE__) . '/geshi');
define ('INCLUDE_LINE_NUMBERS', false);

/**
 * Includes:
 */
require_once PATH_TO_GESHI.'/geshi.php';

/**
 * @package plugins
 */
class syntax_highlight_plugin extends Plugin
{
	var $code = 'syntax_highlight';
	var $name = 'Syntax Highlighter';
	var $priority = 10;
	var $version = '1.1';
	var $group = 'rendering';
	
	var $apply_rendering = 'always';
	var $author = 'Mariano Iglesias';
	var $help_url = '';
		
	var $include_line_numbers = INCLUDE_LINE_NUMBERS;

	/**
	 * Init
	 *
	 * This gets called after a plugin has been registered/instantiated.
	 */
	function PluginInit( & $params )
	{
		$this->short_desc = $this->T_('formats source code with highlight');
		$this->long_desc = $this->T_('This plugin uses Geshi to highlight a piece of generic sourcecode with style.');
	}
	
	function RenderItemAsHtml( & $params )
	{
		$content = & $params['data'];
		return $this->render( $content, $params['format'] );		
	}


	function render( & $content, $format )
	{
		// Search for code to be highlighted
	
		$pattern = "/(<\/?pre(\s+lang=\"(.*?)\")?>)/";
		$content_parts = preg_split($pattern, $content, -1, PREG_SPLIT_DELIM_CAPTURE);
	
		$modified_content = '';
		$code_line = null;
		$code_language = null;
	
		for ($i=0, $limiti = count($content_parts); $i < $limiti; $i++ )
		{
			$element = $content_parts[$i];
	
			if (preg_match($pattern, $element))
			{
				if (!isset($code_line) && strpos(strtolower($element), 'lang') !== false)
				{
					$code_line = 0;
					$code_language = null;
				}
				else if (strpos(strtolower($element), 'lang') === false && strpos(strtolower($element), '/pre') === false)
				{
					$code_line = -1;
				}
				else
				{
					$code_line = null;
				}
			}
			else if (isset($code_line) && $code_line >= 0)
			{
				$code_line++;
				
				if ($code_line == 2)
				{
					$code_language = $element;
				}
				else if ($code_line > 2 && isset($code_language))
				{
					$element = str_replace('&amp;', '&', $element);
					$element = str_replace('&lt;', '<', $element);
					$element = str_replace('&gt;', '>', $element);
				
					$modified_content .= '<div class="code">';
					$modified_content .= "<!-- language: $code_language -->";
					$modified_content .= $this->highlight($element, $code_language);
					$modified_content .= '</div>';
				}
			}
			else
			{
				$modified_content .= ($code_line === -1 ? '<pre>' : '') . $element . ($code_line === -1 ? '</pre>' : '');
			}
		}
		
		$content = $modified_content;
		
		return true;
	}

	function highlight($source, $language = 'php')
	{
		$geshi =& new GeSHi(str_replace('\"', '"', $source), $language, PATH_TO_GESHI . '/geshi');
	
		$geshi->set_header_type(GESHI_HEADER_PRE);
	
		if ($this->include_line_numbers)
		{
			$geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
		}
	
		return $geshi->parse_code();
	}
}


?>

I hope I got it right.. it works for me anyway. :)

23 Nov 14, 2009 15:12

Please find bellow an adaptation for b2evolution 2.x (I've tested with my debian 2.4.3 installed).


<?php
/*
 * Plugin Name: Syntax Highlight, Version: 1.2
 *
 * Author: Mariano Iglesias - http://www.marianoiglesias.com.ar
 *         Laurent Mazet - http://www.softndesign.org
 *
 * STEP ONE: Save this as _syntax_highlight.renderer.php and upload it to your
 * plugins/renderers folder
 *
 * STEP TWO: Download GeSHi from http://qbnz.com/highlighter and unzip inside
 * your plugins/renderers folder
 *
 * Within your b2evolution posts, place any sourcecode that you wish to have
 * highlighted within the following tags:
 *
 * <pre lang="LANGUAGE">
 * </pre>
 *
 * Where LANGUAGE is any of the available GeSHi languages. For example:
 *
 * <pre lang="php">$my_variable = 'Hello b2evo!';</pre>
 *
 * <pre> tags without lang attribute will not be parsed by GeSHi and will
 * remain as they are.
 */
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );

/**
 * Configuration for this plugin
 */

define ('PATH_TO_GESHI', '/usr/share/php-geshi');

/**
 * Includes:
 */
require_once PATH_TO_GESHI.'/geshi.php';

/**
 * @package plugins
 */
class syntax_highlight_plugin extends Plugin
{
   var $code = 'syntax_highlight';
   var $name = 'Syntax Highlighter';
   var $priority = 20;
   var $version = '1.2';
   var $apply_rendering = 'opt-out';
   var $group = 'rendering';
   var $short_desc;
   var $long_desc;
   var $number_of_installs = 1;

   var $line_numbers = false;
   var $framebox = false;

   /**
    * Init
    */
   function PluginInit( & $params )
   {
      $this->short_desc = T_('formats source code with highlight');
      $this->long_desc = T_('This plugin uses Geshi to highlight a piece of generic sourcecode with style.');
   }

   /**
    * @return array
    */
   function GetDefaultSettings()
   {
      return array(
         'line_numbers' => array(
            'label' => T_('Line numbers'),
            'type' => 'checkbox',
            'defaultvalue' => false,
            'note' => T_('Prefix each line by a number.'),
         ),
         'framebox' => array (
            'label' => T_('Framebox'),
            'type' => 'checkbox',
            'defaultvalue' => false,
            'note' => T_('Block code are inserted in a box'),
         ),
      );
   }

   function RenderItemAsHtml( & $params )
   {

      $this->line_numbers = $this->Settings->get('line_numbers');
      $this->framebox = $this->Settings->get('framebox');

      $content = & $params['data'];

      // Search for code to be highlighted

      $pattern = "/(<\/?pre(\s+lang=\"(.*?)\")?>)/";
      $content_parts = preg_split($pattern, $content, -1, PREG_SPLIT_DELIM_CAPTURE);

      $modified_content = '';
      $code_line = null;
      $code_language = null;
         
      for ($i=0, $limiti = count($content_parts); $i < $limiti; $i++ )
      {
         $element = $content_parts[$i];
         
         if (preg_match($pattern, $element))
         {
            if (!isset($code_line) && strpos(strtolower($element), 'lang') !== false)
            {
               $code_line = 0;
               $code_language = null;
            }
            else if (strpos(strtolower($element), 'lang') === false && strpos(strtolower($element), '/pre') === false)
            {
               $code_line = -1;
            }
            else
            {
               $code_line = null;
            }
         }
         else if (isset($code_line) && $code_line >= 0)
         {
            $code_line++;
          
            if ($code_line == 2)
            {
               $code_language = $element;
            }
            else if ($code_line > 2 && isset($code_language))
            {
               $element = str_replace('&amp;', '&', $element);
               $element = str_replace('&lt;', '<', $element);
               $element = str_replace('&gt;', '>', $element);
              
	       $modified_content .= '<div class="code">';
               if ($this->framebox) $modified_content .= '<blockquote>';
               $modified_content .= $this->highlight(trim ($element), $code_language);
               if ($this->framebox) $modified_content .= '</blockquote>';
               $modified_content .= '</div>';
            }
         }
         else
         {
            $modified_content .= ($code_line === -1 ? '<pre>' : '') . $element . ($code_line === -1 ? '</pre>' : '');
         }
      }
      $content = $modified_content;

      return true;
   }
   
   function highlight($source, $language = 'php')
   {
      $geshi =& new GeSHi(str_replace('\"', '"', $source), $language, PATH_TO_GESHI . '/geshi');

      $geshi->set_header_type(GESHI_HEADER_DIV);
      
      if ($this->line_numbers)
      {
         $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
      }

      return $geshi->parse_code();
   }
}

?>

BR,

Laurent


Form is loading...