# HG changeset patch # User Dan # Date 1198122940 18000 # Node ID ab66d6d1f1f4994b607658cd6605f5ce1e5a7bfc # Parent 474f8be559435acbde533646cef5fab189ad541e# Parent e17cc42d77cf55fb2a9a08f97c11e48318cc2a36 Redid merge, the previous one had a few problems diff -r 474f8be55943 -r ab66d6d1f1f4 .hgtags --- a/.hgtags Fri Dec 07 18:47:37 2007 -0500 +++ b/.hgtags Wed Dec 19 22:55:40 2007 -0500 @@ -9,3 +9,5 @@ 90632c09ed7ec816da708df1341d9f4019de9adf feature-freeze f948557af0681389165a23419968965fcebcbdd0 devel-freeze 95dc632bf0846b5a7d7d841a4fe9518964a1cc9a release +f8356d9c3481b7ebb88dbf70637d8f5d2cca4528 rebrand +d409d7fcf6f8bc638e0282101fb823ccf3e29e59 release diff -r 474f8be55943 -r ab66d6d1f1f4 README --- a/README Fri Dec 07 18:47:37 2007 -0500 +++ b/README Wed Dec 19 22:55:40 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 474f8be55943 -r ab66d6d1f1f4 ajax.php --- a/ajax.php Fri Dec 07 18:47:37 2007 -0500 +++ b/ajax.php Wed Dec 19 22:55:40 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()) @@ -99,13 +97,26 @@ echo PageUtils::checkusername($_GET['name']); break; case "getsource": - $p = ( isset($_GET['pagepass']) ) ? $_GET['pagepass'] : false; - echo PageUtils::getsource($paths->page, $p); + $password = ( isset($_GET['pagepass']) ) ? $_GET['pagepass'] : false; + $page = new PageProcessor($paths->page_id, $paths->namespace); + $page->password = $password; + if ( $src = $page->fetch_source() ) + { + echo $src; + } + else if ( $src !== false ) + { + echo ''; + } + else + { + echo 'err_access_denied'; + } break; case "getpage": // echo PageUtils::getpage($paths->page, false, ( (isset($_GET['oldid'])) ? $_GET['oldid'] : false )); $revision_id = ( (isset($_GET['oldid'])) ? intval($_GET['oldid']) : 0 ); - $page = new PageProcessor( $paths->cpage['urlname_nons'], $paths->namespace, $revision_id ); + $page = new PageProcessor( $paths->page_id, $paths->namespace, $revision_id ); $pagepass = ( isset($_REQUEST['pagepass']) ) ? $_REQUEST['pagepass'] : ''; $page->password = $pagepass; @@ -115,10 +126,10 @@ case "savepage": $summ = ( isset($_POST['summary']) ) ? $_POST['summary'] : ''; $minor = isset($_POST['minor']); - $e = PageUtils::savepage($paths->cpage['urlname_nons'], $paths->namespace, $_POST['text'], $summ, $minor); + $e = PageUtils::savepage($paths->page_id, $paths->namespace, $_POST['text'], $summ, $minor); if($e=='good') { - $page = new PageProcessor($paths->cpage['urlname_nons'], $paths->namespace); + $page = new PageProcessor($paths->page_id, $paths->namespace); $page->send(); } else @@ -127,16 +138,16 @@ } break; case "protect": - echo PageUtils::protect($paths->cpage['urlname_nons'], $paths->namespace, (int)$_POST['level'], $_POST['reason']); + echo PageUtils::protect($paths->page_id, $paths->namespace, (int)$_POST['level'], $_POST['reason']); break; case "histlist": - echo PageUtils::histlist($paths->cpage['urlname_nons'], $paths->namespace); + echo PageUtils::histlist($paths->page_id, $paths->namespace); break; case "rollback": echo PageUtils::rollback( (int)$_GET['id'] ); break; case "comments": - $comments = new Comments($paths->cpage['urlname_nons'], $paths->namespace); + $comments = new Comments($paths->page_id, $paths->namespace); if ( isset($_POST['data']) ) { $comments->process_json($_POST['data']); @@ -147,37 +158,37 @@ } break; case "rename": - echo PageUtils::rename($paths->cpage['urlname_nons'], $paths->namespace, $_POST['newtitle']); + echo PageUtils::rename($paths->page_id, $paths->namespace, $_POST['newtitle']); break; case "flushlogs": - echo PageUtils::flushlogs($paths->cpage['urlname_nons'], $paths->namespace); + echo PageUtils::flushlogs($paths->page_id, $paths->namespace); break; case "deletepage": $reason = ( isset($_POST['reason']) ) ? $_POST['reason'] : false; if ( empty($reason) ) die('Please enter a reason for deleting this page.'); - echo PageUtils::deletepage($paths->cpage['urlname_nons'], $paths->namespace, $reason); + echo PageUtils::deletepage($paths->page_id, $paths->namespace, $reason); break; case "delvote": - echo PageUtils::delvote($paths->cpage['urlname_nons'], $paths->namespace); + echo PageUtils::delvote($paths->page_id, $paths->namespace); break; case "resetdelvotes": - echo PageUtils::resetdelvotes($paths->cpage['urlname_nons'], $paths->namespace); + echo PageUtils::resetdelvotes($paths->page_id, $paths->namespace); break; case "getstyles": echo PageUtils::getstyles($_GET['id']); break; case "catedit": - echo PageUtils::catedit($paths->cpage['urlname_nons'], $paths->namespace); + echo PageUtils::catedit($paths->page_id, $paths->namespace); break; case "catsave": - echo PageUtils::catsave($paths->cpage['urlname_nons'], $paths->namespace, $_POST); + echo PageUtils::catsave($paths->page_id, $paths->namespace, $_POST); break; case "setwikimode": - echo PageUtils::setwikimode($paths->cpage['urlname_nons'], $paths->namespace, (int)$_GET['mode']); + echo PageUtils::setwikimode($paths->page_id, $paths->namespace, (int)$_GET['mode']); break; case "setpass": - echo PageUtils::setpass($paths->cpage['urlname_nons'], $paths->namespace, $_POST['password']); + echo PageUtils::setpass($paths->page_id, $paths->namespace, $_POST['password']); break; case "fillusername": break; @@ -232,7 +243,7 @@ if(!$id1 || !$id2) { echo '

Invalid request.

'; $template->footer(); break; } if(!preg_match('#^([0-9]+)$#', (string)$_GET['diff1']) || !preg_match('#^([0-9]+)$#', (string)$_GET['diff2'] )) { echo '

SQL injection attempt

