Skip to content

Instantly share code, notes, and snippets.

@meltingice
Created October 2, 2009 01:15
Show Gist options
  • Save meltingice/199371 to your computer and use it in GitHub Desktop.
Save meltingice/199371 to your computer and use it in GitHub Desktop.
<?php
/*
* Osimo - next-generation forum system
* Licensed under GPLv3 (GPL-LICENSE.txt)
*
* os-includes/bbcode/bbparser.php - osimo's bbcode parser
* This can be used on any site, just call bb2html()
*/
function bb2html($post)
{
/*******************************************
* PLEASE READ: If you are not using this *
* BBCode parser as a part of Osimo, change *
* $isOsimo below to false or else you will *
* get errors! *
*******************************************/
$isOsimo = true;
/* Remove all HTML tags from the string just in case any got through somehow */
$post = strip_tags($post);
/* Remove any attempts to run javascript */
$post = str_ireplace('javascript:','',$post);
$post = runNoBBScan($post);
/* Define some basic BBCode */
$bbcode = array(
"[b]","[/b]",
"[i]","[/i]",
"[u]","[/u]",
"[list]","[/list]",
"[*]","[/*]",
"[code]","[/code]",
"[right]","[/right]",
"[left]","[/left]",
"[center]","[/center]",
"[row]","[/row]");
/* ... and its HTML equivalent */
$html = array(
"<strong>","</strong>",
"<i>","</i>",
"<u>","</u>",
"<ul>","</ul>",
"<li>","</li>",
"<code>","</code>",
"<div style=\"text-align:right\">","</div>",
"<div style=\"text-align:left\">","</div>",
"<div style=\"text-align:center\">","</div>",
"<tr>","</tr>");
$post = bbCleaner($post);
/* Convert all the basic BBCodes */
$post = str_ireplace($bbcode,$html,$post);
/* Now for the more complicated BBCode conversion */
$post = runBBScan($post);
$post = str_replace("\n","<br />",$post);
/* Finally, process smilies */
if($isOsimo){ $post = processSmilies($post); }
return $post;
}
/* No-BBCode Scan
* Scans the post and makes sure that
* everything in-between [nocode][/nocode]
* does not get interpreted as bbcode
*/
function runNoBBScan($post,$offset=0)
{
$type = "nocode";
$tag = "[$type]";
$pos = stripos($post,$tag,$offset);
if($pos!==false)
{
$offset = $pos+strlen($tag);
$pos2 = stripos($post,"[/$type]",$offset);
if($pos2!==false)
{
$data = substr($post,$offset,($pos2-$offset));
$offset = $pos2 + strlen("[/$type]");
}
$edited = str_replace("[","&#91;",$data);
$edited = str_replace("]","&#93;",$edited);
$post = substr_replace($post,$edited,$pos,(($pos2+strlen("[/$type]"))-$pos));
return runNoBBScan($post,$offset);
}
return $post;
}
/*
* BBCode cleaner
* Checks to make sure all tags are closed.
* Not too fancy, but avoids html errors
*/
function bbCleaner($post)
{
$bbcode = array(
"b",
"i",
"u",
"list",
"*",
"code",
"right",
"left",
"center"
);
foreach($bbcode as $tag)
{
/* Replace all tags with lower-case versions */
$post = str_ireplace("[$tag]","[$tag]",$post);
$post = str_ireplace("[/$tag]","[/$tag]",$post);
/* Count number of open tags */
$open = substr_count($post,strtolower("[$tag]"));
//$open += substr_count($post,strtoupper("[$tag]"));
/* Count number of closed tags */
$closed = substr_count($post,strtolower("[/$tag]"));
//$closed += substr_count($post,strtoupper("[/$tag]"));
/* Case 1: More open than closed */
if($open>$closed)
{
for($i=0;$i<($open-$closed);$i++)
{
$post .= "[/$tag]";
}
}
/* Case 2: More closed than open */
elseif($closed>$open)
{
for($i=0;$i<($closed-$open);$i++)
{
$post = "[$tag]".$post;
}
}
}
return $post;
}
function runBBScan($post)
{
$post = fancyBB($post,'email');
$post = fancyBB($post,'url');
$post = fancyBB($post,'size');
$post = fancyBB($post,'font');
$post = fancyBB($post,'color');
$post = fancyBB($post,'img');
$post = fancyBB($post,'spoiler');
$post = fancyBB($post,'quote');
$post = fancyBB($post,'align');
$post = fancyBB($post,'cell');
$post = fancyBB($post,'table');
return $post;
}
function fancyBB($post,$type,$offset=0)
{
$tag = "[$type]";
$pos = stripos($post,$tag,$offset);
if($pos!==false)
{
$offset = $pos+strlen($tag);
$pos2 = stripos($post,"[/$type]",$offset);
if($pos2!==false)
{
$data = substr($post,$offset,($pos2-$offset));
$offset = $pos2 + strlen("[/$type]");
$start = $pos;
}
}
else
{
/* check for tag with attribute */
$_tag = "[$type=";
$_pos = stripos($post,$_tag,$offset);
if($_pos!==false)
{
/* Attr found, get value */
$offset = $_pos+strlen($_tag);
$_pos2 = strpos($post,']',$offset);
if($_pos2!==false)
{
/* Got attr value */
$data1 = substr($post,$offset,($_pos2-$offset));
$offset = $_pos2+1;
$_pos3 = stripos($post,"[/$type]",$offset);
if($_pos3!==false)
{
$data2 = substr($post,$offset,($_pos3-$offset));
$offset = $_pos3 + strlen("[/$type]");
$attr = true;
$start = $_pos;
}
}
}
else
{
return $post;
}
}
if($type=='email')
{
if($attr)
{
$search = "[email=".$data1."]".$data2."[/email]";
if(strpos($data1,"\"")!==false){ $data1 = str_replace("\"","",$data1); }
$replace = "<a href=\"mailto:$data1\">$data2</a>";
$end = strlen($search);
}
else
{
$search = "[email]".$data."[/email]";
$replace = "<a href=\"mailto:$data\">$data</a>";
$end = strlen($search);
}
//$post = str_ireplace($search,$replace,$post);
error_log("Replacing $type ($start,$end): $replace");
$post = substr_replace($post,$replace,$start,$end);
}
if($type=='url')
{
if($attr)
{
$search = "[url=".$data1."]".$data2."[/url]";
if(strpos($data1,"\"")!==false){ $data1 = str_replace("\"","",$data1); }
if(strpos($data1,"mailto:")===false)
{
$data1 = urlFilter($data1);
}
$data2 = runBBScan($data2);
$end = strlen("[url=".$data1."]".$data2."[/url]");
$replace = "<a target=\"_blank\" href=\"$data1\">$data2</a>";
}
else
{
$search = "[url]".$data."[/url]";
$data = urlFilter($data);
$end = strlen("[url]".$data."[/url]");
$replace = "<a target=\"_blank\" href=\"$data\">$data</a>";
}
//$post = str_ireplace($search,$replace,$post);
error_log("Replacing $type ($start,$end): $replace");
$post = substr_replace($post,$replace,$start,$end);
}
if($type=='img')
{
$search = "[img]".$data."[/img]";
$data = urlFilter($data);
$replace = "<img src=\"$data\" alt=\"image\" />";
$end = strlen($search);
//$post = str_ireplace($search,$replace,$post);
error_log("Replacing $type ($start,$end): $replace");
$post = substr_replace($post,$replace,$start,$end);
}
if($type=='size')
{
$search = "[size=".$data1."]".$data2."[/size]";
$data2 = runBBScan($data2);
if(strpos($data1,"\"")!==false){ $data1 = str_replace("\"","",$data1); }
if(strpos($data1,"px")!==false){ $replace = "<span style=\"font-size:{$data1}\">{$data2}</span>"; }
else { $replace = "<span style=\"font-size:{$data1}px\">{$data2}</span>"; }
$end = strlen("[size=".$data1."]".$data2."[/size]");
//$post = str_ireplace($search,$replace,$post);
error_log("Replacing $type ($start,$end): $replace");
$post = substr_replace($post,$replace,$start,$end);
}
if($type=='font')
{
$search = "[font=".$data1."]".$data2."[/font]";
$data2 = runBBScan($data2);
if(strpos($data1,"\"")!==false){ $data1 = str_replace("\"","",$data1); }
$replace = "<span style=\"font-family:{$data1}\">{$data2}</span>";
//$post = str_ireplace($search,$replace,$post);
$end = strlen("[font=".$data1."]".$data2."[/font]");
error_log("Replacing $type ($start,$end): $replace");
$post = substr_replace($post,$replace,$start,$end);
}
if($type=='color')
{
$search = "[color=".$data1."]".$data2."[/color]";
$data2 = runBBScan($data2);
if(strpos($data1,"\"")!==false){ $data1 = str_replace("\"","",$data1); }
$replace = "<span style=\"color:{$data1}\">{$data2}</span>";
$end = strlen("[color=".$data1."]".$data2."[/color]");
//$post = str_ireplace($search,$replace,$post);
error_log("Replacing $type ($start,$end): $replace");
$post = substr_replace($post,$replace,$start,$end);
}
if($type=='spoiler')
{
$search = "[spoiler]".$data."[/spoiler]";
$data = runBBScan($data);
$replace = "<span style=\"background: #000000 none repeat scroll 0% 0%; color: #000000; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial\">{$data}</span>";
//$post = str
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment