# HG changeset patch # User Dan # Date 1197760214 18000 # Node ID 112debff64bd6b268d39bf04743045a5adc94d11 # Parent 8be996c3740dccf30ea470a597cd28bf9ce38cfb SURPRISE! Preliminary PostgreSQL support added. The required schema file is not present in this commit and will be included at a later date. No installer support is implemented. Also in this commit: several fixes including was broken in template compiler; set fixed width on included images to prevent the thumbnail box from getting huge; added a much more friendly interface to AJAX responses that are invalid JSON diff -r 8be996c3740d -r 112debff64bd README --- a/README Wed Dec 12 21:46:28 2007 -0500 +++ b/README Sat Dec 15 18:10:14 2007 -0500 @@ -1,5 +1,5 @@ Enano CMS -Version 1.0.2 +Version 1.0.3 ----------------------------- Thanks for downloading Enano! If you're looking for an installation guide, @@ -74,7 +74,7 @@ CHANGES IN THIS RELEASE ----------------------------- -Please see for a list of changes in +Please see for a list of changes in this release. UPGRADING FROM PREVIOUS RELEASES diff -r 8be996c3740d -r 112debff64bd ajax.php --- a/ajax.php Wed Dec 12 21:46:28 2007 -0500 +++ b/ajax.php Sat Dec 15 18:10:14 2007 -0500 @@ -18,11 +18,6 @@ if ( isset($_GET['_mode']) && $_GET['_mode'] == 'fillusername' ) { // setup and load a very basic, specialized instance of the Enano API - function dc_here($m) { return false; } - function dc_dump($a, $g) { return false; } - function dc_watch($n) { return false; } - function dc_start_timer($u) { return false; } - function dc_stop_timer($m) { return false; } function microtime_float() { list($usec, $sec) = explode(" ", microtime()); @@ -41,7 +36,14 @@ require(ENANO_ROOT.'/includes/functions.php'); require(ENANO_ROOT.'/includes/dbal.php'); require(ENANO_ROOT.'/includes/json.php'); - $db = new mysql(); + + require(ENANO_ROOT . '/config.php'); + unset($dbuser, $dbpasswd); + if ( !isset($dbdriver) ) + $dbdriver = 'mysql'; + + $db = new $dbdriver(); + $db->connect(); // result is sent using JSON @@ -62,14 +64,10 @@ die( $json->encode($return) ); } $allowanon = ( isset($_GET['allowanon']) && $_GET['allowanon'] == '1' ) ? '' : ' AND user_id > 1'; - $q = $db->sql_query('SELECT username FROM '.table_prefix.'users WHERE lcase(username) LIKE lcase(\'%'.$name.'%\')' . $allowanon . ' ORDER BY username ASC;'); + $q = $db->sql_query('SELECT username FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username) LIKE ' . ENANO_SQLFUNC_LOWERCASE . '(\'%'.$name.'%\')' . $allowanon . ' ORDER BY username ASC;'); if ( !$q ) { - $return = array( - 'mode' => 'error', - 'error' => 'MySQL error selecting username data: '.addslashes(mysql_error()) - ); - die( $json->encode($return) ); + $db->die_json(); } $i = 0; while($r = $db->fetchrow()) @@ -277,7 +275,7 @@ $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); $ret = array('tags' => array(), 'user_level' => $session->user_level, 'can_add' => $session->get_permissions('tag_create')); - $q = $db->sql_query('SELECT t.tag_id, t.tag_name, pg.pg_target IS NOT NULL AS used_in_acl, t.user FROM '.table_prefix.'tags AS t + $q = $db->sql_query('SELECT t.tag_id, t.tag_name, pg.pg_target IS NOT NULL AS used_in_acl, t.user_id FROM '.table_prefix.'tags AS t LEFT JOIN '.table_prefix.'page_groups AS pg ON ( ( pg.pg_type = ' . PAGE_GRP_TAGGED . ' AND pg.pg_target=t.tag_name ) OR ( pg.pg_type IS NULL AND pg.pg_target IS NULL ) ) WHERE t.page_id=\'' . $db->escape($paths->cpage['urlname_nons']) . '\' AND t.namespace=\'' . $db->escape($paths->namespace) . '\';'); @@ -288,11 +286,11 @@ { $can_del = true; - $perm = ( $row['user'] != $session->user_id ) ? + $perm = ( $row['user_id'] != $session->user_id ) ? 'tag_delete_other' : 'tag_delete_own'; - if ( $row['user'] == 1 && !$session->user_logged_in ) + if ( $row['user_id'] == 1 && !$session->user_logged_in ) // anonymous user trying to delete tag (hardcode blacklisted) $can_del = false; @@ -364,7 +362,7 @@ $db->free_result(); // we're good - $q = $db->sql_query('INSERT INTO '.table_prefix.'tags(tag_name,page_id,namespace,user) VALUES(\'' . $tag . '\', \'' . $db->escape($paths->cpage['urlname_nons']) . '\', \'' . $db->escape($paths->namespace) . '\', ' . $session->user_id . ');'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'tags(tag_name,page_id,namespace,user_id) VALUES(\'' . $tag . '\', \'' . $db->escape($paths->cpage['urlname_nons']) . '\', \'' . $db->escape($paths->namespace) . '\', ' . $session->user_id . ');'); if ( !$q ) $db->_die(); @@ -380,7 +378,7 @@ if ( empty($tag_id) ) die('Invalid tag ID'); - $q = $db->sql_query('SELECT t.tag_id, t.user, t.page_id, t.namespace, pg.pg_target IS NOT NULL AS used_in_acl FROM '.table_prefix.'tags AS t + $q = $db->sql_query('SELECT t.tag_id, t.user_id, t.page_id, t.namespace, pg.pg_target IS NOT NULL AS used_in_acl FROM '.table_prefix.'tags AS t LEFT JOIN '.table_prefix.'page_groups AS pg ON ( pg.pg_id IS NULL OR ( pg.pg_target = t.tag_name AND pg.pg_type = ' . PAGE_GRP_TAGGED . ' ) ) WHERE t.tag_id=' . $tag_id . ';'); @@ -399,11 +397,11 @@ else $perms = $session->fetch_page_acl($row['page_id'], $row['namespace']); - $perm = ( $row['user'] != $session->user_id ) ? + $perm = ( $row['user_id'] != $session->user_id ) ? 'tag_delete_other' : 'tag_delete_own'; - if ( $row['user'] == 1 && !$session->user_logged_in ) + if ( $row['user_id'] == 1 && !$session->user_logged_in ) // anonymous user trying to delete tag (hardcode blacklisted) die('You are not authorized to delete this tag.'); diff -r 8be996c3740d -r 112debff64bd includes/clientside/static/acl.js --- a/includes/clientside/static/acl.js Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/clientside/static/acl.js Sat Dec 15 18:10:14 2007 -0500 @@ -27,6 +27,17 @@ ajaxPost(stdAjaxPrefix+'&_mode=acljson', 'acl_params='+params, function() { if(ajax.readyState == 4) { + var response = String(ajax.responseText + ''); + if ( response.substr(0, 1) != '{' ) + { + handle_invalid_json(ajax.responseText); + return false; + } + try { + data = parseJSON(ajax.responseText); + } catch(e) { + handle_invalid_json(ajax.responseText); + } __aclBuildWizardWindow(); groups = parseJSON(ajax.responseText); if ( groups.mode == 'error' ) @@ -307,10 +318,16 @@ ajaxPost(stdAjaxPrefix+'&_mode=acljson', 'acl_params='+params, function() { if(ajax.readyState == 4) { + var response = String(ajax.responseText + ''); + if ( response.substr(0, 1) != '{' ) + { + handle_invalid_json(ajax.responseText); + return false; + } try { data = parseJSON(ajax.responseText); } catch(e) { - aclDebug(e+"\n\nResponse:\n"+ajax.responseText); + handle_invalid_json(ajax.responseText); } aclDataCache = data; switch(data.mode) @@ -470,7 +487,7 @@ aclDebug(data.text); break; default: - alert("Invalid JSON response from server\nMode: "+data.mode+"\nJSON string: "+ajax.responseText); + handle_invalid_json(ajax.responseText); break; } } diff -r 8be996c3740d -r 112debff64bd includes/clientside/static/ajax.js --- a/includes/clientside/static/ajax.js Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/clientside/static/ajax.js Sat Dec 15 18:10:14 2007 -0500 @@ -42,6 +42,81 @@ ajax.send(parms); } +/** + * Show a friendly error message depicting an AJAX response that is not valid JSON + * @param string Response text + * @param string Custom error message. If omitted, the default will be shown. + */ + +function handle_invalid_json(response, customerror) +{ + var mainwin = $('ajaxEditContainer').object; + mainwin.innerHTML = ''; + + // Title + var h3 = document.createElement('h3'); + h3.appendChild(document.createTextNode('The site encountered an error while processing your request.')); + mainwin.appendChild(h3); + + if ( typeof(customerror) == 'string' ) + { + var el = document.createElement('p'); + el.appendChild(document.createTextNode(customerror)); + mainwin.appendChild(el); + } + else + { + customerror = 'We unexpectedly received the following response from the server. The response should have been in the JSON '; + customerror += 'serialization format, but the response wasn\'t composed only of the JSON response. There are three possible triggers'; + customerror += 'for this problem:'; + var el = document.createElement('p'); + el.appendChild(document.createTextNode(customerror)); + mainwin.appendChild(el); + var ul = document.createElement('ul'); + var li1 = document.createElement('li'); + var li2 = document.createElement('li'); + var li3 = document.createElement('li'); + li1.appendChild(document.createTextNode('The server sent back a bad HTTP response code and thus sent an error page instead of running Enano. This indicates a possible problem with your server, and is not likely to be a bug with Enano.')); + var osc_exception = ( window.location.hostname == 'demo.opensourcecms.com' ) ? ' This is KNOWN to be the case with the OpenSourceCMS.com demo version of Enano.' : ''; + li2.appendChild(document.createTextNode('The server sent back the expected JSON response, but also injected some code into the response that should not be there. Typically this consists of advertisement code. In this case, the administrator of this site will have to contact their web host to have advertisements disabled.' + osc_exception)); + li3.appendChild(document.createTextNode('It\'s possible that Enano triggered a PHP error or warning. In this case, you may be looking at a bug in Enano.')); + + ul.appendChild(li1); + ul.appendChild(li2); + ul.appendChild(li3); + mainwin.appendChild(ul); + } + + var p2 = document.createElement('p'); + p2.appendChild(document.createTextNode('The response received from the server is as follows:')); + mainwin.appendChild(p2); + + var pre = document.createElement('pre'); + pre.appendChild(document.createTextNode(response)); + mainwin.appendChild(pre); + + var p3 = document.createElement('p'); + p3.appendChild(document.createTextNode('You may also choose to view the response as HTML. ')); + var a = document.createElement('a'); + a.appendChild(document.createTextNode('View as HTML...')); + a._resp = response; + a.id = 'invalidjson_link'; + a.onclick = function() + { + var mb = new messagebox(MB_YESNO | MB_ICONEXCLAMATION, 'Do you really want to view this response as HTML?', 'If the response was changed during transmission to include malicious code, you may be allowing that malicious code to run by viewing the response as HTML. Only do this if you have reviewed the response text and have found no suspicious code in it.'); + mb.onclick['Yes'] = function() + { + var html = $('invalidjson_link').object._resp; + var win = window.open('about:blank', 'invalidjson_htmlwin', 'width=550,height=400,status=no,toolbars=no,toolbar=no,address=no,scroll=yes'); + win.document.write(html); + } + return false; + } + a.href = '#'; + p3.appendChild(a); + mainwin.appendChild(p3); +} + function ajaxEscape(text) { /* @@ -926,7 +1001,7 @@ resptext = resptext.substr(0, resptext.length-1); if ( resptext.substr(0, 1) != '{' ) { - alert('Invalid JSON response from server:\n' + resptext); + handle_invalid_json(resptext); return false; } var json = parseJSON(resptext); @@ -1026,7 +1101,7 @@ resptext = resptext.substr(0, resptext.length-1); if ( resptext.substr(0, 1) != '{' ) { - alert('Invalid JSON response from server:\n' + resptext); + handle_invalid_json(resptext); return false; } var json = parseJSON(resptext); diff -r 8be996c3740d -r 112debff64bd includes/clientside/static/faders.js --- a/includes/clientside/static/faders.js Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/clientside/static/faders.js Sat Dec 15 18:10:14 2007 -0500 @@ -74,6 +74,8 @@ * onclick - an array of functions to be called on button click events * NOTE: key names are to be strings, and they must be the value of the input, CaSe-SeNsItIvE * onbeforeclick - same as onclick but called before the messagebox div is destroyed + * Methods: + * destroy: kills the running message box * Example: * var my_message = new messagebox(MB_OK|MB_ICONSTOP, 'Error logging in', 'The username and/or password is incorrect. Please check the username and retype your password'); * my_message.onclick['OK'] = function() { @@ -267,6 +269,14 @@ { this.text_area.innerHTML = text; }; + + this.destroy = function() + { + var mbdiv = document.getElementById('messageBox'); + mbdiv.parentNode.removeChild(mbdiv.nextSibling); + mbdiv.parentNode.removeChild(mbdiv); + enlighten(true); + }; //domObjChangeOpac(0, mydiv); //domObjChangeOpac(0, master_div); diff -r 8be996c3740d -r 112debff64bd includes/clientside/static/misc.js --- a/includes/clientside/static/misc.js Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/clientside/static/misc.js Sat Dec 15 18:10:14 2007 -0500 @@ -335,7 +335,8 @@ var response = String(ajax.responseText); if ( response.substr(0,1) != '{' ) { - alert('Invalid JSON response from server: ' + response); + handle_invalid_json(response); + ajax_auth_mb_cache.destroy(); return false; } response = parseJSON(response); diff -r 8be996c3740d -r 112debff64bd includes/comment.php --- a/includes/comment.php Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/comment.php Sat Dec 15 18:10:14 2007 -0500 @@ -113,7 +113,7 @@ ON ( ( b.user_id=' . $session->user_id.' AND b.buddy_user_id=c.user_id ) OR b.user_id IS NULL) WHERE page_id=\'' . $this->page_id . '\' AND namespace=\'' . $this->namespace . '\' - GROUP BY c.comment_id + GROUP BY c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,u.user_level,u.user_id,u.signature,b.buddy_id,b.is_friend ORDER BY c.time ASC;'); $count_appr = 0; $count_total = 0; diff -r 8be996c3740d -r 112debff64bd includes/common.php --- a/includes/common.php Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/common.php Sat Dec 15 18:10:14 2007 -0500 @@ -151,7 +151,13 @@ // The first thing we need to do is start the database connection. At this point, for all we know, Enano might not // even be installed. If this connection attempt fails and it's because of a missing or corrupt config file, the // user will be redirected (intelligently) to install.php. -$db = new mysql(); + +require(ENANO_ROOT . '/config.php'); +unset($dbuser, $dbpasswd); +if ( !isset($dbdriver) ) + $dbdriver = 'mysql'; + +$db = new $dbdriver(); $db->connect(); // The URL separator is the character appended to contentPath + url_title type strings. diff -r 8be996c3740d -r 112debff64bd includes/dbal.php --- a/includes/dbal.php Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/dbal.php Sat Dec 15 18:10:14 2007 -0500 @@ -124,6 +124,12 @@ { $this->enable_errorhandler(); + define('ENANO_DBLAYER', 'MYSQL'); + define('ENANO_SQLFUNC_LOWERCASE', 'lcase'); + define('ENANO_SQL_MULTISTRING_PRFIX', ''); + define('ENANO_SQL_BOOLEAN_TRUE', 'true'); + define('ENANO_SQL_BOOLEAN_FALSE', 'false'); + if ( defined('IN_ENANO_INSTALL') && !defined('IN_ENANO_UPGRADE') ) { @include(ENANO_ROOT.'/config.new.php'); @@ -778,4 +784,747 @@ } } +class postgresql { + var $num_queries, $query_backtrace, $query_times, $query_sources, $latest_result, $latest_query, $_conn, $sql_stack_fields, $sql_stack_values, $debug; + var $row = array(); + var $rowset = array(); + var $errhandler; + + function enable_errorhandler() + { + // echo "DBAL: enabling error handler
"; + if ( function_exists('debug_backtrace') ) + { + $this->errhandler = set_error_handler('db_error_handler'); + } + } + + function disable_errorhandler() + { + // echo "DBAL: disabling error handler
"; + if ( $this->errhandler ) + { + set_error_handler($this->errhandler); + } + else + { + restore_error_handler(); + } + } + + function sql_backtrace() + { + return implode("\n-------------------------------------------------------------------\n", $this->query_backtrace); + } + + function ensure_connection() + { + if(!$this->_conn) + { + $this->connect(); + } + } + + function _die($t = '') { + if(defined('ENANO_HEADERS_SENT')) { + ob_clean(); + } + header('HTTP/1.1 500 Internal Server Error'); + $bt = $this->latest_query; // $this->sql_backtrace(); + $e = htmlspecialchars(pg_last_error()); + if($e=='') $e='<none>'; + $t = ( !empty($t) ) ? $t : '<No error description provided>'; + global $email; + $email_info = ( defined('ENANO_CONFIG_FETCHED') && is_object($email) ) ? ', at <' . $email->jscode() . $email->encryptEmail(getConfig('contact_email')) . '>' : ''; + $internal_text = '