'; $template->footer(); break; } - echo PageUtils::pagediff($paths->cpage['urlname_nons'], $paths->namespace, $id1, $id2); + echo PageUtils::pagediff($paths->page_id, $paths->namespace, $id1, $id2); break; case "jsres": die('// ERROR: this section is deprecated and has moved to includes/clientside/static/enano-lib-basic.js.'); @@ -277,10 +288,10 @@ $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) . '\';'); + WHERE t.page_id=\'' . $db->escape($paths->page_id) . '\' AND t.namespace=\'' . $db->escape($paths->namespace) . '\';'); if ( !$q ) $db->_die(); @@ -288,11 +299,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; @@ -340,7 +351,7 @@ } // check if tag is already on page - $q = $db->sql_query('SELECT 1 FROM '.table_prefix.'tags WHERE page_id=\'' . $db->escape($paths->cpage['urlname_nons']) . '\' AND namespace=\'' . $db->escape($paths->namespace) . '\' AND tag_name=\'' . $tag . '\';'); + $q = $db->sql_query('SELECT 1 FROM '.table_prefix.'tags WHERE page_id=\'' . $db->escape($paths->page_id) . '\' AND namespace=\'' . $db->escape($paths->namespace) . '\' AND tag_name=\'' . $tag . '\';'); if ( !$q ) $db->_die(); if ( $db->numrows() > 0 ) @@ -364,7 +375,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->page_id) . '\', \'' . $db->escape($paths->namespace) . '\', ' . $session->user_id . ');'); if ( !$q ) $db->_die(); @@ -380,7 +391,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 . ';'); @@ -394,16 +405,16 @@ $row = $db->fetchrow(); $db->free_result(); - if ( $row['page_id'] == $paths->cpage['urlname_nons'] && $row['namespace'] == $paths->namespace ) + if ( $row['page_id'] == $paths->page_id && $row['namespace'] == $paths->namespace ) $perms =& $session; 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 474f8be55943 -r ab66d6d1f1f4 cron.php --- a/cron.php Fri Dec 07 18:47:37 2007 -0500 +++ b/cron.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.0.2 (Coblynau) + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License diff -r 474f8be55943 -r ab66d6d1f1f4 includes/captcha.php --- a/includes/captcha.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/captcha.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * captcha.php - visual confirmation system used during registration * diff -r 474f8be55943 -r ab66d6d1f1f4 includes/clientside/jsres.php --- a/includes/clientside/jsres.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/clientside/jsres.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * jsres.php - the Enano client-side runtime, a.k.a. AJAX on steroids * @@ -40,7 +40,7 @@ { echo "/* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * [Aggressively compressed] Javascript client code * Copyright (C) 2006-2007 Dan Fuhry * Enano is Free Software, licensed under the GNU General Public License; see http://enanocms.org/ for details. diff -r 474f8be55943 -r ab66d6d1f1f4 includes/clientside/static/acl.js diff -r 474f8be55943 -r ab66d6d1f1f4 includes/clientside/static/ajax.js --- a/includes/clientside/static/ajax.js Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/clientside/static/ajax.js Wed Dec 19 22:55:40 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) { /* @@ -925,7 +1000,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); @@ -1025,7 +1100,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 474f8be55943 -r ab66d6d1f1f4 includes/clientside/static/faders.js --- a/includes/clientside/static/faders.js Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/clientside/static/faders.js Wed Dec 19 22:55:40 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() { @@ -275,6 +277,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 474f8be55943 -r ab66d6d1f1f4 includes/clientside/static/misc.js --- a/includes/clientside/static/misc.js Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/clientside/static/misc.js Wed Dec 19 22:55:40 2007 -0500 @@ -402,7 +402,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); @@ -447,56 +448,77 @@ } var disableme = ( disable_controls ) ? 'disabled="disabled" ' : ''; form_html += ' \ - \ - \ - \ - \ - \ - ' + captcha_html + ' \ - \ - \ + \ +
' + $lang.get('user_login_field_username') + ': \ -
' + $lang.get('user_login_field_password') + ': \ -
\ +
\ + \ + \ + \ + \ + \ + ' + captcha_html + ' \ + \ + \ - \ -
' + $lang.get('user_login_field_username') + ': \ +
' + $lang.get('user_login_field_password') + ': \ +
\ ' + $lang.get('user_login_ajax_link_fullform', { link_full_form: makeUrlNS('Special', 'Login/' + title, 'level=' + level) }) + '
'; if ( level <= USER_LEVEL_MEMBER ) { form_html += ' \ - ' + $lang.get('user_login_ajax_link_forgotpass', { forgotpass_link: makeUrlNS('Special', 'PasswordReset') }) + '
\ - ' + $lang.get('user_login_createaccount_blurb', { reg_link: makeUrlNS('Special', 'Register') }); + ' + $lang.get('user_login_ajax_link_forgotpass', { forgotpass_link: makeUrlNS('Special', 'PasswordReset') }) + '
\ + ' + $lang.get('user_login_createaccount_blurb', { reg_link: makeUrlNS('Special', 'Register') }); } form_html += '
\ -
\ - \ - \ -
'; +
\ + \ + \ + '; ajax_auth_mb_cache.updateContent(form_html); $('messageBox').object.nextSibling.firstChild.tabindex = '3'; if ( typeof(response.username) == 'string' ) { $('ajaxlogin_user').object.value = response.username; - $('ajaxlogin_pass').object.focus(); + if ( IE ) + { + setTimeout("document.forms['ajax_login_form'].password.focus();", 200); + } + else + { + $('ajaxlogin_pass').object.focus(); + } } else { - $('ajaxlogin_user').object.focus(); + if ( IE ) + { + setTimeout("document.forms['ajax_login_form'].username.focus();", 200); + } + else + { + $('ajaxlogin_user').object.focus(); + } } - if ( ajax_auth_show_captcha ) - { - $('ajaxlogin_captcha_code').object.onblur = function(e) { if ( !shift ) $('messageBox').object.nextSibling.firstChild.focus(); }; - $('ajaxlogin_captcha_code').object.onkeypress = function(e) { if ( !e && IE ) return true; if ( e.keyCode == 13 ) $('messageBox').object.nextSibling.firstChild.click(); }; - } - else + var enter_obj = ( ajax_auth_show_captcha ) ? 'ajaxlogin_captcha_code' : 'ajaxlogin_pass'; + $(enter_obj).object.onblur = function(e) { if ( !shift ) $('messageBox').object.nextSibling.firstChild.focus(); }; + $(enter_obj).object.onkeypress = function(e) { - $('ajaxlogin_pass').object.onblur = function(e) { if ( !shift ) $('messageBox').object.nextSibling.firstChild.focus(); }; - $('ajaxlogin_pass').object.onkeypress = function(e) { if ( !e && IE ) return true; if ( e.keyCode == 13 ) $('messageBox').object.nextSibling.firstChild.click(); }; - } - if ( disable_controls ) - { - var panel = document.getElementById('messageBoxButtons'); - panel.firstChild.disabled = true; - } + // Trigger a form submit when the password field is focused and the user presses enter + + // IE doesn't give us an event object when it should - check window.event. If that + // still fails, give up. + if ( !e ) + { + e = window.event; + } + if ( !e && IE ) + { + return true; + } + if ( e.keyCode == 13 ) + { + ajaxValidateLogin(); + } + }; /* ## This causes the background image to disappear under Fx 2 if ( shown_error ) diff -r 474f8be55943 -r ab66d6d1f1f4 includes/comment.php --- a/includes/comment.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/comment.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License @@ -54,7 +54,7 @@ global $db, $session, $paths, $template, $plugins; // Common objects // Initialize permissions - if ( $page_id == $paths->cpage['urlname_nons'] && $namespace == $paths->namespace ) + if ( $page_id == $paths->page_id && $namespace == $paths->namespace ) $this->perms =& $GLOBALS['session']; else $this->perms = $session->fetch_page_acl($page_id, $namespace); @@ -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 474f8be55943 -r ab66d6d1f1f4 includes/common.php --- a/includes/common.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/common.php Wed Dec 19 22:55:40 2007 -0500 @@ -155,7 +155,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(); + +@include(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. @@ -347,7 +353,7 @@ // If the site is disabled, bail out, unless we're trying to log in or administer the site if(getConfig('site_disabled') == '1' && $session->user_level < USER_LEVEL_ADMIN) { - if ( $paths->namespace == 'Admin' || ( $paths->namespace == 'Special' && ( $paths->cpage['urlname_nons'] == 'CSS' || $paths->cpage['urlname_nons'] == 'Administration' || $paths->cpage['urlname_nons'] == 'Login' ) ) ) + if ( $paths->namespace == 'Admin' || ( $paths->namespace == 'Special' && ( $paths->page_id == 'CSS' || $paths->page_id == 'Administration' || $paths->page_id == 'Login' ) ) ) { // do nothing; allow execution to continue } diff -r 474f8be55943 -r ab66d6d1f1f4 includes/constants.php --- a/includes/constants.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/constants.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * constants.php - important defines used Enano-wide * diff -r 474f8be55943 -r ab66d6d1f1f4 includes/dbal.php --- a/includes/dbal.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/dbal.php Wed Dec 19 22:55:40 2007 -0500 @@ -120,46 +120,56 @@ return $internal_text; } - function connect() + function connect($manual_credentials = false, $dbhost = false, $dbuser = false, $dbpasswd = false, $dbname = false) { $this->enable_errorhandler(); - if ( defined('IN_ENANO_INSTALL') && !defined('IN_ENANO_UPGRADE') ) - { - @include(ENANO_ROOT.'/config.new.php'); - } - else + 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 ( !$manual_credentials ) { - @include(ENANO_ROOT.'/config.php'); - } + 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 ( 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 ( !defined('ENANO_INSTALLED') && !defined('MIDGET_INSTALLED') && !defined('IN_ENANO_INSTALL') ) { - if ( isset($_SERVER['PATH_INFO']) && !preg_match('/index\.php$/', $_SERVER['PATH_INFO']) ) + // scriptPath isn't set yet - we need to autodetect it to avoid infinite redirects + if ( !defined('scriptPath') ) { - $_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'; + 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="); } - $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; } - $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 = @mysql_connect($dbhost, $dbuser, $dbpasswd); unset($dbuser); unset($dbpasswd); // Security @@ -778,4 +788,750 @@ } } +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($manual_credentials = false, $dbhost = false, $dbuser = false, $dbpasswd = false, $dbname = false) + { + $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 ( !$manual_credentials ) + { + 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 474f8be55943 -r ab66d6d1f1f4 includes/email.php --- a/includes/email.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/email.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License diff -r 474f8be55943 -r ab66d6d1f1f4 includes/functions.php --- a/includes/functions.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/functions.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.0.2 (Coblynau) + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License @@ -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; } @@ -567,7 +574,7 @@ $q = $db->sql_query('SELECT p.urlname, p.namespace, p.name, p.namespace=\'Category\' AS is_category FROM '.table_prefix.'categories AS c LEFT JOIN '.table_prefix.'pages AS p ON ( p.urlname = c.page_id AND p.namespace = c.namespace ) - WHERE c.category_id=\'' . $db->escape($paths->cpage['urlname_nons']) . '\' + WHERE c.category_id=\'' . $db->escape($paths->page_id) . '\' ORDER BY is_category DESC, p.name ASC;'); if ( !$q ) { @@ -679,7 +686,7 @@ echo ''; echo '
' . $lang->get('catedit_catbox_lbl_categories') . ' '; - $where = '( c.page_id=\'' . $db->escape($paths->cpage['urlname_nons']) . '\' AND c.namespace=\'' . $db->escape($paths->namespace) . '\' )'; + $where = '( c.page_id=\'' . $db->escape($paths->page_id) . '\' AND c.namespace=\'' . $db->escape($paths->namespace) . '\' )'; $prefix = table_prefix; $sql = <<namespace != 'File') return null; // Prevent unnecessary work - $selfn = $paths->cpage['urlname_nons']; // substr($paths->page, strlen($paths->nslist['File']), strlen($paths->cpage)); - if(substr($paths->cpage['name'], 0, strlen($paths->nslist['File']))==$paths->nslist['File']) $selfn = substr($paths->cpage['urlname_nons'], strlen($paths->nslist['File']), strlen($paths->cpage['urlname_nons'])); + $selfn = $paths->page_id; // substr($paths->page, strlen($paths->nslist['File']), strlen($paths->cpage)); + if(substr($paths->cpage['name'], 0, strlen($paths->nslist['File']))==$paths->nslist['File']) $selfn = substr($paths->page_id, strlen($paths->nslist['File']), strlen($paths->page_id)); $q = $db->sql_query('SELECT mimetype,time_id,size FROM '.table_prefix.'files WHERE page_id=\''.$selfn.'\' ORDER BY time_id DESC;'); if(!$q) $db->_die('The file type could not be fetched.'); - if($db->numrows() < 1) { echo '

Uploaded file

There are no files uploaded with this name yet. Upload a file...


'; return; } + if($db->numrows() < 1) { echo '

Uploaded file

There are no files uploaded with this name yet. Upload a file...


