diff --git a/tools/docgen/generate/updater.php b/tools/docgen/generate/updater.php
new file mode 100755
index 00000000..9f8c5f23
--- /dev/null
+++ b/tools/docgen/generate/updater.php
@@ -0,0 +1,566 @@
+
$lin) {
+ $line = trim($lin);
+
+ if($line == "") continue;
+
+ if(substr($line,0,7) == "#define")
+ AddDefine(substr($line,8));
+
+ if(($line == "/**" && !$isanotherone) || $linescount == $line_num){
+ if(isset($lines[1])){
+ $temp = explode(" ",$lines[1][0]);
+ $type = GetFunctionType($temp[0]);
+ if($type > 0){
+ MakeFunction($lines, implode("", $lines[1]) ,$type,$basename);
+ }else
+ MakeConstant($lines,$basename);
+ }
+
+ $lines = Array();
+ $isanotherone = false;
+ $commented = true;
+ }
+
+ if($line == "{")
+ $isanotherone = true;
+ elseif($line{0} == "}")
+ $isanotherone = false;
+
+ if($commented){
+ $lines[0][] = $line;
+ } else {
+ $lines[1][] = $lin;
+ }
+
+ if($line == "*/" && !$isanotherone)
+ $commented = false;
+ }
+ return implode("",$thelines);
+}
+
+function AddDefine($str){
+ if($str{0} == "_")
+ return;
+ global $defines;
+
+ //Sryl, Preg match is just not working out, too much iregularitires
+ //The * will bug the preg_match
+ /*$str = str_replace("*","",$str);
+ $pattern = '/([$A-Z|8|_^]+)\b([^.*]+)([ | | ]\/)/';
+
+ if(!preg_match($pattern, $str, $matches,PREG_OFFSET_CAPTURE)){
+ echo $str . "\n";
+ return;
+ }
+
+ $new = substr($str , $matches[2][1] + strlen($matches[2][0]) );
+ if(strlen($new) > 0){
+ $new = str_replace(
+ Array ("/**", "<" , "","/"),
+ Array ("", "" , "",""),
+ $new
+ );
+ }
+ */
+ $stage = 0;
+ $stageinfo = Array('','','');
+
+ $strlen = strlen($str);
+ for($i=0; $i < $strlen; $i++){
+ if(trim($str{$i}) == "" && $stage == 0){
+ $stage++;
+ continue;
+ }
+
+ if($str{$i} == "/"){
+ if(substr($str,$i,3) == "/**"){
+ $stage++;
+ $i += 3;
+ continue;
+ }
+ }
+
+ if($str{$i} == "*"){
+ if(substr($str,$i,2) == '*/'){
+ break;
+ }
+ }
+ $stageinfo[$stage] .= $str{$i};
+ }
+
+ foreach($stageinfo as $i => $a)
+ $stageinfo[$i] = trim($a);
+
+ if($stageinfo[1] != ""){
+ $defines[] = Array (
+ 'variable' => $stageinfo[0],
+ 'value' => wordwrap(trim($stageinfo[1]) , 35, " " , true ),
+ 'comment' => isset($stageinfo[2]) ? trim($stageinfo[2]) : "",
+ );
+ }
+
+
+ if($stageinfo[0] == "SOURCEMOD_VERSION"){
+ global $version;
+ $version = str_replace('"',"",$stageinfo[1]);
+ }
+}
+
+function MakeConstant($lines,$file){
+ global $consts;
+
+ $info = Array();
+ $content = Array();
+
+ foreach($lines[0] as $line){
+ if(substr($line,0,1) != "*") continue;
+ $thesub = trim(substr($line,2));
+ if($thesub == "") continue;
+
+ $info[] = $thesub;
+ }
+
+ $theinfo = str_replace("@section","", implode("\n",$info));
+
+ if(strpos($theinfo,"All rights reserved.")){
+ $theinfo = "Unclassified ";
+ $newline = Array();
+
+ foreach($lines[1] as $lin){
+ $line = trim($lin);
+ if(substr($line,0,7) == "#define" && $line{8} != "_")
+ $newline[] = $line . "\n";
+ }
+ if(count($newline) == 0)
+ return;
+
+ $lines[1] = $newline;
+ }
+
+ $consts[] = Array(
+ 'info' => $theinfo,
+ 'content' => trim(implode('',$lines[1])),
+ 'file' => $file,
+ );
+}
+
+function MakeFunction($lines,$function,$type,$file){
+ global $funcs;
+
+ $description = Array();
+ $funcinput = Array();
+ $return = Array();
+ $onerror = Array();
+ $notes = Array();
+ $depreached = 0;
+
+ $infostarted = false;
+ $lastone = 0;
+
+
+ foreach($lines[0] as $line){
+ if(substr($line,0,1) != "*") continue;
+ $thesub = trim(substr($line,2));
+ if($thesub == "") continue;
+
+
+ if ($thesub{0} == "@")
+ $infostarted = true;
+
+ if(!$infostarted){
+ $description[] = $thesub;
+ }
+
+ if ($infostarted && $thesub{0} != "@"){
+ switch ($lastone) {
+ case 0:
+ // if(!isset($funcinput[ count($funcinput) - 1 ]))
+ // echo $file . "\n" . $function . "\n\n";
+ $funcinput[ count($funcinput) - 1 ] .= " " . $thesub;
+ break;
+ case 1: $return[ count($return) - 1 ] .= " " . $thesub; break;
+ case 2: $onerror[ count($onerror) - 1 ] .= " " . $thesub; break;
+ case 3: $notes[ count($notes) - 1 ] .= " " . $thesub; break;
+ case 4: $description[ count($description) - 1 ] .= " " . $thesub; break;
+ }
+ }
+
+ if(!$infostarted)
+ $continue;
+
+ if(substr($thesub, 0, 7) == "@return"){
+ $return[] = trim(substr($thesub, 7));
+ $lastone = 1;
+ } elseif(substr($thesub, 0, 11) == "@deprecated"){
+ $depreached = 1;
+ } elseif(substr($thesub, 0, 6) == "@error"){
+ $onerror[] = trim(substr($thesub, 6));
+ $lastone = 2;
+ } elseif(substr($thesub, 0, 9) == "@noreturn"){
+ $return[] = 0;
+ } elseif(substr($thesub, 0, 5) == "@note"){
+ $notes[] = substr($thesub, 5);
+ $lastone = 3;
+ } elseif(substr($thesub, 0, 6) == "@param") {
+ $funcinput[] = substr($thesub, 6);
+ $lastone = 0;
+ } elseif(substr($thesub, 0, 6) == "@brief") {
+ $description[] = substr($thesub, 6);
+ $lastone = 4;
+ }
+ }
+
+ /*$fullcommand = str_replace(
+ Array("Float:","Handle:","Action:","bool:","any:","GroupId:","Function:","ReplySource:","QueryCookie:"),
+ Array("","","","","","","","",""),
+ $function);*/
+
+ $temp = explode("(",$function);
+ $func = $temp[0];
+ if(strpos($func, " ") !== false){
+ $func = trim(substr( $func , strpos($func , " ") ));
+ }
+
+ if(strpos($function, "{") !== false){
+ $function = trim(substr( $function, 0, strpos($function, "{") ));
+ }
+
+ $thestrpos = strpos($func,":");
+ if($thestrpos !== false){
+ $func = substr($func ,$thestrpos + 1);
+ }
+
+ $funcs[] = Array(
+ 'description' => implode("\n",$description),
+ 'input' => implode("\n",$funcinput),
+ 'function' => $func,
+ 'fullfunc' => trim($function),
+ 'return' => implode("\n",$return),
+ 'onerror' => implode("\n",$onerror),
+ 'notes' => implode("\n",$notes),
+ 'file' => $file,
+ 'typeof' => $type,
+ 'depreached' => $depreached
+ );
+}
+
+function db_query($query){
+ $q = mysql_query($query);
+ if(!$q){
+ echo "\n" . mysql_error() . "\n" . $query . " ";
+ }
+ return $q;
+}
+
+function GetFileAddr(){
+ $lines = file("http://www.sourcemod.net/builds.php");
+
+ foreach ($lines as $line_num => $lin) {
+ if(substr($lin, 0, 13) == " ", $a);
+ return $b[0];
+ }
+ }
+ }
+ }
+}
+
+function DownloadNew(){
+ global $thebasedir;
+ copy( GetFileAddr() ,'build.zip');
+
+ $zip = new ZipArchive;
+ if ($zip->open('build.zip') === TRUE) {
+ $zip->extractTo($thebasedir . "/build/" );
+ $zip->close();
+ } else {
+ exit( 'Failed to zip' );
+ }
+}
+
+function full_rmdir( $dir ){
+ if ( !is_writable( $dir ) ){
+ if ( !@chmod( $dir, 0777 ) ){
+ return FALSE;
+ }
+ }
+ $d = dir( $dir );
+ while ( FALSE !== ( $entry = $d->read() ) ){
+ if ( $entry == '.' || $entry == '..' ){
+ continue;
+ }
+ $entry = $dir . '/' . $entry;
+ if ( is_dir( $entry ) ){
+ if ( !$this->full_rmdir( $entry ) ){
+ return FALSE;
+ }
+ continue;
+ }
+ if ( !@unlink( $entry ) ){
+ $d->close();
+ return FALSE;
+ }
+ }
+ $d->close();
+ return rmdir( $dir );
+}
+
+function FindFileID($file){
+ global $tableinfo;
+ foreach($tableinfo['sm_smfiles'] as $fname => $id)
+ if($file == $fname)
+ return $id;
+ return -1;
+}
+
+
+function FindUnusedid($arrayname){
+ global $tableinfo;
+// if(!isset($tableinfo[ $arrayname ]))
+// return 0;
+
+ $tempinfo = array_flip($tableinfo[ $arrayname ]);
+ $i = 0;
+ //Hope this works!!
+ while( TRUE ){
+ if(!isset($tempinfo[ $i ]))
+ return $i;
+ $i++;
+ }
+}
+
+
+if($downloadnew)
+ DownloadNew();
+if(strlen(trim($dir)) == 0)
+ $dir = $thebasedir . '/build/addons/sourcemod/scripting/include';
+$files = Array();
+
+if(!($dir_handle = opendir($dir))){
+ exit('Could not open ' . $dir);
+}
+
+while($file = readdir($dir_handle)){
+ if($file == "." || $file == "..") continue;
+
+ if(substr($file, -4, 4) == ".inc"){
+ $filedir = $dir . "/" . $file;
+
+// if($file == "version.inc"){
+// GetVersion($filedir);
+// } else {
+ $files[] = Array(
+ 'Addr' => $filedir,
+ 'name' => $file,
+// 'fcount' => 0,
+// 'ccount' => 0,
+ 'content' => DecodeTheFile($filedir),
+ );
+// }
+ }
+}
+closedir($dir_handle);
+
+$link = mysql_connect($host, $user, $password)
+ or die('Could not connect: ' . mysql_error());
+mysql_select_db($database) or die('Could not select database');
+
+
+db_query("TRUNCATE TABLE `sm_smconst`");
+db_query("TRUNCATE TABLE `sm_smfilescon`");
+db_query("TRUNCATE TABLE `sm_smdefine`");
+db_query("UPDATE sm_smfunctions SET depreached = 2 WHERE typeof <> 4");
+
+//db_query("TRUNCATE TABLE `smfiles`");
+//db_query("TRUNCATE TABLE `smfunctions`");
+
+$tables = Array (
+ 'sm_smfiles' => Array ('filename','id'),
+ 'sm_smfunctions' => Array ('func','id'),
+);
+
+foreach ($tables as $name => $table){
+ $result = db_query('SELECT ' . $table[0] . ',' . $table[1] . ' FROM ' . $name);
+
+ $tableinfo[$name] = Array();
+
+ while ($line = mysql_fetch_array($result, MYSQL_NUM)) {
+ $tableinfo[$name][$line[0]] = $line[1];
+ }
+
+ mysql_free_result($result);
+}
+
+foreach($files as $file){
+ $onlyname = str_replace('.inc','',$file['name']);
+
+ if(!isset($tableinfo['sm_smfiles'][ $file['name'] ])){
+ //0 is a ID, so count will make it just right...
+ $tableinfo['sm_smfiles'][ $file['name'] ] = FindUnusedid('sm_smfiles');
+ db_query('INSERT INTO sm_smfiles(id,name,filename) VALUES ('. $tableinfo['sm_smfiles'][ $file['name'] ] .',"'.$onlyname.'","'.$file['name'].'")');
+ }
+
+ db_query('INSERT INTO `sm_smfilescon` VALUES ('. $tableinfo['sm_smfiles'][ $file['name'] ] .',\''. addslashes( $file['content'] ) .'\')');
+
+ $javascript .= 'SMfiles['. $tableinfo['sm_smfiles'][ $file['name'] ] .'] = "'. $onlyname .'"' . "\n";
+
+}
+
+
+foreach($funcs as $go){
+ $gop = str_replace('"', '\"', $go );
+
+ $fid = FindFileID($gop['file']);
+
+ $javacontent = PrepareJava($gop['description'] );
+
+ if(isset($tableinfo['sm_smfunctions'][ $gop['function'] ])){
+ $sql = 'UPDATE sm_smfunctions
+ SET fullfunc = "'.$gop['fullfunc'].'",
+ description = "'.$gop['description'].'",
+ `treturn` = "'.$gop['return'].'",
+ `onerror` = "'.$gop['onerror'].'",
+ `funcinput` = "'.$gop['input'].'",
+ inc = '.$fid.',
+ incname = "'.$gop['file'].'",
+ typeof ='.$gop['typeof'].',
+ depreached = '.$gop['depreached'].'
+ WHERE id = '. $tableinfo['sm_smfunctions'][ $gop['function'] ] .'';
+ } else {
+ $tableinfo['sm_smfunctions'][ $gop['function'] ] = FindUnusedid('sm_smfunctions');
+ $sql = 'INSERT INTO sm_smfunctions(id,func,fullfunc,description,`treturn`,`onerror`,`funcinput`,inc,incname,typeof,version) VALUES
+ ('. $tableinfo['sm_smfunctions'][ $gop['function'] ] .',
+ "'.$gop['function'].'",
+ "'.$gop['fullfunc'].'",
+ "'.$javacontent.'",
+ "'.$gop['return'].'",
+ "'.$gop['onerror'].'",
+ "'.$gop['input'].'",
+ '.$fid.',
+ "'.$gop['file'].'",
+ '.$gop['typeof'].',
+ \''.$version.'\'
+ )';
+ }
+
+ $javascript .= 'SMfunctions['. $tableinfo['sm_smfunctions'][ $gop['function'] ] .'] = Array ("'.$gop['function'].'","'.$javacontent.'");' . "\n";
+
+ $filefunclist[$fid][] = $tableinfo['sm_smfunctions'][ $gop['function'] ];
+
+ $query = db_query($sql);
+}
+
+foreach($consts as $go){
+ $gop = str_replace('"', '\"', $go );
+ $fid = FindFileID($gop['file']);
+
+ $sql = 'INSERT INTO sm_smconst(fileid,descrip,`fulltext`) VALUES
+ ('.$fid.',
+ "'.$gop['info'].'",
+ "'.$gop['content'].'"
+ )';
+
+ $query = db_query($sql);
+}
+
+foreach($filefunclist as $id => $go){
+ $javascript .= 'SMfiledata['. $id .'] = Array ('. implode(",",$go) .');' . "\n";
+}
+
+foreach($defines as $id => $go){
+ $gop = str_replace('"', '\"', $go );
+ $sql = 'INSERT INTO `sm_smdefine` (`id`,`variable` ,`value` ,`comment`) VALUES ('.$id.',"'.$gop['variable'].'", "'.$gop['value'].'", "'.$gop['comment'].'")';
+ $javascript .= 'SMconstant['.$id.'] = Array ("'. PrepareJava($gop['variable']) .'","'. PrepareJava($gop['value']) .'","'. PrepareJava($gop['comment']) .'");' . "\n";
+ db_query($sql);
+}
+
+db_query('UPDATE `sm_sminfo` SET infob = "'.$version.'" WHERE master = "version"');
+
+foreach($tableinfo['sm_smfiles'] as $fid){
+ db_query('UPDATE sm_smfiles SET
+`fcount` = (SELECT COUNT(*) FROM sm_smfunctions WHERE inc = '.$fid.'),
+`ccount` = (SELECT COUNT(*) FROM sm_smconst WHERE fileid = '.$fid.')
+WHERE id = '.$fid.'');
+}
+
+$res = mysql_query("SELECT id FROM sm_smfunctions WHERE depreached = 2");
+while (($row = mysql_fetch_array($res)) !== FALSE)
+{
+ db_query("DELETE FROM sm_smposts WHERE func = " . $row[0]);
+ db_query("DELETE FROM sm_smfunctions WHERE id = " . $row[0]);
+}
+
+mysql_free_result($res);
+
+mysql_close($link);
+
+//$filename = "SMfuncs.js";
+if (!$handle = fopen($filename, 'w')) {
+ echo "Cannot open file ($filename)";
+ exit;
+}
+
+echo $javascript;
+
+ // Write $somecontent to our opened file.
+if (fwrite($handle, $javascript) === FALSE) {
+ echo "Cannot write to file ($filename)";
+ exit;
+}
+
+fclose($handle);
+
+?>
diff --git a/tools/docgen/sql/schema.sql b/tools/docgen/sql/schema.sql
new file mode 100644
index 00000000..17eadc21
--- /dev/null
+++ b/tools/docgen/sql/schema.sql
@@ -0,0 +1,163 @@
+-- phpMyAdmin SQL Dump
+-- version 4.2.2
+-- http://www.phpmyadmin.net
+--
+-- Host: db01
+-- Generation Time: Jul 31, 2014 at 12:10 PM
+-- Server version: 5.5.11-log
+-- PHP Version: 5.5.13
+
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET time_zone = "+00:00";
+
+--
+-- Database: `smdocs`
+--
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `sm_smconst`
+--
+
+CREATE TABLE IF NOT EXISTS `sm_smconst` (
+`id` int(11) NOT NULL,
+ `fileid` int(11) NOT NULL,
+ `descrip` tinytext NOT NULL,
+ `fulltext` text NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=141 ;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `sm_smdefine`
+--
+
+CREATE TABLE IF NOT EXISTS `sm_smdefine` (
+ `id` int(11) NOT NULL,
+ `variable` varchar(64) NOT NULL,
+ `value` tinytext NOT NULL,
+ `comment` tinytext NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `sm_smfiles`
+--
+
+CREATE TABLE IF NOT EXISTS `sm_smfiles` (
+ `id` int(11) NOT NULL,
+ `name` varchar(32) NOT NULL,
+ `filename` varchar(32) NOT NULL,
+ `fcount` int(11) NOT NULL,
+ `ccount` int(11) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `sm_smfilescon`
+--
+
+CREATE TABLE IF NOT EXISTS `sm_smfilescon` (
+ `id` int(11) NOT NULL,
+ `cont` text NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `sm_smfunctions`
+--
+
+CREATE TABLE IF NOT EXISTS `sm_smfunctions` (
+ `id` int(11) NOT NULL,
+ `func` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
+ `fullfunc` text NOT NULL,
+ `description` text NOT NULL,
+ `treturn` tinytext NOT NULL,
+ `onerror` tinytext NOT NULL,
+ `funcinput` text NOT NULL,
+ `exemple` text NOT NULL,
+ `inc` int(11) NOT NULL,
+ `incname` varchar(32) NOT NULL,
+ `typeof` int(11) NOT NULL,
+ `depreached` tinyint(1) NOT NULL,
+ `version` varchar(32) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `sm_sminfo`
+--
+
+CREATE TABLE IF NOT EXISTS `sm_sminfo` (
+ `master` varchar(32) NOT NULL,
+ `infoa` int(11) NOT NULL,
+ `infob` varchar(32) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `sm_smposts`
+--
+
+CREATE TABLE IF NOT EXISTS `sm_smposts` (
+`id` int(11) NOT NULL,
+ `file` int(11) NOT NULL,
+ `func` int(11) NOT NULL,
+ `time` int(11) NOT NULL,
+ `poster` varchar(32) NOT NULL,
+ `body` text NOT NULL,
+ `ip` varchar(16) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=311 ;
+
+--
+-- Indexes for dumped tables
+--
+
+--
+-- Indexes for table `sm_smconst`
+--
+ALTER TABLE `sm_smconst`
+ ADD PRIMARY KEY (`id`), ADD KEY `fileid` (`fileid`);
+
+--
+-- Indexes for table `sm_smdefine`
+--
+ALTER TABLE `sm_smdefine`
+ ADD PRIMARY KEY (`id`);
+
+--
+-- Indexes for table `sm_smfiles`
+--
+ALTER TABLE `sm_smfiles`
+ ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `name` (`name`);
+
+--
+-- Indexes for table `sm_smfilescon`
+--
+ALTER TABLE `sm_smfilescon`
+ ADD PRIMARY KEY (`id`);
+
+--
+-- Indexes for table `sm_smfunctions`
+--
+ALTER TABLE `sm_smfunctions`
+ ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `name` (`func`), ADD KEY `inc` (`inc`);
+
+--
+-- Indexes for table `sm_sminfo`
+--
+ALTER TABLE `sm_sminfo`
+ ADD KEY `master` (`master`);
+
+--
+-- Indexes for table `sm_smposts`
+--
+ALTER TABLE `sm_smposts`
+ ADD PRIMARY KEY (`id`), ADD KEY `ip` (`ip`);
+
diff --git a/tools/docgen/www/Login.php b/tools/docgen/www/Login.php
new file mode 100644
index 00000000..5c92b30d
--- /dev/null
+++ b/tools/docgen/www/Login.php
@@ -0,0 +1,112 @@
+ 100)
+ return 'Invalid user or password.';
+
+ mysql_select_db('am');
+
+ $query = db_query('SELECT userid, password, salt FROM vb_user WHERE username = "'. mysql_real_escape_string($_REQUEST['user']) .'"');
+
+ if(mysql_num_rows($query) == 0){
+ mysql_free_result($query);
+ mysql_select_db($dbname);
+ return 'Invalid user or password.';
+ }
+
+ $info = mysql_fetch_array($query, MYSQL_ASSOC);
+
+ $pw = md5($_REQUEST['pw'] . $info['salt'] );
+
+ //echo $pw . ' ';
+
+ if($pw != $info['password']){
+ mysql_free_result($query);
+ mysql_select_db($dbname);
+ return 'Invalid user or password.';
+ }
+
+ if(isset($_REQUEST['forever']) && $_REQUEST['forever'] == 1)
+ $time = 0;
+ else
+ $time = time() + 3600 * 24;
+
+
+ $data = serialize( Array($info['userid'], md5($pw . $context['user']['ip'])) );
+
+ //print_r($data);
+
+ //Yay, by now he has login and password correct, let's give him a cookie
+ setcookie($cookiename, $data, $time, '/', $cookieaddr, 0 ,1);
+
+ mysql_free_result($query);
+ mysql_select_db($dbname);
+
+ return 'ok';
+}
+
+
+
+?>
diff --git a/tools/docgen/www/Settings.php b/tools/docgen/www/Settings.php
new file mode 100755
index 00000000..2e8c0440
--- /dev/null
+++ b/tools/docgen/www/Settings.php
@@ -0,0 +1,19 @@
+
diff --git a/tools/docgen/www/Source.php b/tools/docgen/www/Source.php
new file mode 100644
index 00000000..2688ae7d
--- /dev/null
+++ b/tools/docgen/www/Source.php
@@ -0,0 +1,358 @@
+";
+ }
+ return $q;
+}
+
+function Main(){
+ global $context;
+ $context['optheader'] = "Main";
+
+ $resul = db_query('SELECT id,name,fcount,ccount FROM `sm_smfiles`',__FILE__,__LINE__);
+ while ($line = mysql_fetch_array($resul, MYSQL_ASSOC)) {
+ $context['fileinfo'][] = Array(
+ 'id' => $line['id'],
+ 'name' => $line['name'],
+ );
+ }
+
+ usort($context['fileinfo'], "SortByName");
+
+}
+
+function SortByName($a, $b)
+{
+ if ($a['name'] == $b['name']) {
+ return 0;
+ }
+ return ($a['name'] < $b['name']) ? -1 : 1;
+}
+
+
+function ShowOpts(){
+ global $context;
+
+ if(!isset($_GET['id']) || $_GET['id'] == "")
+ exit("No Results found.");
+
+ if(strlen($_GET['id']) > 30)
+ exit("No Results found.");
+
+ $context['usetopandbo'] = Array ( false,false);
+
+ $query = 'SELECT id,func,inc FROM `sm_smfunctions` WHERE LCASE(func) LIKE \'%'.strtolower(mysql_real_escape_string($_GET['id'])).'%\' OR description LIKE \'%'.mysql_real_escape_string($_GET['id']).' %\' COLLATE latin1_swedish_ci';
+ $result = db_query($query,__FILE__,__LINE__);
+
+ $context['answers'] = Array();
+
+ $context['numresults'] = mysql_num_rows($result);
+
+ if($context['numresults'] > 100)
+ return;
+
+ $files = Array ();
+ $i = 0;
+
+ if($context['numresults'] > 0){
+ while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
+ $context['answers'][ $line['inc'] ][ $line['id'] ] = $line['func'];
+
+ $context['lastone'][ $line['inc'] ] = $line['id'];
+
+ if(!isset( $files [ $line['inc'] ])){
+ $files [ $line['inc'] ] = $i;
+ $i++;
+ }
+ }
+
+ $fliped = array_flip( $files );
+ $query = db_query('SELECT id,name FROM `sm_smfiles` WHERE id IN ('. implode(",",$fliped) .')',__FILE__,__LINE__);
+
+ while ($line = mysql_fetch_array($query, MYSQL_ASSOC)) {
+ $context['files'][ $line['id'] ] = $line['name'];
+ }
+ }
+}
+
+function ShowInfo(){
+ global $context;
+
+ if(!isset($_GET['id']) || $_GET['id'] == "")
+ exit("No Results found.");
+
+ $query = 'SELECT func,fullfunc,description,treturn,funcinput,exemple,inc,incname,typeof,onerror,version FROM `sm_smfunctions` WHERE id = '.intval($_GET['id']).' LIMIT 1';
+ $result = db_query($query,__FILE__,__LINE__);
+
+
+ $context['numresults'] = mysql_num_rows($result);
+
+ if($context['numresults'] > 0){
+ $context['answers'] = mysql_fetch_array($result, MYSQL_ASSOC);
+ $context['topmenu'][] = Array (
+ $context['answers']['incname'],
+ 'index.php?action=file&id='.$context['answers']['inc']
+ );
+ $context['optheader'] = $context['answers']['func'];
+
+
+ $result = db_query('SELECT fcount,ccount FROM `sm_smfiles` WHERE id = '.$context['answers']['inc'].' LIMIT 1',__FILE__,__LINE__);
+ $context['fileinfo'] = mysql_fetch_array($result, MYSQL_ASSOC);
+
+ $result = db_query('SELECT time,poster,body FROM `sm_smposts` WHERE file = '.$context['answers']['inc'].' AND func = '.intval($_GET['id']).'',__FILE__,__LINE__);
+ $context['sm']['pcount'] = mysql_num_rows($result);
+ if($context['sm']['pcount'] > 0){
+ $context['sm']['posts'] = Array();
+ while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
+ $context['sm']['posts'][] = Array (
+ 'poster' => $line['poster'],
+ 'time' => date("F j, Y, g:i a",$line['time']),
+ 'body' => parse_bbc($line['body']),
+ );
+ }
+ }
+ }
+}
+
+function ShowFile(){
+ global $context;
+
+ if(!isset($_GET['id']) || $_GET['id'] == "" || strlen($_GET['id']) > 2)
+ exit("No Results found.");
+
+ $result = db_query('SELECT name,filename,fcount,ccount FROM `sm_smfiles` WHERE id = '.intval($_GET['id']).' LIMIT 1',__FILE__,__LINE__);
+
+ $context['letters'] = Array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v');
+ $context['numresults'] = mysql_num_rows($result);
+
+ if($context['numresults'] > 0){
+ $info = mysql_fetch_array($result, MYSQL_ASSOC);
+
+ $context['name'] = $info['name'];
+ $context['filename'] = $info['filename'];
+ $context['fcount'] = $info['fcount'];
+ $context['ccount'] = $info['ccount'];
+ $context['optheader'] = $info['filename'];
+
+ $result = db_query('SELECT time,poster,body FROM `sm_smposts` WHERE file = '.intval($_GET['id']).' AND func = -1',__FILE__,__LINE__);
+ $context['sm']['pcount'] = mysql_num_rows($result);
+ if($context['sm']['pcount'] > 0){
+ $context['sm']['posts'] = Array();
+ while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
+ $context['sm']['posts'][] = Array (
+ 'poster' => $line['poster'],
+ 'time' => date("F j, Y, g:i a",$line['time']),
+ 'body' => parse_bbc($line['body']),
+ );
+ }
+ }
+
+
+ $context['topmenu'][] = Array (
+ $context['filename'],
+ 'index.php?action=file&id='.$_GET['id']
+ );
+
+ if(isset($_GET['type']) && $info['fcount'] > 0) return LoadThis(0);
+ if(isset($_GET['file'])) return LoadThis(2);
+ if($info['ccount'] > 0) return LoadThis(1);
+ if($info['fcount'] > 0) return LoadThis(0);
+ return LoadThis(2);
+ }
+
+}
+
+function LoadThis($type){
+ global $context;
+ $context['goon'] = $type;
+
+ switch($type){
+ case 0:
+ $resul = db_query('SELECT id,func,description FROM `sm_smfunctions` WHERE inc = '.intval($_GET['id']).'',__FILE__,__LINE__);
+ while ($line = mysql_fetch_array($resul, MYSQL_ASSOC)) {
+ $context['infos'][] = Array(
+ 'id' => $line['id'],
+ 'func' => $line['func'],
+ 'desc' => $line['description'],
+ );
+ }
+ break;
+ case 1:
+ $resul = db_query('SELECT descrip,`fulltext` FROM `sm_smconst` WHERE fileid = '.intval($_GET['id']).'',__FILE__,__LINE__);
+ while ($line = mysql_fetch_array($resul, MYSQL_ASSOC)) {
+ $context['infos'][] = $line;
+ }
+ break;
+ case 2:
+ $resul = db_query('SELECT cont FROM `sm_smfilescon` WHERE id = '.intval($_GET['id']).'',__FILE__,__LINE__);
+ $context['infos'] = mysql_fetch_array($resul, MYSQL_ASSOC);
+ break;
+ }
+}
+
+function HighLight(){
+ global $context;
+
+ $context['goon'] = isset($_GET['goon']);
+
+ if($context['goon']){
+ if(isset($_POST['signature']) && trim($_POST['signature']) != ""){
+ $newinfo =stripslashes($_POST['signature']);
+ HighLightThis($newinfo);
+ } elseif (is_uploaded_file($_FILES['uploadedfile']['tmp_name'])) {
+ switch ($_FILES['uploadedfile']['error']){
+ case 1: $context['imagerror'] = 'The uploaded file exceeds max size.'; break;
+ case 2: $context['imagerror'] = 'The uploaded file exceeds max size.'; break;
+ case 3: $context['imagerror'] = 'The uploaded file was only partially uploaded.'; break;
+ case 7: $context['imagerror'] = 'Failed to write file to disk.'; break;
+ case 8: $context['imagerror'] = 'File upload stopped by extension.'; break;
+ }
+
+ if(isset($context['imagerror']))
+ return;
+
+ $code = file_get_contents($_FILES['uploadedfile']['tmp_name']);
+ HighLightThis($code);
+
+ $context['topmenu'][] = Array (
+ $_FILES['uploadedfile']['name'],
+ 'index.php?action=codehigh'
+ );
+ } else {
+ $context['imagerror'] = 'Could not upload file, or no data found.';
+ $context['topmenu'][] = Array (
+ 'MyCode',
+ 'index.php?action=codehigh'
+ );
+ }
+ }
+}
+
+function HighLightThis($code){
+ global $context;
+
+ $search[0] = Array('<?php ','?>');
+ $replace[1] = Array('','');
+
+ $theresults = Array();
+
+ $result = mysql_query('SELECT id,func FROM sm_smfunctions') or die('Query failed: ' . mysql_error());
+ while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
+ $theresults[] = Array (
+ 'id' => $line['id'],
+ 'func' => $line['func'],
+ 'strlen' => strlen($line['func']),
+ );
+ }
+
+ //I need to sort it and do that stupid thing of $thereplaceid so that one function becomes two, like SetClientListeningFlags and SetClientListening
+ usort($theresults, "CompareSTRLEN");
+
+ foreach($theresults as $go){
+ $thereplaceid = "!>";
+ $search[0][] = $go['func'];
+ $replace[0][] = $thereplaceid;
+
+ $search[1][] = $thereplaceid;
+ $replace[1][] = ' ' . $go['func'] . ' ';
+ }
+
+ $result = mysql_query('SELECT id,variable FROM sm_smdefine') or die('Query failed: ' . mysql_error());
+ while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
+ $search[2][] = $line['variable'];
+ $replace[2][] = '' . $line['variable'] . ' ';
+ }
+
+ $str = highlight_string('', true);
+ $str = str_replace($search[0], $replace[0], $str);
+ $str = str_replace($search[1], $replace[1], $str);
+ $str = str_replace($search[2], $replace[2], $str);
+
+ $context['str'] = $str; //explode(" ",$str);
+}
+
+function PreviewPost(){
+ echo parse_bbc(stripslashes($_POST['message']));
+ die();
+}
+
+function PostThis(){
+ global $context,$templatefunc;
+
+ if($context['user']['guest'])
+ exit("3");
+
+ if(!isset($_GET['id']) || $_GET['id'] == '' || strlen($_GET['id']) > 5)
+ exit("0");
+
+ $typearray = Array ( 'file' , 'func');
+ if(!isset($_GET['type']) || array_search($_GET['type'], $typearray) === false)
+ exit("0");
+
+ if(!isset($_POST['message']) || $_POST['message'] == '')
+ exit("1");
+
+ $time = time();
+
+ $query = db_query('SELECT time FROM sm_smposts WHERE ip = "'.$context['user']['ip'].'" ORDER BY time DESC LIMIT 1',__FILE__,__LINE__);
+ if(mysql_num_rows($query) > 0){
+ $line = mysql_fetch_array($query, MYSQL_NUM);
+ if($time < $line[0] + 15)
+ exit("2");
+ }
+
+
+ switch($_GET['type']){
+ case "file":
+ $query = db_query('SELECT id FROM sm_smfiles WHERE id = '.intval($_GET['id']).' LIMIT 1',__FILE__,__LINE__);
+ if(mysql_num_rows($query) == 0)
+ exit("0");
+
+
+ $file = $_GET['id'];
+ $func = -1;
+
+ $afterfunc = "ShowFile";
+ break;
+ case "func":
+ $query = db_query('SELECT inc FROM sm_smfunctions WHERE id = '.intval($_GET['id']).' LIMIT 1',__FILE__,__LINE__);
+ if(mysql_num_rows($query) == 0)
+ exit("0");
+
+ $line = mysql_fetch_array($query);
+
+ $file = $line[0];
+ $func = $_GET['id'];
+
+ $afterfunc = "ShowInfo";
+ break;
+ }
+
+ db_query('INSERT INTO sm_smposts(file,func,time,poster,body,ip) VALUES
+ ('.$file.','.$func.','.$time.',"'. $context['user']['name'] .'",\''.mysql_real_escape_string($_POST['message']).'\',"'.$context['user']['ip'].'")',__FILE__,__LINE__);
+
+ $afterfunc();
+ $templatefunc = $afterfunc . "_template";
+}
+
+function LoginWebiste(){
+ echo LoginUser();
+ exit;
+}
+
+function LogOutWebsite(){
+ global $cookieaddr, $scripturl, $cookiename;
+ setcookie ($cookiename, '', time() - 100000, '/', $cookieaddr, 0 ,1);
+
+ echo 'Logging out...';
+ sleep(2);
+ echo '';
+ exit;
+}
+?>
diff --git a/tools/docgen/www/bbc_parse.php b/tools/docgen/www/bbc_parse.php
new file mode 100644
index 00000000..31202aa4
--- /dev/null
+++ b/tools/docgen/www/bbc_parse.php
@@ -0,0 +1,1560 @@
+ strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false,
+ 'is_opera6' => strpos($_SERVER['HTTP_USER_AGENT'], 'Opera 6') !== false,
+ 'is_opera7' => strpos($_SERVER['HTTP_USER_AGENT'], 'Opera 7') !== false || strpos($_SERVER['HTTP_USER_AGENT'], 'Opera/7') !== false,
+ 'is_opera8' => strpos($_SERVER['HTTP_USER_AGENT'], 'Opera 8') !== false || strpos($_SERVER['HTTP_USER_AGENT'], 'Opera/8') !== false,
+ 'is_ie4' => strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 4') !== false && strpos($_SERVER['HTTP_USER_AGENT'], 'WebTV') === false,
+ 'is_safari' => strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') !== false,
+ 'is_mac_ie' => strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 5.') !== false && strpos($_SERVER['HTTP_USER_AGENT'], 'Mac') !== false,
+ 'is_web_tv' => strpos($_SERVER['HTTP_USER_AGENT'], 'WebTV') !== false,
+ 'is_konqueror' => strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false,
+ 'is_firefox' => strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox') !== false,
+ 'is_firefox1' => strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox/1.') !== false,
+ 'is_firefox2' => strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox/2.') !== false,
+);
+
+
+ $context['browser']['is_gecko'] = strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false && !$context['browser']['is_safari'] && !$context['browser']['is_konqueror'];
+
+// Internet Explorer 5 and 6 are often "emulated".
+$context['browser']['is_ie7'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
+$context['browser']['is_ie6'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 6') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
+$context['browser']['is_ie5.5'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 5.5') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
+$context['browser']['is_ie5'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 5.0') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
+$context['browser']['is_ie'] = $context['browser']['is_ie4'] || $context['browser']['is_ie5'] || $context['browser']['is_ie5.5'] || $context['browser']['is_ie6'] || $context['browser']['is_ie7'];
+$context['browser']['needs_size_fix'] = ($context['browser']['is_ie5'] || $context['browser']['is_ie5.5'] || $context['browser']['is_ie4'] || $context['browser']['is_opera6']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Mac') === false;
+// This isn't meant to be reliable, it's just meant to catch most bots to prevent PHPSESSID from showing up.
+$ci_user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
+$context['browser']['possibly_robot'] = (strpos($_SERVER['HTTP_USER_AGENT'], 'Mozilla') === false && strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') === false) || strpos($ci_user_agent, 'googlebot') !== false || strpos($ci_user_agent, 'slurp') !== false || strpos($ci_user_agent, 'crawl') !== false;
+
+
+$modSettings['max_image_width'] = 400;
+$modSettings['max_image_height'] = 400;
+$modSettings['autoLinkUrls'] = true;
+$context['utf8'] = false;
+
+
+// Parse bulletin board code in a string, as well as smileys optionally.
+function parse_bbc($message)
+{
+ global $txt, $scripturl, $context, $modSettings, $user_info;
+ static $bbc_codes = array(), $itemcodes = array(), $no_autolink_tags = array();
+ static $disabled;
+
+ // Sift out the bbc for a performance improvement.
+ if (empty($bbc_codes) || $message === false)
+ {
+ $disabled['flash'] = true;
+ /* The following bbc are formatted as an array, with keys as follows:
+
+ tag: the tag's name - should be lowercase!
+
+ type: one of...
+ - (missing): [tag]parsed content[/tag]
+ - unparsed_equals: [tag=xyz]parsed content[/tag]
+ - parsed_equals: [tag=parsed data]parsed content[/tag]
+ - unparsed_content: [tag]unparsed content[/tag]
+ - closed: [tag], [tag/], [tag /]
+ - unparsed_commas: [tag=1,2,3]parsed content[/tag]
+ - unparsed_commas_content: [tag=1,2,3]unparsed content[/tag]
+ - unparsed_equals_content: [tag=...]unparsed content[/tag]
+
+ parameters: an optional array of parameters, for the form
+ [tag abc=123]content[/tag]. The array is an associative array
+ where the keys are the parameter names, and the values are an
+ array which may contain the following:
+ - match: a regular expression to validate and match the value.
+ - quoted: true if the value should be quoted.
+ - validate: callback to evaluate on the data, which is $data.
+ - value: a string in which to replace $1 with the data.
+ either it or validate may be used, not both.
+ - optional: true if the parameter is optional.
+
+ test: a regular expression to test immediately after the tag's
+ '=', ' ' or ']'. Typically, should have a \] at the end.
+ Optional.
+
+ content: only available for unparsed_content, closed,
+ unparsed_commas_content, and unparsed_equals_content.
+ $1 is replaced with the content of the tag. Parameters
+ are repalced in the form {param}. For unparsed_commas_content,
+ $2, $3, ..., $n are replaced.
+
+ before: only when content is not used, to go before any
+ content. For unparsed_equals, $1 is replaced with the value.
+ For unparsed_commas, $1, $2, ..., $n are replaced.
+
+ after: similar to before in every way, except that it is used
+ when the tag is closed.
+
+ disabled_content: used in place of content when the tag is
+ disabled. For closed, default is '', otherwise it is '$1' if
+ block_level is false, '$1
' elsewise.
+
+ disabled_before: used in place of before when disabled. Defaults
+ to '' if block_level, '' if not.
+
+ disabled_after: used in place of after when disabled. Defaults
+ to '
' if block_level, '' if not.
+
+ block_level: set to true the tag is a "block level" tag, similar
+ to HTML. Block level tags cannot be nested inside tags that are
+ not block level, and will not be implicitly closed as easily.
+ One break following a block level tag may also be removed.
+
+ trim: if set, and 'inside' whitespace after the begin tag will be
+ removed. If set to 'outside', whitespace after the end tag will
+ meet the same fate.
+
+ validate: except when type is missing or 'closed', a callback to
+ validate the data as $data. Depending on the tag's type, $data
+ may be a string or an array of strings (corresponding to the
+ replacement.)
+
+ quoted: when type is 'unparsed_equals' or 'parsed_equals' only,
+ may be not set, 'optional', or 'required' corresponding to if
+ the content may be quoted. This allows the parser to read
+ [tag="abc]def[esdf]"] properly.
+
+ require_parents: an array of tag names, or not set. If set, the
+ enclosing tag *must* be one of the listed tags, or parsing won't
+ occur.
+
+ require_children: similar to require_parents, if set children
+ won't be parsed if they are not in the list.
+
+ disallow_children: similar to, but very different from,
+ require_children, if it is set the listed tags will not be
+ parsed inside the tag.
+ */
+
+ $codes = array(
+ array(
+ 'tag' => 'abbr',
+ 'type' => 'unparsed_equals',
+ 'before' => '',
+ 'after' => ' ',
+ 'quoted' => 'optional',
+ 'disabled_after' => ' ($1)',
+ ),
+ array(
+ 'tag' => 'acronym',
+ 'type' => 'unparsed_equals',
+ 'before' => '',
+ 'after' => ' ',
+ 'quoted' => 'optional',
+ 'disabled_after' => ' ($1)',
+ ),
+ array(
+ 'tag' => 'anchor',
+ 'type' => 'unparsed_equals',
+ 'test' => '[#]?([A-Za-z][A-Za-z0-9_\-]*)\]',
+ 'before' => ' ',
+ 'after' => '',
+ ),
+ array(
+ 'tag' => 'b',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'black',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'blue',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'br',
+ 'type' => 'closed',
+ 'content' => ' ',
+ ),
+ array(
+ 'tag' => 'code',
+ 'type' => 'unparsed_content',
+ 'content' => '' . ($context['browser']['is_gecko'] ? '
$1 ' : '$1') . '
',
+ // !!! Maybe this can be simplified?
+ 'validate' => isset($disabled['code']) ? null : create_function('&$tag, &$data, $disabled', '
+ global $context;
+
+ if (!isset($disabled[\'code\']))
+ {
+ $php_parts = preg_split(\'~(<\?php|\?>)~\', $data, -1, PREG_SPLIT_DELIM_CAPTURE);
+
+ for ($php_i = 0, $php_n = count($php_parts); $php_i < $php_n; $php_i++)
+ {
+ // Do PHP code coloring?
+ if ($php_parts[$php_i] != \'<?php\')
+ continue;
+
+ $php_string = \'\';
+ while ($php_i + 1 < count($php_parts) && $php_parts[$php_i] != \'?>\')
+ {
+ $php_string .= $php_parts[$php_i];
+ $php_parts[$php_i++] = \'\';
+ }
+ $php_parts[$php_i] = highlight_php_code($php_string . $php_parts[$php_i]);
+ }
+
+ // Fix the PHP code stuff...
+ $data = str_replace("\t ", "\t", implode(\'\', $php_parts));
+
+ // Older browsers are annoying, aren\'t they?
+ if ($context[\'browser\'][\'is_ie4\'] || $context[\'browser\'][\'is_ie5\'] || $context[\'browser\'][\'is_ie5.5\'])
+ $data = str_replace("\t", "\t ", $data);
+ elseif (!$context[\'browser\'][\'is_gecko\'])
+ $data = str_replace("\t", "\t ", $data);
+ }'),
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'code',
+ 'type' => 'unparsed_equals_content',
+ 'content' => '' . ($context['browser']['is_gecko'] ? '
$1 ' : '$1') . '
',
+ // !!! Maybe this can be simplified?
+ 'validate' => isset($disabled['code']) ? null : create_function('&$tag, &$data, $disabled', '
+ global $context;
+
+ if (!isset($disabled[\'code\']))
+ {
+ $php_parts = preg_split(\'~(<\?php|\?>)~\', $data[0], -1, PREG_SPLIT_DELIM_CAPTURE);
+
+ for ($php_i = 0, $php_n = count($php_parts); $php_i < $php_n; $php_i++)
+ {
+ // Do PHP code coloring?
+ if ($php_parts[$php_i] != \'<?php\')
+ continue;
+
+ $php_string = \'\';
+ while ($php_i + 1 < count($php_parts) && $php_parts[$php_i] != \'?>\')
+ {
+ $php_string .= $php_parts[$php_i];
+ $php_parts[$php_i++] = \'\';
+ }
+ $php_parts[$php_i] = highlight_php_code($php_string . $php_parts[$php_i]);
+ }
+
+ // Fix the PHP code stuff...
+ $data[0] = str_replace("\t ", "\t", implode(\'\', $php_parts));
+
+ // Older browsers are annoying, aren\'t they?
+ if ($context[\'browser\'][\'is_ie4\'] || $context[\'browser\'][\'is_ie5\'] || $context[\'browser\'][\'is_ie5.5\'])
+ $data = str_replace("\t", "\t ", $data);
+ elseif (!$context[\'browser\'][\'is_gecko\'])
+ $data = str_replace("\t", "\t ", $data);
+ }'),
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'center',
+ 'before' => '',
+ 'after' => '
',
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'color',
+ 'type' => 'unparsed_equals',
+ 'test' => '(#[\da-fA-F]{3}|#[\da-fA-F]{6}|[A-Za-z]{1,12})\]',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'email',
+ 'type' => 'unparsed_content',
+ 'content' => '$1 ',
+ // !!! Should this respect guest_hideContacts?
+ 'validate' => create_function('&$tag, &$data, $disabled', '$data = strtr($data, array(\' \' => \'\'));'),
+ ),
+ array(
+ 'tag' => 'email',
+ 'type' => 'unparsed_equals',
+ 'before' => '',
+ 'after' => ' ',
+ // !!! Should this respect guest_hideContacts?
+ 'disallow_children' => array('email', 'ftp', 'url', 'iurl'),
+ 'disabled_after' => ' ($1)',
+ ),
+ array(
+ 'tag' => 'ftp',
+ 'type' => 'unparsed_content',
+ 'content' => '$1 ',
+ 'validate' => create_function('&$tag, &$data, $disabled', '$data = strtr($data, array(\' \' => \'\'));'),
+ ),
+ array(
+ 'tag' => 'ftp',
+ 'type' => 'unparsed_equals',
+ 'before' => '',
+ 'after' => ' ',
+ 'disallow_children' => array('email', 'ftp', 'url', 'iurl'),
+ 'disabled_after' => ' ($1)',
+ ),
+ array(
+ 'tag' => 'font',
+ 'type' => 'unparsed_equals',
+ 'test' => '[A-Za-z0-9_,\-\s]+?\]',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'flash',
+ 'type' => 'unparsed_commas_content',
+ 'test' => '\d+,\d+\]',
+ 'content' => ($context['browser']['is_ie'] && !$context['browser']['is_mac_ie'] ? '$1 ' : '$1 '),
+ 'validate' => create_function('&$tag, &$data, $disabled', '
+ if (isset($disabled[\'url\']))
+ $tag[\'content\'] = \'$1\';'),
+ 'disabled_content' => '$1 ',
+ ),
+ array(
+ 'tag' => 'green',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'glow',
+ 'type' => 'unparsed_commas',
+ 'test' => '[#0-9a-zA-Z\-]{3,12},([012]\d{1,2}|\d{1,2})(,[^]]+)?\]',
+ 'before' => $context['browser']['is_ie'] ? '' : '',
+ 'after' => $context['browser']['is_ie'] ? '
' : '',
+ ),
+ array(
+ 'tag' => 'hr',
+ 'type' => 'closed',
+ 'content' => ' ',
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'html',
+ 'type' => 'unparsed_content',
+ 'content' => '$1',
+ 'block_level' => true,
+ 'disabled_content' => '$1',
+ ),
+ array(
+ 'tag' => 'img',
+ 'type' => 'unparsed_content',
+ 'parameters' => array(
+ 'alt' => array('optional' => true),
+ 'width' => array('optional' => true, 'value' => ' width="$1"', 'match' => '(\d+)'),
+ 'height' => array('optional' => true, 'value' => ' height="$1"', 'match' => '(\d+)'),
+ ),
+ 'content' => ' ',
+ 'validate' => create_function('&$tag, &$data, $disabled', '$data = strtr($data, array(\' \' => \'\'));'),
+ 'disabled_content' => '($1)',
+ ),
+ array(
+ 'tag' => 'img',
+ 'type' => 'unparsed_content',
+ 'parameters' => array(
+ 'alt' => array('optional' => true),
+ 'width' => array('optional' => true, 'value' => ' width="$1"', 'match' => '(\d+)'),
+ 'height' => array('optional' => true, 'value' => ' height="$1"', 'match' => '(\d+)'),
+ ),
+ 'content' => ' ',
+ 'validate' => create_function('&$tag, &$data, $disabled', '$data = strtr($data, array(\' \' => \'\'));'),
+ 'disabled_content' => '($1)',
+ ),
+ array(
+ 'tag' => 'video',
+ 'type' => 'newunparsed_content',
+ 'content' => '$1 ',
+ 'validate' => create_function('&$tag, &$data, $disabled', '$data = strtr($data, array(\' \' => \'\'));'),
+ 'disabled_content' => '($1)',
+ ),
+ array(
+ 'tag' => 'img',
+ 'type' => 'unparsed_content',
+ 'content' => ' ',
+ 'validate' => create_function('&$tag, &$data, $disabled', '$data = strtr($data, array(\' \' => \'\'));'),
+ 'disabled_content' => '($1)',
+ ),
+ array(
+ 'tag' => 'i',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'iurl',
+ 'type' => 'unparsed_content',
+ 'content' => '$1 ',
+ 'validate' => create_function('&$tag, &$data, $disabled', '$data = strtr($data, array(\' \' => \'\'));'),
+ ),
+ array(
+ 'tag' => 'iurl',
+ 'type' => 'unparsed_equals',
+ 'before' => '',
+ 'after' => ' ',
+ 'validate' => create_function('&$tag, &$data, $disabled', '
+ if (substr($data, 0, 1) == \'#\')
+ $data = \'#post_\' . substr($data, 1);'),
+ 'disallow_children' => array('email', 'ftp', 'url', 'iurl'),
+ 'disabled_after' => ' ($1)',
+ ),
+ array(
+ 'tag' => 'li',
+ 'before' => '',
+ 'after' => ' ',
+ 'trim' => 'outside',
+ 'require_parents' => array('list'),
+ 'block_level' => true,
+ 'disabled_before' => '',
+ 'disabled_after' => ' ',
+ ),
+ array(
+ 'tag' => 'list',
+ 'before' => '',
+ 'trim' => 'inside',
+ 'require_children' => array('li'),
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'list',
+ 'parameters' => array(
+ 'type' => array('match' => '(none|disc|circle|square|decimal|decimal-leading-zero|lower-roman|upper-roman|lower-alpha|upper-alpha|lower-greek|lower-latin|upper-latin|hebrew|armenian|georgian|cjk-ideographic|hiragana|katakana|hiragana-iroha|katakana-iroha)'),
+ ),
+ 'before' => '',
+ 'trim' => 'inside',
+ 'require_children' => array('li'),
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'left',
+ 'before' => '',
+ 'after' => '
',
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'ltr',
+ 'before' => '',
+ 'after' => '
',
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'me',
+ 'type' => 'unparsed_equals',
+ 'before' => '* $1 ',
+ 'after' => '
',
+ 'quoted' => 'optional',
+ 'block_level' => true,
+ 'disabled_before' => '/me ',
+ 'disabled_after' => ' ',
+ ),
+ array(
+ 'tag' => 'move',
+ 'before' => '',
+ 'after' => ' ',
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'nobbc',
+ 'type' => 'unparsed_content',
+ 'content' => '$1',
+ ),
+ array(
+ 'tag' => 'pre',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'php',
+ 'type' => 'unparsed_content',
+ 'content' => '',
+ 'validate' => create_function('&$tag, &$data, $disabled', '
+ if (!isset($disabled[\'php\']))
+ {
+ $add_begin = substr(trim($data), 0, 5) != \'<?\';
+ $data = highlight_php_code($add_begin ? \'<?php \' . $data . \'?>\' : $data);
+ if ($add_begin)
+ $data = preg_replace(array(\'~^(.+?)<\?.{0,40}?php( |\s)~\', \'~\?>((?:(font|span)>)*)$~\'), \'$1\', $data, 2);
+ }'),
+ 'block_level' => true,
+ 'disabled_content' => '$1',
+ ),
+ array(
+ 'tag' => 'sm',
+ 'type' => 'unparsed_content',
+ 'content' => '$1
',
+ 'validate' => create_function('&$tag, &$data, $disabled', '
+ $add_begin = substr(trim($data), 0, 5) != \'<?\';
+ $data = highlight_sm_code($add_begin ? \'<?php \' . $data . \'?>\' : $data);
+ if ($add_begin)
+ $data = preg_replace(array(\'~^(.+?)<\?.{0,40}?php( |\s)~\', \'~\?>((?:(font|span)>)*)$~\'), \'$1\', $data, 2);
+ '),
+ 'block_level' => true,
+ 'disabled_content' => '$1',
+ ),
+ array(
+ 'tag' => 'quote',
+ 'before' => '',
+ 'after' => '
',
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'quote',
+ 'parameters' => array(
+ 'author' => array('match' => '(.{1,192}?)', 'quoted' => true, 'validate' => 'parse_bbc'),
+ ),
+ 'before' => '',
+ 'after' => '
',
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'quote',
+ 'type' => 'parsed_equals',
+ 'before' => '',
+ 'after' => '
',
+ 'quoted' => 'optional',
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'quote',
+ 'parameters' => array(
+ 'author' => array('match' => '(.{1,192}?)', 'validate' => 'parse_bbc'),
+ ),
+ 'before' => '',
+ 'after' => '
',
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'right',
+ 'before' => '',
+ 'after' => '
',
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'red',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'rtl',
+ 'before' => '',
+ 'after' => '
',
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 's',
+ 'before' => '',
+ 'after' => '',
+ ),
+ array(
+ 'tag' => 'size',
+ 'type' => 'unparsed_equals',
+ 'test' => '([1-9][\d]?p[xt]|(?:x-)?small(?:er)?|(?:x-)?large[r]?)\]',
+ // !!! line-height
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'size',
+ 'type' => 'unparsed_equals',
+ 'test' => '[1-9]\]',
+ // !!! line-height
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'sub',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'sup',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'shadow',
+ 'type' => 'unparsed_commas',
+ 'test' => '[#0-9a-zA-Z\-]{3,12},(left|right|top|bottom|[0123]\d{0,2})\]',
+ 'before' => $context['browser']['is_ie'] ? '' : '',
+ 'after' => ' ',
+ 'validate' => $context['browser']['is_ie'] ? create_function('&$tag, &$data, $disabled', '
+ if ($data[1] == \'left\')
+ $data[1] = 270;
+ elseif ($data[1] == \'right\')
+ $data[1] = 90;
+ elseif ($data[1] == \'top\')
+ $data[1] = 0;
+ elseif ($data[1] == \'bottom\')
+ $data[1] = 180;
+ else
+ $data[1] = (int) $data[1];') : create_function('&$tag, &$data, $disabled', '
+ if ($data[1] == \'top\' || (is_numeric($data[1]) && $data[1] < 50))
+ return \'0 -2px\';
+ elseif ($data[1] == \'right\' || (is_numeric($data[1]) && $data[1] < 100))
+ return \'2px 0\';
+ elseif ($data[1] == \'bottom\' || (is_numeric($data[1]) && $data[1] < 190))
+ return \'0 2px\';
+ elseif ($data[1] == \'left\' || (is_numeric($data[1]) && $data[1] < 280))
+ return \'-2px 0\';
+ else
+ return \'0 0\';'),
+ ),
+ array(
+ 'tag' => 'time',
+ 'type' => 'unparsed_content',
+ 'content' => '$1',
+ 'validate' => create_function('&$tag, &$data, $disabled', '
+ if (is_numeric($data))
+ $data = timeformat($data);
+ else
+ $tag[\'content\'] = \'[time]$1[/time]\';'),
+ ),
+ array(
+ 'tag' => 'tt',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'table',
+ 'before' => '',
+ 'trim' => 'inside',
+ 'require_children' => array('tr'),
+ 'block_level' => true,
+ ),
+ array(
+ 'tag' => 'tr',
+ 'before' => '',
+ 'after' => ' ',
+ 'require_parents' => array('table'),
+ 'require_children' => array('td'),
+ 'trim' => 'both',
+ 'block_level' => true,
+ 'disabled_before' => '',
+ 'disabled_after' => '',
+ ),
+ array(
+ 'tag' => 'td',
+ 'before' => ' ',
+ 'after' => ' ',
+ 'require_parents' => array('tr'),
+ 'trim' => 'outside',
+ 'block_level' => true,
+ 'disabled_before' => '',
+ 'disabled_after' => '',
+ ),
+ array(
+ 'tag' => 'url',
+ 'type' => 'unparsed_content',
+ 'content' => '$1 ',
+ 'validate' => create_function('&$tag, &$data, $disabled', '$data = strtr($data, array(\' \' => \'\'));'),
+ ),
+ array(
+ 'tag' => 'url',
+ 'type' => 'unparsed_equals',
+ 'before' => '',
+ 'after' => ' ',
+ 'disallow_children' => array('email', 'ftp', 'url', 'iurl'),
+ 'disabled_after' => ' ($1)',
+ ),
+ array(
+ 'tag' => 'u',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ array(
+ 'tag' => 'white',
+ 'before' => '',
+ 'after' => ' ',
+ ),
+ );
+
+ // This is mainly for the bbc manager, so it's easy to add tags above. Custom BBC should be added above this line.
+ if ($message === false)
+ return $codes;
+
+ // So the parser won't skip them.
+ $itemcodes = array(
+ '*' => '',
+ '@' => 'disc',
+ '+' => 'square',
+ 'x' => 'square',
+ '#' => 'square',
+ 'o' => 'circle',
+ 'O' => 'circle',
+ '0' => 'circle',
+ );
+
+ // Inside these tags autolink is not recommendable.
+ $no_autolink_tags = array(
+ 'url',
+ 'iurl',
+ 'ftp',
+ 'email',
+ );
+
+ foreach ($codes as $c)
+ $bbc_codes[substr($c['tag'], 0, 1)][] = $c;
+ $codes = null;
+ }
+
+ $open_tags = array();
+ $message = strtr($message, array("\n" => ' '));
+
+ // The non-breaking-space looks a bit different each time.
+ $non_breaking_space = '\xA0';
+
+ $pos = -1;
+ while ($pos !== false)
+ {
+ $last_pos = isset($last_pos) ? max($pos, $last_pos) : $pos;
+ $pos = strpos($message, '[', $pos + 1);
+
+ // Failsafe.
+ if ($pos === false || $last_pos > $pos)
+ $pos = strlen($message) + 1;
+
+ // Can't have a one letter smiley, URL, or email! (sorry.)
+ if ($last_pos < $pos - 1)
+ {
+ // We want to eat one less, and one more, character (for smileys.)
+ $last_pos = max($last_pos - 1, 0);
+ $data = substr($message, $last_pos, $pos - $last_pos + 1);
+
+ // Take care of some HTML!
+ if (strpos($data, '<') !== false) // !empty($modSettings['enablePostHTML']) &&
+ {
+ $data = preg_replace('~<a\s+href=(?:")?((?:http://|ftp://|https://|ftps://|mailto:).+?)(?:")?>~i', '[url=$1]', $data);
+ $data = preg_replace('~</a>~i', '[/url]', $data);
+
+ // should be empty.
+ $empty_tags = array('br', 'hr');
+ foreach ($empty_tags as $tag)
+ $data = str_replace(array('<' . $tag . '>', '<' . $tag . '/>', '<' . $tag . ' />'), '[' . $tag . ' /]', $data);
+
+ // b, u, i, s, pre... basic tags.
+ $closable_tags = array('b', 'u', 'i', 's', 'em', 'ins', 'del', 'pre', 'blockquote');
+ foreach ($closable_tags as $tag)
+ {
+ $diff = substr_count($data, '<' . $tag . '>') - substr_count($data, '</' . $tag . '>');
+ $data = strtr($data, array('<' . $tag . '>' => '<' . $tag . '>', '</' . $tag . '>' => '' . $tag . '>'));
+
+ if ($diff > 0)
+ $data .= str_repeat('' . $tag . '>', $diff);
+ }
+
+ // Do - with security... action= -> action-.
+ preg_match_all('~<img\s+src=(?:")?((?:http://|ftp://|https://|ftps://).+?)(?:")?(?:\s+alt=(?:")?(.*?)(?:")?)?(?:\s?/)?>~i', $data, $matches, PREG_PATTERN_ORDER);
+ if (!empty($matches[0]))
+ {
+ $replaces = array();
+ foreach ($matches[1] as $match => $imgtag)
+ {
+ // No alt?
+ if (!isset($matches[2][$match]))
+ $matches[2][$match] = '';
+
+ // Remove action= from the URL - no funny business, now.
+ if (preg_match('~action(=|%3d)(?!dlattach)~i', $imgtag) != 0)
+ $imgtag = preg_replace('~action(=|%3d)(?!dlattach)~i', 'action-', $imgtag);
+
+ // Check if the image is larger than allowed.
+ if (!empty($modSettings['max_image_width']) && !empty($modSettings['max_image_height']))
+ {
+ list ($width, $height) = url_image_size($imgtag);
+
+ if (!empty($modSettings['max_image_width']) && $width > $modSettings['max_image_width'])
+ {
+ $height = (int) (($modSettings['max_image_width'] * $height) / $width);
+ $width = $modSettings['max_image_width'];
+ }
+
+ if (!empty($modSettings['max_image_height']) && $height > $modSettings['max_image_height'])
+ {
+ $width = (int) (($modSettings['max_image_height'] * $width) / $height);
+ $height = $modSettings['max_image_height'];
+ }
+
+ // Set the new image tag.
+ $replaces[$matches[0][$match]] = ' ';
+ }
+ else
+ $replaces[$matches[0][$match]] = ' ';
+ }
+
+ $data = strtr($data, $replaces);
+ }
+ }
+
+ if (!empty($modSettings['autoLinkUrls']))
+ {
+ // Are we inside tags that should be auto linked?
+ $no_autolink_area = false;
+ if (!empty($open_tags))
+ {
+ foreach ($open_tags as $open_tag)
+ if (in_array($open_tag['tag'], $no_autolink_tags))
+ $no_autolink_area = true;
+ }
+
+ // Don't go backwards.
+ $lastAutoPos = isset($lastAutoPos) ? $lastAutoPos : 0;
+ if ($pos < $lastAutoPos)
+ $no_autolink_area = true;
+ $lastAutoPos = $pos;
+
+ if (!$no_autolink_area)
+ {
+ // Parse any URLs.... have to get rid of the @ problems some things cause... stupid email addresses.
+ if (!isset($disabled['url']) && (strpos($data, '://') !== false || strpos($data, 'www.') !== false))
+ {
+ // Switch out quotes really quick because they can cause problems.
+ $data = strtr($data, array(''' => '\'', ' ' => $context['utf8'] ? "\xC2\xA0" : "\xA0", '"' => '>">', '"' => '<"<', '<' => '\.(;\'"]|^)((?:http|https|ftp|ftps)://[\w\-_%@:|]+(?:\.[\w\-_%]+)*(?::\d+)?(?:/[\w\-_\~%\.@,\?&;=#+:\'\\\\]*|[\(\{][\w\-_\~%\.@,\?&;=#(){}+:\'\\\\]*)*[/\w\-_\~%@\?;=#}\\\\])~i', '~(?<=[\s>(\'<]|^)(www(?:\.[\w\-_]+)+(?::\d+)?(?:/[\w\-_\~%\.@,\?&;=#+:\'\\\\]*|[\(\{][\w\-_\~%\.@,\?&;=#(){}+:\'\\\\]*)*[/\w\-_\~%@\?;=#}\\\\])~i'), array('[url]$1[/url]', '[url=http://$1]$1[/url]'), $data);
+ $data = strtr($data, array('\'' => ''', $context['utf8'] ? "\xC2\xA0" : "\xA0" => ' ', '>">' => '"', '<"<' => '"', ' '<'));
+ }
+
+ // Next, emails...
+ if (!isset($disabled['email']) && strpos($data, '@') !== false)
+ {
+ $data = preg_replace('~(?<=[\?\s' . $non_breaking_space . '\[\]()*\\\;>]|^)([\w\-\.]{1,80}@[\w\-]+\.[\w\-\.]+[\w\-])(?=[?,\s' . $non_breaking_space . '\[\]()*\\\]|$| | |>|<|"|'|\.(?:\.|;| |\s|$| ))~' . ($context['utf8'] ? 'u' : ''), '[email]$1[/email]', $data);
+ $data = preg_replace('~(?<= )([\w\-\.]{1,80}@[\w\-]+\.[\w\-\.]+[\w\-])(?=[?\.,;\s' . $non_breaking_space . '\[\]()*\\\]|$| | |>|<|"|')~' . ($context['utf8'] ? 'u' : ''), '[email]$1[/email]', $data);
+ }
+ }
+ }
+
+ $data = strtr($data, array("\t" => ' '));
+
+ /*if (!empty($modSettings['fixLongWords']) && $modSettings['fixLongWords'] > 5)
+ {
+ // This is SADLY and INCREDIBLY browser dependent.
+ if ($context['browser']['is_gecko'] || $context['browser']['is_konqueror'])
+ $breaker = ' ';
+ // Opera...
+ elseif ($context['browser']['is_opera'])
+ $breaker = ' ';
+ // Internet Explorer...
+ else
+ $breaker = ' ';
+
+ // PCRE will not be happy if we don't give it a short.
+ $modSettings['fixLongWords'] = (int) min(65535, $modSettings['fixLongWords']);
+
+ // The idea is, find words xx long, and then replace them with xx + space + more.
+ if (strlen($data) > $modSettings['fixLongWords'])
+ {
+ // This is done in a roundabout way because $breaker has "long words" :P.
+ $data = strtr($data, array($breaker => '< >', ' ' => $context['utf8'] ? "\xC2\xA0" : "\xA0"));
+ $data = preg_replace(
+ '~(?<=[>;:!? ' . $non_breaking_space . '\]()]|^)([\w\.]{' . $modSettings['fixLongWords'] . ',})~e' . ($context['utf8'] ? 'u' : ''),
+ "preg_replace('/(.{" . ($modSettings['fixLongWords'] - 1) . '})/' . ($context['utf8'] ? 'u' : '') . "', '\\\$1< >', '\$1')",
+ $data);
+ $data = strtr($data, array('< >' => $breaker, $context['utf8'] ? "\xC2\xA0" : "\xA0" => ' '));
+ }
+ }*/
+
+ // Do any smileys!
+ /*if ($smileys === true)
+ parsesmileys($data);
+ */
+
+ // If it wasn't changed, no copying or other boring stuff has to happen!
+ if ($data != substr($message, $last_pos, $pos - $last_pos + 1))
+ {
+ $message = substr($message, 0, $last_pos) . $data . substr($message, $pos + 1);
+
+ // Since we changed it, look again incase we added or removed a tag. But we don't want to skip any.
+ $old_pos = strlen($data) + $last_pos - 1;
+ $pos = strpos($message, '[', $last_pos);
+ $pos = $pos === false ? $old_pos : min($pos, $old_pos);
+ }
+ }
+
+ // Are we there yet? Are we there yet?
+ if ($pos >= strlen($message) - 1)
+ break;
+
+ $tags = strtolower(substr($message, $pos + 1, 1));
+
+ if ($tags == '/' && !empty($open_tags))
+ {
+ $pos2 = strpos($message, ']', $pos + 1);
+ if ($pos2 == $pos + 2)
+ continue;
+ $look_for = strtolower(substr($message, $pos + 2, $pos2 - $pos - 2));
+
+ $to_close = array();
+ $block_level = null;
+ do
+ {
+ $tag = array_pop($open_tags);
+ if (!$tag)
+ break;
+
+ if (!empty($tag['block_level']))
+ {
+ // Only find out if we need to.
+ if ($block_level === false)
+ {
+ array_push($open_tags, $tag);
+ break;
+ }
+
+ // The idea is, if we are LOOKING for a block level tag, we can close them on the way.
+ if (strlen($look_for) > 0 && isset($bbc_codes[$look_for{0}]))
+ {
+ foreach ($bbc_codes[$look_for{0}] as $temp)
+ if ($temp['tag'] == $look_for)
+ {
+ $block_level = !empty($temp['block_level']);
+ break;
+ }
+ }
+
+ if ($block_level !== true)
+ {
+ $block_level = false;
+ array_push($open_tags, $tag);
+ break;
+ }
+ }
+
+ $to_close[] = $tag;
+ }
+ while ($tag['tag'] != $look_for);
+
+ // Did we just eat through everything and not find it?
+ if ((empty($open_tags) && (empty($tag) || $tag['tag'] != $look_for)))
+ {
+ $open_tags = $to_close;
+ continue;
+ }
+ elseif (!empty($to_close) && $tag['tag'] != $look_for)
+ {
+ if ($block_level === null && isset($look_for{0}, $bbc_codes[$look_for{0}]))
+ {
+ foreach ($bbc_codes[$look_for{0}] as $temp)
+ if ($temp['tag'] == $look_for)
+ {
+ $block_level = !empty($temp['block_level']);
+ break;
+ }
+ }
+
+ // We're not looking for a block level tag (or maybe even a tag that exists...)
+ if (!$block_level)
+ {
+ foreach ($to_close as $tag)
+ array_push($open_tags, $tag);
+ continue;
+ }
+ }
+
+ foreach ($to_close as $tag)
+ {
+ $message = substr($message, 0, $pos) . $tag['after'] . substr($message, $pos2 + 1);
+ $pos += strlen($tag['after']);
+ $pos2 = $pos - 1;
+
+ // See the comment at the end of the big loop - just eating whitespace ;).
+ if (!empty($tag['block_level']) && substr($message, $pos, 6) == ' ')
+ $message = substr($message, 0, $pos) . substr($message, $pos + 6);
+ if (!empty($tag['trim']) && $tag['trim'] != 'inside' && preg_match('~( | |\s)*~', substr($message, $pos), $matches) != 0)
+ $message = substr($message, 0, $pos) . substr($message, $pos + strlen($matches[0]));
+ }
+
+ if (!empty($to_close))
+ {
+ $to_close = array();
+ $pos--;
+ }
+
+ continue;
+ }
+
+ // No tags for this character, so just keep going (fastest possible course.)
+ if (!isset($bbc_codes[$tags]))
+ continue;
+
+ $inside = empty($open_tags) ? null : $open_tags[count($open_tags) - 1];
+ $tag = null;
+ foreach ($bbc_codes[$tags] as $possible)
+ {
+ // Not a match?
+ if (strtolower(substr($message, $pos + 1, strlen($possible['tag']))) != $possible['tag'])
+ continue;
+
+ $next_c = substr($message, $pos + 1 + strlen($possible['tag']), 1);
+
+ // A test validation?
+ if (isset($possible['test']) && preg_match('~^' . $possible['test'] . '~', substr($message, $pos + 1 + strlen($possible['tag']) + 1)) == 0)
+ continue;
+ // Do we want parameters?
+ elseif (!empty($possible['parameters']))
+ {
+ if ($next_c != ' ')
+ continue;
+ }
+ elseif (isset($possible['type']))
+ {
+ // Do we need an equal sign?
+ if (in_array($possible['type'], array('unparsed_equals', 'unparsed_commas', 'unparsed_commas_content', 'unparsed_equals_content', 'parsed_equals')) && $next_c != '=')
+ continue;
+ // Maybe we just want a /...
+ if ($possible['type'] == 'closed' && $next_c != ']' && substr($message, $pos + 1 + strlen($possible['tag']), 2) != '/]' && substr($message, $pos + 1 + strlen($possible['tag']), 3) != ' /]')
+ continue;
+ // An immediate ]?
+ if ($possible['type'] == 'unparsed_content' && $next_c != ']')
+ continue;
+ }
+ // No type means 'parsed_content', which demands an immediate ] without parameters!
+ elseif ($next_c != ']')
+ continue;
+
+ // Check allowed tree?
+ if (isset($possible['require_parents']) && ($inside === null || !in_array($inside['tag'], $possible['require_parents'])))
+ continue;
+ elseif (isset($inside['require_children']) && !in_array($possible['tag'], $inside['require_children']))
+ continue;
+ // If this is in the list of disallowed child tags, don't parse it.
+ elseif (isset($inside['disallow_children']) && in_array($possible['tag'], $inside['disallow_children']))
+ continue;
+
+ $pos1 = $pos + 1 + strlen($possible['tag']) + 1;
+
+ // This is long, but it makes things much easier and cleaner.
+ if (!empty($possible['parameters']))
+ {
+ $preg = array();
+ foreach ($possible['parameters'] as $p => $info)
+ $preg[] = '(\s+' . $p . '=' . (empty($info['quoted']) ? '' : '"') . (isset($info['match']) ? $info['match'] : '(.+?)') . (empty($info['quoted']) ? '' : '"') . ')' . (empty($info['optional']) ? '' : '?');
+
+ // Okay, this may look ugly and it is, but it's not going to happen much and it is the best way of allowing any order of parameters but still parsing them right.
+ $match = false;
+ $orders = permute($preg);
+ foreach ($orders as $p)
+ if (preg_match('~^' . implode('', $p) . '\]~i', substr($message, $pos1 - 1), $matches) != 0)
+ {
+ $match = true;
+ break;
+ }
+
+ // Didn't match our parameter list, try the next possible.
+ if (!$match)
+ continue;
+
+ $params = array();
+ for ($i = 1, $n = count($matches); $i < $n; $i += 2)
+ {
+ $key = strtok(ltrim($matches[$i]), '=');
+ if (isset($possible['parameters'][$key]['value']))
+ $params['{' . $key . '}'] = strtr($possible['parameters'][$key]['value'], array('$1' => $matches[$i + 1]));
+ elseif (isset($possible['parameters'][$key]['validate']))
+ $params['{' . $key . '}'] = $possible['parameters'][$key]['validate']($matches[$i + 1]);
+ else
+ $params['{' . $key . '}'] = $matches[$i + 1];
+
+ // Just to make sure: replace any $ or { so they can't interpolate wrongly.
+ $params['{' . $key . '}'] = strtr($params['{' . $key . '}'], array('$' => '$', '{' => '{'));
+ }
+
+ foreach ($possible['parameters'] as $p => $info)
+ {
+ if (!isset($params['{' . $p . '}']))
+ $params['{' . $p . '}'] = '';
+ }
+
+ $tag = $possible;
+
+ // Put the parameters into the string.
+ if (isset($tag['before']))
+ $tag['before'] = strtr($tag['before'], $params);
+ if (isset($tag['after']))
+ $tag['after'] = strtr($tag['after'], $params);
+ if (isset($tag['content']))
+ $tag['content'] = strtr($tag['content'], $params);
+
+ $pos1 += strlen($matches[0]) - 1;
+ }
+ else
+ $tag = $possible;
+ break;
+ }
+
+ // Item codes are complicated buggers... they are implicit [li]s and can make [list]s!
+ if ($tag === null && isset($itemcodes[substr($message, $pos + 1, 1)]) && substr($message, $pos + 2, 1) == ']' && !isset($disabled['list']) && !isset($disabled['li']))
+ {
+ if (substr($message, $pos + 1, 1) == '0' && !in_array(substr($message, $pos - 1, 1), array(';', ' ', "\t", '>')))
+ continue;
+ $tag = $itemcodes[substr($message, $pos + 1, 1)];
+
+ // First let's set up the tree: it needs to be in a list, or after an li.
+ if ($inside === null || ($inside['tag'] != 'list' && $inside['tag'] != 'li'))
+ {
+ $open_tags[] = array(
+ 'tag' => 'list',
+ 'after' => '',
+ 'block_level' => true,
+ 'require_children' => array('li'),
+ 'disallow_children' => isset($inside['disallow_children']) ? $inside['disallow_children'] : null,
+ );
+ $code = '';
+ }
+ // We're in a list item already: another itemcode? Close it first.
+ elseif ($inside['tag'] == 'li')
+ {
+ array_pop($open_tags);
+ $code = '';
+ }
+ else
+ $code = '';
+
+ // Now we open a new tag.
+ $open_tags[] = array(
+ 'tag' => 'li',
+ 'after' => '',
+ 'trim' => 'outside',
+ 'block_level' => true,
+ 'disallow_children' => isset($inside['disallow_children']) ? $inside['disallow_children'] : null,
+ );
+
+ // First, open the tag...
+ $code .= '';
+ $message = substr($message, 0, $pos) . $code . substr($message, $pos + 3);
+ $pos += strlen($code) - 1;
+
+ // Next, find the next break (if any.) If there's more itemcode after it, keep it going - otherwise close!
+ $pos2 = strpos($message, ' ', $pos);
+ $pos3 = strpos($message, '[/', $pos);
+ if ($pos2 !== false && ($pos2 <= $pos3 || $pos3 === false))
+ {
+ preg_match('~^( | |\s|\[)+~', substr($message, $pos2 + 6), $matches);
+ $message = substr($message, 0, $pos2) . (!empty($matches[0]) && substr($matches[0], -1) == '[' ? '[/li]' : '[/li][/list]') . substr($message, $pos2);
+
+ $open_tags[count($open_tags) - 2]['after'] = ' ';
+ }
+ // Tell the [list] that it needs to close specially.
+ else
+ {
+ // Move the li over, because we're not sure what we'll hit.
+ $open_tags[count($open_tags) - 1]['after'] = '';
+ $open_tags[count($open_tags) - 2]['after'] = '';
+ }
+
+ continue;
+ }
+
+ // Implicitly close lists and tables if something other than what's required is in them. This is needed for itemcode.
+ if ($tag === null && $inside !== null && !empty($inside['require_children']))
+ {
+ array_pop($open_tags);
+
+ $message = substr($message, 0, $pos) . $inside['after'] . substr($message, $pos);
+ $pos += strlen($inside['after']) - 1;
+ }
+
+ // No tag? Keep looking, then. Silly people using brackets without actual tags.
+ if ($tag === null)
+ continue;
+
+ // Propagate the list to the child (so wrapping the disallowed tag won't work either.)
+ if (isset($inside['disallow_children']))
+ $tag['disallow_children'] = isset($tag['disallow_children']) ? array_unique(array_merge($tag['disallow_children'], $inside['disallow_children'])) : $inside['disallow_children'];
+
+ // Is this tag disabled?
+ if (isset($disabled[$tag['tag']]))
+ {
+ if (!isset($tag['disabled_before']) && !isset($tag['disabled_after']) && !isset($tag['disabled_content']))
+ {
+ $tag['before'] = !empty($tag['block_level']) ? '' : '';
+ $tag['after'] = !empty($tag['block_level']) ? '
' : '';
+ $tag['content'] = isset($tag['type']) && $tag['type'] == 'closed' ? '' : (!empty($tag['block_level']) ? '$1
' : '$1');
+ }
+ elseif (isset($tag['disabled_before']) || isset($tag['disabled_after']))
+ {
+ $tag['before'] = isset($tag['disabled_before']) ? $tag['disabled_before'] : (!empty($tag['block_level']) ? '' : '');
+ $tag['after'] = isset($tag['disabled_after']) ? $tag['disabled_after'] : (!empty($tag['block_level']) ? '
' : '');
+ }
+ else
+ $tag['content'] = $tag['disabled_content'];
+ }
+
+ // The only special case is 'html', which doesn't need to close things.
+ if (!empty($tag['block_level']) && $tag['tag'] != 'html' && empty($inside['block_level']))
+ {
+ $n = count($open_tags) - 1;
+ while (empty($open_tags[$n]['block_level']) && $n >= 0)
+ $n--;
+
+ // Close all the non block level tags so this tag isn't surrounded by them.
+ for ($i = count($open_tags) - 1; $i > $n; $i--)
+ {
+ $message = substr($message, 0, $pos) . $open_tags[$i]['after'] . substr($message, $pos);
+ $pos += strlen($open_tags[$i]['after']);
+ $pos1 += strlen($open_tags[$i]['after']);
+
+ // Trim or eat trailing stuff... see comment at the end of the big loop.
+ if (!empty($open_tags[$i]['block_level']) && substr($message, $pos, 6) == ' ')
+ $message = substr($message, 0, $pos) . substr($message, $pos + 6);
+ if (!empty($open_tags[$i]['trim']) && $tag['trim'] != 'inside' && preg_match('~( | |\s)*~', substr($message, $pos), $matches) != 0)
+ $message = substr($message, 0, $pos) . substr($message, $pos + strlen($matches[0]));
+
+ array_pop($open_tags);
+ }
+ }
+
+ // No type means 'parsed_content'.
+ if (!isset($tag['type']))
+ {
+ // !!! Check for end tag first, so people can say "I like that [i] tag"?
+ $open_tags[] = $tag;
+ $message = substr($message, 0, $pos) . $tag['before'] . substr($message, $pos1);
+ $pos += strlen($tag['before']) - 1;
+ }
+ // Don't parse the content, just skip it.
+ elseif ($tag['type'] == 'unparsed_content')
+ {
+ $pos2 = stripos($message, '[/' . substr($message, $pos + 1, strlen($tag['tag'])) . ']', $pos1);
+ if ($pos2 === false)
+ continue;
+
+ $data = substr($message, $pos1, $pos2 - $pos1);
+
+ if (!empty($tag['block_level']) && substr($data, 0, 6) == ' ')
+ $data = substr($data, 6);
+
+ if (isset($tag['validate']))
+ $tag['validate']($tag, $data, $disabled);
+
+
+ $code = strtr($tag['content'], array('$1' => $data));
+ $message = substr($message, 0, $pos) . $code . substr($message, $pos2 + 3 + strlen($tag['tag']));
+ $pos += strlen($code) - 1;
+ }
+
+ elseif ($tag['type'] == 'newunparsed_content')
+ {
+ $pos2 = stripos($message, '[/' . substr($message, $pos + 1, strlen($tag['tag'])) . ']', $pos1);
+ if ($pos2 === false)
+ continue;
+
+ $data = trim(substr($message, $pos1, $pos2 - $pos1));
+ $oldata = $data;
+
+ $extrainfo = @parse_url($data);
+ if(!$extrainfo)
+ continue;
+
+ if($extrainfo['host'] == "video.google.com" || $extrainfo['host'] == "www.video.google.com"){
+ $thehead = 'Google video - Link to page ';
+ $data = ' ';
+
+ } elseif($extrainfo['host'] == "www.youtube.com" || $extrainfo['host'] =="youtube.com"){
+ $thehead = 'YouTube - Link to page ';
+ $newextra = substr($extrainfo['query'],2);
+ $data = ' ';
+ } else
+ continue;
+ //elseif(substr($extrainfo['query'],-4,4) == ".avi"){
+
+ if (!empty($tag['block_level']) && substr($data, 0, 6) == ' ')
+ $data = substr($data, 6);
+
+ if (isset($tag['validate']))
+ $tag['validate']($tag, $data, $disabled);
+
+ $code = ''.$thehead.'
' . $data . '
';
+ //$code = strtr($tag['content'], array('$1' => $data));
+ $message = substr($message, 0, $pos) . $code . substr($message, $pos2 + 3 + strlen($tag['tag']));
+ $pos += strlen($code) - 1;
+ }
+
+ // Don't parse the content, just skip it.
+ elseif ($tag['type'] == 'unparsed_equals_content')
+ {
+ // The value may be quoted for some tags - check.
+ if (isset($tag['quoted']))
+ {
+ $quoted = substr($message, $pos1, 6) == '"';
+ if ($tag['quoted'] != 'optional' && !$quoted)
+ continue;
+
+ if ($quoted)
+ $pos1 += 6;
+ }
+ else
+ $quoted = false;
+
+ $pos2 = strpos($message, $quoted == false ? ']' : '"]', $pos1);
+ if ($pos2 === false)
+ continue;
+ $pos3 = stripos($message, '[/' . substr($message, $pos + 1, strlen($tag['tag'])) . ']', $pos2);
+ if ($pos3 === false)
+ continue;
+
+ $data = array(
+ substr($message, $pos2 + ($quoted == false ? 1 : 7), $pos3 - ($pos2 + ($quoted == false ? 1 : 7))),
+ substr($message, $pos1, $pos2 - $pos1)
+ );
+
+ if (!empty($tag['block_level']) && substr($data[0], 0, 6) == ' ')
+ $data[0] = substr($data[0], 6);
+
+ // Validation for my parking, please!
+ if (isset($tag['validate']))
+ $tag['validate']($tag, $data, $disabled);
+
+ $code = strtr($tag['content'], array('$1' => $data[0], '$2' => $data[1]));
+ $message = substr($message, 0, $pos) . $code . substr($message, $pos3 + 3 + strlen($tag['tag']));
+ $pos += strlen($code) - 1;
+ }
+ // A closed tag, with no content or value.
+ elseif ($tag['type'] == 'closed')
+ {
+ $pos2 = strpos($message, ']', $pos);
+ $message = substr($message, 0, $pos) . $tag['content'] . substr($message, $pos2 + 1);
+ $pos += strlen($tag['content']) - 1;
+ }
+ // This one is sorta ugly... :/. Unforunately, it's needed for flash.
+ elseif ($tag['type'] == 'unparsed_commas_content')
+ {
+ $pos2 = strpos($message, ']', $pos1);
+ if ($pos2 === false)
+ continue;
+ $pos3 = stripos($message, '[/' . substr($message, $pos + 1, strlen($tag['tag'])) . ']', $pos2);
+ if ($pos3 === false)
+ continue;
+
+ // We want $1 to be the content, and the rest to be csv.
+ $data = explode(',', ',' . substr($message, $pos1, $pos2 - $pos1));
+ $data[0] = substr($message, $pos2 + 1, $pos3 - $pos2 - 1);
+
+ if (isset($tag['validate']))
+ $tag['validate']($tag, $data, $disabled);
+
+ $code = $tag['content'];
+ foreach ($data as $k => $d)
+ $code = strtr($code, array('$' . ($k + 1) => trim($d)));
+ $message = substr($message, 0, $pos) . $code . substr($message, $pos3 + 3 + strlen($tag['tag']));
+ $pos += strlen($code) - 1;
+ }
+ // This has parsed content, and a csv value which is unparsed.
+ elseif ($tag['type'] == 'unparsed_commas')
+ {
+ $pos2 = strpos($message, ']', $pos1);
+ if ($pos2 === false)
+ continue;
+
+ $data = explode(',', substr($message, $pos1, $pos2 - $pos1));
+
+ if (isset($tag['validate']))
+ $tag['validate']($tag, $data, $disabled);
+
+ // Fix after, for disabled code mainly.
+ foreach ($data as $k => $d)
+ $tag['after'] = strtr($tag['after'], array('$' . ($k + 1) => trim($d)));
+
+ $open_tags[] = $tag;
+
+ // Replace them out, $1, $2, $3, $4, etc.
+ $code = $tag['before'];
+ foreach ($data as $k => $d)
+ $code = strtr($code, array('$' . ($k + 1) => trim($d)));
+ $message = substr($message, 0, $pos) . $code . substr($message, $pos2 + 1);
+ $pos += strlen($code) - 1;
+ }
+ // A tag set to a value, parsed or not.
+ elseif ($tag['type'] == 'unparsed_equals' || $tag['type'] == 'parsed_equals')
+ {
+ // The value may be quoted for some tags - check.
+ if (isset($tag['quoted']))
+ {
+ $quoted = substr($message, $pos1, 6) == '"';
+ if ($tag['quoted'] != 'optional' && !$quoted)
+ continue;
+
+ if ($quoted)
+ $pos1 += 6;
+ }
+ else
+ $quoted = false;
+
+ $pos2 = strpos($message, $quoted == false ? ']' : '"]', $pos1);
+ if ($pos2 === false)
+ continue;
+
+ $data = substr($message, $pos1, $pos2 - $pos1);
+
+ // Validation for my parking, please!
+ if (isset($tag['validate']))
+ $tag['validate']($tag, $data, $disabled);
+
+ // For parsed content, we must recurse to avoid security problems.
+ if ($tag['type'] != 'unparsed_equals')
+ $data = parse_bbc($data);
+
+ $tag['after'] = strtr($tag['after'], array('$1' => $data));
+
+ $open_tags[] = $tag;
+
+ $code = strtr($tag['before'], array('$1' => $data));
+ $message = substr($message, 0, $pos) . $code . substr($message, $pos2 + ($quoted == false ? 1 : 7));
+ $pos += strlen($code) - 1;
+ }
+
+ // If this is block level, eat any breaks after it.
+ if (!empty($tag['block_level']) && substr($message, $pos + 1, 6) == ' ')
+ $message = substr($message, 0, $pos + 1) . substr($message, $pos + 7);
+
+ // Are we trimming outside this tag?
+ if (!empty($tag['trim']) && $tag['trim'] != 'outside' && preg_match('~( | |\s)*~', substr($message, $pos + 1), $matches) != 0)
+ $message = substr($message, 0, $pos + 1) . substr($message, $pos + 1 + strlen($matches[0]));
+ }
+
+ // Close any remaining tags.
+ while ($tag = array_pop($open_tags))
+ $message .= $tag['after'];
+
+ if (substr($message, 0, 1) == ' ')
+ $message = ' ' . substr($message, 1);
+
+ // Cleanup whitespace.
+ $message = strtr($message, array(' ' => ' ', "\r" => '', "\n" => ' ', ' ' => ' ', '
' => "\n"));
+
+ // Cache the output if it took some time...
+ if (isset($cache_key, $cache_t) && array_sum(explode(' ', microtime())) - array_sum(explode(' ', $cache_t)) > 0.05)
+ cache_put_data($cache_key, $message, 240);
+
+ return $message;
+}
+
+function highlight_php_code($code)
+{
+ global $context;
+
+ // Remove special characters.
+ $code = un_htmlspecialchars(strtr($code, array(' ' => "\n", "\t" => 'SMF_TAB();', '[' => '[')));
+
+ $oldlevel = error_reporting(0);
+ $buffer = str_replace(array("\n", "\r"), '', @highlight_string($code, true));
+
+ error_reporting($oldlevel);
+
+ // Yes, I know this is kludging it, but this is the best way to preserve tabs from PHP :P.
+ $buffer = preg_replace('~SMF_TAB((font|span)><(font color|span style)="[^"]*?">)?\(\);~', "\t ", $buffer);
+
+ return strtr($buffer, array('\'' => ''', '' => '', '
' => ''));
+}
+
+function CompareSTRLEN( $a , $b){
+ if ($a['strlen'] == $b['strlen']) {
+ return 0;
+ }
+ return ($a['strlen'] > $b['strlen']) ? -1 : 1;
+}
+
+
+function PrepareSMList(){
+ global $context;
+
+ if(isset($context['sm']['search']))
+ return;
+
+ $context['sm']['haslibary'] = isset($context['sm']['haslibary']) ? $context['sm']['haslibary'] : false;
+
+ $theresults = Array();
+
+ $resultquery = $context['sm']['haslibary'] ? '' : ',description';
+ $result = db_query('SELECT id,func'. $resultquery.' FROM sm_smfunctions',__FILE__,__LINE__);
+
+ while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
+ $theresults[] = Array (
+ 'id' => $line['id'],
+ 'func' => $line['func'],
+ 'strlen' => strlen($line['func']),
+ 'descriptions' => $context['sm']['haslibary'] ? '' : $line['description']
+ );
+ }
+
+ //I need to sort it and do that stupid thing of $thereplaceid so that one function becomes two, like SetClientListeningFlags and SetClientListening
+ usort($theresults, "CompareSTRLEN");
+
+ foreach($theresults as $go){
+ $thereplaceid = "!>";
+ $context['sm']['search'][0][0][] = $go['func'];
+ $context['sm']['search'][0][1][] = $thereplaceid;
+
+ $context['sm']['search'][1][0][] = $thereplaceid;
+ if($context['sm']['haslibary'])
+ $context['sm']['search'][1][1][] = '' . $go['func'] . ' ';
+ else
+ $context['sm']['search'][1][1][] = '' . $go['func'] . ' ';
+ }
+
+
+ $resultquery = $context['sm']['haslibary'] ? '' : ',value,comment';
+ $result = mysql_query('SELECT id,variable'. $resultquery.' FROM sm_smdefine') or die('Query failed: ' . mysql_error());
+ while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
+ $context['sm']['search'][2][0][] = $line['variable'];
+ if($context['sm']['haslibary'])
+ $context['sm']['search'][2][1][] = '' . $line['variable'] . ' ';
+ else{
+ $context['sm']['search'][2][1][] = '' . $line['variable'] . ' ';
+ }
+ }
+}
+
+// Highlight any code...
+function highlight_sm_code($code)
+{
+ global $context;
+
+ // Remove special characters.
+ $code = un_htmlspecialchars(strtr($code, array(' ' => "\n", "\t" => 'SMF_TAB();', '[' => '[')));
+
+ $oldlevel = error_reporting(0);
+
+
+ $buffer = str_replace(array("\n", "\r"), '', @highlight_string($code, true));
+
+ error_reporting($oldlevel);
+
+ $newbuffer = explode(" ", $buffer);
+
+ //print_r($newbuffer);
+
+ $buffer = "";
+ $numcount = strlen ( count ( $newbuffer ));
+ foreach($newbuffer as $i => $line){
+ $bgcolor = $i % 2 ? 'style="background-color: #D0D0E0;"' : '';
+ $buffer .= '';
+ $c = $i + 1;
+ for($a = $numcount - strlen($c); $a > 0 ; $a-- )
+ $buffer .= "0";
+ $buffer .= $c . ': ' . $line . "\n";
+ }
+
+ // Yes, I know this is kludging it, but this is the best way to preserve tabs from PHP :P.
+ $buffer = preg_replace('~SMF_TAB((font|span)><(font color|span style)="[^"]*?">)?\(\);~', "\t ", $buffer);
+
+ if(!isset($context['sm']['search']))
+ PrepareSMList();
+
+
+ $buffer = strtr($buffer, array('\'' => ''', '' => '', '
' => ''));
+
+ foreach($context['sm']['search'] as $replace){
+ $buffer = str_replace($replace[0], $replace[1], $buffer);
+ }
+ return $buffer;
+}
+
+// Removes special entities from strings. Compatibility...
+function un_htmlspecialchars($string)
+{
+ return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES)) + array(''' => '\'', ' ' => ' '));
+}
+?>
\ No newline at end of file
diff --git a/tools/docgen/www/header.jpg b/tools/docgen/www/header.jpg
new file mode 100644
index 00000000..4e1258df
Binary files /dev/null and b/tools/docgen/www/header.jpg differ
diff --git a/tools/docgen/www/imgs/channel.gif b/tools/docgen/www/imgs/channel.gif
new file mode 100644
index 00000000..d2c60c2e
Binary files /dev/null and b/tools/docgen/www/imgs/channel.gif differ
diff --git a/tools/docgen/www/imgs/tree_end.gif b/tools/docgen/www/imgs/tree_end.gif
new file mode 100644
index 00000000..b89d56e1
Binary files /dev/null and b/tools/docgen/www/imgs/tree_end.gif differ
diff --git a/tools/docgen/www/imgs/tree_mid.gif b/tools/docgen/www/imgs/tree_mid.gif
new file mode 100644
index 00000000..2c8de45a
Binary files /dev/null and b/tools/docgen/www/imgs/tree_mid.gif differ
diff --git a/tools/docgen/www/index.php b/tools/docgen/www/index.php
new file mode 100644
index 00000000..681db5b1
--- /dev/null
+++ b/tools/docgen/www/index.php
@@ -0,0 +1,58 @@
+ 'Main',
+ 'file' => 'ShowFile',
+ 'gethint' => 'ShowOpts',
+ 'show' => 'ShowInfo',
+ 'codehigh' => 'HighLight',
+ 'previewpost' => 'PreviewPost',
+ 'post' => 'PostThis',
+ 'login' => 'LoginWebiste',
+ 'logout' => 'LogOutWebsite',
+);
+
+$context['optheader'] = "";
+$context['usetopandbo'] = Array ( true, true );
+$context['topmenu'] = Array();
+
+if(!isset($_GET['action']))
+ $action = $actions['main'];
+else
+ $action = isset($actions[$_GET['action']]) ? $actions[$_GET['action']] : $actions['main'];
+
+$templatefunc = $action . "_template";
+
+$action();
+
+
+// Check if compressed output is enabled, supported, and not already being done.
+if (!headers_sent() && ob_get_length() == 0){
+ // If zlib is being used, turn off output compression.
+ if (@ini_get('zlib.output_compression') != '1' && @ini_get('output_handler') != 'ob_gzhandler' && @version_compare(PHP_VERSION, '4.2.0') != -1)
+ ob_start('ob_gzhandler');
+}
+if($context['usetopandbo'][0]) Headertemplate();
+$templatefunc();
+if($context['usetopandbo'][1]) Footertemplate();
+
+//print_r($context);
+?>
diff --git a/tools/docgen/www/md5.js b/tools/docgen/www/md5.js
new file mode 100644
index 00000000..1deed6c6
--- /dev/null
+++ b/tools/docgen/www/md5.js
@@ -0,0 +1,248 @@
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
+var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
+var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length
+ */
+function core_md5(x, len)
+{
+ /* append padding */
+ x[len >> 5] |= 0x80 << ((len) % 32);
+ x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+ var a = 1732584193;
+ var b = -271733879;
+ var c = -1732584194;
+ var d = 271733878;
+
+ for(var i = 0; i < x.length; i += 16)
+ {
+ var olda = a;
+ var oldb = b;
+ var oldc = c;
+ var oldd = d;
+
+ a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+ d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+ c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
+ b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+ a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+ d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
+ c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+ b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+ a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
+ d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+ c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+ b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+ a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
+ d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+ c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+ b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
+
+ a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+ d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+ c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
+ b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+ a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+ d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
+ c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+ b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+ a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
+ d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+ c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+ b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
+ a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+ d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+ c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
+ b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+ a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+ d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+ c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
+ b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+ a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+ d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
+ c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+ b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+ a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
+ d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+ c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+ b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
+ a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+ d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+ c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
+ b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+ a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+ d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
+ c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+ b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+ a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
+ d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+ c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+ b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+ a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
+ d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+ c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+ b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
+ a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+ d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+ c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
+ b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+ a = safe_add(a, olda);
+ b = safe_add(b, oldb);
+ c = safe_add(c, oldc);
+ d = safe_add(d, oldd);
+ }
+ return Array(a, b, c, d);
+
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+ return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+ return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+ return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+ return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+ return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data
+ */
+function core_hmac_md5(key, data)
+{
+ var bkey = str2binl(key);
+ if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+ var ipad = Array(16), opad = Array(16);
+ for(var i = 0; i < 16; i++)
+ {
+ ipad[i] = bkey[i] ^ 0x36363636;
+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
+ }
+
+ var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+ return core_md5(opad.concat(hash), 512 + 128);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+ return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+ return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert a string to an array of little-endian words
+ * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+ */
+function str2binl(str)
+{
+ var bin = Array();
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < str.length * chrsz; i += chrsz)
+ bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+ return bin;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2str(bin)
+{
+ var str = "";
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < bin.length * 32; i += chrsz)
+ str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+ return str;
+}
+
+/*
+ * Convert an array of little-endian words to a hex string.
+ */
+function binl2hex(binarray)
+{
+ var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i++)
+ {
+ str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+ hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
+ }
+ return str;
+}
+
+/*
+ * Convert an array of little-endian words to a base-64 string
+ */
+function binl2b64(binarray)
+{
+ var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i += 3)
+ {
+ var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
+ | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+ | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+ for(var j = 0; j < 4; j++)
+ {
+ if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+ else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+ }
+ }
+ return str;
+}
\ No newline at end of file
diff --git a/tools/docgen/www/script.js b/tools/docgen/www/script.js
new file mode 100644
index 00000000..d7214459
--- /dev/null
+++ b/tools/docgen/www/script.js
@@ -0,0 +1,421 @@
+opnedtab = -1;
+var previewPopupWindow;
+MainInformation = "";
+var smf_images_url = "http://nican132.com/forum/Themes/halflife_11final/images";
+var smf_formSubmitted = false;
+var currentSwap = true;
+
+function FlipPostSpan(){
+ document.getElementById("postspan").style.display = currentSwap ? "" : "none";
+ currentSwap = !currentSwap;
+}
+
+currentLoginSwap = true;
+
+function FlipLoginBox(){
+ document.getElementById("LoginBox").style.display = currentLoginSwap ? "" : "none";
+ currentLoginSwap = !currentLoginSwap;
+}
+
+function myMouseMove(e){
+ if (!e){
+ var e = window.event;
+ }
+ if (e.pageX){
+ myDiv.style.left = (e.pageX + 10) + "px";
+ myDiv.style.top = (e.pageY + 10) + "px";
+ }else{
+ myDiv.style.left = e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft) + 20;
+ myDiv.style.top = e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + 20;
+ }
+}
+
+function ResetSearch(){
+ document.getElementById("txt1").value="";
+ showHint("");
+}
+
+function hideSMFunc(){
+ myDiv = document.getElementById("serverbox");
+ myDiv.style.visibility = "hidden";
+ document.onmousemove = "";
+}
+
+function LoadPopUP(html){
+ myDiv = document.getElementById("serverbox");
+ myDiv.innerHTML = html;
+ myDiv.style.visibility = "visible";
+ document.onmousemove = myMouseMove;
+}
+
+
+function showSMfunc(id){
+ html = '';
+ html += SMfunctions[id][0];
+ html += '
';
+ html += SMfunctions[id][1];
+ html += '
';
+
+ LoadPopUP(html);
+}
+
+function showSMconst(id){
+ html = '';
+ html += SMconstant[id][0];
+ html += '
';
+ html += SMconstant[id][1];
+ html += ' ';
+ html += SMconstant[id][2];
+ html += '
';
+
+ LoadPopUP(html);
+}
+
+String.prototype.trim = function () {
+ return this.replace(/^\s*/, "").replace(/\s*$/, "");
+}
+
+function PrintMain(x){
+ html = '';
+ html += '
';
+ html += SMfiles[x] + '
';
+ return html;
+}
+
+var xmlHttp
+var BodyHttp
+
+function showHint(str){
+ str=str.trim();
+ if (str.length==0){
+ //html = "";
+ //for (x in SMfiles){
+ // html += PrintMain(x);
+ //}
+ document.getElementById("txtHint").innerHTML= MainInformation;
+ return
+ }
+
+ xmlHttp=GetXmlHttpObject()
+
+ if (xmlHttp==null){
+ alert ("Browser does not support HTTP Request")
+ return
+ }
+
+ document.getElementById("txtHint").innerHTML="Loading... "
+
+ var url="index.php?action=gethint&id="+str;
+ xmlHttp.onreadystatechange=stateChanged
+ xmlHttp.open("GET",url,true)
+ xmlHttp.send(null)
+}
+
+function stateChanged(){
+ if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete"){
+ document.getElementById("txtHint").innerHTML=xmlHttp.responseText
+ }
+}
+
+function LoadMainPage(url){
+ BodyHttp=GetXmlHttpObject()
+
+ if (BodyHttp==null){
+ alert ("Browser does not support HTTP Request")
+ return
+ }
+ ShowLoading()
+
+ BodyHttp.onreadystatechange=MainStateChanged
+ BodyHttp.open("GET",url,true)
+ BodyHttp.send(null)
+}
+
+function MainStateChanged(){
+ if (BodyHttp.readyState==4 || BodyHttp.readyState=="complete"){
+ HideLoading()
+ document.getElementById("MainBody").innerHTML=BodyHttp.responseText
+ }
+}
+
+function ShowCustomLink(page){
+ LoadMainPage("index.php?" + page);
+}
+
+function ShowFunction(id){
+ hideSMFunc()
+ LoadMainPage("index.php?action=show&id="+id);
+}
+
+function ShowFileInfo(id){
+ LoadMainPage("index.php?action=file&id="+id);
+}
+function ShowLoading(){
+ ly = document.getElementById("AdminPopUP");
+
+ ly.style.zindex = "100";
+ ly.style.display = "block";
+}
+
+function HideLoading(){
+ document.getElementById("AdminPopUP").style.display = "none";
+}
+
+function SpanArea(id, hashtml){
+ if(opnedtab >= 0){
+ document.getElementById( SMfiles[opnedtab] ).innerHTML="";
+ if(opnedtab == id){
+ opnedtab = -1;
+ return
+ }
+ }
+ opnedtab = id;
+ ShowFileInfo(id);
+
+ if(!SMfiledata[id])
+ return;
+
+ html = "";
+ arycount = SMfiledata[id].length -1
+
+ for (x in SMfiledata[id]){
+ html += '';
+ html += SMfunctions[ SMfiledata[id][x] ][0] + " ";
+
+ }
+ if(html != "")
+ document.getElementById( SMfiles[id] ).innerHTML=html
+
+}
+
+function getHTMLDocument(url, callback)
+{
+ if (!window.XMLHttpRequest)
+ return false;
+
+ var myDoc = new XMLHttpRequest();
+ if (typeof(callback) != "undefined")
+ {
+ myDoc.onreadystatechange = function ()
+ {
+ if (myDoc.readyState != 4)
+ return;
+
+ if (myDoc.responseText != null && myDoc.status == 200){
+ callback(myDoc.responseText);
+ }
+ };
+ }
+ myDoc.open('GET', url, true);
+ myDoc.send(null);
+
+ return true;
+}
+
+function SubmitLoginInfo(){
+ ShowLoading();
+
+ var url = "index.php?action=login&user=" + document.getElementById("user").value;
+ url += "&pw=" + hex_md5(document.getElementById("pw").value);
+ if(document.getElementById("forever").checked)
+ url += "&forever=1";
+ else
+ url += "&forever=0";
+
+ getHTMLDocument(url, Revivelogin);
+
+ return false;
+}
+
+function Revivelogin(html){
+ HideLoading();
+ if(html == "ok"){
+ window.location="index.php"
+ return;
+ }
+
+ alert(html);
+}
+
+// Send a post form to the server using XMLHttpRequest.
+function senHTMLDocument(url, content, callback)
+{
+ if (!window.XMLHttpRequest)
+ return false;
+
+ var sendDoc = new window.XMLHttpRequest();
+ if (typeof(callback) != "undefined")
+ {
+ sendDoc.onreadystatechange = function ()
+ {
+ if (sendDoc.readyState != 4)
+ return;
+
+ if (sendDoc.responseText != null && sendDoc.status == 200)
+ callback(sendDoc.responseText);
+ else
+ callback(false);
+ };
+ }
+ sendDoc.open('POST', url, true);
+ if (typeof(sendDoc.setRequestHeader) != "undefined")
+ sendDoc.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+ sendDoc.send(content);
+
+ return true;
+}
+
+function GetXmlHttpObject(){
+ var xmlHttp=null;
+ try{
+ // Firefox, Opera 8.0+, Safari
+ xmlHttp=new XMLHttpRequest();
+ }
+ catch (e){
+ // Internet Explorer
+ try{
+ xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
+ }
+ catch (e){
+ xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ }
+ return xmlHttp;
+}
+
+function surroundText(text1, text2, textarea)
+{
+ // Can a text range be created?
+ if (typeof(textarea.caretPos) != "undefined" && textarea.createTextRange)
+ {
+ var caretPos = textarea.caretPos, temp_length = caretPos.text.length;
+
+ caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == ' ' ? text1 + caretPos.text + text2 + ' ' : text1 + caretPos.text + text2;
+
+ if (temp_length == 0)
+ {
+ caretPos.moveStart("character", -text2.length);
+ caretPos.moveEnd("character", -text2.length);
+ caretPos.select();
+ }
+ else
+ textarea.focus(caretPos);
+ }
+ // Mozilla text range wrap.
+ else if (typeof(textarea.selectionStart) != "undefined")
+ {
+ var begin = textarea.value.substr(0, textarea.selectionStart);
+ var selection = textarea.value.substr(textarea.selectionStart, textarea.selectionEnd - textarea.selectionStart);
+ var end = textarea.value.substr(textarea.selectionEnd);
+ var newCursorPos = textarea.selectionStart;
+ var scrollPos = textarea.scrollTop;
+
+ textarea.value = begin + text1 + selection + text2 + end;
+
+ if (textarea.setSelectionRange)
+ {
+ if (selection.length == 0)
+ textarea.setSelectionRange(newCursorPos + text1.length, newCursorPos + text1.length);
+ else
+ textarea.setSelectionRange(newCursorPos, newCursorPos + text1.length + selection.length + text2.length);
+ textarea.focus();
+ }
+ textarea.scrollTop = scrollPos;
+ }
+ // Just put them on the end, then.
+ else
+ {
+ textarea.value += text1 + text2;
+ textarea.focus(textarea.value.length - 1);
+ }
+}
+
+function textToEntities(text)
+{
+ var entities = "";
+ for (var i = 0; i < text.length; i++)
+ {
+ var charcode = text.charCodeAt(i);
+ if ((charcode >= 48 && charcode <= 57) || (charcode >= 65 && charcode <= 90) || (charcode >= 97 && charcode <= 122))
+ entities += text.charAt(i);
+ else
+ entities += "" + charcode + ";";
+ }
+
+ return entities;
+}
+
+function bbc_highlight(something, mode){
+ something.style.backgroundImage = "url(" + smf_images_url + (mode ? "/bbc/bbc_hoverbg.gif)" : "/bbc/bbc_bg.gif)");
+}
+
+function PreviewPost(){
+ x = new Array();
+ var textFields = ["message"];
+
+ ShowLoading();
+
+ for (i in textFields)
+ if (document.forms.postmodify.elements[textFields[i]])
+ x[x.length] = textFields[i] + "=" + escape(textToEntities(document.forms.postmodify[textFields[i]].value.replace(//g, "&#"))).replace(/\+/g, "%2B");
+
+ senHTMLDocument("index.php?action=previewpost", x.join("&"), PreviewPostSent);
+
+ return false;
+}
+
+function PreviewPostSent(html){
+ if (previewPopupWindow)
+ previewPopupWindow.close();
+
+ HideLoading();
+
+ thespan = document.getElementById("previewspan");
+
+ thespan.style.display = "";
+ thespan.innerHTML = "Preview: " + html + "
";
+}
+
+function submitThisOnce(form,id,post)
+{
+ if (typeof(form.form) != "undefined")
+ form = form.form;
+
+ for (var i = 0; i < form.length; i++)
+ if (typeof(form[i]) != "undefined" && form[i].tagName.toLowerCase() == "textarea")
+ form[i].readOnly = true;
+
+ x = new Array();
+ var textFields = ["message","poster"];
+
+ ShowLoading();
+
+
+ for (i in textFields)
+ if (document.forms.postmodify.elements[textFields[i]])
+ x[x.length] = textFields[i] + "=" + escape(textToEntities(document.forms.postmodify[textFields[i]].value.replace(//g, "&#"))).replace(/\+/g, "%2B");
+
+ senHTMLDocument("index.php?action=post&id=" + id + "&type=" + post, x.join("&"), SentPost);
+
+ return false;
+}
+
+function SentPost(html){
+ HideLoading();
+ html=html.trim();
+
+ if(html == "0")
+ return alert("Invalid data.")
+ else if (html == "1")
+ return alert("No body data.")
+ else if (html == "2")
+ return alert("Please at least wait 15 secs between each post.");
+ else if (html == "3")
+ return alert("Please login before posting.");
+ else
+ document.getElementById("MainBody").innerHTML= html;
+
+}
+
diff --git a/tools/docgen/www/style.css b/tools/docgen/www/style.css
new file mode 100644
index 00000000..ee892628
--- /dev/null
+++ b/tools/docgen/www/style.css
@@ -0,0 +1,81 @@
+tr.tpc:hover
+{
+ background-color: #595959;
+}
+
+a
+{
+ text-decoration: none;
+ color: blue;
+}
+a:hover
+{
+ text-decoration: underline;
+}
+
+a img{
+ border: 0;
+}
+
+body, td, th , tr
+{
+ font-size: small;
+ font-family: verdana, sans-serif;
+}
+
+/* The main body of the entire forum. */
+body
+{
+ background-color: #bebebe;
+ margin: 0px;
+}
+
+.descript{
+ visibility: hidden;
+ z-index: 200;
+ position: absolute;
+ background-color: #FFFFFF;
+ border: 1px solid black;
+ font-size: x-small;
+ font-family: verdana, sans-serif;
+}
+
+.UpperTab{
+ background-color: #D0D2D6;
+ width: 100px;
+ font-size: 12pt;
+ text-align:center;
+}
+
+.LoadingBox{
+ background-color: #D8D8D8;
+ border: 1px solid black;
+ position: absolute;
+ padding: 10px;
+ right: 50px;
+ top: 50px;
+}
+
+.phpcode
+{
+ color: #000000;
+ background-color: #D7DADC;
+ border: 1px solid #000000;
+ margin: 1px;
+ padding: 1px;
+ font-size: x-small;
+ line-height: 1.4em;
+ width: 95%;
+}
+
+.smfunc
+{
+ color: black;
+ font-weight: bold;
+}
+
+.smconst
+{
+ color: blue;
+ font-weight: bold;
+}
diff --git a/tools/docgen/www/template.php b/tools/docgen/www/template.php
new file mode 100644
index 00000000..da6130d1
--- /dev/null
+++ b/tools/docgen/www/template.php
@@ -0,0 +1,347 @@
+
+ '.$context['optheader'] .' - SourceMod Scripting API Reference
+
+
+
+
+
+
+
+
+
+
+
+
+ ';
+
+
+ if($context['user']['guest']){
+ echo '
+
+
';
+ } else{
+ echo 'Hey, '.$context['user']['name'].' .
+ Logout
';
+ }
+
+ echo '
+
+ Welcome to the SourceMod Scripting API Reference.
+ For more information, see the SourceMod Scripting Wiki , which contains tutorials on specific topics.
+
+
+ Your browser must support JavaScript to use this tool.
+ Enter a search term on the left to look for symbols in the SourceMod include files.
+ Alternately, click a file on the left to browse its functions/symbols or see its contents.
+ Click "Reset" to get back to the main page, or "Link to page" to link someone to the page you\'re seeing.
+
+
+
+
+
+ ';
+
+ echo 'Search:
';
+
+
+ echo '
+
';
+
+ foreach($context['fileinfo'] as $file){
+ echo '
+
+ '.$file['name'].'
+
';
+ }
+
+ echo '
+
+
+
+
+ API site created by Nican | SourceMod v.'. $context['globalinfo']['version'][1] .'
+
';
+
+ echo '';
+}
+
+function GenerateLink($backwards = false){
+ $link = "";
+ foreach($_GET as $name => $info){
+ $link .= htmlspecialchars(urlencode($name)) . '=' . htmlspecialchars(urlencode($info)) . '&';
+ }
+
+ if($backwards)
+ $link = str_replace("fastload","action",$link);
+ else
+ $link = str_replace("action","fastload",$link);
+
+ return $link;
+}
+
+function PrintUpperTab($fileid, $fcount, $ccount){
+ global $context;
+ $fileid = (int)$fileid;
+ echo '
+ ';
+
+ if( $ccount > 0)
+ echo 'Constants ';
+ else
+ echo 'Constants';
+
+ echo ' ';
+
+ if($fcount > 0)
+ echo 'Functions ';
+ else
+ echo 'Functions';
+
+ echo ' ';
+ echo 'File
+
+ Link to page
+
';
+}
+
+function ShowOpts_template(){
+ global $context;
+
+ if($context['numresults'] > 100){
+ echo 'More than 100 results found. Please try something smaller';
+ return;
+ }
+
+ echo '';
+ if($context['numresults'] > 0){
+ foreach ($context['files'] as $fid => $file){
+ echo '
+ '. $file .' ';
+
+ foreach ($context['answers'][ $fid ] as $id => $func){
+ echo '
' . $func . " ";
+ }
+ echo '
';
+ }
+ }
+ echo '
';
+ echo $context['numresults']. ' results found.';
+
+}
+
+//func,fullfunc,description,treturn,funcinput,exemple,inc,typeof
+
+function ShowInfo_template(){
+ global $context;
+
+ if($context['numresults'] > 0){
+ PrintUpperTab( $context['answers']['inc'] , $context['fileinfo']['fcount'], $context['fileinfo']['fcount']);
+
+ echo '';
+
+ //echo '
[ Source Mod ] [ '.$context['answers']['incname'].' ] ';
+ echo '
' . $context['answers']['func'] . '
+
Syntax: ';
+
+ highlight_string($context['answers']['fullfunc']);
+
+ echo '
Usage: ' . $context['answers']['funcinput'] . ' ';
+
+ echo '
Notes :
'. $context['answers']['description'] . '
+
+
Return: ' , $context['answers']['treturn'] != "0" ? $context['answers']['treturn'] : 'No return. ' , '
';
+
+ echo '
Version Added: ' . $context['answers']['version'] . ' ';
+
+ if($context['answers']['onerror'] != "")
+ echo '
On error / Errors: ' , $context['answers']['onerror'] != "" ? $context['answers']['onerror'] : 'No error. ' , '
';
+
+ echo '
';
+
+ PrintPostingSection('func');
+ } else
+ echo 'No result found on that id.';
+
+}
+
+function ShowFile_template(){
+ global $context;
+
+ if($context['numresults'] > 0){
+ PrintUpperTab( $_GET['id'] , $context['fcount'], $context['ccount']);
+
+ echo '';
+
+ switch($context['goon']){
+ case 0:
+ echo '
';
+ foreach($context['infos'] as $i => $ans){
+ echo '' . $ans['func'] . ' ' . $ans['desc'] . ' ';
+ }
+ echo '
';
+ break;
+ case 1:
+ echo '
';
+ foreach($context['infos'] as $id => $info){
+ echo '
+
' . $info['descrip'] . '
+
';
+ }
+ break;
+ case 2:
+ echo '
'.$context['infos']['cont'].' ';
+ break;
+ }
+
+ echo '
';
+ PrintPostingSection('file');
+
+ } else
+ echo 'No result found on that id.';
+}
+
+function PrintPostingSection($type){
+ global $context;
+
+ echo '
+ 0 comments Post a new comment
+
+ ';
+
+ if($context['user']['guest']){
+ echo 'Please login before posting ';
+ } else {
+ echo '';
+
+ }
+
+ echo '
+ ';
+ if($context['sm']['pcount'] > 0){
+ foreach($context['sm']['posts'] as $post){
+ echo ''. $post['poster'] .' '. $post['time'] .'
+ '. $post['body'] .'
';
+ }
+ } else {
+ echo ' No posts posted ';
+ }
+ echo '
';
+}
+
+function Footertemplate(){
+ global $context;
+
+ /*echo '
+
+
Nican132.com | SourceMod v.
'. $context['globalinfo']['version'][1] .'
+
';*/
+
+}
+
+function HighLight_template(){
+ global $context;
+
+ if($context['goon']){
+ if(isset($context['imagerror']))
+ echo 'There was an error:' . $context['imagerror'];
+ else {
+ echo "\n" . '
' . "\n" . $context['str'];
+ }
+ } else {
+ echo '
+ In this section you can upload any file .sp and the website will automaticly highlight the codes in a easy way to understang it.Function still beta.
+
+ Upload a file:
+
+
+ OR
+ Enter the code here:
+
+
+ ';
+ }
+}
+?>