]> git.mxchange.org Git - ctracker.git/commitdiff
First implemenation
authorRoland Haeder <roland@mxchange.org>
Thu, 31 Dec 2009 02:36:49 +0000 (02:36 +0000)
committerRoland Haeder <roland@mxchange.org>
Thu, 31 Dec 2009 02:36:49 +0000 (02:36 +0000)
.gitattributes
.gitignore [new file with mode: 0644]
config/.htaccess [new file with mode: 0644]
config/db_config.php.dist [new file with mode: 0644]
ctracker.php [new file with mode: 0644]
libs/.htaccess [new file with mode: 0644]
libs/lib_ [new file with mode: 0644]
libs/lib_connect.php [new file with mode: 0644]
libs/lib_detector.php [new file with mode: 0644]
libs/lib_general.php [new file with mode: 0644]

index 41cadca709f710b5912a0f844661accf1e55a2cd..cf92e911d0ed8cea8586ef9d823e4dec2a0be20a 100644 (file)
@@ -1,8 +1,16 @@
 * text=auto !eol
+config/.htaccess -text
+config/db_config.php.dist -text
+/ctracker.php -text
 docs/COPYING -text
 docs/NEWS -text
 docs/README -text
 docs/THANKS -text
 docs/TODO -text
 docs/TODOs.txt -text