'; return; } $r = $db->fetchrow(); $mimetype = $r['mimetype']; $datestring = date('F d, Y h:i a', (int)$r['time_id']); @@ -1134,7 +1141,8 @@ '1.0.1' => 'Loch Ness', '1.0.1.1'=> 'Loch Ness internal bugfix build', '1.0.2b1'=> 'Coblynau unstable', - '1.0.2' => 'Coblynau' + '1.0.2' => 'Coblynau', + '1.0.3' => 'Dyrad' ); $version = enano_version(); if ( isset($names[$version]) ) @@ -2228,7 +2236,6 @@ function paginate_array($q, $num_results, $result_url, $start = 0, $perpage = 10, $header = '', $footer = '') { global $db, $session, $paths, $template, $plugins; // Common objects - $parser = $template->makeParserText($tpl_text); $num_pages = ceil ( $num_results / $perpage ); $out = ''; $i = 0; @@ -2415,7 +2422,20 @@ function sanitize_page_id($page_id) { - + global $db, $session, $paths, $template, $plugins; // Common objects + + if ( isset($paths->nslist['User']) ) + { + if ( preg_match('/^' . preg_quote($paths->nslist['User']) . '/', $page_id) ) + { + $ip = preg_replace('/^' . preg_quote($paths->nslist['User']) . '/', '', $page_id); + if ( is_valid_ip($ip) ) + { + return $page_id; + } + } + } + // Remove character escapes $page_id = dirtify_page_id($page_id); @@ -2446,7 +2466,7 @@ else $page_id_cleaned .= $pid_dirty[$id]; } - + // global $mime_types; // $exts = array_keys($mime_types); @@ -2470,11 +2490,9 @@ $page_id = str_replace(' ', '_', $page_id); // Exception for userpages for IP addresses - if ( preg_match('/^' . preg_quote($paths->nslist['User']) . '/', $page_id) ) + if ( is_valid_ip($page_id) ) { - $ip = preg_replace('/^' . preg_quote($paths->nslist['User']) . '/', '', $page_id); - if ( is_valid_ip($ip) ) - return $page_id; + return $page_id; } preg_match_all('/\.[A-Fa-f0-9][A-Fa-f0-9]/', $page_id, $matches); @@ -2487,7 +2505,7 @@ $char = chr($char); $page_id = str_replace($matches[0][$id], $char, $page_id); } - + return $page_id; } @@ -2672,7 +2690,8 @@ function sanitize_tag($tag) { $tag = strtolower($tag); - $tag = preg_replace('/[^\w _@\$%\^&-]+/', '', $tag); + $tag = preg_replace('/[^\w @\$%\^&-]+/', '', $tag); + $tag = str_replace('_', ' ', $tag); $tag = trim($tag); return $tag; } diff -r 474f8be55943 -r ab66d6d1f1f4 includes/graphs.php --- a/includes/graphs.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/graphs.php Wed Dec 19 22:55:40 2007 -0500 @@ -740,198 +740,310 @@ // Graph Generator for PHP // Originally located at http://szewo.com/php/graph, but link was broken, so this file was retrieved from: // http://web.archive.org/web/20030130065944/szewo.com/php/graph/graph.class.php3.txt -// License unknown +// License unknown, however sources on the web have shown this to be either GPL or public domain. class GraphMaker_compat { - var $_values; - var $_ShowLabels; - var $_ShowCounts; - var $_ShowCountsMode; + var $_values; + var $_ShowLabels; + var $_ShowCounts; + var $_ShowCountsMode; - var $_BarWidth; - var $_GraphWidth; - var $_BarImg; - var $_BarBorderWidth; - var $_BarBorderColor; - var $_RowSortMode; - var $_TDClassHead; - var $_TDClassLabel; - var $_TDClassCount; - var $_GraphTitle; + var $_BarWidth; + var $_GraphWidth; + var $_BarImg; + var $_BarBorderWidth; + var $_BarBorderColor; + var $_BarBackgroundColor; + var $_RowSortMode; + var $_TDClassHead; + var $_TDClassLabel; + var $_TDClassCount; + var $_GraphTitle; - function __construct() { - $this->_values = array(); - $this->_ShowLabels = true; - $this->_BarWidth = 16; - $this->_GraphWidth = 360; - $this->_BarImg = "NULL"; - $this->_BarBorderWidth = 0; - $this->_BarBorderColor = "red"; - $this->_ShowCountsMode = 2; - $this->_RowSortMode = 1; - $this->_TDClassHead = "grphh"; - $this->_TDClassLabel = "grph"; - $this->_TDClassCount = "grphc"; - $this->_GraphTitle="Graph title"; - } - - function GraphMaker_compat() { - $this->__construct(); - } + function __construct() { + $this->_values = array(); + $this->_ShowLabels = true; + $this->_BarWidth = 32; + $this->_GraphWidth = 360; + $this->_BarImg = scriptPath . "/images/graphbit.png"; + $this->_BarBorderWidth = 0; + $this->_BarBorderColor = "red"; + $this->_ShowCountsMode = 2; + $this->_RowSortMode = 1; + $this->_TDClassHead = "graph-title"; + $this->_TDClassLabel = "graph-label"; + $this->_TDClassCount = "graph-count"; + $this->_GraphTitle="Graph title"; + $this->_BarBackgroundColor = "#456798"; + } - function SetBarBorderWidth($width) { - $this->_BarBorderWidth = $width; - } - function SetBorderColor($color) { - $this->_BarBorderColor = $color; - } + function GraphMaker_compat() { + $this->__construct(); + } + + function SetBarBorderWidth($width) { + $this->_BarBorderWidth = $width; + } + function SetBorderColor($color) { + $this->_BarBorderColor = $color; + } + + function SetBarBackgroundColor($color) + { + $this->_BarBackgroundColor = $color; + } // mode = 1 labels asc, 2 label desc - function SetSortMode($mode) { - switch ($mode) { - case 1: - asort($this->_values); - break; - case 2: - arsort($this->_values); - break; - default: - break; - } + function SetSortMode($mode) { + switch ($mode) { + case 1: + asort($this->_values); + break; + case 2: + arsort($this->_values); + break; + default: + break; + } - } + } - function AddValue($labelName, $theValue) { - array_push($this->_values, array("label" => $labelName, "value" => $theValue)); + function AddValue($labelName, $theValue) { + array_push($this->_values, array("label" => $labelName, "value" => $theValue)); + } - } - function SetBarWidth($width) { - $this->_BarWidth = $width; - } - function SetBarImg($img) { - $this->_BarImg = $img; - } - function SetShowLabels($lables) { - $this->_ShowLabels = $labels; - } - function SetGraphWidth($width) { - $this->_GraphWidth = $width; - } - function SetGraphTitle($title) { - $this->_GraphTitle = $title; - } - //mode = percentage or counts - function SetShowCountsMode($mode) { - $this->_ShowCountsMode = $mode; - } - //mode = none(0) label(1) or count(2) - function SetRowSortMode($sortmode) { - $this->_RowSortMode = $sortmode; - } + function SetBarData($data) + { + foreach ( $data as $name => $value ) + { + $this->AddValue($name, $value); + } + } + function DrawGraph() + { + $this->BarGraphVert(); + } + function SetBarWidth($width) + { + $this->_BarWidth = $width; + } + function SetBarImg($img) + { + $this->_BarImg = $img; + } + function SetShowLabels($lables) + { + $this->_ShowLabels = $labels; + } + function SetGraphWidth($width) + { + $this->_GraphWidth = $width; + } + function SetGraphTitle($title) + { + $this->_GraphTitle = $title; + } + //mode = percentage or counts + function SetShowCountsMode($mode) + { + $this->_ShowCountsMode = $mode; + } + //mode = none(0) label(1) or count(2) + function SetRowSortMode($sortmode) + { + $this->_RowSortMode = $sortmode; + } + + function SetTDClassHead($class) + { + $this->_TDClassHead = $class; + } + function SetTDClassLabel($class) + { + $this->_TDClassLabel = $class; + } + function SetTDClassCount($class) + { + $this->_TDClassCount = $class; + } + function GetMaxVal() + { + $maxval = 0; + foreach ( $this->_values as $value ) + { + if ( $maxval < $value["value"] ) + { + $maxval = $value["value"]; + } + } + return $maxval; + } + function BarGraphVert() + { + $maxval = $this->GetMaxVal(); + foreach($this->_values as $value) + { + $sumval += $value["value"]; + } + + $this->SetSortMode($this->_RowSortMode); + + echo "\n\n
\n\n "; + + if ( strlen($this->_GraphTitle) > 0 ) + { + echo "\n \n \n "; + } + + echo "\n "; + $css_class = 'row1'; + + foreach($this->_values as $value) + { + $css_class = ( $css_class == 'row1' ) ? 'row3' : 'row1'; + echo " "; - foreach($this->_values as $value) { - echo ""; - } - echo ""; - } - - echo "
_values)."\" class=\"".$this->_TDClassHead."\">".$this->_GraphTitle."
\n "; + $width = $this->_BarWidth; + $height = ceil( $value["value"] * $this->_GraphWidth / $maxval ); + + echo "
_BarBackgroundColor}; border: ".$this->_BarBorderWidth."px solid ".$this->_BarBorderColor."\">\n "; + echo "
\n "; + + // echo "_BarImg."\" height=\"$width\" width=\"$height\" "; + // echo " style=\"border: ".$this->_BarBorderWidth."px solid ".$this->_BarBorderColor."\""; + // echo ">"; - function SetTDClassHead($class) { - $this->_TDClassHead = $class; - } - function SetTDClassLabel($class) { - $this->_TDClassLabel = $class; - } - function SetTDClassCount($class) { - $this->_TDClassCount = $class; - } - function GetMaxVal() { - $maxval = 0; - foreach($this->_values as $value) if($maxval<$value["value"]) $maxval = $value["value"]; - return $maxval; - } - function BarGraphVert() { - $maxval = $this->GetMaxVal(); - foreach($this->_values as $value) $sumval += $value["value"]; - $this->SetSortMode($this->_RowSortMode); - echo ""; - if (strlen($this->_GraphTitle)>0) echo ""; - echo ""; - foreach($this->_values as $value) { - echo ""; - } - echo ""; - if ($this->_ShowCountsMode>0) { - echo ""; - foreach($this->_values as $value) { - switch ($this->_ShowCountsMode) { - case 1: - $count = round(100*$value["value"]/$sumval)."%"; - break; - case 2: - $count = $value["value"]; - break; /* Exit the switch and the while. */ - default: - break; - } - echo ""; - } - echo ""; - } + echo "\n "; + } + echo "\n "; + if ( $this->_ShowCountsMode > 0 ) + { + $css_class = 'row1'; + echo "\n "; + foreach($this->_values as $value) + { + $css_class = ( $css_class == 'row1' ) ? 'row3' : 'row1'; + switch ($this->_ShowCountsMode) + { + case 1: + $count = round ( 100 * $value["value"] / $sumval ) . "%"; + break; + case 2: + $count = $value["value"]; + break; + default: + break; + } + echo " \n "; + } + echo "\n"; + } + + if ($this->_ShowLabels) + { + $css_class = 'row1'; + echo " \n "; + foreach($this->_values as $value) + { + $css_class = ( $css_class == 'row1' ) ? 'row3' : 'row1'; + echo " \n "; + } + echo "\n"; + } + + echo "
_TDClassHead."\">".$this->_GraphTitle."
"; - $height = $this->_BarWidth; - $width=ceil($value["value"]*$this->_GraphWidth/$maxval); - echo "
_BarBorderWidth."px solid ".$this->_BarBorderColor."\""; - echo ">"; - echo "
$count
_TDClassCount."\">$count
_TDClassLabel."\""; + echo ">".$value["label"]."
"; + } - if ($this->_ShowLabels) { - echo "
".$value["label"]."
"; - } + function BarGraphHoriz() + { + $maxval = $this->GetMaxVal(); + + foreach($this->_values as $value) + { + $sumval += $value["value"]; + } + + $this->SetSortMode($this->_RowSortMode); + + echo ""; + + if ( strlen($this->_GraphTitle) > 0 ) + { + echo ""; + } + foreach($this->_values as $value) + { + if ($this->_ShowLabels) + { + echo ""; + echo ""; + } + echo ""; + if ( $this->_ShowCountsMode > 0 ) + { + switch ($this->_ShowCountsMode) + { + case 1: + $count = round(100 * $value["value"] / $sumval )."%"; + break; + case 2: + $count = $value["value"]; + break; /* Exit the switch and the while. */ + default: + break; + } + echo ""; + } + echo ""; + } + echo "
_ShowCountsMode > 0 ) + { + echo " colspan=\"2\""; + } + echo " class=\"".$this->_TDClassHead."\">".$this->_GraphTitle."
_TDClassLabel."\""; + if ( $this->_ShowCountsMode > 0 ) + { + echo " colspan=\"2\""; + } + echo ">".$value["label"]."
_TDClassCount."\">$count"; + $height = $this->_BarWidth; + $width = ceil( $value["value"] * $this->_GraphWidth / $maxval ); + echo "
_BarBorderWidth."px solid ".$this->_BarBorderColor."\">\n "; + echo "
\n "; + //echo "_BarImg."\" height=$height width=$width "; + //echo " style=\"border: ".$this->_BarBorderWidth."px solid ".$this->_BarBorderColor."\""; + //echo ">"; + echo "
"; + } + /** + * Dummy functions for compatibility with the GD version of the class + */ + + function SetGraphPadding($a, $b, $c, $d) + { + return true; + } + function SetBarPadding($a) + { + return true; + } + function SetAxisStep($a) + { + return true; + } + function SetGraphBackgroundTransparent($r, $g, $b, $a) + { + return true; + } + function SetGraphTransparency($a) + { + return true; + } + function SetGraphAreaHeight($a) + { + return true; + } +} - - function BarGraphHoriz() { - $maxval = $this->GetMaxVal(); - foreach($this->_values as $value) $sumval += $value["value"]; - $this->SetSortMode($this->_RowSortMode); - echo ""; - if (strlen($this->_GraphTitle)>0) { - echo ""; - } - foreach($this->_values as $value) { - if ($this->_ShowLabels) { - echo ""; - echo ""; - } - echo ""; - if ($this->_ShowCountsMode>0) { - switch ($this->_ShowCountsMode) { - case 1: - $count = round(100*$value["value"]/$sumval)."%"; - break; - case 2: - $count = $value["value"]; - break; /* Exit the switch and the while. */ - default: - break; - } - echo ""; - } - echo ""; - } - echo "
_ShowCountsMode>0) echo " colspan=2"; - echo " class=\"".$this->_TDClassHead."\">".$this->_GraphTitle."
".$value["label"]."
$count"; - $height = $this->_BarWidth; - $width=ceil($value["value"]*$this->_GraphWidth/$maxval); - echo "_BarImg."\" height=$height width=$width "; - echo " style=\"border: ".$this->_BarBorderWidth."px solid ".$this->_BarBorderColor."\""; - echo ">"; - echo "
"; - } -} - diff -r 474f8be55943 -r ab66d6d1f1f4 includes/js-compressor.php --- a/includes/js-compressor.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/js-compressor.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * Javascript compression library - used to compact the client-side Javascript code (all 72KB of it!) to save some bandwidth * diff -r 474f8be55943 -r ab66d6d1f1f4 includes/pageprocess.php --- a/includes/pageprocess.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/pageprocess.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * pageprocess.php - intelligent retrieval of pages * Copyright (C) 2006-2007 Dan Fuhry * @@ -15,6 +15,7 @@ /** * Class to handle fetching page text (possibly from a cache) and formatting it. + * As of 1.0.4, this also handles the fetching and editing of certain data for pages. * @package Enano * @subpackage UI * @copyright 2007 Dan Fuhry @@ -113,6 +114,13 @@ ); /** + * The list of errors raised in the class. + * @var array + */ + + var $_errors = array(); + + /** * Constructor. * @param string The page ID (urlname) of the page * @param string The namespace of the page @@ -313,6 +321,177 @@ } /** + * Fetches the wikitext or HTML source for the page. + * @return string + */ + + function fetch_source() + { + if ( !$this->perms->get_permissions('view_source') ) + { + return false; + } + if ( !$this->page_exists ) + { + return ''; + } + return $this->fetch_text(); + } + + /** + * Updates the content of the page. + * @param string The new text for the page + * @param string A summary of edits made to the page. + * @return bool True on success, false on failure + */ + + function update_page($text, $edit_summary = false) + { + global $db, $session, $paths, $template, $plugins; // Common objects + + // Create the page if it doesn't exist + if ( !$this->page_exists ) + { + if ( !$this->create_page() ) + { + return false; + } + } + + // + // Validation + // + + $page_id = $db->escape($this->page_id); + $namespace = $db->escape($this->namespace); + + $q = $db->sql_query('SELECT protected FROM ' . table_prefix . "pages WHERE urlname='$page_id' AND namespace='$namespace';"); + if ( !$q ) + $db->_die('PageProcess updating page content'); + if ( $db->numrows() < 1 ) + { + $this->raise_error('Page doesn\'t exist in the database'); + return false; + } + + // Do we have permission to edit the page? + if ( !$this->perms->get_permissions('edit_page') ) + { + $this->raise_error('You do not have permission to edit this page.'); + return false; + } + + list($protection) = $db->fetchrow_num(); + $db->free_result(); + + if ( $protection == 1 ) + { + // The page is protected - do we have permission to edit protected pages? + if ( !$this->perms->get_permissions('even_when_protected') ) + { + $this->raise_error('This page is protected, and you do not have permission to edit protected pages.'); + return false; + } + } + else if ( $protection == 2 ) + { + // The page is semi-protected. + if ( + ( !$session->user_logged_in || // Is the user logged in? + ( $session->user_logged_in && $session->reg_time + ( 4 * 86400 ) >= time() ) ) // If so, have they been registered for 4 days? + && !$this->perms->get_permissions('even_when_protected') ) // And of course, is there an ACL that overrides semi-protection? + { + $this->raise_error('This page is protected, and you do not have permission to edit protected pages.'); + return false; + } + } + + // Protection validated + + } + + /** + * Creates the page if it doesn't already exist. + * @return bool True on success, false on failure. + */ + + function create_page() + { + global $db, $session, $paths, $template, $plugins; // Common objects + + // Do we have permission to create the page? + if ( !$this->perms->get_permissions('create_page') ) + { + $this->raise_error('You do not have permission to create this page.'); + return false; + } + + // Does it already exist? + if ( $this->page_exists ) + { + $this->raise_error('The page already exists.'); + return false; + } + + // It's not in there. Perform validation. + + // We can't create special, admin, or external pages. + if ( $this->namespace == 'Special' || $this->namespace == 'Admin' || $this->namespace == 'Anonymous' ) + { + $this->raise_error('You cannot create Special or Admin pages - they can\'t be stored in the database.'); + return false; + } + + // Guess the proper title + $name = dirtify_page_id($this->page_id); + + // Check for the restricted Project: prefix + if ( substr($this->page_id, 0, 8) == 'Project:' ) + { + $this->raise_error('The prefix "Project:" is reserved for internal links and can\'t be used on a page name.'); + return false; + } + + // Validation successful - insert the page + + $metadata = array( + 'urlname' => $this->page_id, + 'namespace' => $this->namespace, + 'name' => $name, + 'special' => 0, + 'visible' => 1, + 'comments_on' => 1, + 'protected' => ( $this->namespace == 'System' ? 1 : 0 ), + 'delvotes' => 0, + 'delvote_ips' => serialize(array()), + 'wiki_mode' => 2 + ); + + $paths->add_page($metadata); + + $page_id = $db->escape($this->page_id); + $namespace = $db->escape($this->namespace); + $name = $db->escape($name); + $protect = ( $this->namespace == 'System' ) ? '1' : '0'; + $blank_array = $db->escape(serialize(array())); + + // Query 1: Metadata entry + $q = $db->sql_query('INSERT INTO ' . table_prefix . "pages(name, urlname, namespace, protected, delvotes, delvote_ips, wiki_mode)\n" + . "VALUES ( '$name', '$page_id', '$namespace', $protect, 0, '$blank_array', 2 );"); + if ( !$q ) + $db->_die('PageProcessor page creation - metadata stage'); + + // Query 2: Text insertion + $q = $db->sql_query('INSERT INTO ' . table_prefix . "page_text(page_id, namespace, page_text)\n" + . "VALUES ( '$page_id', '$namespace', '' );"); + if ( !$q ) + $db->_die('PageProcessor page creation - text stage'); + + // Page created. We're good! + return true; + } + + /** * Sets internal variables. * @access private */ @@ -337,7 +516,7 @@ } // Does the page "exist"? - if ( $paths->cpage['urlname_nons'] == $page_id && $paths->namespace == $namespace && !$paths->page_exists && ( $this->namespace != 'Admin' || ($this->namespace == 'Admin' && !function_exists($fname) ) ) ) + if ( $paths->page_id == $page_id && $paths->namespace == $namespace && !$paths->page_exists && ( $this->namespace != 'Admin' || ($this->namespace == 'Admin' && !function_exists($fname) ) ) ) { $this->page_exists = false; } @@ -355,7 +534,7 @@ { $page_id = str_replace('.2e', '.', $page_id); - if ( $paths->cpage['urlname_nons'] == $page_id && $paths->namespace == $namespace && !$paths->page_exists && ( $this->namespace != 'Admin' || ($this->namespace == 'Admin' && !function_exists($fname) ) ) ) + if ( $paths->page_id == $page_id && $paths->namespace == $namespace && !$paths->page_exists && ( $this->namespace != 'Admin' || ($this->namespace == 'Admin' && !function_exists($fname) ) ) ) { $this->page_exists = false; } @@ -457,7 +636,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 ) @@ -628,7 +807,7 @@ global $email; $page_urlname = dirtify_page_id($this->page_id); - if ( $this->page_id == $paths->cpage['urlname_nons'] && $this->namespace == $paths->namespace ) + if ( $this->page_id == $paths->page_id && $this->namespace == $paths->namespace ) { $page_name = ( isset($paths->cpage['name']) ) ? $paths->cpage['name'] : $this->page_id; } @@ -667,7 +846,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(); @@ -805,7 +984,13 @@ echo '
'; echo ''; - + + $code = $plugins->setHook('userpage_sidebar_left'); + foreach ( $code as $cmd ) + { + eval($cmd); + } + echo '
'; @@ -921,6 +1106,12 @@ echo '' . htmlspecialchars($target_username) . ' hasn\'t posted any real-life contact information.'; } + $code = $plugins->setHook('userpage_sidebar_right'); + foreach ( $code as $cmd ) + { + eval($cmd); + } + echo ' '; @@ -1247,6 +1438,30 @@ } + /** + * Raises an error. + * @param string Error string + */ + + function raise_error($string) + { + if ( !is_string($string) ) + return false; + $this->_errors[] = $string; + } + + /** + * Retrieves the latest error from the error stack and returns it ('pops' the error stack) + * @return string + */ + + function pop_error() + { + if ( count($this->_errors) < 1 ) + return false; + return array_pop($this->_errors); + } + } // class PageProcessor ?> diff -r 474f8be55943 -r ab66d6d1f1f4 includes/pageutils.php --- a/includes/pageutils.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/pageutils.php Wed Dec 19 22:55:40 2007 -0500 @@ -203,7 +203,7 @@ else echo ' Return to the homepage.