The site was unable to finish serving your request.

+

We apologize for the inconveience, but an error occurred in the Enano database layer. Please report the full text of this page to the administrator of this site' . $email_info . '.

+

Description or location of error: '.$t.'
+ Error returned by PostgreSQL extension: ' . $e . '
+ Most recent SQL query:

+
'.$bt.'
'; + if(defined('ENANO_CONFIG_FETCHED')) die_semicritical('Database error', $internal_text); + else grinding_halt('Database error', $internal_text); + exit; + } + + function die_json() + { + $e = addslashes(htmlspecialchars(pg_last_error())); + $q = addslashes($this->latest_query); + $t = "{'mode':'error','error':'An error occurred during database query.\nQuery was:\n $q\n\nError returned by PostgreSQL: $e'}"; + die($t); + } + + function get_error($t = '') { + header('HTTP/1.1 500 Internal Server Error'); + $bt = $this->sql_backtrace(); + $e = htmlspecialchars(pg_last_error()); + if($e=='') $e='<none>'; + global $email; + $email_info = ( defined('ENANO_CONFIG_FETCHED') && is_object($email) ) ? ', at <' . $email->jscode() . $email->encryptEmail(getConfig('contact_email')) . '>' : ''; + $internal_text = '

The site was unable to finish serving your request.

+

We apologize for the inconveience, but an error occurred in the Enano database layer. Please report the full text of this page to the administrator of this site' . $email_info . '.

+

Description or location of error: '.$t.'
+ Error returned by MySQL extension: ' . $e . '
+ Most recent SQL query:

+
'.$bt.'
'; + return $internal_text; + } + + function connect() + { + $this->enable_errorhandler(); + + define('ENANO_DBLAYER', 'PGSQL'); + define('ENANO_SQLFUNC_LOWERCASE', 'lower'); + define('ENANO_SQL_MULTISTRING_PRFIX', 'E'); + define('ENANO_SQL_BOOLEAN_TRUE', '1'); + define('ENANO_SQL_BOOLEAN_FALSE', '0'); + + if ( defined('IN_ENANO_INSTALL') && !defined('IN_ENANO_UPGRADE') ) + { + @include(ENANO_ROOT.'/config.new.php'); + } + else + { + @include(ENANO_ROOT.'/config.php'); + } + + if ( isset($crypto_key) ) + unset($crypto_key); // Get this sucker out of memory fast + + if ( !defined('ENANO_INSTALLED') && !defined('MIDGET_INSTALLED') && !defined('IN_ENANO_INSTALL') ) + { + // scriptPath isn't set yet - we need to autodetect it to avoid infinite redirects + if ( !defined('scriptPath') ) + { + if ( isset($_SERVER['PATH_INFO']) && !preg_match('/index\.php$/', $_SERVER['PATH_INFO']) ) + { + $_SERVER['REQUEST_URI'] = preg_replace(';' . preg_quote($_SERVER['PATH_INFO']) . '$;', '', $_SERVER['REQUEST_URI']); + } + if ( !preg_match('/\.php$/', $_SERVER['REQUEST_URI']) ) + { + // user requested http://foo/enano as opposed to http://foo/enano/index.php + $_SERVER['REQUEST_URI'] .= '/index.php'; + } + $sp = dirname($_SERVER['REQUEST_URI']); + if($sp == '/' || $sp == '\\') $sp = ''; + define('scriptPath', $sp); + define('contentPath', "$sp/index.php?title="); + } + $loc = scriptPath . '/install.php'; + // header("Location: $loc"); + redirect($loc, 'Enano not installed', 'We can\'t seem to find an Enano installation (valid config file). You will be transferred to the installation wizard momentarily...', 3); + exit; + } + $this->_conn = @pg_connect("host=$dbhost port=5432 dbname=$dbname user=$dbuser password=$dbpasswd"); + unset($dbuser); + unset($dbpasswd); // Security + + if ( !$this->_conn ) + { + grinding_halt('Enano is having a problem', '

Error: couldn\'t connect to PostgreSQL.
'.pg_last_error().'

'); + } + + // Reset some variables + $this->query_backtrace = array(); + $this->query_times = array(); + $this->query_sources = array(); + $this->num_queries = 0; + + $this->debug = ( defined('ENANO_DEBUG') ); + + // We're in! + $this->disable_errorhandler(); + return true; + } + + function sql_query($q) + { + $this->enable_errorhandler(); + + if ( $this->debug && function_exists('debug_backtrace') ) + { + $backtrace = @debug_backtrace(); + if ( is_array($backtrace) ) + { + $bt = $backtrace[0]; + if ( isset($backtrace[1]['class']) ) + { + if ( $backtrace[1]['class'] == 'sessionManager' ) + { + $bt = $backtrace[1]; + } + } + $this->query_sources[$q] = substr($bt['file'], strlen(ENANO_ROOT) + 1) . ', line ' . $bt['line']; + } + unset($backtrace); + } + + $this->num_queries++; + $this->query_backtrace[] = $q; + $this->latest_query = $q; + // First make sure we have a connection + if ( !$this->_conn ) + { + $this->_die('A database connection has not yet been established.'); + } + // Does this query look malicious? + if ( !$this->check_query($q) ) + { + $this->report_query($q); + grinding_halt('SQL Injection attempt', '

Enano has caught and prevented an SQL injection attempt. Your IP address has been recorded and the administrator has been notified.

Query was:

'.htmlspecialchars($q).'
'); + } + + $time_start = microtime_float(); + $r = pg_query($q); + $this->query_times[$q] = microtime_float() - $time_start; + $this->latest_result = $r; + $this->disable_errorhandler(); + return $r; + } + + function sql_unbuffered_query($q) + { + $this->enable_errorhandler(); + + $this->num_queries++; + $this->query_backtrace[] = '(UNBUFFERED) ' . $q; + $this->latest_query = $q; + // First make sure we have a connection + if ( !$this->_conn ) + { + $this->_die('A database connection has not yet been established.'); + } + // Does this query look malicious? + if ( !$this->check_query($q) ) + { + $this->report_query($q); + grinding_halt('SQL Injection attempt', '

Enano has caught and prevented an SQL injection attempt. Your IP address has been recorded and the administrator has been notified.

Query was:

'.htmlspecialchars($q).'
'); + } + + $time_start = microtime_float(); + $r = pg_query($q); + $this->query_times[$q] = microtime_float() - $time_start; + $this->latest_result = $r; + $this->disable_errorhandler(); + return $r; + } + + /** + * Checks a SQL query for possible signs of injection attempts + * @param string $q the query to check + * @return bool true if query passed check, otherwise false + */ + + function check_query($q, $debug = false) + { + if($debug) echo "\$db->check_query(): checking query: ".htmlspecialchars($q).'
'."\n"; + $sz = strlen($q); + $quotechar = false; + $quotepos = 0; + $prev_is_quote = false; + $just_started = false; + for ( $i = 0; $i < strlen($q); $i++, $c = substr($q, $i, 1) ) + { + $next = substr($q, $i+1, 1); + $next2 = substr($q, $i+2, 1); + $prev = substr($q, $i-1, 1); + $prev2 = substr($q, $i-2, 1); + if(isset($c) && in_array($c, Array('"', "'", '`'))) + { + if($quotechar) + { + if ( + ( $quotechar == $c && $quotechar != $next && ( $quotechar != $prev || $just_started ) && $prev != '\\') || + ( $prev2 == '\\' && $prev == $quotechar && $quotechar == $c ) + ) + { + $quotechar = false; + if($debug) echo('$db->check_query(): just finishing a quote section, quoted string: '.htmlspecialchars(substr($q, $quotepos, $i - $quotepos + 1)) . '
'); + $q = substr($q, 0, $quotepos) . 'SAFE_QUOTE' . substr($q, $i + 1, strlen($q)); + if($debug) echo('$db->check_query(): Filtered query: '.$q.'
'); + $i = $quotepos; + } + } + else + { + $quotechar = $c; + $quotepos = $i; + $just_started = true; + } + if($debug) echo '$db->check_query(): found quote char as pos: '.$i.'
'; + continue; + } + $just_started = false; + } + if(substr(trim($q), strlen(trim($q))-1, 1) == ';') $q = substr(trim($q), 0, strlen(trim($q))-1); + for($i=0;$i'; + else $e .= $c; + } + echo 'Injection attempt caught at pos: '.$i.'
'; + } + return false; + } + } + if ( preg_match('/[\s]+(SAFE_QUOTE|[\S]+)=\\1($|[\s]+)/', $q, $match) ) + { + if ( $debug ) echo 'Found always-true test in query, injection attempt caught, match:
' . '
' . print_r($match, true) . '
'; + return false; + } + return true; + } + + /** + * Set the internal result pointer to X + * @param int $pos The number of the row + * @param resource $result The MySQL result resource - if not given, the latest cached query is assumed + * @return true on success, false on failure + */ + + function sql_data_seek($pos, $result = false) + { + $this->enable_errorhandler(); + if(!$result) + $result = $this->latest_result; + if(!$result) + { + $this->disable_errorhandler(); + return false; + } + if(pg_result_seek($result, $pos)) + { + $this->disable_errorhandler(); + return true; + } + else + { + $this->disable_errorhandler(); + return false; + } + } + + /** + * Reports a bad query to the admin + * @param string $query the naughty query + * @access private + */ + + function report_query($query) + { + global $session; + if(is_object($session) && defined('ENANO_MAINSTREAM')) + $username = $session->username; + else + $username = 'Unavailable'; + $query = $this->escape($query); + $q = $this->sql_query('INSERT INTO '.table_prefix.'logs(log_type, action, time_id, date_string, page_text, author, edit_summary) + VALUES(\'security\', \'sql_inject\', '.time().', \'\', \''.$query.'\', \''.$username.'\', \''.$_SERVER['REMOTE_ADDR'].'\');'); + } + + /** + * Returns the ID of the row last inserted. + * @return int + */ + + function insert_id() + { + return @pg_last_oid(); + } + + function fetchrow($r = false) { + $this->enable_errorhandler(); + if(!$this->_conn) return false; + if(!$r) $r = $this->latest_result; + if(!$r) $this->_die('$db->fetchrow(): an invalid MySQL resource was passed.'); + $row = pg_fetch_assoc($r); + $this->disable_errorhandler(); + return $row; + } + + function fetchrow_num($r = false) { + $this->enable_errorhandler(); + if(!$r) $r = $this->latest_result; + if(!$r) $this->_die('$db->fetchrow(): an invalid MySQL resource was passed.'); + $row = pg_fetch_row($r); + $this->disable_errorhandler(); + return $row; + } + + function numrows($r = false) { + $this->enable_errorhandler(); + if(!$r) $r = $this->latest_result; + if(!$r) $this->_die('$db->fetchrow(): an invalid MySQL resource was passed.'); + $n = pg_num_rows($r); + $this->disable_errorhandler(); + return $n; + } + + function escape($str) + { + $this->enable_errorhandler(); + $str = pg_escape_string($str); + $this->disable_errorhandler(); + return $str; + } + + function free_result($result = false) + { + $this->enable_errorhandler(); + if(!$result) + $result = $this->latest_result; + if(!$result) + { + $this->disable_errorhandler(); + return null; + } + pg_free_result($result); + $this->disable_errorhandler(); + return null; + } + + function close() { + pg_close($this->_conn); + unset($this->_conn); + } + + // phpBB DBAL compatibility + function sql_fetchrow($r = false) + { + return $this->fetchrow($r); + } + function sql_freeresult($r = false) + { + if(!$this->_conn) return false; + if(!$r) $r = $this->latest_result; + if(!$r) $this->_die('$db->fetchrow(): an invalid MySQL resource was passed.'); + $this->free_result($r); + } + function sql_numrows($r = false) + { + return $this->numrows(); + } + function sql_affectedrows($r = false, $f, $n) + { + if(!$this->_conn) return false; + if(!$r) $r = $this->latest_result; + if(!$r) $this->_die('$db->fetchrow(): an invalid MySQL resource was passed.'); + return pg_affected_rows(); + } + + function sql_type_cast(&$value) + { + if ( is_float($value) ) + { + return doubleval($value); + } + if ( is_integer($value) || is_bool($value) ) + { + return intval($value); + } + if ( is_string($value) || empty($value) ) + { + return '\'' . $this->sql_escape_string($value) . '\''; + } + // uncastable var : let's do a basic protection on it to prevent sql injection attempt + return '\'' . $this->sql_escape_string(htmlspecialchars($value)) . '\''; + } + + function sql_statement(&$fields, $fields_inc='') + { + // init result + $this->sql_fields = $this->sql_values = $this->sql_update = ''; + if ( empty($fields) && empty($fields_inc) ) + { + return; + } + + // process + if ( !empty($fields) ) + { + $first = true; + foreach ( $fields as $field => $value ) + { + // field must contain a field name + if ( !empty($field) && is_string($field) ) + { + $value = $this->sql_type_cast($value); + $this->sql_fields .= ( $first ? '' : ', ' ) . $field; + $this->sql_values .= ( $first ? '' : ', ' ) . $value; + $this->sql_update .= ( $first ? '' : ', ' ) . $field . ' = ' . $value; + $first = false; + } + } + } + if ( !empty($fields_inc) ) + { + foreach ( $fields_inc as $field => $indent ) + { + if ( $indent != 0 ) + { + $this->sql_update .= (empty($this->sql_update) ? '' : ', ') . $field . ' = ' . $field . ($indent < 0 ? ' - ' : ' + ') . abs($indent); + } + } + } + } + + function sql_stack_reset($id='') + { + if ( empty($id) ) + { + $this->sql_stack_fields = array(); + $this->sql_stack_values = array(); + } + else + { + $this->sql_stack_fields[$id] = array(); + $this->sql_stack_values[$id] = array(); + } + } + + function sql_stack_statement(&$fields, $id='') + { + $this->sql_statement($fields); + if ( empty($id) ) + { + $this->sql_stack_fields = $this->sql_fields; + $this->sql_stack_values[] = '(' . $this->sql_values . ')'; + } + else + { + $this->sql_stack_fields[$id] = $this->sql_fields; + $this->sql_stack_values[$id][] = '(' . $this->sql_values . ')'; + } + } + + function sql_stack_insert($table, $transaction=false, $line='', $file='', $break_on_error=true, $id='') + { + if ( (empty($id) && empty($this->sql_stack_values)) || (!empty($id) && empty($this->sql_stack_values[$id])) ) + { + return false; + } + switch( SQL_LAYER ) + { + case 'mysql': + case 'mysql4': + if ( empty($id) ) + { + $sql = 'INSERT INTO ' . $table . ' + (' . $this->sql_stack_fields . ') VALUES ' . implode(",\n", $this->sql_stack_values); + } + else + { + $sql = 'INSERT INTO ' . $table . ' + (' . $this->sql_stack_fields[$id] . ') VALUES ' . implode(",\n", $this->sql_stack_values[$id]); + } + $this->sql_stack_reset($id); + return $this->sql_query($sql, $transaction, $line, $file, $break_on_error); + break; + default: + $count_sql_stack_values = empty($id) ? count($this->sql_stack_values) : count($this->sql_stack_values[$id]); + $result = !empty($count_sql_stack_values); + for ( $i = 0; $i < $count_sql_stack_values; $i++ ) + { + if ( empty($id) ) + { + $sql = 'INSERT INTO ' . $table . ' + (' . $this->sql_stack_fields . ') VALUES ' . $this->sql_stack_values[$i]; + } + else + { + $sql = 'INSERT INTO ' . $table . ' + (' . $this->sql_stack_fields[$id] . ') VALUES ' . $this->sql_stack_values[$id][$i]; + } + $result &= $this->sql_query($sql, $transaction, $line, $file, $break_on_error); + } + $this->sql_stack_reset($id); + return $result; + break; + } + } + + function sql_subquery($field, $sql, $line='', $file='', $break_on_error=true, $type=TYPE_INT) + { + // sub-queries doable + $this->sql_get_version(); + if ( !in_array(SQL_LAYER, array('mysql', 'mysql4')) || (($this->sql_version[0] + ($this->sql_version[1] / 100)) >= 4.01) ) + { + return $sql; + } + + // no sub-queries + $ids = array(); + $result = $this->sql_query(trim($sql), false, $line, $file, $break_on_error); + while ( $row = $this->sql_fetchrow($result) ) + { + $ids[] = $type == TYPE_INT ? intval($row[$field]) : '\'' . $this->sql_escape_string($row[$field]) . '\''; + } + $this->sql_freeresult($result); + return empty($ids) ? 'NULL' : implode(', ', $ids); + } + + function sql_col_id($expr, $alias) + { + $this->sql_get_version(); + return in_array(SQL_LAYER, array('mysql', 'mysql4')) && (($this->sql_version[0] + ($this->sql_version[1] / 100)) <= 4.01) ? $alias : $expr; + } + + function sql_get_version() + { + if ( empty($this->sql_version) ) + { + $this->sql_version = array(0, 0, 0); + switch ( SQL_LAYER ) + { + case 'mysql': + case 'mysql4': + if ( function_exists('mysql_get_server_info') ) + { + $lo_version = explode('-', mysql_get_server_info()); + $this->sql_version = explode('.', $lo_version[0]); + $this->sql_version = array(intval($this->sql_version[0]), intval($this->sql_version[1]), intval($this->sql_version[2]), $lo_version[1]); + } + break; + + case 'postgresql': + case 'mssql': + case 'mssql-odbc': + default: + break; + } + } + return $this->sql_version; + } + + function sql_error() + { + if ( $this->_conn ) + { + return mysql_error(); + } + else + { + return array(); + } + } + function sql_escape_string($t) + { + return mysql_real_escape_string($t); + } + function sql_close() + { + $this->close(); + } + function sql_fetchrowset($query_id = 0) + { + if( !$query_id ) + { + $query_id = $this->query_result; + } + + if( $query_id ) + { + unset($this->rowset[$query_id]); + unset($this->row[$query_id]); + + while($this->rowset[$query_id] = mysql_fetch_array($query_id, MYSQL_ASSOC)) + { + $result[] = $this->rowset[$query_id]; + } + + return $result; + } + else + { + return false; + } + } + /** + * Generates and outputs a report of all the SQL queries made during execution. Should only be called after everything's over with. + */ + + function sql_report() + { + global $db, $session, $paths, $template, $plugins; // Common objects + if ( !$session->get_permissions('mod_misc') ) + { + die_friendly('Access denied', '

You are not authorized to generate a SQL backtrace.

'); + } + // Create copies of variables that may be changed after header is called + $backtrace = $this->query_backtrace; + $times = $this->query_times; + $template->header(); + echo '

SQL query log and timetable

'; + echo '
+ '; + $i = 0; + foreach ( $backtrace as $query ) + { + $i++; + $unbuffered = false; + if ( substr($query, 0, 13) == '(UNBUFFERED) ' ) + { + $query = substr($query, 13); + $unbuffered = true; + } + if ( $i == 1 ) + { + echo ' + + '; + } + else + { + echo ' + + '; + } + echo ' + + + + + + + + + + + '; + if ( isset($this->query_sources[$query]) ) + { + echo ' + + + '; + } + } + if ( function_exists('array_sum') ) + { + $query_time_total = array_sum($this->query_times); + echo ' + + '; + } + echo '
SQL backtrace for a normal page load of ' . htmlspecialchars($paths->cpage['urlname']) . '
 
Query:
' . htmlspecialchars($query) . '
Time:' . number_format($this->query_times[$query], 6) . ' seconds
Unbuffered:' . ( $unbuffered ? 'Yes' : 'No' ) . '
Called from:' . $this->query_sources[$query] . '
+ Total time taken for SQL queries: ' . round( $query_time_total, 6 ) . ' seconds +
+
'; + $template->footer(); + } +} + ?> diff -r 8be996c3740d -r 112debff64bd includes/functions.php --- a/includes/functions.php Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/functions.php Sat Dec 15 18:10:14 2007 -0500 @@ -260,7 +260,14 @@ global $db, $session, $paths, $template, $plugins; // Common objects $page_id_key = $paths->nslist[ $namespace ] . $page_id; - $page_data = $paths->pages[$page_id_key]; + if ( isset($paths->pages[$page_id_key]) ) + { + $page_data = $paths->pages[$page_id_key]; + } + else + { + $page_data = array(); + } $title = ( isset($page_data['name']) ) ? $page_data['name'] : $paths->nslist[$namespace] . str_replace('_', ' ', dirtify_page_id( $page_id ) ); return $title; } diff -r 8be996c3740d -r 112debff64bd includes/pageprocess.php --- a/includes/pageprocess.php Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/pageprocess.php Sat Dec 15 18:10:14 2007 -0500 @@ -459,7 +459,7 @@ if ( $this->revision_id ) { - echo '
Notice:
The page you are viewing was archived on '.date('F d, Y \a\t h:i a', $this->revision_id).'.
View current version | Restore this version

'; + echo '
Notice:
The page you are viewing was archived on '.date('F d, Y \a\t h:i a', $this->revision_id).'.
View current version | Restore this version

'; } if ( $redir_enabled ) @@ -669,7 +669,7 @@ LEFT JOIN '.table_prefix.'comments AS c ON ( ( c.user_id=u.user_id AND c.name=u.username AND c.approved=1 ) OR ( c.comment_id IS NULL AND c.approved IS NULL ) ) WHERE u.username=\'' . $db->escape($target_username) . '\' - GROUP BY u.user_id;'); + GROUP BY u.username, u.user_id, u.real_name, u.email, u.reg_time,x.user_id, x.user_aim, x.user_yahoo, x.user_msn, x.user_xmpp, x.user_homepage, x.user_location, x.user_job, x.user_hobbies, x.email_public;'); if ( !$q ) $db->_die(); diff -r 8be996c3740d -r 112debff64bd includes/pageutils.php --- a/includes/pageutils.php Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/pageutils.php Sat Dec 15 18:10:14 2007 -0500 @@ -378,11 +378,11 @@ $msg = $db->escape($message); - $minor = $minor ? 'true' : 'false'; - $q='INSERT INTO ' . table_prefix.'logs(log_type,action,time_id,date_string,page_id,namespace,page_text,char_tag,author,edit_summary,minor_edit) VALUES(\'page\', \'edit\', '.time().', \''.date('d M Y h:i a').'\', \'' . $paths->cpage['urlname_nons'] . '\', \'' . $paths->namespace . '\', \'' . $msg . '\', \'' . $uid . '\', \'' . $session->username . '\', \'' . $db->escape(htmlspecialchars($summary)) . '\', ' . $minor . ');'; + $minor = $minor ? ENANO_SQL_BOOLEAN_TRUE : ENANO_SQL_BOOLEAN_FALSE; + $q='INSERT INTO ' . table_prefix.'logs(log_type,action,time_id,date_string,page_id,namespace,page_text,char_tag,author,edit_summary,minor_edit) VALUES(\'page\', \'edit\', '.time().', \''.date('d M Y h:i a').'\', \'' . $paths->cpage['urlname_nons'] . '\', \'' . $paths->namespace . '\', ' . ENANO_SQL_MULTISTRING_PRFIX . '\'' . $msg . '\', \'' . $uid . '\', \'' . $session->username . '\', \'' . $db->escape(htmlspecialchars($summary)) . '\', ' . $minor . ');'; if(!$db->sql_query($q)) $db->_die('The history (log) entry could not be inserted into the logs table.'); - $q = 'UPDATE ' . table_prefix.'page_text SET page_text=\'' . $msg . '\',char_tag=\'' . $uid . '\' WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';'; + $q = 'UPDATE ' . table_prefix.'page_text SET page_text=' . ENANO_SQL_MULTISTRING_PRFIX . '\'' . $msg . '\',char_tag=\'' . $uid . '\' WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';'; $e = $db->sql_query($q); if(!$e) $db->_die('Enano was unable to save the page contents. Your changes have been lost :\'(.'); @@ -443,7 +443,7 @@ if ( !$name ) $name = str_replace('_', ' ', $page_id); $regex = '#^([A-z0-9 _\-\.\/\!\@\(\)]*)$#is'; - if(!preg_match($regex, $page)) + if(!preg_match($regex, $name)) { //echo 'Notice: PageUtils::createPage: Name contains invalid characters
'; return 'Name contains invalid characters'; @@ -1414,7 +1414,8 @@ if(!$e) $db->_die('The current page text could not be selected; as a result, creating the backup of the page failed. Please make a backup copy of the page by clicking Edit this page and then clicking Save Changes.'); $row = $db->fetchrow(); $db->free_result(); - $q='INSERT INTO ' . table_prefix.'logs(log_type,action,time_id,date_string,page_id,namespace,page_text,char_tag,author,edit_summary,minor_edit) VALUES(\'page\', \'edit\', '.time().', \''.date('d M Y h:i a').'\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $db->escape($row['page_text']) . '\', \'' . $row['char_tag'] . '\', \'' . $session->username . '\', \''."Automatic backup created when logs were purged".'\', '.'false'.');'; + $minor_edit = ( ENANO_DBLAYER == 'MYSQL' ) ? 'false' : '0'; + $q='INSERT INTO ' . table_prefix.'logs(log_type,action,time_id,date_string,page_id,namespace,page_text,char_tag,author,edit_summary,minor_edit) VALUES(\'page\', \'edit\', '.time().', \''.date('d M Y h:i a').'\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $db->escape($row['page_text']) . '\', \'' . $row['char_tag'] . '\', \'' . $session->username . '\', \''."Automatic backup created when logs were purged".'\', '.$minor_edit.');'; if(!$db->sql_query($q)) $db->_die('The history (log) entry could not be inserted into the logs table.'); } return('The logs for this page have been cleared. A backup of this page has been added to the logs table so that this page can be restored in case of vandalism or spam later.'); diff -r 8be996c3740d -r 112debff64bd includes/paths.php --- a/includes/paths.php Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/paths.php Sat Dec 15 18:10:14 2007 -0500 @@ -696,7 +696,12 @@ { global $db, $session, $paths, $template, $plugins; // Common objects // sha1('') returns "da39a3ee5e6b4b0d3255bfef95601890afd80709" - $texts = 'SELECT t.page_text, CONCAT(\'ns=\',t.namespace,\';pid=\',t.page_id) AS page_idstring, t.page_id, t.namespace FROM '.table_prefix.'page_text AS t + + $concat_column = ( ENANO_DBLAYER == 'MYSQL' ) ? + 'CONCAT(\'ns=\',t.namespace,\';pid=\',t.page_id)' : + "'ns=' || t.namespace || ';pid=' || t.page_id"; + + $texts = 'SELECT t.page_text, ' . $concat_column . ' AS page_idstring, t.page_id, t.namespace FROM '.table_prefix.'page_text AS t LEFT JOIN '.table_prefix.'pages AS p ON ( t.page_id=p.urlname AND t.namespace=p.namespace ) WHERE p.namespace=t.namespace @@ -810,13 +815,26 @@ $search->buildIndex(Array("ns={$namespace};pid={$page_id}"=>$row['page_text'] . ' ' . $this->pages[$idstring]['name'])); $new_index = $search->index; - $keys = array_keys($search->index); - foreach($keys as $i => $k) + if ( ENANO_DBLAYER == 'MYSQL' ) { - $c =& $keys[$i]; - $c = hexencode($c, '', ''); + $keys = array_keys($search->index); + foreach($keys as $i => $k) + { + $c =& $keys[$i]; + $c = hexencode($c, '', ''); + } + $keys = "word=0x" . implode ( " OR word=0x", $keys ) . ""; } - $keys = "word=0x" . implode ( " OR word=0x", $keys ) . ""; + else + { + $keys = array_keys($search->index); + foreach($keys as $i => $k) + { + $c =& $keys[$i]; + $c = $db->escape($c); + } + $keys = "word='" . implode ( "' OR word='", $keys ) . "'"; + } $query = $db->sql_query('SELECT word,page_names FROM '.table_prefix.'search_index WHERE '.$keys.';'); diff -r 8be996c3740d -r 112debff64bd includes/render.php --- a/includes/render.php Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/render.php Sat Dec 15 18:10:14 2007 -0500 @@ -889,7 +889,7 @@ { $side = ( $clear == '|left' ) ? 'left' : 'right'; $opposite = ( $clear == '|left' ) ? 'right' : 'left'; - $clear_text .= "float: $side; margin-$opposite: 20px;"; + $clear_text .= "float: $side; margin-$opposite: 20px; width: {$r_width}px;"; $complete_tag .= 'style="' . $clear_text . '" '; } $complete_tag .= '>'; diff -r 8be996c3740d -r 112debff64bd includes/search.php --- a/includes/search.php Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/search.php Sat Dec 15 18:10:14 2007 -0500 @@ -194,7 +194,7 @@ $where_any[] = $term; } - $col_word = ( $case_sensitive ) ? 'word' : 'lcase(word)'; + $col_word = ( $case_sensitive ) ? 'word' : ENANO_SQLFUNC_LOWERCASE . '(word)'; $where_any = ( count($where_any) > 0 ) ? '( ' . $col_word . ' = \'' . implode('\' OR ' . $col_word . ' = \'', $where_any) . '\' )' : ''; // generate query @@ -353,10 +353,14 @@ // We can skip this stage if none of these special terms apply - $text_col = ( $case_sensitive ) ? 'page_text' : 'lcase(page_text)'; - $name_col = ( $case_sensitive ) ? 'name' : 'lcase(name)'; - $text_col_join = ( $case_sensitive ) ? 't.page_text' : 'lcase(t.page_text)'; - $name_col_join = ( $case_sensitive ) ? 'p.name' : 'lcase(p.name)'; + $text_col = ( $case_sensitive ) ? 'page_text' : ENANO_SQLFUNC_LOWERCASE . '(page_text)'; + $name_col = ( $case_sensitive ) ? 'name' : ENANO_SQLFUNC_LOWERCASE . '(name)'; + $text_col_join = ( $case_sensitive ) ? 't.page_text' : ENANO_SQLFUNC_LOWERCASE . '(t.page_text)'; + $name_col_join = ( $case_sensitive ) ? 'p.name' : ENANO_SQLFUNC_LOWERCASE . '(p.name)'; + + $concat_column = ( ENANO_DBLAYER == 'MYSQL' ) ? + 'CONCAT(\'ns=\',t.namespace,\';pid=\',t.page_id)' : + "'ns=' || t.namespace || ';pid=' || t.page_id"; if ( count($query_phrase['any']) > 0 || count($query_phrase['req']) > 0 ) { @@ -384,7 +388,7 @@ $and_clause = ( $where_any != '' ) ? 'AND ' : ''; $where_req = ( count($where_req) > 0 ) ? "{$and_clause}" . implode(" AND\n ", $where_req) : ''; - $sql = 'SELECT CONCAT("ns=",t.namespace,";pid=",t.page_id) AS id, p.name FROM ' . table_prefix . "page_text AS t\n" + $sql = 'SELECT ' . $concat_column . ' AS id, p.name FROM ' . table_prefix . "page_text AS t\n" . " LEFT JOIN " . table_prefix . "pages AS p\n" . " ON ( p.urlname = t.page_id AND p.namespace = t.namespace )\n" . " WHERE\n $where_any\n $where_req;"; @@ -441,7 +445,7 @@ { $text_where[] = $db->escape($page_id); } - $text_where = '( CONCAT("ns=",t.namespace,";pid=",t.page_id) = \'' . implode('\' OR CONCAT("ns=",t.namespace,";pid=",t.page_id) = \'', $text_where) . '\' )'; + $text_where = '( ' . $concat_column . ' = \'' . implode('\' OR ' . $concat_column . ' = \'', $text_where) . '\' )'; if ( count($query['not']) > 0 ) $text_where .= ' AND'; @@ -456,7 +460,7 @@ } $where_not = ( count($where_not) > 0 ) ? "$text_col NOT LIKE '%" . implode("%' AND $text_col NOT LIKE '%", $where_not) . "%'" : ''; - $sql = 'SELECT CONCAT("ns=",t.namespace,";pid=",t.page_id) AS id, t.page_id, t.namespace, CHAR_LENGTH(t.page_text) AS page_length, t.page_text, p.name AS page_name FROM ' . table_prefix . "page_text AS t + $sql = 'SELECT ' . $concat_column . ' AS id, t.page_id, t.namespace, CHAR_LENGTH(t.page_text) AS page_length, t.page_text, p.name AS page_name FROM ' . table_prefix . "page_text AS t LEFT JOIN " . table_prefix . "pages AS p ON ( p.urlname = t.page_id AND p.namespace = t.namespace ) WHERE $text_where $where_not;"; @@ -569,7 +573,7 @@ arsort($scores); // Divisor for calculating relevance scores - $divisor = ( count($query['any']) + count($query_phrase['any']) + count($query['req']) + count($query_phrase['not']) ) * 1.5; + $divisor = ( count($query['any']) + count($query_phrase['any']) + count($query['req']) + count($query['not']) ) * 1.5; foreach ( $scores as $page_id => $score ) { @@ -847,7 +851,7 @@ // Navigate backwards until a space character is found $chunk = substr($pt, 0, ( $i - 75 )); $final_chunk = $chunk; - for ( $j = strlen($chunk); $j > 0; $j = $j - 1 ) + for ( $j = strlen($chunk) - 1; $j > 0; $j = $j - 1 ) { if ( in_array($chunk{$j}, $space_chars) ) { diff -r 8be996c3740d -r 112debff64bd includes/sessions.php --- a/includes/sessions.php Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/sessions.php Sat Dec 15 18:10:14 2007 -0500 @@ -602,7 +602,7 @@ $db_username = $this->prepare_text($username); // Select the user data from the table, and decrypt that so we can verify the password - $this->sql('SELECT password,old_encryption,user_id,user_level,theme,style,temp_password,temp_password_time FROM '.table_prefix.'users WHERE lcase(username)=\''.$db_username_lower.'\' OR username=\'' . $db_username . '\';'); + $this->sql('SELECT password,old_encryption,user_id,user_level,theme,style,temp_password,temp_password_time FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username)=\''.$db_username_lower.'\' OR username=\'' . $db_username . '\';'); if($db->numrows() < 1) { // This wasn't logged in <1.0.2, dunno how it slipped through @@ -730,7 +730,7 @@ $success = false; // Retrieve the real password from the database - $this->sql('SELECT password,old_encryption,user_id,user_level,temp_password,temp_password_time FROM '.table_prefix.'users WHERE lcase(username)=\''.$this->prepare_text(strtolower($username)).'\';'); + $this->sql('SELECT password,old_encryption,user_id,user_level,temp_password,temp_password_time FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username)=\''.$this->prepare_text(strtolower($username)).'\';'); if ( $db->numrows() < 1 ) { // This wasn't logged in <1.0.2, dunno how it slipped through @@ -1002,7 +1002,8 @@ . ' ON ( p.message_to=u.username AND p.message_read=0 )' . "\n" . ' WHERE k.session_key=\''.$keyhash.'\'' . "\n" . ' AND k.salt=\''.$salt.'\'' . "\n" - . ' GROUP BY u.user_id;'); + . ' GROUP BY u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,x.user_id, x.user_aim, x.user_yahoo, x.user_msn, x.user_xmpp, x.user_homepage, x.user_location, x.user_job, x.user_hobbies, x.email_public;'); + if ( !$query ) { $query = $this->sql('SELECT u.user_id AS uid,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,COUNT(p.message_id) AS num_pms FROM '.table_prefix.'session_keys AS k @@ -1012,7 +1013,7 @@ ON ( p.message_to=u.username AND p.message_read=0 ) WHERE k.session_key=\''.$keyhash.'\' AND k.salt=\''.$salt.'\' - GROUP BY u.user_id;'); + GROUP BY u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level;'); } if($db->numrows() < 1) { @@ -1362,14 +1363,28 @@ if ( $this->user_logged_in ) { // check by IP, email, and username - $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE \n" - . " ( ban_type = " . BAN_IP . " AND is_regex = 0 ) OR \n" - . " ( ban_type = " . BAN_IP . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' REGEXP ban_value ) OR \n" - . " ( ban_type = " . BAN_USER . " AND is_regex = 0 AND ban_value = '{$this->username}' ) OR \n" - . " ( ban_type = " . BAN_USER . " AND is_regex = 1 AND '{$this->username}' REGEXP ban_value ) OR \n" - . " ( ban_type = " . BAN_EMAIL . " AND is_regex = 0 AND ban_value = '{$this->email}' ) OR \n" - . " ( ban_type = " . BAN_EMAIL . " AND is_regex = 1 AND '{$this->email}' REGEXP ban_value ) \n" - . " ORDER BY ban_type ASC;"; + if ( ENANO_DBLAYER == 'MYSQL' ) + { + $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE \n" + . " ( ban_type = " . BAN_IP . " AND is_regex = 0 ) OR \n" + . " ( ban_type = " . BAN_IP . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' REGEXP ban_value ) OR \n" + . " ( ban_type = " . BAN_USER . " AND is_regex = 0 AND ban_value = '{$this->username}' ) OR \n" + . " ( ban_type = " . BAN_USER . " AND is_regex = 1 AND '{$this->username}' REGEXP ban_value ) OR \n" + . " ( ban_type = " . BAN_EMAIL . " AND is_regex = 0 AND ban_value = '{$this->email}' ) OR \n" + . " ( ban_type = " . BAN_EMAIL . " AND is_regex = 1 AND '{$this->email}' REGEXP ban_value ) \n" + . " ORDER BY ban_type ASC;"; + } + else if ( ENANO_DBLAYER == 'PGSQL' ) + { + $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE \n" + . " ( ban_type = " . BAN_IP . " AND is_regex = 0 ) OR \n" + . " ( ban_type = " . BAN_IP . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' LIKE ban_value ) OR \n" + . " ( ban_type = " . BAN_USER . " AND is_regex = 0 AND ban_value = '{$this->username}' ) OR \n" + . " ( ban_type = " . BAN_USER . " AND is_regex = 1 AND '{$this->username}' LIKE ban_value ) OR \n" + . " ( ban_type = " . BAN_EMAIL . " AND is_regex = 0 AND ban_value = '{$this->email}' ) OR \n" + . " ( ban_type = " . BAN_EMAIL . " AND is_regex = 1 AND '{$this->email}' LIKE ban_value ) \n" + . " ORDER BY ban_type ASC;"; + } $q = $this->sql($sql); if ( $db->numrows() > 0 ) { @@ -1400,10 +1415,20 @@ else { // check by IP only - $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE - ( ban_type = " . BAN_IP . " AND is_regex = 0 ) OR - ( ban_type = " . BAN_IP . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' REGEXP ban_value ) - ORDER BY ban_type ASC;"; + if ( ENANO_DBLAYER == 'MYSQL' ) + { + $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE + ( ban_type = " . BAN_IP . " AND is_regex = 0 ) OR + ( ban_type = " . BAN_IP . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' REGEXP ban_value ) + ORDER BY ban_type ASC;"; + } + else if ( ENANO_DBLAYER == 'PGSQL' ) + { + $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE + ( ban_type = " . BAN_IP . " AND is_regex = 0 ) OR + ( ban_type = " . BAN_IP . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' LIKE ban_value ) + ORDER BY ban_type ASC;"; + } $q = $this->sql($sql); if ( $db->numrows() > 0 ) { @@ -1463,7 +1488,7 @@ $real_name = $this->prepare_text($real_name); $nameclause = ( $real_name != '' ) ? ' OR real_name=\''.$real_name.'\'' : ''; - $q = $this->sql('SELECT * FROM '.table_prefix.'users WHERE lcase(username)=\''.strtolower($username).'\' OR email=\''.$email.'\''.$nameclause.';'); + $q = $this->sql('SELECT * FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username)=\''.strtolower($username).'\' OR email=\''.$email.'\''.$nameclause.';'); if($db->numrows() > 0) { $r = 'The '; @@ -1748,7 +1773,7 @@ } elseif(is_string($user)) { - $q = $this->sql('SELECT user_id,username,email FROM '.table_prefix.'users WHERE lcase(username)=lcase(\''.$db->escape($user).'\');'); + $q = $this->sql('SELECT user_id,username,email FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username)=' . ENANO_SQLFUNC_LOWERCASE . '(\''.$db->escape($user).'\');'); } else { @@ -2476,7 +2501,7 @@ { $code = $this->generate_captcha_code($len); $hash = md5(microtime() . mt_rand()); - $this->sql('INSERT INTO '.table_prefix.'session_keys(session_key,salt,auth_level,source_ip,user_id) VALUES(\''.$hash.'\', \''.$s.'\', -1, \''.ip2hex($_SERVER['REMOTE_ADDR']).'\', -2);'); + $this->sql('INSERT INTO '.table_prefix.'session_keys(session_key,salt,auth_level,source_ip,user_id) VALUES(\''.$hash.'\', \'\', -1, \''.ip2hex($_SERVER['REMOTE_ADDR']).'\', -2);'); return $hash; } @@ -2711,7 +2736,7 @@ } // Build a query to grab ACL info - $bs = 'SELECT rules FROM '.table_prefix.'acl WHERE ' . "\n" + $bs = 'SELECT rules,target_type,target_id FROM '.table_prefix.'acl WHERE ' . "\n" . ' ( '; $q = Array(); $q[] = '( target_type='.ACL_TYPE_USER.' AND target_id='.$session->user_id.' )'; diff -r 8be996c3740d -r 112debff64bd includes/template.php --- a/includes/template.php Wed Dec 12 21:46:28 2007 -0500 +++ b/includes/template.php Sat Dec 15 18:10:14 2007 -0500 @@ -1072,7 +1072,7 @@ // // System messages - $text = preg_replace('//is', '\' . $this->tplWikiFormat($pages->sysMsg(\'\\1\')) . \'', $text); + $text = preg_replace('//is', '\' . $this->tplWikiFormat($paths->sysMsg(\'\\1\')) . \'', $text); // Template variables $text = preg_replace('/\{([A-z0-9_-]+?)\}/is', '\' . $this->tpl_strings[\'\\1\'] . \'', $text); diff -r 8be996c3740d -r 112debff64bd index.php --- a/index.php Wed Dec 12 21:46:28 2007 -0500 +++ b/index.php Sat Dec 15 18:10:14 2007 -0500 @@ -20,10 +20,10 @@ // Set up gzip encoding before any output is sent - $aggressive_optimize_html = true; + $aggressive_optimize_html = false; global $do_gzip; - $do_gzip = true; + $do_gzip = false; if(isset($_SERVER['PATH_INFO'])) $v = $_SERVER['PATH_INFO']; elseif(isset($_GET['title'])) $v = $_GET['title']; diff -r 8be996c3740d -r 112debff64bd plugins/SpecialAdmin.php --- a/plugins/SpecialAdmin.php Wed Dec 12 21:46:28 2007 -0500 +++ b/plugins/SpecialAdmin.php Sat Dec 15 18:10:14 2007 -0500 @@ -474,28 +474,28 @@ { if(isset($_POST['enable_uploads']) && getConfig('enable_uploads') != '1') { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES("security","upload_enable",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'upload_enable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\');'); if ( !$q ) $db->_die(); setConfig('enable_uploads', '1'); } else if ( !isset($_POST['enable_uploads']) && getConfig('enable_uploads') == '1' ) { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES("security","upload_disable",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'upload_disable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\');'); if ( !$q ) $db->_die(); setConfig('enable_uploads', '0'); } if(isset($_POST['enable_imagemagick']) && getConfig('enable_imagemagick') != '1') { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES("security","magick_enable",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'magick_enable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\');'); if ( !$q ) $db->_die(); setConfig('enable_imagemagick', '1'); } else if ( !isset($_POST['enable_imagemagick']) && getConfig('enable_imagemagick') == '1' ) { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES("security","magick_disable",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'magick_disable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\');'); if ( !$q ) $db->_die(); setConfig('enable_imagemagick', '0'); @@ -510,14 +510,14 @@ } if(isset($_POST['file_history']) && getConfig('file_history') != '1' ) { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES("security","filehist_enable",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'filehist_enable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\');'); if ( !$q ) $db->_die(); setConfig('file_history', '1'); } else if ( !isset($_POST['file_history']) && getConfig('file_history') == '1' ) { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES("security","filehist_disable",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'filehist_disable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\');'); if ( !$q ) $db->_die(); setConfig('file_history', '0'); @@ -526,7 +526,7 @@ { $old = getConfig('imagemagick_path'); $oldnew = "{$old}||{$_POST['imagemagick_path']}"; - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES("security","magick_path",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($oldnew) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'magick_path\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\',\'' . $db->escape($oldnew) . '\');'); if ( !$q ) $db->_die(); setConfig('imagemagick_path', $_POST['imagemagick_path']); @@ -592,7 +592,7 @@ switch($_GET['action']) { case "enable": - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES("security","plugin_enable",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($_GET['plugin']) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'plugin_enable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',"' . $db->escape($session->username) . '","' . $db->escape($_GET['plugin']) . '");'); if ( !$q ) $db->_die(); setConfig('plugin_'.$_GET['plugin'], '1'); @@ -605,7 +605,7 @@ } if ( !in_array($_GET['plugin'], $plugins->system_plugins) ) { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES("security","plugin_disable",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($_GET['plugin']) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'plugin_disable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',"' . $db->escape($session->username) . '","' . $db->escape($_GET['plugin']) . '");'); if ( !$q ) $db->_die(); setConfig('plugin_'.$_GET['plugin'], '0'); @@ -840,276 +840,6 @@ auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN ) - { - echo '

Error: Not authenticated

It looks like your administration session is invalid or you are not authorized to access this administration page. Please re-authenticate to continue.

'; - return; - } - - if ( isset($_GET['src']) && $_GET['src'] == 'get' && !empty($_GET['user']) ) - { - $_POST['go'] = true; - $_POST['username'] = $_GET['user']; - } - - if(isset($_POST['go'])) - { - // We need the user ID before we can do anything - $q = $db->sql_query('SELECT user_id,username,email,real_name,style,user_level,account_active FROM '.table_prefix.'users WHERE username=\'' . $db->escape($_POST['username']) . '\''); - if ( !$q ) - { - die('Error selecting user ID: '.mysql_error()); - } - if ( $db->numrows() < 1 ) - { - echo('User does not exist, please enter another username.'); - return; - } - $r = $db->fetchrow(); - $db->free_result(); - if(isset($_POST['save'])) - { - $_POST['level'] = intval($_POST['level']); - - $new_level = $_POST['level']; - $old_level = intval($r['user_level']); - - if ( defined('ENANO_DEMO_MODE') ) - { - echo '
You cannot delete or modify user accounts in demo mode - they are cleaned up once every two hours.
'; - $re = Array('permission denied'); - } - else - { - $re = $session->update_user((int)$r['user_id'], $_POST['new_username'], false, $_POST['new_pass'], $_POST['email'], $_POST['real_name'], false, $_POST['level']); - } - - if($re == 'success') - { - - if ( $new_level != $old_level ) - { - $user_id = intval($r['user_id']); - // We need to update group memberships - if ( $old_level == USER_LEVEL_ADMIN ) - { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES("security","u_from_admin",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($_POST['new_username']) . '");'); - if ( !$q ) - $db->_die(); - $session->remove_user_from_group($user_id, GROUP_ID_ADMIN); - } - else if ( $old_level == USER_LEVEL_MOD ) - { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES("security","u_from_mod",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($_POST['new_username']) . '");'); - if ( !$q ) - $db->_die(); - $session->remove_user_from_group($user_id, GROUP_ID_MOD); - } - - if ( $new_level == USER_LEVEL_ADMIN ) - { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES("security","u_to_admin",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($_POST['new_username']) . '");'); - if ( !$q ) - $db->_die(); - $session->add_user_to_group($user_id, GROUP_ID_ADMIN, false); - } - else if ( $new_level == USER_LEVEL_MOD ) - { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES("security","u_to_mod",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($_POST['new_username']) . '");'); - if ( !$q ) - $db->_die(); - $session->add_user_to_group($user_id, GROUP_ID_MOD, false); - } - } - - // update account activation - if ( isset($_POST['account_active']) ) - { - // activate account - $q = $db->sql_query('UPDATE '.table_prefix.'users SET account_active=1 WHERE user_id=' . intval($r['user_id']) . ';'); - if ( !$q ) - $db->_die(); - } - else - { - // deactivate account and throw away the old key - $actkey = sha1 ( microtime() . mt_rand() ); - $q = $db->sql_query('UPDATE '.table_prefix.'users SET account_active=0,activation_key=\'' . $actkey . '\' WHERE user_id=' . intval($r['user_id']) . ';'); - if ( !$q ) - $db->_die(); - } - - echo('
Your changes have been saved.
'); - } - else - { - echo('
Error saving changes: '.implode('
', $re).'
'); - } - $q = $db->sql_query('SELECT user_id,username,email,real_name,style,user_level,account_active FROM '.table_prefix.'users WHERE username=\''.$db->escape($_POST['username']).'\''); - if ( !$q ) - { - die('Error selecting user ID: '.mysql_error()); - } - if($db->numrows($q) < 1) - { - die('User does not exist, please enter another username.'); - } - $r = mysql_fetch_object($q); - $db->free_result(); - } - elseif(isset($_POST['deleteme']) && isset($_POST['delete_conf'])) - { - if ( defined('ENANO_DEMO_MODE') ) - { - echo '
You cannot delete or modify user accounts in demo mode - they are cleaned up once every two hours.
'; - } - else - { - $q = $db->sql_query('DELETE FROM users WHERE user_id='.$r['user_id'].';'); - if($q) - { - echo '
The user account "'.$r['username'].'" was deleted.
'; - } - else - { - echo '
The user account "'.$r['username'].'" could not be deleted due to a database error.

'.$db->get_error().'
'; - } - } - } - else - { - $disabled = ( $r['user_id'] == $session->user_id ) ? ' disabled="disabled" ' : ''; - $evt_get_score = ( getConfig('pw_strength_enable') == '1' ) ? 'onkeyup="password_score_field(this);" style="margin-right: 7px;" ' : ''; - $meter = ( getConfig('pw_strength_enable') == '1' ) ? '

Password complexity requirements are not enforced here.

' : ''; - echo(' -

Edit User Info

-
- - - - '.$meter.' - - - ' . ( ( !empty($disabled) ) ? '' : '' ) . ' - - - -
Username:
New Password:
E-mail:
Real Name:
To change your e-mail address, password, or real name, please use the user control panel.
User level:

If this is unchecked, the activation key will be reset, meaning that any activation e-mails sent will be invalidated.
Delete user: -
-
-
- '); - } - } - else if(isset($_POST['clearsessions'])) - { - if ( defined('ENANO_DEMO_MODE') ) - { - echo '
Sorry Charlie, no can do. You might mess up other people logged into the demo site.
'; - } - else - { - // Get the current session information so the user doesn't get logged out - $aes = new AESCrypt(); - $sk = md5(strrev($session->sid_super)); - $qb = $db->sql_query('SELECT session_key,salt,auth_level,source_ip,time FROM '.table_prefix.'session_keys WHERE session_key=\''.$sk.'\' AND user_id='.$session->user_id.' AND auth_level='.USER_LEVEL_ADMIN); - if ( !$qb ) - { - die('Error selecting session key info block B: '.$db->get_error()); - } - if ( $db->numrows($qb) < 1 ) - { - die('Error: cannot read admin session info block B, aborting table clear process'); - } - $qa = $db->sql_query('SELECT session_key,salt,auth_level,source_ip,time FROM '.table_prefix.'session_keys WHERE session_key=\''.md5($session->sid).'\' AND user_id='.$session->user_id.' AND auth_level='.USER_LEVEL_MEMBER); - if ( !$qa ) - { - die('Error selecting session key info block A: '.$db->get_error()); - } - if ( $db->numrows($qa) < 1 ) - { - die('Error: cannot read user session info block A, aborting table clear process'); - } - $ra = mysql_fetch_object($qa); - $rb = mysql_fetch_object($qb); - $db->free_result($qa); - $db->free_result($qb); - - $db->sql_query('DELETE FROM '.table_prefix.'session_keys;'); - $db->sql_query('INSERT INTO '.table_prefix.'session_keys( session_key,salt,user_id,auth_level,source_ip,time ) VALUES( \''.$ra->session_key.'\', \''.$ra->salt.'\', \''.$session->user_id.'\', \''.$ra->auth_level.'\', \''.$ra->source_ip.'\', '.$ra->time.' ),( \''.$rb->session_key.'\', \''.$rb->salt.'\', \''.$session->user_id.'\', \''.$rb->auth_level.'\', \''.$rb->source_ip.'\', '.$rb->time.' )'); - - echo(' -
The session key table has been cleared. Your database should be a little bit smaller now.
- '); - } - } - echo(' -

User Management

-
-

Username: '.$template->username_field('username').'

-

Clear session keys table

-

It\'s a good idea to clean out your session keys table every once in a while, since this helps to reduce database size. During this process you will be logged off and (hopefully) logged back on automatically. The side effects of this include all users except you being logged off.

-

-
- '); - if(isset($_GET['action']) && isset($_GET['user'])) - { - switch($_GET['action']) - { - case "activate": - $e = $db->sql_query('SELECT activation_key FROM '.table_prefix.'users WHERE username=\'' . $db->escape($_GET['user']) . '\''); - if($e) - { - $row = $db->fetchrow(); - $db->free_result(); - if($session->activate_account($_GET['user'], $row['activation_key'])) { echo '
The user account "'.$_GET['user'].'" has been activated.
'; $db->sql_query('DELETE FROM '.table_prefix.'logs WHERE time_id=' . $db->escape($_GET['logid'])); } - else echo '
The user account "'.$_GET['user'].'" has NOT been activated, possibly because the account is already active.
'; - } else echo '
Error activating account: '.mysql_error().'
'; - break; - case "sendemail": - if($session->send_activation_mail($_GET['user'])) { echo '
The user "'.$_GET['user'].'" has been sent an e-mail with an activation link.
'; $db->sql_query('DELETE FROM '.table_prefix.'logs WHERE time_id=' . $db->escape($_GET['logid'])); } - else echo '
The user account "'.$_GET['user'].'" has not been activated, probably because of a bad SMTP configuration.
'; - break; - case "deny": - $e = $db->sql_query('DELETE FROM '.table_prefix.'logs WHERE log_type=\'admin\' AND action=\'activ_req\' AND edit_summary=\'' . $db->escape($_GET['user']) . '\';'); - if(!$e) echo '
Error during row deletion: '.mysql_error().'
'; - else echo '
All activation requests for the user "'.$_GET['user'].'" have been deleted.
'; - break; - } - } - $q = $db->sql_query('SELECT l.log_type, l.action, l.time_id, l.date_string, l.author, l.edit_summary, u.user_coppa FROM '.table_prefix.'logs AS l - LEFT JOIN '.table_prefix.'users AS u - ON ( u.username = l.edit_summary OR u.username IS NULL ) - WHERE log_type=\'admin\' AND action=\'activ_req\' ORDER BY time_id DESC;'); - if($q) - { - if($db->numrows() > 0) - { - $n = $db->numrows(); - if($n == 1) $s = $n . ' user is'; - else $s = $n . ' users are'; - echo '

'.$s . ' awaiting account activation

'; - echo '
- - '; - $cls = 'row2'; - while($row = $db->fetchrow()) - { - if($cls == 'row2') $cls = 'row1'; - else $cls = 'row2'; - $coppa = ( $row['user_coppa'] == '1' ) ? 'Yes' : 'No'; - echo ''; - } - echo '
Date of requestRequested byRequested forCOPPA userActions
'.date('F d, Y h:i a', $row['time_id']).''.$row['author'].''.$row['edit_summary'].'' . $coppa . 'Activate nowSend activation e-mailDeny request
'; - } - $db->free_result(); - } -} -*/ - function page_Admin_GroupManager() { global $db, $session, $paths, $template, $plugins; // Common objects diff -r 8be996c3740d -r 112debff64bd plugins/admin/SecurityLog.php --- a/plugins/admin/SecurityLog.php Wed Dec 12 21:46:28 2007 -0500 +++ b/plugins/admin/SecurityLog.php Sat Dec 15 18:10:14 2007 -0500 @@ -62,7 +62,7 @@ global $db, $session, $paths, $template, $plugins; // Common objects if ( $session->auth_level < USER_LEVEL_ADMIN ) { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES("security","seclog_unauth",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'seclog_unauth\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '");'); if ( !$q ) $db->_die(); die('Security log: unauthorized attempt to fetch. Call has been logged and reported to the administrators.'); diff -r 8be996c3740d -r 112debff64bd plugins/admin/UserManager.php --- a/plugins/admin/UserManager.php Wed Dec 12 21:46:28 2007 -0500 +++ b/plugins/admin/UserManager.php Sat Dec 15 18:10:14 2007 -0500 @@ -205,14 +205,14 @@ // We need to update group memberships if ( $existing_level == USER_LEVEL_ADMIN ) { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES("security","u_from_admin",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_from_admin\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); if ( !$q ) $db->_die(); $session->remove_user_from_group($user_id, GROUP_ID_ADMIN); } else if ( $existing_level == USER_LEVEL_MOD ) { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES("security","u_from_mod",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_from_mod\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); if ( !$q ) $db->_die(); $session->remove_user_from_group($user_id, GROUP_ID_MOD); @@ -220,14 +220,14 @@ if ( $user_level == USER_LEVEL_ADMIN ) { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES("security","u_to_admin",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_to_admin\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); if ( !$q ) $db->_die(); $session->add_user_to_group($user_id, GROUP_ID_ADMIN, false); } else if ( $user_level == USER_LEVEL_MOD ) { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES("security","u_to_mod",UNIX_TIMESTAMP(),"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_to_mod\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); if ( !$q ) $db->_die(); $session->add_user_to_group($user_id, GROUP_ID_MOD, false); @@ -293,7 +293,7 @@ $q = $db->sql_query('SELECT u.user_id AS authoritative_uid, u.username, u.email, u.real_name, u.signature, u.account_active, u.user_level, x.* FROM '.table_prefix.'users AS u LEFT JOIN '.table_prefix.'users_extra AS x ON ( u.user_id = x.user_id OR x.user_id IS NULL ) - WHERE ( lcase(u.username) = \'' . $db->escape(strtolower($username)) . '\' OR u.username = \'' . $db->escape($username) . '\' ) AND u.user_id != 1;'); + WHERE ( ' . ENANO_SQLFUNC_LOWERCASE . '(u.username) = \'' . $db->escape(strtolower($username)) . '\' OR u.username = \'' . $db->escape($username) . '\' ) AND u.user_id != 1;'); if ( !$q ) $db->_die();