+libs/.htaccess -text
+libs/lib_ -text
+libs/lib_connect.php -text
+libs/lib_detector.php -text
+libs/lib_general.php -text
 /todo-builder.sh -text
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..bc2af6d
--- /dev/null
@@ -0,0 +1 @@
+config/db_config.php
diff --git a/config/.htaccess b/config/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/config/db_config.php.dist b/config/db_config.php.dist
new file mode 100644 (file)
index 0000000..4a4c683
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Database configuration
+ *
+ * @author             Roland Haeder <webmaster@ship-simu.org>
+ * @version            3.0.0
+ * @copyright  Copyright (c) 2009 Cracker Tracker Team
+ * @license            GNU GPL 3.0 or any newer version
+ * @link               http://www.ship-simu.org
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Host name
+$GLOBALS['ctracker_host'] = 'localhost';
+
+// Database name
+$GLOBALS['ctracker_dbname'] = 'ctracker';
+
+// User
+$GLOBALS['ctracker_user'] = 'ctracker';
+
+// Password
+$GLOBALS['ctracker_password'] = '';
+
+// Debugging should be disabled by default
+// $GLOBALS['ctracker_debug'] = true;
+
+// [EOF]
+?>
diff --git a/ctracker.php b/ctracker.php
new file mode 100644 (file)
index 0000000..5f7bf94
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/**
+ *
+ * Cracker Tracker Protection System - Enhanced Edition
+ * Created by: Christian Knerr - www.cback.de
+ * Enhanced by: Roland Haeder - www.ship-simu.org
+ * phpBB Users: Please use our complete phpBB2 Mod!
+ *
+ * @author             Roland Haeder <webmaster@ship-simu.org>
+ * @version            3.0.0
+ * @copyright  Copyright (c) 2009 Cracker Tracker Team
+ * @license            GNU GPL 3.0 or any newer version
+ * @link               http://www.ship-simu.org
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Include files
+include('config/db_config.php');
+include('libs/lib_general.php');
+include('libs/lib_detector.php');
+include('libs/lib_connect.php');
+
+// Init
+initCrackerTrackerArrays();
+
+// If no email is defined, asume default. This code should be removed
+if (!defined('__CTRACKER_EMAIL')) {
+       define('__CTRACKER_EMAIL', 'webmaster@mxchange.org');
+} // END - if
+
+// If it differs to original and the *whole* request string is not in whitelist
+// then blog the attempt
+if (isCrackerTrackerWormDetected()) {
+       // Send the email, this must be the last line because it contains a die()
+       sendCrackerTrackerMail();
+} // END - if
+
+// Suspicious POST data detected?
+if (isCrackerTrackerPostAttackDetected()) {
+       // Send the email, this must be the last line because it contains a die()
+       sendCrackerTrackerPostMail();
+} // END - if
+
+// [EOF]
+?>
diff --git a/libs/.htaccess b/libs/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/libs/lib_ b/libs/lib_
new file mode 100644 (file)
index 0000000..4cb27ab
--- /dev/null
+++ b/libs/lib_
@@ -0,0 +1,26 @@
+<?php
+/**
+ * 
+ *
+ * @author             Roland Haeder <webmaster@ship-simu.org>
+ * @version            3.0.0
+ * @copyright  Copyright (c) 2009 Cracker Tracker Team
+ * @license            GNU GPL 3.0 or any newer version
+ * @link               http://www.ship-simu.org
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// [EOF]
+?>
diff --git a/libs/lib_connect.php b/libs/lib_connect.php
new file mode 100644 (file)
index 0000000..800b07e
--- /dev/null
@@ -0,0 +1,155 @@
+<?php
+/**
+ * Database connection library
+ *
+ * @author             Roland Haeder <webmaster@ship-simu.org>
+ * @version            3.0.0
+ * @copyright  Copyright (c) 2009 Cracker Tracker Team
+ * @license            GNU GPL 3.0 or any newer version
+ * @link               http://www.ship-simu.org
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Function to aquire a database link
+function aquireCrackerTrackerDatabaseLink () {
+       // Is the link up?
+       if (!isCrackerTrackerDatabaseLinkUp()) {
+               // Then connect to the database
+               $GLOBALS['ctracker_link'] = mysql_connect($GLOBALS['ctracker_host'], $GLOBALS['ctracker_user'], $GLOBALS['ctracker_password']) or crackerTrackerDatabaseError(__FUNCTION__, __LINE__);
+
+               // Select the database
+               if (!mysql_select_db($GLOBALS['ctracker_dbname'], $GLOBALS['ctracker_link'])) {
+                       // Attempt has failed
+                       crackerTrackerDatabaseError(__FUNCTION__, __LINE__);
+               } // END - if
+       } // END - if
+}
+
+// Checks if the link is up
+function isCrackerTrackerDatabaseLinkUp () {
+       return ((isset($GLOBALS['ctracker_link'])) && (is_resource($GLOBALS['ctracker_link'])));
+}
+
+// Database error detected
+function crackerTrackerDatabaseError ($F, $L) {
+       // Should we debug?
+       if (isCrackerTrackerDebug()) {
+               // Output error
+               print 'Function    : ' . $F . '<br />';
+               print 'Line        : ' . $L . '<br />';
+               print 'MySQL error : ' . mysql_error() . '<br />';
+               print 'Last SQL    : '. $GLOBALS['ctracker_last_sql'] . '<br />';
+       } // END - if
+
+       // Currently only die here
+       crackerTrackerDie();
+}
+
+// Closes a maybe open database link
+function crackerTrackerCloseDatabaseLink () {
+       // Is the link up?
+       if (isCrackerTrackerDatabaseLinkUp()) {
+               // Did it work?
+               if (!mysql_close($GLOBALS['ctracker_link'])) {
+                       // Remove the link from global array
+                       unset($GLOBALS['ctracker_link']);
+
+                       // Attempt has failed
+                       crackerTrackerDatabaseError(__FUNCTION__, __LINE__);
+               } // END - if
+       } // END - if
+
+       // Remove the link from global array
+       unset($GLOBALS['ctracker_link']);
+}
+
+// Inserts given array, if IP/check_worm combination was not found
+function crackerTrackerInsertArray ($rowData) {
+       // Is it found?
+       if (!isCrackerTrackerEntryFound($rowData)) {
+               // Insert first attempt stamp
+               $rowData['first_attempt'] = 'NOW()';
+               $rowData['count'] = '1';
+
+               // Prepare SQL
+               $SQL = 'INSERT INTO `ctracker_data` (`' . implode('`,`', array_keys($rowData)) . '`) VALUES(' . implode_secure($rowData) . ')';
+
+               // Run it
+               runCrackerTrackerSql($SQL, __FUNCTION__, __LINE__);
+       } else {
+               // Only update the entry
+               updateCrackerTrackerEntry($rowData);
+       }
+}
+
+// Updates a given entry by just counting it up
+function updateCrackerTrackerEntry ($rowData) {
+       // Construct the SELECT query
+       $SQL = 'UPDATE `ctracker_data` SET `count`=`count`+1 WHERE `remote_addr`="' . crackerTrackerEscapeString($rowData['remote_addr']) . '" AND `check_worm` = "' . crackerTrackerEscapeString($rowData['check_worm']) . '" LIMIT 1';
+
+       // Run the SQL and check if we have one line
+       runCrackerTrackerSql($SQL, __FUNCTION__, __LINE__);
+}
+
+// Checks if an entry with IP/check_worm combination is there
+function isCrackerTrackerEntryFound ($rowData) {
+       // Construct the SELECT query
+       $SQL = 'SELECT `id` FROM `ctracker_data` WHERE `remote_addr`="' . crackerTrackerEscapeString($rowData['remote_addr']) . '" AND `check_worm` = "' . crackerTrackerEscapeString($rowData['check_worm']) . '" LIMIT 1';
+
+       // Run the SQL and check if we have one line
+       return (mysql_num_rows(runCrackerTrackerSql($SQL, __FUNCTION__, __LINE__)) == 1);
+}
+
+// Escapes the string
+function crackerTrackerEscapeString ($string) {
+       // Is the link up?
+       if (!isCrackerTrackerDatabaseLinkUp()) {
+               // Then we cant use mysql_real_escape_string!
+               $string = addslashes($string);
+       } elseif (function_exists('mysql_real_escape_string')) {
+               // Use mysql_real_escape_string()
+               $string = mysql_real_escape_string($string, $GLOBALS['ctracker_link']);
+       } elseif (function_exists('mysql_escape_string')) {
+               // Use deprecated function
+               $string = mysql_escape_string($string, $GLOBALS['ctracker_link']);
+       } else {
+               // Use fall-back (bad!)
+               $string = addslashes($string);
+       }
+
+       // Return the secured string
+       return $string;
+} // END - if
+
+// Runs an SQL query and checks for errors
+function runCrackerTrackerSql ($SQL, $F, $L) {
+       // Is the link up?
+       if (!isCrackerTrackerDatabaseLinkUp()) {
+               // Abort here
+               crackerTrackerDie();
+       } // END - if
+
+       // Remember last SQL
+       $GLOBALS['ctracker_last_sql'] = $SQL;
+
+       // Run the query
+       $GLOBALS['ctracker_last_result'] = mysql_query($SQL, $GLOBALS['ctracker_link']) or crackerTrackerDatabaseError(__FUNCTION__, __LINE__);
+
+       // And return it
+       return $GLOBALS['ctracker_last_result'];
+}
+
+// [EOF]
+?>
diff --git a/libs/lib_detector.php b/libs/lib_detector.php
new file mode 100644 (file)
index 0000000..eb9ed1d
--- /dev/null
@@ -0,0 +1,214 @@
+<?php
+/**
+ * Detector library
+ *
+ * @author             Roland Haeder <webmaster@ship-simu.org>
+ * @version            3.0.0
+ * @copyright  Copyright (c) 2009 Cracker Tracker Team
+ * @license            GNU GPL 3.0 or any newer version
+ * @link               http://www.ship-simu.org
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Initializes all detector arrays
+function initCrackerTrackerArrays () {
+       // Set error_reporting
+       if (isCrackerTrackerDebug()) {
+               // For debugging purposes, this is fine
+               @error_reporting(E_ALL, E_STRICT);
+       } else {
+               // No output
+               @error_reporting(0);
+       }
+
+       // Whitelist some absolute query strings (see below)
+       $GLOBALS['whitelist'] = array(
+               'cmd=new',   // LinPHA
+               'cmd=edit',  // LinPHA
+               'cmd=lostpw' // LinPHA
+       );
+
+       // Attacks we should detect and blok
+       $GLOBALS['wormprotector'] = array(
+               'chr(', 'chr=', 'chr%20', '%20chr', 'wget%20', '%20wget', 'wget(',
+               'cmd=', '%20cmd', 'cmd%20', 'rush=', '%20rush', 'rush%20',
+               'union%20', '%20union', 'union(', 'union=', 'echr(', '%20echr', 'echr%20', 'echr=',
+               'esystem(', 'esystem%20', 'cp%20', '%20cp', 'cp(', 'mdir%20', '%20mdir', 'mdir(',
+               'mcd%20', 'mrd%20', 'rm%20', '%20mcd', '%20mrd', '%20rm',
+               'mcd(', 'mrd(', 'rm(', 'mcd=', 'mrd=', 'mv%20', 'rmdir%20', 'mv(', 'rmdir(',
+               'chmod(', 'chmod%20', '%20chmod', 'chmod(', 'chmod=', 'chown%20', 'chgrp%20', 'chown(', 'chgrp(',
+               'locate%20', 'grep%20', 'locate(', 'grep(', 'diff%20', 'kill%20', 'kill(', 'killall',
+               'passwd%20', '%20passwd', 'passwd(', 'telnet%20', 'vi(', 'vi%20', 'cgi-', '.eml',
+               'insert%20into', 'select%20', 'nigga(', '%20nigga', 'nigga%20', 'fopen', 'fwrite', '%20like', 'like%20',
+               '$_request', '$_get', '$request', '$get', '.system', 'HTTP_PHP', '&aim', '%20getenv', 'getenv%20',
+               'new_password', '&icq','/etc/passwd','/etc/shadow', '/etc/groups', '/etc/gshadow',
+               'HTTP_USER_AGENT', 'HTTP_HOST', 'wget%20', 'uname\x20-a', 'bin/id', '/bin/', '/chgrp',
+               '/chown', '/usr/bin', 'g\+\+', 'bin/python', 'bin/tclsh', 'bin/nasm', 'perl%20', 'traceroute%20',
+               'ping%20', '.pl', 'bin/xterm', 'lsof%20', '.conf', 'motd%20', 'HTTP/1.', '.inc.php', '.lib.php',
+               'config.php', 'file\://', 'window.open', '<SCRIPT>', 'javascript\://', 'img src', 'img%20src', '.jsp',
+               'ftp.exe', 'xp_enumdsn', 'xp_availablemedia', 'xp_filelist', 'xp_cmdshell', 'nc.exe', '.htpasswd',
+               'servlet', '/etc/passwd', 'wwwacl', '~root', '~ftp', '.js', '.jsp', '.history', 'bash_history',
+               '.bash_history', '~nobody', 'server-info', 'server-status', 'reboot%20', 'halt%20',
+               'powerdown%20', '/home/ftp', '/home/www', 'secure_site, ok', 'chunked', 'org.apache', '/servlet/con',
+               '<script', '/robot.txt' ,'/perl' ,'mod_gzip_status', 'db_mysql.inc', '.inc', 'select%20from',
+               'select from', 'drop%20', '.system', 'getenv', 'http_', '_php', 'php_', 'phpinfo()', '\<?php', '?\>', 'sql=',
+               'div style=', 'overflow: auto', 'height: 1px', 'cc%20', 'admin_action=', 'path=', 'action=http',
+               'page=http', 'module=http', 'op=http', 'id=http', 'id%3Dhttp', 'action%3Dhttp', 'page%3Dhttp',
+               'module%3Dhttp', 'op%3Dhttp', 'starhack', '../../', 'directory=http', 'dir=http', 'busca', 'uol.com'
+       );
+
+       // Block these words found in POST requests
+       $GLOBALS['post_blacklist'] = array(
+               // These two lines are for detecting hidden link spam in wikis, forums, guestbooks, etc.
+               'div style=', 'overflow:auto', 'height:1px', 'width:1px', 'display:hidden',
+               'overflow: auto', 'height: 1px', 'display: hidden',
+               // "Common" login name from VHCS exploiters ;-)
+               'starhack', 'DeLiMehmet', 'hisset', 'Hisset', 'delimert', 'MecTruy',
+               'busca'
+       );
+}
+
+// Checks for worms
+function isCrackerTrackerWormDetected () {
+       // Check against the whole list
+       $GLOBALS['checkworm'] = str_replace($GLOBALS['wormprotector'], '*', $_SERVER['QUERY_STRING']);
+
+       // If it differs to original and the *whole* request string is not in whitelist
+       // then blog the attempt
+       return ($GLOBALS['checkworm'] != $_SERVER['QUERY_STRING'] && (!in_array($_SERVER['QUERY_STRING'], $GLOBALS['whitelist'])));
+}
+
+// Checks POST data
+function isCrackerTrackerPostAttackDetected () {
+       // Implode recursive the whole $_POST array
+       $GLOBALS['post_track'] = implode_r('', $_POST);
+
+       // Check for suspicious POST data
+       $GLOBALS['check_post'] = str_replace($GLOBALS['post_blacklist'], '*', $GLOBALS['post_track']);
+
+       // Is it detected?
+       return ((isCrackerTrackerWormDetected()) || ($GLOBALS['check_post'] != $GLOBALS['post_track']));
+}
+
+// Prepares a mail and send it out
+function sendCrackerTrackerMail () {
+       // Mail content
+       $mail = "Attack detected:
+-----------------------------------------------------
+Remote-IP: ".$_SERVER['REMOTE_ADDR']."
+User-Agent: ".$_SERVER['HTTP_USER_AGENT']."
+Request-string: ".$_SERVER['QUERY_STRING']."
+Filtered string: ".$GLOBALS['checkworm']."
+Server: ".$_SERVER['SERVER_NAME']."
+Script: ".$_SERVER['SCRIPT_NAME']."
+Referrer: ".$_SERVER['HTTP_REFERRER']."
+-----------------------------------------------------
+";
+
+       // Log the attack
+       crackerTrackerLogAttack();
+
+       // Send it out
+       crackerTrackerSendMail($mail);
+
+       // And die here
+       crackerTrackerDie();
+}
+
+// Sends a mail out
+function crackerTrackerSendMail ($mail) {
+       // Construct dummy array
+       $rowData = array(
+               'remote_addr' => $_SERVER['REMOTE_ADDR'],
+               'check_worm'  => $GLOBALS['checkworm']
+       );
+
+       // Only send email if not yet found
+       if (!isCrackerTrackerEntryFound($rowData)) {
+               // Send the email out only in non-debug mode
+               if (isCrackerTrackerDebug()) {
+                       // Output message
+                       print '<pre>' . $mail . '</pre>';
+
+                       // All fine
+                       return true;
+               } else {
+                       // Send it
+                       return mail(constant('__CTRACKER_EMAIL'), 'CTracker: Attack detected!', $mail, 'From: ctracker@mxchange.org');
+               }
+       } // END - if
+}
+
+// Sends a detected POST attack mail
+function sendCrackerTrackerPostMail () {
+       // Mail text
+       $mail = "POST-Attack detected:
+-----------------------------------------------------
+Remote-IP: ".$_SERVER['REMOTE_ADDR']."
+User-Agent: ".$_SERVER['HTTP_USER_AGENT']."
+POST string: ".$GLOBALS['post_track']."
+Filtered worm string: ".$GLOBALS['checkworm']."
+Filtered POST string: ".$GLOBALS['check_post']."
+Server: ".$_SERVER['SERVER_NAME']."
+Script: ".$_SERVER['SCRIPT_NAME']."
+-----------------------------------------------------
+";
+
+       // Log the attack
+       crackerTrackerLogAttack();
+
+       // Send it out
+       crackerTrackerSendMail($mail);
+
+       // And die here
+       crackerTrackerDie();
+}
+
+// Sleeps for a random time and aborts the script
+function crackerTrackerDie () {
+       // Close database link
+       crackerTrackerCloseDatabaseLink();
+
+       // Sleep a little to waste the attacker's time
+       if (!isCrackerTrackerDebug()) sleep(mt_rand(10,30));
+
+       // Bye, bye...
+       die();
+}
+
+// Logs the attack attempt
+function crackerTrackerLogAttack () {
+       // Aquire database link
+       aquireCrackerTrackerDatabaseLink();
+
+
+       // Prepare array for database insert
+       $rowData = array(
+               'remote_addr'     => $_SERVER['REMOTE_ADDR'],
+               'user_agent'      => $_SERVER['HTTP_USER_AGENT'],
+               'post_data'       => $GLOBALS['post_track'],
+               'check_worm'      => $GLOBALS['checkworm'],
+               'check_post'      => $GLOBALS['check_post'],
+               'server_name'     => $_SERVER['SERVER_NAME'],
+               'script_name'     => $_SERVER['SCRIPT_NAME'],
+               'referer'         => $_SERVER['HTTP_REFERER']
+       );
+
+       // Insert the array in database
+       crackerTrackerInsertArray($rowData);
+}
+
+// [EOF]
+?>
diff --git a/libs/lib_general.php b/libs/lib_general.php
new file mode 100644 (file)
index 0000000..ff81bb9
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+/**
+ * General functions library
+ *
+ * @author             Roland Haeder <webmaster@ship-simu.org>
+ * @version            3.0.0
+ * @copyright  Copyright (c) 2009 Cracker Tracker Team
+ * @license            GNU GPL 3.0 or any newer version
+ * @link               http://www.ship-simu.org
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+if (!function_exists('implode_r')) {
+       // Implode recursive a multi-dimension array, taken from www.php.net
+       function implode_r ($glue, $array, $array_name = NULL) {
+               $return = array();
+               while(list($key,$value) = @each($array)) {
+                       if(is_array($value)) {
+                               // Is an array again, so call recursive
+                               $return[] = implode_r($glue, $value, (string) $key);
+                       } else {
+                               if($array_name != NULL) {
+                                       $return[] = $array_name . '[' . (string) $key . ']=' . $value . "\n";
+                               } else {
+                                       $return[] = $key . '=' . $value."\n";
+                               }
+                       }
+               } // END - while
+
+               // Return resulting array
+               return(implode($glue, $return));
+       } // END - function
+} // END - if
+
+if (!function_exists('implode_secure')) {
+       // Implode a simple array with a 'call-back' to our escaper function
+       function implode_secure ($array) {
+               // Return string
+               $return = '';
+
+               // Implode all data
+               foreach ($array as $entry) {
+                       // Don't escape some
+                       if (in_array($entry, array('NOW()'))) {
+                               // Add it with non-string glue
+                               $return .= $entry . ',';
+                       } elseif (empty($entry)) {
+                               // Empty strings need no escaping
+                               $return .= '"",';
+                       } else {
+                               // Secure this string and add it
+                               $return .= '"' . crackerTrackerEscapeString($entry) . '",';
+                       }
+               } // END - foreach
+
+               // Remove last char
+               $return = substr($return, 0, -1);
+
+               // Return this string
+               return $return;
+       } // END - function
+} // END - if
+
+// Getter for ctracker_debug
+function isCrackerTrackerDebug () {
+       return $GLOBALS['ctracker_debug'];
+}
+
+// [EOF]
+?>