'; if ( $session->get_permissions('history_rollback') ) { - $e = $db->sql_query('SELECT * FROM ' . table_prefix.'logs WHERE action=\'delete\' AND page_id=\'' . $paths->cpage['urlname_nons'] . '\' AND namespace=\'' . $pid[1] . '\' ORDER BY time_id DESC;'); + $e = $db->sql_query('SELECT * FROM ' . table_prefix.'logs WHERE action=\'delete\' AND page_id=\'' . $paths->page_id . '\' AND namespace=\'' . $pid[1] . '\' ORDER BY time_id DESC;'); if ( !$e ) { $db->_die('The deletion log could not be selected.'); @@ -379,11 +379,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->page_id . '\', \'' . $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 :\'(.'); @@ -444,7 +444,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'; @@ -664,7 +664,7 @@ } $db->free_result(); echo '

' . $lang->get('history_heading_other') . '

'; - $q = 'SELECT time_id,action,date_string,page_id,namespace,author,edit_summary,minor_edit FROM ' . table_prefix.'logs WHERE log_type=\'page\' AND action!=\'edit\' AND page_id=\'' . $paths->cpage['urlname_nons'] . '\' AND namespace=\'' . $paths->namespace . '\' ORDER BY time_id DESC;'; + $q = 'SELECT time_id,action,date_string,page_id,namespace,author,edit_summary,minor_edit FROM ' . table_prefix.'logs WHERE log_type=\'page\' AND action!=\'edit\' AND page_id=\'' . $paths->page_id . '\' AND namespace=\'' . $paths->namespace . '\' ORDER BY time_id DESC;'; if ( !$db->sql_query($q) ) { $db->_die('The history data for the page "' . htmlspecialchars($paths->cpage['name']) . '" could not be selected.'); @@ -1403,7 +1403,7 @@ } if( ( $session->get_permissions('rename') && ( ( $prot && $session->get_permissions('even_when_protected') ) || !$prot ) ) && ( $paths->namespace != 'Special' && $paths->namespace != 'Admin' )) { - $e = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,page_id,namespace,author,edit_summary) VALUES('.time().', \''.date('d M Y h:i a').'\', \'page\', \'rename\', \'' . $db->escape($paths->cpage['urlname_nons']) . '\', \'' . $paths->namespace . '\', \'' . $db->escape($session->username) . '\', \'' . $db->escape($paths->cpage['name']) . '\')'); + $e = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,page_id,namespace,author,edit_summary) VALUES('.time().', \''.date('d M Y h:i a').'\', \'page\', \'rename\', \'' . $db->escape($paths->page_id) . '\', \'' . $paths->namespace . '\', \'' . $db->escape($session->username) . '\', \'' . $db->escape($paths->cpage['name']) . '\')'); if ( !$e ) { $db->_die('The page title could not be updated.'); @@ -1459,7 +1459,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 $lang->get('ajax_clearlogs_success'); @@ -1652,7 +1653,7 @@ ob_start(); $_ob = ''; - $e = $db->sql_query('SELECT category_id FROM ' . table_prefix.'categories WHERE page_id=\'' . $paths->cpage['urlname_nons'] . '\' AND namespace=\'' . $paths->namespace . '\''); + $e = $db->sql_query('SELECT category_id FROM ' . table_prefix.'categories WHERE page_id=\'' . $paths->page_id . '\' AND namespace=\'' . $paths->namespace . '\''); if(!$e) jsdie('Error selecting category information for current page: '.mysql_error()); $cat_current = Array(); while($r = $db->fetchrow()) @@ -2246,7 +2247,7 @@

- +
'; diff -r 474f8be55943 -r ab66d6d1f1f4 includes/paths.php --- a/includes/paths.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/paths.php Wed Dec 19 22:55:40 2007 -0500 @@ -18,7 +18,7 @@ */ class pathManager { - var $pages, $custom_page, $cpage, $page, $fullpage, $page_exists, $namespace, $nslist, $admin_tree, $wiki_mode, $page_protected, $template_cache, $anonymous_page; + var $pages, $custom_page, $cpage, $page, $fullpage, $page_exists, $page_id, $namespace, $nslist, $admin_tree, $wiki_mode, $page_protected, $template_cache, $anonymous_page; function __construct() { global $db, $session, $paths, $template, $plugins; // Common objects @@ -293,6 +293,7 @@ { $this->page_exists = true; $this->cpage = $this->pages[$this->page]; + $this->page_id =& $this->cpage['urlname_nons']; $this->namespace = $this->cpage['namespace']; if(!isset($this->cpage['wiki_mode'])) $this->cpage['wiki_mode'] = 2; @@ -341,7 +342,7 @@ $pid_cleaned = sanitize_page_id($this->page); if ( $pid_cleaned != $this->page ) { - redirect($pid_cleaned, 'Sanitizer message', 'page id sanitized', 0); + redirect(makeUrl($pid_cleaned), 'Sanitizer message', 'page id sanitized', 0); } if ( !is_array($this->cpage) ) @@ -375,6 +376,7 @@ } } $this->namespace = $this->cpage['namespace']; + $this->page_id =& $this->cpage['urlname_nons']; if($this->namespace=='System') { @@ -701,7 +703,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 @@ -815,13 +822,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.';'); @@ -995,5 +1015,5 @@ } } - + ?> diff -r 474f8be55943 -r ab66d6d1f1f4 includes/plugins.php --- a/includes/plugins.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/plugins.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License diff -r 474f8be55943 -r ab66d6d1f1f4 includes/render.php --- a/includes/render.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/render.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.0.2 (Coblynau) + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * render.php - handles fetching pages and parsing them into HTML * @@ -44,7 +44,7 @@ $perms =& $session; - if ( $page_id != $paths->cpage['urlname_nons'] || $namespace != $paths->namespace ) + if ( $page_id != $paths->page_id || $namespace != $paths->namespace ) { unset($perms); unset($perms); // PHP <5.1.5 Zend bug @@ -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 474f8be55943 -r ab66d6d1f1f4 includes/search.php --- a/includes/search.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/search.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * search.php - algorithm used to search pages * @@ -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 474f8be55943 -r ab66d6d1f1f4 includes/sessions.php --- a/includes/sessions.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/sessions.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.0.2 (Coblynau) + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * sessions.php - everything related to security and user management * @@ -663,7 +663,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 @@ -881,7 +881,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 @@ -1209,7 +1209,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 @@ -1219,7 +1220,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) { @@ -1572,14 +1573,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']}' ~ 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}' ~ 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}' ~ ban_value ) \n" + . " ORDER BY ban_type ASC;"; + } $q = $this->sql($sql); if ( $db->numrows() > 0 ) { @@ -1610,10 +1625,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']}' ~ ban_value ) + ORDER BY ban_type ASC;"; + } $q = $this->sql($sql); if ( $db->numrows() > 0 ) { @@ -1673,7 +1698,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 '; @@ -1958,7 +1983,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 { @@ -2459,7 +2484,7 @@ } // PAGE group info - $pg_list = $paths->get_page_groups($paths->cpage['urlname_nons'], $paths->namespace); + $pg_list = $paths->get_page_groups($paths->page_id, $paths->namespace); $pg_info = ''; foreach ( $pg_list as $g_id ) { @@ -2479,7 +2504,7 @@ } // The reason we're using an ORDER BY statement here is because ACL_TYPE_GROUP is less than ACL_TYPE_USER, causing the user's individual // permissions to override group permissions. - $bs .= implode(" OR\n ", $q) . " )\n AND (" . $pg_info . ' ( page_id=\''.$db->escape($paths->cpage['urlname_nons']).'\' AND namespace=\''.$db->escape($paths->namespace).'\' ) ) + $bs .= implode(" OR\n ", $q) . " )\n AND (" . $pg_info . ' ( page_id=\''.$db->escape($paths->page_id).'\' AND namespace=\''.$db->escape($paths->namespace).'\' ) ) ORDER BY target_type ASC, page_id ASC, namespace ASC;'; $q = $this->sql($bs); if ( $row = $db->fetchrow() ) @@ -2686,7 +2711,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; } @@ -2921,7 +2946,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 474f8be55943 -r ab66d6d1f1f4 includes/stats.php --- a/includes/stats.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/stats.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * stats.php - handles statistics for pages (disablable in the admin CP) * @@ -22,7 +22,7 @@ { if(!$page_id || !$namespace) { - $page_id = $paths->cpage['urlname_nons']; + $page_id = $paths->page_id; $namespace = $paths->namespace; } if($namespace == 'Special' || $namespace == 'Admin') diff -r 474f8be55943 -r ab66d6d1f1f4 includes/tagcloud.php --- a/includes/tagcloud.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/tagcloud.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License diff -r 474f8be55943 -r ab66d6d1f1f4 includes/template.php --- a/includes/template.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/template.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.0.2 (Coblynau) + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License @@ -261,7 +261,7 @@ if ( $session->get_permissions('read') && getConfig('enable_comments')=='1' && $paths->namespace != 'Special' && $paths->namespace != 'Admin' && $paths->cpage['comments_on'] == 1 ) { - $e = $db->sql_query('SELECT approved FROM '.table_prefix.'comments WHERE page_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace=\''.$paths->namespace.'\';'); + $e = $db->sql_query('SELECT approved FROM '.table_prefix.'comments WHERE page_id=\''.$paths->page_id.'\' AND namespace=\''.$paths->namespace.'\';'); if ( !$e ) { $db->_die(); @@ -646,7 +646,7 @@ $this->tpl_bool['stupid_mode'] = false; - $this->tpl_bool['in_admin'] = ( ( $paths->cpage['urlname_nons'] == 'Administration' && $paths->namespace == 'Special' ) || $paths->namespace == 'Admin' ); + $this->tpl_bool['in_admin'] = ( ( $paths->page_id == 'Administration' && $paths->namespace == 'Special' ) || $paths->namespace == 'Admin' ); $p = ( isset($_GET['printable']) ) ? '/printable' : ''; @@ -768,7 +768,7 @@ 'ADMIN_LINK'=>$admin_link, 'THEME_LINK'=>$theme_link, 'SEARCH_ACTION'=>makeUrlNS('Special', 'Search'), - 'INPUT_TITLE'=>( urlSeparator == '&' ? '' : ''), + 'INPUT_TITLE'=>( urlSeparator == '&' ? '' : ''), 'INPUT_AUTH'=>( $session->sid_super ? '' : ''), 'TEMPLATE_DIR'=>scriptPath.'/themes/'.$this->theme, 'THEME_ID'=>$this->theme, @@ -776,7 +776,7 @@ 'JS_DYNAMIC_VARS'=>$js_dynamic, 'UNREAD_PMS'=>$session->unread_pms, 'URL_ABOUT_ENANO' => makeUrlNS('Special', 'About_Enano', '', true), - 'REPORT_URI' => makeUrl($paths->page, 'do=sql_report', true) + 'REPORT_URI' => makeUrl($paths->fullpage, 'do=sql_report', true) ); foreach ( $paths->nslist as $ns_id => $ns_prefix ) @@ -1101,7 +1101,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); @@ -1764,7 +1764,7 @@ function notify_unread_pms() { global $db, $session, $paths, $template, $plugins; // Common objects - if ( ( $paths->cpage['urlname_nons'] == 'PrivateMessages' || $paths->cpage['urlname_nons'] == 'Preferences' ) && $paths->namespace == 'Special' ) + if ( ( $paths->page_id == 'PrivateMessages' || $paths->page_id == 'Preferences' ) && $paths->namespace == 'Special' ) { return ''; } diff -r 474f8be55943 -r ab66d6d1f1f4 includes/wikiengine/Tables.php --- a/includes/wikiengine/Tables.php Fri Dec 07 18:47:37 2007 -0500 +++ b/includes/wikiengine/Tables.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License diff -r 474f8be55943 -r ab66d6d1f1f4 index.php --- a/index.php Fri Dec 07 18:47:37 2007 -0500 +++ b/index.php Wed Dec 19 22:55:40 2007 -0500 @@ -23,7 +23,7 @@ $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']; @@ -64,7 +64,7 @@ case 'view': // echo PageUtils::getpage($paths->page, true, ( (isset($_GET['oldid'])) ? $_GET['oldid'] : false )); $rev_id = ( (isset($_GET['oldid'])) ? intval($_GET['oldid']) : 0 ); - $page = new PageProcessor( $paths->cpage['urlname_nons'], $paths->namespace, $rev_id ); + $page = new PageProcessor( $paths->page_id, $paths->namespace, $rev_id ); $page->send_headers = true; $pagepass = ( isset($_REQUEST['pagepass']) ) ? sha1($_REQUEST['pagepass']) : ''; $page->password = $pagepass; @@ -79,7 +79,7 @@ default: $act = ( isset ($_GET['action']) ) ? $_GET['action'] : false; $id = ( isset ($_GET['id']) ) ? intval($_GET['id']) : -1; - echo PageUtils::comments_html($paths->cpage['urlname_nons'], $paths->namespace, $act, Array('id'=>$id)); + echo PageUtils::comments_html($paths->page_id, $paths->namespace, $act, Array('id'=>$id)); break; case 'postcomment': if(empty($_POST['name']) || @@ -88,8 +88,8 @@ ) { echo 'Invalid request'; break; } $cid = ( isset($_POST['captcha_id']) ) ? $_POST['captcha_id'] : false; $cin = ( isset($_POST['captcha_input']) ) ? $_POST['captcha_input'] : false; - PageUtils::addcomment($paths->cpage['urlname_nons'], $paths->namespace, $_POST['name'], $_POST['subj'], $_POST['text'], $cin, $cid); // All filtering, etc. is handled inside this method - echo PageUtils::comments_html($paths->cpage['urlname_nons'], $paths->namespace); + PageUtils::addcomment($paths->page_id, $paths->namespace, $_POST['name'], $_POST['subj'], $_POST['text'], $cin, $cid); // All filtering, etc. is handled inside this method + echo PageUtils::comments_html($paths->page_id, $paths->namespace); break; case 'editcomment': if(!isset($_GET['id']) || ( isset($_GET['id']) && !preg_match('#^([0-9]+)$#', $_GET['id']) )) { echo '

