<?php
/**
* Geshi Syntax Higlighting Plugin for Joomla. Uses the Geshi Highlighting Engine/Class.
* @version 1.0.1
* @copyright (c) 2006, Fiji Web Design, www.fijiwebdesign.com
* @license GNU/GPL
*/
defined( '_VALID_MOS' ) or
die( 'Direct Access to this location is not allowed.' );
$_MAMBOTS->registerFunction( 'onPrepareContent', 'geshibot_onDisplayContent');
// load the geshi bot to parse content
function geshibot_onDisplayContent ($published, &$row, &$params, $page = 0 ) {
global $mosConfig_absolute_path;
-
// check whether mambot has been unpublished
if ( !$published ) {
return true;
}
-
// params
if (!
isset($GLOBALS['GESHIBOT_PARAMS'])) { $GLOBALS['GESHIBOT_PARAMS'] = geshibot_getParams('geshibot', 'content'); // parameters
}
$botParams =& $GLOBALS['GESHIBOT_PARAMS'];
-
if (intval($botParams->
def( 'tag' )) ==
0) { $regex = "/<pre\s*(.*?)>(.*?)<\/pre>/is";
} else {
$regex = "/{geshibot(\s| )*(.*?)}(.*?){\/geshibot}/is";
}
-
// define users gid for access priviledges
if (isset($row->
modified_by) &&
$row->
modified_by !=
0) { $author_id = $row->modified_by;
} else {
$author_id =
isset($row->
created_by) ?
$row->
created_by :
0;
}
geshibot_setGID($author_id);
-
//echo geshibot_object2HTML($row);
-
// replace code with syntax highlighted code
$row->
text =
str_replace('{joomla_dir}',
$mosConfig_absolute_path,
$row->
text);
-
?>
<script type="text/javascript">
<!--
-
<?php
if ($botParams->
def( 'joomla_css' ) ==
'yes' && !
defined('geshi_joomla_css')) { define('geshi_joomla_css',
1);
?>
/**
* Replaces the geshi default classes with mambo/joomla classes
*/
function replaceGeshiWithMamboClasses() {
if (document && document.getElementsByTagName) {
var pre_items = document.getElementsByTagName('pre');
var n = pre_items.length;
for(var i = 0; i < n; i++) {
// divs
var divs = pre_items[i].getElementsByTagName('div');
var dlen = divs.length;
for (var j = 0; j < dlen; j++) {
if (divs[j].className == 'head') { // header
var className = 'sectiontableheader';
} else if (divs[j].className == 'foot') { // footer
var className = 'small';
} else if (divs[j].className == ' ') { // code lines
var className = 'sectiontableentry1';
} else {
var className = '';
}
divs[j].className += ' '+className;
}
-
// anchors
var a_items = pre_items[i].getElementsByTagName('a');
var alen = a_items.length;
for (var l = 0; l < alen; l++) {
a_items[l].target = '_blank';
a_items[l].setAttribute('target', '_blank');
}
-
// list items
var li_items = pre_items[i].getElementsByTagName('li');
var ilen = li_items.length;
for (var k = 0; k < ilen; k++) {
li_items[k].className += ' sectiontableentry1';
}
}
}
}
// initiate our class replacements
addLoadEvent(replaceGeshiWithMamboClasses);
<?php } ?>
-
<?php
if ($botParams->
def( 'show_copy' ) ==
'yes' && !
defined('geshi_show_copy')) { ?>
// add copy link to code highlights
function addCodeView() {
if (document && document.getElementsByTagName) {
var divs = document.getElementsByTagName('div');
var dlen = divs.length;
for (var j = 0; j < dlen; j++) {
var pattern = new RegExp("(^|\\s)foot(\\s|$)");
if ( pattern.test(divs[j].className) ) { // footer class
if (divs[j]._button == 1) continue;
<?php if (intval($botParams->
def( 'show_copy_type')) ==
0) { ?> divs[j].innerHTML += ' <input type="button" onclick="botgeshi_copy(this); return false;" value="<?php echo $botParams->def( 'show_copy_label', 'View Source' ); ?>" class="button" />';
<?php } else { ?>
divs[j].innerHTML += ' <a href="#" onclick="botgeshi_copy(this); return false;"><?php echo $botParams->def( 'show_copy_label', 'View Source' ); ?></a>';
<?php } ?>
divs[j]._button = 1;
}
}
}
}
-
// copy the code text to new window
function botgeshi_copy(_this) {
if (_this && _this.parentNode) {
var source = _this.parentNode.parentNode.nextSibling;
var name = source.className;
var _source = botgeshi_decode(source.innerHTML);
_source = '<textarea style="width: 100%; height: 100%;">'+html2entities(_source)+'</textarea>';
writeSourceWindow(_source, name, '[source view]');
}
}
-
// writes content to a new window
function writeSourceWindow(txt, name, title) {
top.winRef = window.open('', name,
'width=550,height=450'
+',menubar=0'
+',toolbar=0'
+',status=0'
+',scrollbars=0'
+',resizable=1');
top.winRef.document.writeln(
'<html><head><title>'+title+'</title></head>'
+'<body bgcolor=white onLoad="self.focus()">'
+txt
+'</body></html>'
);
top.winRef.document.body.style.overflow = 'hidden'; // hide scroll in FF
top.winRef.document.close();
top.winRef.focus();
}
-
// decode uriencoded text
function botgeshi_decode(txt) {
txt = txt.replace(/\+/g, ' ');
if (decodeURIComponent) {
return decodeURIComponent(txt);
}
if (unescape) {
return unescape(txt);
}
return txt;
}
-
function html2entities(str){
var re = /[<>"'&]/g
str = str.replace(re, function(m) { return replacechar(m); });
return str;
}
-
function replacechar(match){
if (match=="<")
return "<";
else if (match==">")
return ">";
else if (match=="\"")
return """;
else if (match=="'")
return "'";
else if (match=="&")
return "&";
}
-
// initiate our class replacements
addLoadEvent(addCodeView);
<?php } ?>
-
/**
* Adds an onload event to the window
*/
function addLoadEvent(fn) {
if (typeof(window.onload) == 'function') {
var _fn = window.onload;
window.onload = function() {
_fn();
fn();
}
} else {
window.onload = fn;
}
}
-
//-->
</script>
-
<?php
-
return true;
}
// get the right match before sending it to our replace function
function geshibot_replace_init($matches) {
$botParams = $GLOBALS['GESHIBOT_PARAMS'];
-
//echo geshibot_object2HTML($matches);
-
if (intval($botParams->
def( 'tag' )) ==
0) { return geshibot_replace($matches);
} else {
$_matches =
array($matches[0],
str_replace('"',
'"',
$matches[2]),
$matches[3]);
return geshibot_replace($_matches);
}
-
-
}
// callback function for preg_replace_callback
function geshibot_replace($matches) {
-
// language
preg_match("/(language|lang)=\"([^\"]*)\"/",
$matches[1],
$_matches);
$language =
isset($_matches[2]) ?
$_matches[2] :
'';
-
// file
preg_match("/(filepath|file)=\"([^\"]*)\"/",
$matches[1],
$_matches);
$file =
isset($_matches[2]) ?
$_matches[2] :
false;
-
// source, htmlDecoded
if ($file) {
$source = geshibot_file_get_contents($file);
} else {
$source = geshibot_decodeHtmlEntities($matches[2]);
}
-
// header
preg_match("/(header|head)=\"([^\"]*)\"/",
$matches[1],
$_matches);
$header =
isset($_matches[2]) ?
$_matches[2] :
'';
-
// footer
preg_match("/(footer|foot)=\"([^\"]*)\"/",
$matches[1],
$_matches);
$footer =
isset($_matches[2]) ?
$_matches[2] :
' ';
-
//echo geshibot_object2HTML(array('tag_attribs'=>$matches[1], 'language'=>$language, 'header'=>$header, 'footer'=>$footer, 'file'=>$file,'source'=>$source)); // debug
-
// highlight code
$h_source = geshibot_geshi ($source, $language, $header, $footer);
-
// retrieve the geshibot params from super globals Array
$botParams = $GLOBALS['GESHIBOT_PARAMS'];
-
if ($botParams->def( 'show_copy' ) == 'yes') {
// return the highlighted code and original code in a div with unique id
$id =
(isset($GLOBALS['geshibot_load_id'])) ?
$GLOBALS['geshibot_load_id']++ :
0;
$GLOBALS['geshibot_load_id'] = $id;
$o_source =
'<div class="original_source_'.
$id.
'" style="display:none;">'.
rawurlencode($source).
'</div>';
return '<div id="geshibot_load_'.
$id.
'_'.
sha1($source).
'">'.
$h_source.
$o_source.
'</div>';
} else {
// return just the highlighted source
return $h_source;
}
}
function geshibot_geshi ($source, $language = 'php', $header = 'Code:', $footer = ' ') {
// include the geshi class
if (!require_once($GLOBALS['mosConfig_absolute_path'].'/mambots/content/geshibot/geshi.class.php')) {
return false;
}
-
// First the initialisation: source code to highlight and the language to use. Make sure
// you sanitise correctly if you use $_POST of course - this very script has had a security
// advisory against it in the past because of this. Please try not to use this script on a
// live site.
$geshi =& new GeSHi($source, $language);
-
// retrieve the geshibot params from super globals Array
$botParams =& $GLOBALS['GESHIBOT_PARAMS'];
-
// Load the Geshi CSS once for each language, if set in Parameters
if ($botParams->def( 'geshibot_css' ) == 'yes') {
if ( !
defined($language.
'_css') ) { echo '<style type="text/css">';
echo $geshi->
get_stylesheet();
define($language.
'_css',
true);
}
}
-
// Use the PRE header. This means less output source since we don't have to output
// everywhere. Of course it also means you can't set the tab width.
$geshi->set_header_type(GESHI_HEADER_PRE);
-
// Enable CSS classes. You can use get_stylesheet() to output a stylesheet for your code. Using
// CSS classes results in much less output source.
$geshi->enable_classes();
-
// Enable line numbers. We want fancy line numbers, and we want every 5th line number to be fancy
if ($botParams->def( 'lines' ) == 'yes') {
$geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS, $botParams->def( 'fancylinenum' ));
}
-
// Set the style for the PRE around the code. The line numbers are contained within this box (not
// XHTML compliant btw, but if you are liberally minded about these things then you'll appreciate
// the reduced source output).
//$geshi->set_overall_style('color: #000066; border: 1px solid #d0d0d0; background-color: #f0f0f0;', true);
-
// Set the style for line numbers. In order to get style for line numbers working, the <li> element
// is being styled. This means that the code on the line will also be styled, and most of the time
// you don't want this. So the set_code_style reverts styles for the line (by using a <div> on the line).
// So the source output looks like this:
//
// <pre style="[set_overall_style styles]"><ol>
// <li style="[set_line_style styles]"><div style="[set_code_style styles]>...</div></li>
// ...
// </ol></pre>
$geshi->set_line_style('font: normal normal 95% \'Courier New\', Courier, monospace; color: #003030;', 'font-weight: bold; color: #006060;', true);
$geshi->set_code_style('color: #000020;', 'color: #000020;');
// Styles for hyperlinks in the code. GESHI_LINK for default styles, GESHI_HOVER for hover style etc...
// note that classes must be enabled for this to work.
$geshi->set_link_styles(GESHI_LINK, 'color: #000060;');
$geshi->set_link_styles(GESHI_HOVER, 'background-color: #f0f000;');
// Use the header/footer functionality. This puts a div with content within the PRE element, so it is
// affected by the styles set by set_overall_style. So if the PRE has a border then the header/footer will
// appear inside it.
$geshi->set_header_content($header);
//$geshi->set_header_content_style('font-family: Verdana, Arial, sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-bottom: 1px solid #d0d0d0; padding: 2px;');
// You can use <TIME> and <VERSION> as placeholders
$geshi->set_footer_content($footer);
//$geshi->set_footer_content_style('font-family: Verdana, Arial, sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-top: 1px solid #d0d0d0; padding: 2px;');
-
// highlight the code using geshi
return $geshi->parse_code();
}
// get the params set for the plugin
function geshibot_getParams($botname, $folder = 'content') {
-
if ( !
isset($_MAMBOTS->_content_mambot_params
[$botname]) ) { // load mambot params info
$query = "SELECT params"
. "\n FROM #__mambots"
. "\n WHERE element = '$botname'"
. "\n AND folder = '$folder'"
;
$database->setQuery( $query );
$database->loadObject($mambot);
// save query to class variable
$_MAMBOTS->_content_mambot_params[$botname] = $mambot;
}
$mambot = $_MAMBOTS->_content_mambot_params[$botname];
$botParams = new mosParameters( $mambot->params );
return $botParams;
}
// decodes html entities
function geshibot_decodeHtmlEntities($text) {
$html_entities_match =
array( "|\<BR>|",
"|\<br \/\>|",
"#<#",
"#>#",
"|'|",
'#"#',
'# #' );
$html_entities_replace =
array( "\n",
"\n",
'<',
'>',
"'",
'"',
' ' );
$text =
preg_replace( $html_entities_match,
$html_entities_replace,
$text );
/*
// Replace 2 spaces with " " so non-tabbed code indents without making huge long lines.
$text = str_replace(" ", " ", $text);
// now Replace 2 spaces with " " to catch odd #s of spaces.
$text = str_replace(" ", " ", $text);
*/
// Replace tabs with " " so tabbed code indents sorta right without making huge long lines.
//$text = str_replace( "\t", ' ', $text );
return $text;
}
// sets the GID of the author
function geshibot_setGID($id) {
$query = "SELECT gid from #__users WHERE id = $id LIMIT 1";
$database->setQuery($query);
$gid = $database->loadResult();
$GLOBALS['geshibot_author_gid'] = $gid;
}
// gets the content of a file if the article author is allowed access
function geshibot_file_get_contents($file) {
$botParams =& $GLOBALS['GESHIBOT_PARAMS'];
-
if ($GLOBALS['geshibot_author_gid'] <
intval($botParams->
def( 'acl_files' ))) { // this user does not have enough access to get file contents
$content =
$botParams->
def( 'acl_files_msg' ).
' author gid:'.
$GLOBALS['geshibot_author_gid'].
' allowed gid:'.
intval($botParams->
def( 'acl_files' ));
} else {
}
return $content;
}
// object dump function, debugging only
define('geshi_debug',
0);
// 0: off, 1: on define('geshi_dump_type',
1);
// 0: html, 1: raw txt function geshibot_object2HTML($obj, $depth = 0) {
if (geshi_debug == 0) return '';
$html = '';
foreach($obj as $i=>$x) {
$html .= '<div class="obj_parent">';
$html .= '<span>'.$i.'</span>';
$html .= geshibot_object2HTML($x, $depth+1);
$html .= '</div>';
} else {
$html .= '<div class="obj_child" style="padding-left:10px;">'.$i.'=>'.geshi_dump2HTML($x).'</div>';
}
}
$html .=
'<div class="obj_child">'.
var_dump($obj).
'</div>';
// catch empty array } else {
$html .= '<div class="obj_child">'.geshi_dump2HTML($obj).'</div>'; // cactch non-arrays/objects
}
return $html;
}
function geshi_dump2HTML($var) {
if (defined('geshi_dump_type') && geshi_dump_type !=
0) { } else {
}
}
if (geshi_debug == 1) {
?>
<style type="text/css">
.obj_parent {
border: 1px solid gray;
margin: 1px;
}
.obj_child {
border: 1px dotted gray;
margin: 1px;
}
</style>
<?php } ?>