Invalid comment ID

'; break; } @@ -108,16 +108,16 @@ break; case 'savecomment': if(empty($_POST['subj']) || empty($_POST['text'])) { echo '

Invalid request

'; break; } - $r = PageUtils::savecomment_neater($paths->cpage['urlname_nons'], $paths->namespace, $_POST['subj'], $_POST['text'], (int)$_POST['id']); + $r = PageUtils::savecomment_neater($paths->page_id, $paths->namespace, $_POST['subj'], $_POST['text'], (int)$_POST['id']); if($r != 'good') { echo "
$r
"; break; } - echo PageUtils::comments_html($paths->cpage['urlname_nons'], $paths->namespace); + echo PageUtils::comments_html($paths->page_id, $paths->namespace); break; case 'deletecomment': if(!empty($_GET['id'])) { - PageUtils::deletecomment_neater($paths->cpage['urlname_nons'], $paths->namespace, (int)$_GET['id']); + PageUtils::deletecomment_neater($paths->page_id, $paths->namespace, (int)$_GET['id']); } - echo PageUtils::comments_html($paths->cpage['urlname_nons'], $paths->namespace); + echo PageUtils::comments_html($paths->page_id, $paths->namespace); break; } $template->footer(); @@ -130,7 +130,7 @@ } if(isset($_POST['_save'])) { - $e = PageUtils::savepage($paths->cpage['urlname_nons'], $paths->namespace, $_POST['page_text'], $_POST['edit_summary'], isset($_POST['minor'])); + $e = PageUtils::savepage($paths->page_id, $paths->namespace, $_POST['page_text'], $_POST['edit_summary'], isset($_POST['minor'])); if ( $e == 'good' ) { redirect(makeUrl($paths->page), $lang->get('editor_msg_save_success_title'), $lang->get('editor_msg_save_success_body'), 3); @@ -171,7 +171,7 @@ break; case 'viewsource': $template->header(); - $text = RenderMan::getPage($paths->cpage['urlname_nons'], $paths->namespace, 0, false, false, false, false); + $text = RenderMan::getPage($paths->page_id, $paths->namespace, 0, false, false, false, false); echo '

@@ -183,7 +183,7 @@ $template->footer(); break; case 'history': - $hist = PageUtils::histlist($paths->cpage['urlname_nons'], $paths->namespace); + $hist = PageUtils::histlist($paths->page_id, $paths->namespace); $template->header(); echo $hist; $template->footer(); @@ -200,7 +200,7 @@ if(isset($_POST['__enanoSaveButton'])) { unset($_POST['__enanoSaveButton']); - $val = PageUtils::catsave($paths->cpage['urlname_nons'], $paths->namespace, $_POST); + $val = PageUtils::catsave($paths->page_id, $paths->namespace, $_POST); if($val == 'GOOD') { header('Location: '.makeUrl($paths->page)); echo 'Redirecting...If you haven\'t been redirected yet, click here.'; break; @@ -213,7 +213,7 @@ header('Location: '.makeUrl($paths->page)); echo 'Redirecting...If you haven\'t been redirected yet, click here.'; break; } $template->header(); - $c = PageUtils::catedit_raw($paths->cpage['urlname_nons'], $paths->namespace); + $c = PageUtils::catedit_raw($paths->page_id, $paths->namespace); echo $c[1]; $template->footer(); break; @@ -227,7 +227,7 @@ if(!empty($_POST['reason'])) { if(!preg_match('#^([0-2]*){1}$#', $_POST['level'])) die_friendly('Error protecting page', '

Request validation failed

'); - PageUtils::protect($paths->cpage['urlname_nons'], $paths->namespace, intval($_POST['level']), $_POST['reason']); + PageUtils::protect($paths->page_id, $paths->namespace, intval($_POST['level']), $_POST['reason']); die_friendly($lang->get('page_protect_lbl_success_title'), '

' . $lang->get('page_protect_lbl_success_body', array( 'page_link' => makeUrl($paths->page) )) . '

'); } @@ -262,7 +262,7 @@ case 'rename': if(!empty($_POST['newname'])) { - $r = PageUtils::rename($paths->cpage['urlname_nons'], $paths->namespace, $_POST['newname']); + $r = PageUtils::rename($paths->page_id, $paths->namespace, $_POST['newname']); die_friendly($lang->get('page_rename_success_title'), '

'.nl2br($r).' ' . $lang->get('etc_return_to_page') . '.

'); } $template->header(); @@ -284,7 +284,7 @@ if(isset($_POST['_downthejohn'])) { $template->header(); - $result = PageUtils::flushlogs($paths->cpage['urlname_nons'], $paths->namespace); + $result = PageUtils::flushlogs($paths->page_id, $paths->namespace); echo '

'.$result.' ' . $lang->get('etc_return_to_page') . '.

'; $template->footer(); break; @@ -302,7 +302,7 @@ if(isset($_POST['_ballotbox'])) { $template->header(); - $result = PageUtils::delvote($paths->cpage['urlname_nons'], $paths->namespace); + $result = PageUtils::delvote($paths->page_id, $paths->namespace); echo '

'.$result.' ' . $lang->get('etc_return_to_page') . '.

'; $template->footer(); break; @@ -334,7 +334,7 @@ if(isset($_POST['_youmaylivealittlelonger'])) { $template->header(); - $result = PageUtils::resetdelvotes($paths->cpage['urlname_nons'], $paths->namespace); + $result = PageUtils::resetdelvotes($paths->page_id, $paths->namespace); echo '

'.$result.' ' . $lang->get('etc_return_to_page') . '.

'; $template->footer(); break; @@ -361,7 +361,7 @@ else { $template->header(); - $result = PageUtils::deletepage($paths->cpage['urlname_nons'], $paths->namespace, $reason); + $result = PageUtils::deletepage($paths->page_id, $paths->namespace, $reason); echo '

'.$result.' ' . $lang->get('etc_return_to_page') . '.

'; $template->footer(); break; @@ -390,7 +390,7 @@ { die_friendly('Invalid request', '

Level not specified

'); } - $q = $db->sql_query('UPDATE '.table_prefix.'pages SET wiki_mode=' . $level . ' WHERE urlname=\'' . $db->escape($paths->cpage['urlname_nons']) . '\' AND namespace=\'' . $paths->namespace . '\';'); + $q = $db->sql_query('UPDATE '.table_prefix.'pages SET wiki_mode=' . $level . ' WHERE urlname=\'' . $db->escape($paths->page_id) . '\' AND namespace=\'' . $paths->namespace . '\';'); if ( !$q ) $db->_die(); redirect(makeUrl($paths->page), htmlspecialchars($paths->cpage['name']), $lang->get('page_wikimode_success_redirect'), 2); @@ -426,7 +426,7 @@ if(!$id1 || !$id2) { echo '

Invalid request.

'; $template->footer(); break; } if(!preg_match('#^([0-9]+)$#', (string)$_GET['diff1']) || !preg_match('#^([0-9]+)$#', (string)$_GET['diff2'] )) { echo '

SQL injection attempt

'; $template->footer(); break; } - echo PageUtils::pagediff($paths->cpage['urlname_nons'], $paths->namespace, $id1, $id2); + echo PageUtils::pagediff($paths->page_id, $paths->namespace, $id1, $id2); $template->footer(); break; case 'detag': @@ -438,7 +438,7 @@ { die_friendly($lang->get('etc_invalid_request_short'), '

' . $lang->get('page_detag_err_page_exists') . '

'); } - $q = $db->sql_query('DELETE FROM '.table_prefix.'tags WHERE page_id=\'' . $db->escape($paths->cpage['urlname_nons']) . '\' AND namespace=\'' . $paths->namespace . '\';'); + $q = $db->sql_query('DELETE FROM '.table_prefix.'tags WHERE page_id=\'' . $db->escape($paths->page_id) . '\' AND namespace=\'' . $paths->namespace . '\';'); if ( !$q ) $db->_die('Detag query, index.php:'.__LINE__); die_friendly($lang->get('page_detag_success_title'), '

' . $lang->get('page_detag_success_body') . '

'); @@ -449,7 +449,7 @@ break; case 'sql_report': $rev_id = ( (isset($_GET['oldid'])) ? intval($_GET['oldid']) : 0 ); - $page = new PageProcessor( $paths->cpage['urlname_nons'], $paths->namespace, $rev_id ); + $page = new PageProcessor( $paths->page_id, $paths->namespace, $rev_id ); $page->send_headers = true; $pagepass = ( isset($_REQUEST['pagepass']) ) ? sha1($_REQUEST['pagepass']) : ''; $page->password = $pagepass; diff -r 474f8be55943 -r ab66d6d1f1f4 install.php --- a/install.php Fri Dec 07 18:47:37 2007 -0500 +++ b/install.php Wed Dec 19 22:55:40 2007 -0500 @@ -45,6 +45,8 @@ global $_starttime, $this_page, $sideinfo; $_starttime = microtime(true); +global $db; + // Determine directory (special case for development servers) if ( strpos(__FILE__, '/repo/') && file_exists('.enanodev') ) { @@ -185,6 +187,9 @@ function stg_mysql_connect($act_get = false) { + global $db; + $db = new mysql(); + static $conn = false; if ( $act_get ) return $conn; @@ -309,15 +314,114 @@ return false; } } + // initialize DBAL + $db->connect(true, $_POST['db_host'], $db_user, $db_pass, $db_name); + // connected and database exists + return true; +} + +function stg_pgsql_connect($act_get = false) +{ + global $db; + $db = new postgresql(); + + static $conn = false; + if ( $act_get ) + return $conn; + + $db_user =& $_POST['db_user']; + $db_pass =& $_POST['db_pass']; + $db_name =& $_POST['db_name']; + + if ( !preg_match('/^[a-z0-9_-]+$/', $db_name) ) + { + $db_name = htmlspecialchars($db_name); + die("

SECURITY: malformed database name \"$db_name\"

"); + } + + // First, try to connect using the normal credentials + $conn = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_user']} password={$_POST['db_pass']}"); + if ( !$conn ) + { + // Connection failed. Do we have the root username and password? + if ( !empty($_POST['db_root_user']) && !empty($_POST['db_root_pass']) ) + { + $conn_root = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_root_user']} password={$_POST['db_root_pass']}"); + if ( !$conn_root ) + { + // Couldn't connect using either set of credentials. Bail out. + return false; + } + unset($db_user, $db_pass); + $db_user = pg_escape_string($_POST['db_user']); + $db_pass = pg_escape_string($_POST['db_pass']); + // Create the user account + $q = @pg_query("CREATE ROLE '$db_user' WITH NOSUPERUSER UNENCRYPTED PASSWORD '$db_pass';", $conn_root); + if ( !$q ) + { + return false; + } + pg_close($conn_root); + $conn = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_user']} password={$_POST['db_pass']}"); + if ( !$conn ) + { + // This should honestly never happen. + return false; + } + } + } + if ( !$q ) + { + // access denied to the database; try the whole root schenanegan again + if ( !empty($_POST['db_root_user']) && !empty($_POST['db_root_pass']) ) + { + $conn_root = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_root_user']} password={$_POST['db_root_pass']}"); + if ( !$conn_root ) + { + // Couldn't connect as root; bail out + return false; + } + unset($db_user, $db_pass); + $db_user = pg_escape_string($_POST['db_user']); + $db_pass = pg_escape_string($_POST['db_pass']); + // create the database, if it doesn't exist + $q = @mysql_query("CREATE DATABASE $db_name WITH OWNER $db_user;", $conn_root); + if ( !$q ) + { + // this really should never fail, so don't give any tolerance to it + return false; + } + // Setting the owner to $db_user should grant all the rights we need + pg_close($conn_root); + // grant tables have hopefully been flushed, kill and reconnect our regular user connection + pg_close($conn); + $conn = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_user']} password={$_POST['db_pass']}"); + if ( !$conn ) + { + return false; + } + } + else + { + return false; + } + // try again + $q = @mysql_query("USE `$db_name`;", $conn); + if ( !$q ) + { + // really failed this time; bail out + return false; + } + } + // initialize DBAL + $db->connect(true, $_POST['db_host'], $db_user, $db_pass, $db_name); // connected and database exists return true; } function stg_drop_tables() { - $conn = stg_mysql_connect(true); - if ( !$conn ) - return false; + global $db; // Our list of tables included in Enano $tables = Array( 'categories', 'comments', 'config', 'logs', 'page_text', 'session_keys', 'pages', 'users', 'users_extra', 'themes', 'buddies', 'banlist', 'files', 'privmsgs', 'sidebar', 'hits', 'search_index', 'groups', 'group_members', 'acl', 'tags', 'page_groups', 'page_group_members' ); @@ -327,7 +431,7 @@ { // Remember that table_prefix is sanitized. $table = "{$_POST['table_prefix']}$table"; - @mysql_query("DROP TABLE $table;", $conn); + $db->sql_query("DROP TABLE $table;", $conn); } return true; } @@ -379,6 +483,8 @@ if ( $act_get ) return $schema; + global $db; + $admin_pass = stg_decrypt_admin_pass(true); $key = stg_generate_aes_key(true); $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); @@ -389,16 +495,29 @@ $admin_user = $_POST['admin_user']; $admin_user = str_replace('_', ' ', $admin_user); - $admin_user = mysql_real_escape_string($admin_user); + $admin_user = $db->escape($admin_user); + + switch ( $_POST['db_driver'] ) + { + case 'mysql': + $schema_file = 'schema.sql'; + break; + case 'postgresql': + $schema_file = 'schema-pg.sql'; + break; + } - $schema = file_get_contents('schema.sql'); - $schema = str_replace('{{SITE_NAME}}', mysql_real_escape_string($_POST['sitename'] ), $schema); - $schema = str_replace('{{SITE_DESC}}', mysql_real_escape_string($_POST['sitedesc'] ), $schema); - $schema = str_replace('{{COPYRIGHT}}', mysql_real_escape_string($_POST['copyright'] ), $schema); + if ( !isset($schema_file) ) + die('insanity'); + + $schema = file_get_contents($schema_file); + $schema = str_replace('{{SITE_NAME}}', $db->escape($_POST['sitename'] ), $schema); + $schema = str_replace('{{SITE_DESC}}', $db->escape($_POST['sitedesc'] ), $schema); + $schema = str_replace('{{COPYRIGHT}}', $db->escape($_POST['copyright'] ), $schema); $schema = str_replace('{{ADMIN_USER}}', $admin_user , $schema); - $schema = str_replace('{{ADMIN_PASS}}', mysql_real_escape_string($admin_pass ), $schema); - $schema = str_replace('{{ADMIN_EMAIL}}', mysql_real_escape_string($_POST['admin_email']), $schema); - $schema = str_replace('{{ENABLE_CACHE}}', mysql_real_escape_string($cacheonoff ), $schema); + $schema = str_replace('{{ADMIN_PASS}}', $db->escape($admin_pass ), $schema); + $schema = str_replace('{{ADMIN_EMAIL}}', $db->escape($_POST['admin_email']), $schema); + $schema = str_replace('{{ENABLE_CACHE}}', $db->escape($cacheonoff ), $schema); $schema = str_replace('{{REAL_NAME}}', '', $schema); $schema = str_replace('{{TABLE_PREFIX}}', $_POST['table_prefix'], $schema); $schema = str_replace('{{VERSION}}', ENANO_VERSION, $schema); @@ -818,6 +937,78 @@ mysql_close($conn); die('good'); break; + case 'pgsql_test': + error_reporting(0); + $dbhost = rawurldecode($_POST['host']); + $dbname = rawurldecode($_POST['name']); + $dbuser = rawurldecode($_POST['user']); + $dbpass = rawurldecode($_POST['pass']); + $dbrootuser = rawurldecode($_POST['root_user']); + $dbrootpass = rawurldecode($_POST['root_pass']); + if($dbrootuser != '') + { + $conn = @pg_connect("host=$dbhost port=5432 user=$dbuser password=$dbpass dbname=$dbname"); + if(!$conn) + { + $e = pg_last_error(); + if(strstr($e, "Lost connection")) + die('host'.$e); + else + die('root'.$e); + } + $rsp = 'good'; + $q = mysql_query('USE `' . mysql_real_escape_string($dbname) . '`;', $conn); + if(!$q) + { + $e = mysql_error(); + if(strstr($e, 'Unknown database')) + { + $rsp .= '_creating_db'; + } + } + mysql_close($conn); + $conn = mysql_connect($dbhost, $dbuser, $dbpass); + if(!$conn) + { + $e = mysql_error(); + if(strstr($e, "Lost connection")) + die('host'.$e); + else + $rsp .= '_creating_user'; + } + mysql_close($conn); + die($rsp); + } + else + { + $conn = mysql_connect($dbhost, $dbuser, $dbpass); + if(!$conn) + { + $e = mysql_error(); + if(strstr($e, "Lost connection")) + die('host'.$e); + else + die('auth'.$e); + } + $q = mysql_query('USE `' . mysql_real_escape_string($dbname) . '`;', $conn); + if(!$q) + { + $e = mysql_error(); + if(strstr($e, 'Unknown database')) + { + die('name'.$e); + } + else + { + die('perm'.$e); + } + } + } + $v = mysql_get_server_info(); + if(version_compare($v, '4.1.17', '<')) die('vers'.$v); + mysql_close($conn); + die('good'); + break; case 'pophelp': $topic = ( isset($_GET['topic']) ) ? $_GET['topic'] : 'invalid'; switch($topic) @@ -892,8 +1083,10 @@ 'welcome' => $lang->get('welcome_modetitle'), 'license' => $lang->get('license_modetitle'), 'sysreqs' => $lang->get('sysreqs_modetitle'), - 'database'=> $lang->get('database_modetitle'), - 'website' => $lang->get('website_modetitle'), + 'database' => $lang->get('database_modetitle'), + 'database_mysql'=> $lang->get('database_mysql_modetitle'), + 'database_pgsql'=> $lang->get('database_pgsql_modetitle'), + 'website' => $lang->get('website_modetitle'), 'login' => $lang->get('login_modetitle'), 'confirm' => $lang->get('confirm_modetitle'), 'install' => $lang->get('install_modetitle'), @@ -1027,12 +1220,17 @@ run_test('return version_compare(\'4.3.0\', PHP_VERSION, \'<\');', $lang->get('sysreqs_req_php'), $lang->get('sysreqs_req_desc_php') ); run_test('return version_compare(\'5.2.0\', PHP_VERSION, \'<\');', $lang->get('sysreqs_req_php5'), $lang->get('sysreqs_req_desc_php5'), true); run_test('return function_exists(\'mysql_connect\');', $lang->get('sysreqs_req_mysql'), $lang->get('sysreqs_req_desc_mysql') ); + run_test('return function_exists(\'pg_connect\');', 'PostgreSQL extension for PHP', 'It seems that your PHP installation does not have the PostgreSQL extension enabled. Because of this, you won\'t be able to use the PostgreSQL database driver. This is OK in the majority of cases. If you want to use PostgreSQL support, you\'ll need to either compile the PHP extension for Postgres or install the extension with your distribution\'s package manager. Windows administrators will need enable php_pgsql.dll in their php.ini.', true); run_test('return @ini_get(\'file_uploads\');', $lang->get('sysreqs_req_uploads'), $lang->get('sysreqs_req_desc_uploads') ); run_test('return is_apache();', $lang->get('sysreqs_req_apache'), $lang->get('sysreqs_req_desc_apache'), true); run_test('return is_writable(ENANO_ROOT.\'/config.new.php\');', $lang->get('sysreqs_req_config'), $lang->get('sysreqs_req_desc_config') ); run_test('return file_exists(\'/usr/bin/convert\');', $lang->get('sysreqs_req_magick'), $lang->get('sysreqs_req_desc_magick'), true); run_test('return is_writable(ENANO_ROOT.\'/cache/\');', $lang->get('sysreqs_req_cachewriteable'), $lang->get('sysreqs_req_desc_cachewriteable'), true); run_test('return is_writable(ENANO_ROOT.\'/files/\');', $lang->get('sysreqs_req_fileswriteable'), $lang->get('sysreqs_req_desc_fileswriteable'), true); + if ( !function_exists('mysql_connect') && !function_exists('pg_connect') ) + { + run_test('return false;', 'No database drivers are available.', 'You need to have at least one database driver working to install Enano. See the warnings on MySQL and PostgreSQL above for more information on installing these database drivers.', false); + } echo ''; if(!$failed) { @@ -1082,6 +1280,76 @@ Choose a database driver'; + echo '

The next step is to choose the database driver that Enano will use. In most cases this is MySQL, but there are certain + advantages to PostgreSQL, which is made available only experimentally.

'; + if ( @file_exists('/etc/enano-is-virt-appliance') ) + { + echo '

You\'re using the Enano virtual appliance.
Unless you configured the appliance manually, PostgreSQL support is not available. In 99% of cases you\'ll want to click MySQL below.

'; + } + + $mysql_disable_reason = ''; + $pgsql_disable_reason = ''; + $mysql_disable = ''; + $pgsql_disable = ''; + if ( !function_exists('mysql_connect') ) + { + $mysql_disable = ' disabled="disabled"'; + $mysql_disable_reason = 'You don\'t have the MySQL PHP extension installed.'; + } + if ( !function_exists('pg_connect') ) + { + $pgsql_disable = ' disabled="disabled"'; + $pgsql_disable_reason = 'You don\'t have the PostgreSQL PHP extensnion installed.'; + } + if ( function_exists('pg_connect') && version_compare(PHP_VERSION, '5.0.0', '<') ) + { + $pgsql_disable = ' disabled="disabled"'; + $pgsql_disable_reason = 'You need to have at least PHP 5 to use the PostgreSQL database driver.'; + } + + echo ''; + ?> + + + + > + MySQL
+ Click this button to use MySQL as the database backend for your site. Most web hosts support MySQL, and if you have + administrative access to your MySQL server, you can create a new database and user during this installation process if you + haven't done so already. +
$mysql_disable_reason"; + } + ?> + +
+ + + > + PostgreSQL
+ Click this button to use PostgreSQL as the database backend for your site. While not as widely supported, PostgreSQL has more + liberal licensing conditions and when properly configured is faster than MySQL. Some plugins may not work with the PostgreSQL + driver. +
$pgsql_disable_reason"; + } + ?> + +
+
+ /> +
+ /> +
+ '; + break; + case "database_mysql": ?> +

Now we need some information that will allow Enano to contact your database server. Enano uses PostgreSQL as a data storage backend, + and we need to have access to a PostgreSQL server in order to continue.

+

If you do not have access to a PostgreSQL server, and you are using your own server, you can download PostgreSQL for free from + PostgreSQL.org.

+ + + + + + + + + + + + + + + +

Database information

Database hostname
This is the hostname (or sometimes the IP address) of your Postgres server. In many cases, this is "localhost".
Good/bad icon
Database name
The name of the actual database. If you don't already have a database, you can create one here, if you have the username and password of a PostgreSQL superuser.
Good/bad icon
Database login
These fields should be the username and password for a role that has permission to create and alter tables, select data, insert data, update data, and delete data. You may or may not choose to allow dropping tables.
Good/bad icon

Optional information

Table prefix
The value that you enter here will be added to the beginning of the name of each Enano table. You may use lowercase letters (a-z), numbers (0-9), and underscores (_).
Good/bad icon
Database administrative login
If the Postgres database or role that you entered above does not exist yet, you can create them here, assuming that you have the login information for a PostgreSQL superuser. Leave these fields blank unless you need to use them.
Good/bad icon
PostgreSQL versionPostgreSQL version information will
be checked when you click "Test
Connection". You need to have at
least PostgreSQL 8.2.0 to install Enano.
Good/bad icon
Delete existing tables?
If this option is checked, all the tables that will be used by Enano will be dropped (deleted) before the schema is executed. Do NOT use this option unless specifically instructed to.
+
footer(); exit; } + if ( !in_array($_POST['db_driver'], array('mysql', 'postgresql')) ) + { + echo 'Invalid database driver.'; + $template->footer(); + exit; + } switch($_POST['urlscheme']) { case "ugly": diff -r 474f8be55943 -r ab66d6d1f1f4 plugins/PrivateMessages.php --- a/plugins/PrivateMessages.php Fri Dec 07 18:47:37 2007 -0500 +++ b/plugins/PrivateMessages.php Wed Dec 19 22:55:40 2007 -0500 @@ -4,13 +4,13 @@ Plugin URI: http://enanocms.org/ Description: Provides the page Special:PrivateMessages, which is used to manage private message functions. Also handles buddy lists. Author: Dan Fuhry -Version: 1.0.2 +Version: 1.0.3 Author URI: http://enanocms.org/ */ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.0.2 + * Version 1.0.3 * Copyright (C) 2006-2007 Dan Fuhry * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License diff -r 474f8be55943 -r ab66d6d1f1f4 plugins/SpecialAdmin.php --- a/plugins/SpecialAdmin.php Fri Dec 07 18:47:37 2007 -0500 +++ b/plugins/SpecialAdmin.php Wed Dec 19 22:55:40 2007 -0500 @@ -4,7 +4,7 @@ Plugin URI: http://enanocms.org/ Description: Provides the page Special:Administration, which is the AJAX frontend to the various Admin pagelets. This plugin cannot be disabled. Author: Dan Fuhry -Version: 1.0.2 +Version: 1.0.3 Author URI: http://enanocms.org/ */ @@ -530,28 +530,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'); @@ -566,14 +566,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'); @@ -582,7 +582,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']); @@ -651,7 +651,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'); @@ -664,7 +664,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'); @@ -905,279 +905,6 @@ auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN ) - { - $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true); - echo '

' . $lang->get('adm_err_not_auth_title') . '

'; - echo '

' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '

'; - 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 @@ -1876,7 +1603,7 @@ $id = md5( microtime() . mt_rand() ); $minor = isset($_POST['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').'\', \'' . $db->escape($_POST['page_id']) . '\', \'' . $db->escape($_POST['namespace']) . '\', \''.$data.'\', \''.$id.'\', \''.$session->username.'\', \''.$db->escape(htmlspecialchars($_POST['summary'])).'\', '.$minor.');'; + $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').'\', \'' . $db->escape($_POST['page_id']) . '\', \'' . $db->escape($_POST['namespace']) . '\', \''.$db->escape($data).'\', \''.$id.'\', \''.$session->username.'\', \''.$db->escape(htmlspecialchars($_POST['summary'])).'\', '.$minor.');'; if(!$db->sql_query($q)) $db->_die('The history (log) entry could not be inserted into the logs table.'); $query = 'UPDATE '.table_prefix.'page_text SET page_text=\''.$db->escape($data).'\',char_tag=\''.$id.'\' WHERE page_id=\'' . $db->escape($_POST['page_id']) . '\' AND namespace=\'' . $db->escape($_POST['namespace']) . '\';'; @@ -1889,12 +1616,12 @@ ?>


- Edit summary:
+ Edit summary:

- - + +       

Not supported +

This function is only supported under the MySQL database driver.

'); + if(isset($_GET['submitting']) && $_GET['submitting'] == 'yes' && defined('ENANO_DEMO_MODE') ) { redirect(makeUrlComplete('Special', 'Administration'), 'Access denied', 'You\'ve got to be kidding me. Forget it, kid.', 4 ); @@ -2538,13 +2269,11 @@ if(defined('SQL_BACKUP_CRYPT')) // Try to increase our time limit - @set_time_limit(300); // five minutes + @set_time_limit(0); // Do the actual export $aesext = ( defined('SQL_BACKUP_CRYPT') ) ? '.tea' : ''; $filename = 'enano_backup_' . date('ymd') . '.sql' . $aesext; ob_start(); - header('Content-disposition: attachment, filename="'.$filename.'";'); - header('Content-type: application/transact-sql'); // Spew some headers $headdate = date('F d, Y \a\t h:i a'); echo <<
_die(); + } + echo $result; } $data = ob_get_contents(); ob_end_clean(); @@ -2591,6 +2325,8 @@ $tea = new TEACrypt(); $data = $tea->encrypt($data, $session->private_key); } + header('Content-disposition: attachment, filename="'.$filename.'";'); + header('Content-type: application/transact-sql'); header('Content-length: '.strlen($data)); echo $data; exit; @@ -2605,7 +2341,14 @@

Additional tables to export:

"; } @@ -418,7 +418,7 @@ {$member['username']} {$addy} {$date} - {$member['COUNT(c.comment_id)']} + {$member['num_comments']} " . ( ( $can_do_admin_stuff ) ? " " : '' ) . " @@ -442,7 +442,7 @@ {$member['username']} {$addy} {$date} - {$member['COUNT(c.comment_id)']} + {$member['num_comments']} " . ( ( $can_do_admin_stuff ) ? " " : '' ) . " diff -r 474f8be55943 -r ab66d6d1f1f4 plugins/SpecialPageFuncs.php --- a/plugins/SpecialPageFuncs.php Fri Dec 07 18:47:37 2007 -0500 +++ b/plugins/SpecialPageFuncs.php Wed Dec 19 22:55:40 2007 -0500 @@ -4,13 +4,13 @@ Plugin URI: http://enanocms.org/ Description: Provides the page Special:CreatePage, which can be used to create new pages. Also adds the About Enano and GNU General Public License pages. Author: Dan Fuhry -Version: 1.0.2 +Version: 1.0.3 Author URI: http://enanocms.org/ */ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.0.2 + * Version 1.0.3 * Copyright (C) 2006-2007 Dan Fuhry * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License @@ -109,6 +109,11 @@ exit; } + $code = $plugins->setHook('page_create_request'); + foreach ( $code as $cmd ) + { + eval($cmd); + } if ( substr($urlname, 0, 8) == 'Project:' ) { $template->header(); @@ -442,9 +447,25 @@ - - Database engine powered by MySQL - + + + Database engine powered by MySQL + + + + Database engine powered by PostgreSQL + + @@ -454,7 +475,23 @@ get('meta_enano_about_lbl_webserver'); ?> get('meta_enano_about_lbl_serverplatform'); ?> get('meta_enano_about_lbl_phpversion'); ?> - get('meta_enano_about_lbl_mysqlversion'); ?>_conn); ?> + + get('meta_enano_about_lbl_mysqlversion'); ?>_conn); ?> + _conn); + $pg_version = $pg_serverdata['server']; + ?> + get('meta_enano_about_lbl_pgsqlversion'); ?> +

user_logged_in ) ? $session->username : false; $response = Array( 'username' => $username, @@ -1504,12 +1505,15 @@ array('%', '_'), $finduser); $finduser = $db->escape($finduser); - $username_where = 'u.username LIKE "' . $finduser . '"'; + $username_where = ENANO_SQLFUNC_LOWERCASE . '(u.username) LIKE \'%' . strtolower($finduser) . '%\''; $finduser_url = 'finduser=' . rawurlencode($_GET['finduser']) . '&'; } else { - $username_where = 'u.username REGEXP "^' . $startletter_sql . '"'; + if ( ENANO_DBLAYER == 'MYSQL' ) + $username_where = 'lcase(u.username) REGEXP lcase("^' . $startletter_sql . '")'; + else if ( ENANO_DBLAYER == 'PGSQL' ) + $username_where = 'lower(u.username) ~ lower(\'^' . $startletter_sql . '\')'; $finduser_url = ''; } @@ -1533,7 +1537,7 @@ '; // determine number of rows - $q = $db->sql_query('SELECT u.user_id FROM '.table_prefix.'users AS u WHERE ' . $username_where . ' AND u.username != "Anonymous";'); + $q = $db->sql_query('SELECT u.user_id FROM '.table_prefix.'users AS u WHERE ' . $username_where . ' AND u.username != \'Anonymous\';'); if ( !$q ) $db->_die(); @@ -1550,7 +1554,7 @@ $q = $db->sql_unbuffered_query('SELECT u.user_id, u.username, u.reg_time, u.email, u.user_level, u.reg_time, x.email_public FROM '.table_prefix.'users AS u LEFT JOIN '.table_prefix.'users_extra AS x ON ( u.user_id = x.user_id ) - WHERE ' . $username_where . ' AND u.username != "Anonymous" + WHERE ' . $username_where . ' AND u.username != \'Anonymous\' ORDER BY ' . $sort_sqllet . ' ' . $target_order . ';'); if ( !$q ) $db->_die(); @@ -1580,7 +1584,7 @@ ' . '
' - . ( urlSeparator == '&' ? '' : '' ) + . ( urlSeparator == '&' ? '' : '' ) . ( $session->sid_super ? '' : '') . '

Find a member: ' . $template->username_field('finduser') . '
You may use the following wildcards: * to match multiple characters, ? to match a single character.

' . '
diff -r 474f8be55943 -r ab66d6d1f1f4 plugins/SpecialUserPrefs.php --- a/plugins/SpecialUserPrefs.php Fri Dec 07 18:47:37 2007 -0500 +++ b/plugins/SpecialUserPrefs.php Wed Dec 19 22:55:40 2007 -0500 @@ -4,13 +4,13 @@ Plugin URI: http://enanocms.org/ Description: Provides the page Special:Preferences. Author: Dan Fuhry -Version: 1.0.2 +Version: 1.0.3 Author URI: http://enanocms.org/ */ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.0.2 + * Version 1.0.3 * Copyright (C) 2006-2007 Dan Fuhry * * This program is Free Software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -47,7 +47,7 @@ { global $db, $session, $paths, $template, $plugins; // Common objects - if ( $paths->namespace != 'Special' || $paths->cpage['urlname_nons'] != 'Preferences' ) + if ( $paths->namespace != 'Special' || $paths->page_id != 'Preferences' ) return false; $tb .= "
    $template->toolbar_menu
"; @@ -599,7 +599,7 @@ $code = $plugins->setHook('userprefs_body'); foreach ( $code as $cmd ) { - if ( eval($code) ) + if ( eval($cmd) ) $good = true; } if ( !$good ) diff -r 474f8be55943 -r ab66d6d1f1f4 plugins/admin/PageGroups.php --- a/plugins/admin/PageGroups.php Fri Dec 07 18:47:37 2007 -0500 +++ b/plugins/admin/PageGroups.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.0.2 (Coblynau) + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License diff -r 474f8be55943 -r ab66d6d1f1f4 plugins/admin/SecurityLog.php --- a/plugins/admin/SecurityLog.php Fri Dec 07 18:47:37 2007 -0500 +++ b/plugins/admin/SecurityLog.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * Copyright (C) 2006-2007 Dan Fuhry * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License @@ -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 474f8be55943 -r ab66d6d1f1f4 plugins/admin/UserManager.php --- a/plugins/admin/UserManager.php Fri Dec 07 18:47:37 2007 -0500 +++ b/plugins/admin/UserManager.php Wed Dec 19 22:55:40 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(); diff -r 474f8be55943 -r ab66d6d1f1f4 themes/oxygen/css/bleu.css --- a/themes/oxygen/css/bleu.css Fri Dec 07 18:47:37 2007 -0500 +++ b/themes/oxygen/css/bleu.css Wed Dec 19 22:55:40 2007 -0500 @@ -233,19 +233,24 @@ td.mdg-menu-btm { height: 12px; background: url(../images/bleu/border-btm.gif); } /* Buttons and textboxes - these settings are used almost everywhere */ -input, textarea, select { border: 1px solid #406080; background-color: #F2F2F2; padding: 3px; font-family: arial, helvetica, sans-serif; font-size: 8pt; } +input, textarea, select, button { border: 1px solid #406080; background-color: #F2F2F2; padding: 3px; font-family: arial, helvetica, sans-serif; font-size: 8pt; } input:hover, textarea:hover, select:hover { border: 1px solid #6080A0; background-color: #F8F8F8; padding: 3px; } input:focus, textarea:focus, select:focus { border: 1px solid #90B0D0; background-color: #FFFFFF; padding: 3px; } label { padding: 3px; cursor: pointer; font-family: arial, helvetica, sans-serif; font-size: 8pt; } label:hover { padding: 3px; cursor: pointer; background-color: #F0F0F0; } input#pageheading { font-size: 14pt; border-bottom: 1px solid #90B0D0; margin-bottom: 0; } -input[type ^="button"], input[type ^="submit"] { +input[type ^="button"], input[type ^="submit"], button { background-image: url(../images/buttonbg.gif); background-repeat: repeat-x; color: #202020; } +input[type ^="image"][disabled ^="disabled"] { + opacity: 0.5; + filter: alpha(opacity=50); +} + /* JWS window theming */ div.jswindow { border: 2px solid #7090B0; border-top: 5px solid #7090B0; padding: 0px; font-family: Trebuchet MS, tahoma, verdana, arial, sans-serif; font-size: 9pt; display: none; position: absolute; background-color: #FFFFFF; } div.titlebar { background-color: #7090B0; color: #FFFFFF; font-family: Trebuchet MS, tahoma, verdana, arial, sans-serif; font-size: 9pt; padding-bottom: 4px; cursor: default; } diff -r 474f8be55943 -r ab66d6d1f1f4 upgrade.php --- a/upgrade.php Fri Dec 07 18:47:37 2007 -0500 +++ b/upgrade.php Wed Dec 19 22:55:40 2007 -0500 @@ -2,7 +2,7 @@ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between - * Version 1.1.1 + * Version 1.0.3 (Dyrad) * upgrade.php - upgrade script * Copyright (C) 2006-2007 Dan Fuhry * @@ -70,7 +70,7 @@ // Everything related to versions goes here! // Valid versions to upgrade from -$valid_versions = Array('1.0b1', '1.0b2', '1.0b3', '1.0b4', '1.0RC1', '1.0RC2', '1.0RC3', '1.0', '1.0.1', '1.0.1.1', '1.0.2b1', '1.0.2', 'Stable1.0ToUnstable1.1'); +$valid_versions = Array('1.0b1', '1.0b2', '1.0b3', '1.0b4', '1.0RC1', '1.0RC2', '1.0RC3', '1.0', '1.0.1', '1.0.1.1', '1.0.2b1', '1.0.2', '1.0.3', 'Stable1.0ToUnstable1.1'); // Basically a list of dependencies, which should be resolved automatically // If, for example, upgrading from 1.0b1 to 1.0RC1 requires one extra query that would not @@ -86,7 +86,8 @@ '1.0' => Array('1.0.1'), '1.0.1' => Array('1.0.1.1'), '1.0.1.1' => Array('1.0.2b1'), - '1.0.2b1' => Array('Stable1.0ToUnstable1.1'), + '1.0.2b1' => Array('1.0.2'), + '1.0.2' => Array('Stable1.0ToUnstable1.1'), 'Stable1.0ToUnstable1.1' => Array('1.1.1') ); $this_version = '1.1.1'; diff -r 474f8be55943 -r ab66d6d1f1f4 upgrade.sql --- a/upgrade.sql Fri Dec 07 18:47:37 2007 -0500 +++ b/upgrade.sql Wed Dec 19 22:55:40 2007 -0500 @@ -14,6 +14,7 @@ ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_lang smallint(5) NOT NULL; ---END Stable1.0ToUnstable1.1--- ---BEGIN 1.0.2--- +-- No DB changes in this release ---END 1.0.2--- ---BEGIN 1.0.2b1--- -- This is really optional, but could reduce confusion if regex page groups get truncated for no apparent reason.