# HG changeset patch
# User Dan
# Date 1196629210 18000
# Node ID e2cb5f1432c8665643a4708c6c4b3e54575d8aa9
# Parent dc08c70ca5505c3c4aa42693c10656896dbd8783# Parent abefe7181c0807176ec0dd1c73224fb4be827e9c
Merging in the newly stable Coblynau
diff -r dc08c70ca550 -r e2cb5f1432c8 .hgtags
--- a/.hgtags Sun Dec 02 15:27:21 2007 -0500
+++ b/.hgtags Sun Dec 02 16:00:10 2007 -0500
@@ -6,3 +6,6 @@
0b5244001799fa29e83bf06c5f14eb69350f171c rebrand
42c6c83b8a004163c9cc2d85f3c8eada3b73adf6 rebrand
d53cc29308f4f4b97fc6d054e9e0855f37137409 rebrand
+90632c09ed7ec816da708df1341d9f4019de9adf feature-freeze
+f948557af0681389165a23419968965fcebcbdd0 devel-freeze
+c36c5034a80052b4dc4710a67513b5b6e3c2fc7b release
diff -r dc08c70ca550 -r e2cb5f1432c8 README
--- a/README Sun Dec 02 15:27:21 2007 -0500
+++ b/README Sun Dec 02 16:00:10 2007 -0500
@@ -55,7 +55,7 @@
be shown on the (renamed) Special:About_Enano page:
"The software used on this website was based on Enano CMS. Copyright
- (C) 2006-2007 Enano Foundation."
+ (C) 2006-2007 Dan Fuhry."
The words "Enano CMS" must link to the page . You may
(at your option) also include a notice of non-endorsement by the Enano
@@ -82,9 +82,8 @@
This tarball includes an upgrade script that can migrate any previous version
of Enano to this one. Before you upload the contents of this tarball to your
-server, be sure to delete the config.php and .htaccess files included with this
-tarball, and back up these two files from your server. (.htaccess only needs to
-be backed up if you're using the Tiny URLs option and/or you have Apache.)
+server, you might want to delete the files config.new.php and .htaccess.new,
+neither of which are needed if you are performing an upgrade.
EXPANDING YOUR SITE'S CAPABILITIES
-----------------------------
diff -r dc08c70ca550 -r e2cb5f1432c8 ajax.php
--- a/ajax.php Sun Dec 02 15:27:21 2007 -0500
+++ b/ajax.php Sun Dec 02 16:00:10 2007 -0500
@@ -21,6 +21,11 @@
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());
+ return ((float)$usec + (float)$sec);
+ }
// Determine directory (special case for development servers)
if ( strpos(__FILE__, '/repo/') && file_exists('.enanodev') )
{
diff -r dc08c70ca550 -r e2cb5f1432c8 images/enano-artwork/installer-greeting-blue.png
Binary file images/enano-artwork/installer-greeting-blue.png has changed
diff -r dc08c70ca550 -r e2cb5f1432c8 images/enano-artwork/installer-greeting-green.png
Binary file images/enano-artwork/installer-greeting-green.png has changed
diff -r dc08c70ca550 -r e2cb5f1432c8 includes/clientside/static/ajax.js
--- a/includes/clientside/static/ajax.js Sun Dec 02 15:27:21 2007 -0500
+++ b/includes/clientside/static/ajax.js Sun Dec 02 16:00:10 2007 -0500
@@ -233,7 +233,7 @@
document.getElementById('protbtn_1').style.textDecoration = 'none';
document.getElementById('protbtn_2').style.textDecoration = 'none';
document.getElementById('protbtn_'+l).style.textDecoration = 'underline';
- ajaxPost(stdAjaxPrefix+'&_mode=protect', 'reason='+escape(r)+'&level='+l, function() {
+ ajaxPost(stdAjaxPrefix+'&_mode=protect', 'reason='+ajaxEscape(r)+'&level='+l, function() {
if(ajax.readyState == 4) {
unsetAjaxLoading();
if(ajax.responseText != 'good')
@@ -250,7 +250,7 @@
r = prompt($lang.get('ajax_rename_prompt'));
if(!r || r=='') return;
setAjaxLoading();
- ajaxPost(stdAjaxPrefix+'&_mode=rename', 'newtitle='+escape(r), function() {
+ ajaxPost(stdAjaxPrefix+'&_mode=rename', 'newtitle='+ajaxEscape(r), function() {
if(ajax.readyState == 4) {
unsetAjaxLoading();
alert(ajax.responseText);
@@ -288,7 +288,7 @@
return;
}
setAjaxLoading();
- ajaxPost(stdAjaxPrefix+'&_mode=deletepage', 'reason=' + escape(reason), function() {
+ ajaxPost(stdAjaxPrefix+'&_mode=deletepage', 'reason=' + ajaxEscape(reason), function() {
if(ajax.readyState == 4) {
unsetAjaxLoading();
alert(ajax.responseText);
@@ -660,7 +660,7 @@
return true;
}
- ajaxPost(stdAjaxPrefix + '&_mode=change_theme', 'theme_id=' + escape(theme_id) + '&style_id=' + escape(style_id), function()
+ ajaxPost(stdAjaxPrefix + '&_mode=change_theme', 'theme_id=' + ajaxEscape(theme_id) + '&style_id=' + ajaxEscape(style_id), function()
{
if ( ajax.readyState == 4 )
{
diff -r dc08c70ca550 -r e2cb5f1432c8 includes/clientside/static/misc.js
--- a/includes/clientside/static/misc.js Sun Dec 02 15:27:21 2007 -0500
+++ b/includes/clientside/static/misc.js Sun Dec 02 16:00:10 2007 -0500
@@ -392,6 +392,10 @@
function ajaxAuthLoginInnerSetup()
{
+ // let's hope this gets the image cached
+ var _ = new Image(32, 32);
+ _.src = scriptPath + "/images/good.gif";
+
ajaxGet(makeUrlNS('Special', 'Login', 'act=getkey'), function() {
if ( ajax.readyState == 4 )
{
@@ -619,6 +623,11 @@
switch(response.result)
{
case 'success':
+ var success_win = '
";
}
class mysql {
- var $num_queries, $query_backtrace, $latest_result, $latest_query, $_conn, $sql_stack_fields, $sql_stack_values;
+ 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');
@@ -47,6 +50,7 @@
function disable_errorhandler()
{
+ // echo "DBAL: disabling error handler ";
if ( $this->errhandler )
{
set_error_handler($this->errhandler);
@@ -57,14 +61,9 @@
}
}
- function sql_backtrace() {
- $qb = explode("\n", $this->query_backtrace);
- $bt = '';
- //for($i=sizeof($qb)-1;$i>=0;$i--) {
- for($i=0;$iquery_backtrace);
}
function ensure_connection()
@@ -127,7 +126,7 @@
dc_here('dbal: trying to connect....');
- if ( defined('IN_ENANO_INSTALL') )
+ if ( defined('IN_ENANO_INSTALL') && !defined('IN_ENANO_UPGRADE') )
{
@include(ENANO_ROOT.'/config.new.php');
}
@@ -149,6 +148,11 @@
{
$_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);
@@ -170,9 +174,13 @@
}
// Reset some variables
- $this->query_backtrace = '';
+ $this->query_backtrace = array();
+ $this->query_times = array();
+ $this->query_sources = array();
$this->num_queries = 0;
+ $this->debug = ( defined('ENANO_DEBUG') );
+
dc_here('dbal: we\'re in, selecting database...');
$q = $this->sql_query('USE `'.$dbname.'`;');
@@ -189,8 +197,27 @@
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 . "\n";
+ $this->query_backtrace[] = $q;
$this->latest_query = $q;
dc_here('dbal: making SQL query: '.$q.'');
// First make sure we have a connection
@@ -205,7 +232,9 @@
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 = mysql_query($q, $this->_conn);
+ $this->query_times[$q] = microtime_float() - $time_start;
$this->latest_result = $r;
$this->disable_errorhandler();
return $r;
@@ -214,8 +243,9 @@
function sql_unbuffered_query($q)
{
$this->enable_errorhandler();
+
$this->num_queries++;
- $this->query_backtrace .= '(UNBUFFERED) ' . $q."\n";
+ $this->query_backtrace[] = '(UNBUFFERED) ' . $q;
$this->latest_query = $q;
dc_here('dbal: making SQL query: '.$q.'');
// First make sure we have a connection
@@ -230,7 +260,9 @@
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 = mysql_unbuffered_query($q, $this->_conn);
+ $this->query_times[$q] = microtime_float() - $time_start;
$this->latest_result = $r;
$this->disable_errorhandler();
return $r;
@@ -681,6 +713,79 @@
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 '
+ Total time taken for SQL queries: ' . round( $query_time_total, 6 ) . ' seconds
+
+
';
+ }
+ echo '
+
';
+ $template->footer();
+ }
}
?>
diff -r dc08c70ca550 -r e2cb5f1432c8 includes/functions.php
--- a/includes/functions.php Sun Dec 02 15:27:21 2007 -0500
+++ b/includes/functions.php Sun Dec 02 16:00:10 2007 -0500
@@ -560,94 +560,6 @@
* Prints out the categorization box found on most regular pages. Doesn't take or return anything, but assumes that the page information is already set in $paths.
*/
- /*
-function show_category_info()
-{
- global $db, $session, $paths, $template, $plugins; // Common objects
- dc_here('functions: showing category info');
- // if($template->no_headers && !strpos($_SERVER['REQUEST_URI'], 'ajax.php')) return '';
- if ( $paths->namespace == 'Category' )
- {
- $q = $db->sql_query('SELECT page_id,namespace FROM '.table_prefix.'categories WHERE category_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace=\'Category\' ORDER BY page_id;');
- if(!$q) $db->_die('The category information could not be selected.');
- $ticker = -1;
- echo '
';
-
- $q = $db->sql_query('SELECT page_id,namespace FROM '.table_prefix.'categories WHERE category_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace!=\'Category\' ORDER BY page_id;');
- if ( !$q )
- {
- $db->_die('The category information could not be selected.');
- }
- $ticker = -1;
- echo '
';
- }
- $q = $db->sql_query('SELECT category_id FROM '.table_prefix.'categories WHERE page_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace=\''.$paths->namespace.'\'');
- if(!$q) $db->_die('The error seems to have occurred during selection of category data.');
- if($db->numrows() > 0) {
- echo '
';
@@ -1051,7 +1051,7 @@
// Determine the name, and whether to link to the user page or not
$name = '';
- if($row['user_id'] > 1) $name .= '';
+ if($row['user_id'] > 1) $name .= '';
$name .= $row['name'];
if($row['user_id'] > 1) $name .= '';
$strings['NAME'] = $name; unset($name);
diff -r dc08c70ca550 -r e2cb5f1432c8 includes/paths.php
--- a/includes/paths.php Sun Dec 02 15:27:21 2007 -0500
+++ b/includes/paths.php Sun Dec 02 16:00:10 2007 -0500
@@ -118,7 +118,8 @@
eval($cmd);
}
- $e = $db->sql_query('SELECT name,urlname,namespace,special,visible,comments_on,protected,delvotes,delvote_ips,wiki_mode,password FROM '.table_prefix.'pages ORDER BY name;');
+ $e = $db->sql_query('SELECT name,urlname,namespace,special,visible,comments_on,protected,delvotes,' . "\n"
+ . ' delvote_ips,wiki_mode,password FROM '.table_prefix.'pages ORDER BY name;');
if( !$e )
{
$db->_die('The error seems to have occured while selecting the page information. File: includes/paths.php; line: '.__LINE__);
@@ -681,17 +682,30 @@
/**
* Rebuilds the search index
+ * @param bool If true, prints out status messages
*/
- function rebuild_search_index()
+ function rebuild_search_index($verbose = false)
{
global $db, $session, $paths, $template, $plugins; // Common objects
$search = new Searcher();
+ if ( $verbose )
+ {
+ echo '
';
// return;
$q = $db->sql_query('DELETE FROM '.table_prefix.'search_index');
diff -r dc08c70ca550 -r e2cb5f1432c8 includes/rijndael.php
--- a/includes/rijndael.php Sun Dec 02 15:27:21 2007 -0500
+++ b/includes/rijndael.php Sun Dec 02 16:00:10 2007 -0500
@@ -16,10 +16,13 @@
define ('ENC_BASE64', 202);
define ('ENC_BINARY', 203);
+$_aes_objcache = array();
+
class AESCrypt {
var $debug = false;
var $mcrypt = false;
+ var $decrypt_cache = array();
// Rijndael parameters -- Valid values are 128, 192, or 256
@@ -128,6 +131,18 @@
$this->debug = $debug;
}
+ function singleton($key_size, $block_size)
+ {
+ global $_aes_objcache;
+ if ( isset($_aes_objcache["$key_size,$block_size"]) )
+ {
+ return $_aes_objcache["$key_size,$block_size"];
+ }
+
+ $_aes_objcache["$key_size,$block_size"] = new AESCrypt($key_size, $block_size);
+ return $_aes_objcache["$key_size,$block_size"];
+ }
+
// Error handler
function trigger_error($text, $level = E_USER_NOTICE)
@@ -804,6 +819,14 @@
{
if ( $text == '' )
return '';
+ $text_orig = $text;
+ if ( isset($this->decrypt_cache[$key]) && is_array($this->decrypt_cache[$key]) )
+ {
+ if ( isset($this->decrypt_cache[$key][$text]) )
+ {
+ return $this->decrypt_cache[$key][$text];
+ }
+ }
switch($input_encoding)
{
case ENC_BINARY:
@@ -838,6 +861,11 @@
}
$dypt = $this->byteArrayToString($dypt);
}
+ if ( !isset($this->decrypt_cache[$key]) )
+ $this->decrypt_cache[$key] = array();
+
+ $this->decrypt_cache[$key][$text_orig] = $dypt;
+
return $dypt;
}
diff -r dc08c70ca550 -r e2cb5f1432c8 includes/search.php
--- a/includes/search.php Sun Dec 02 15:27:21 2007 -0500
+++ b/includes/search.php Sun Dec 02 16:00:10 2007 -0500
@@ -19,7 +19,7 @@
* @param array $arr2
* @return array
*/
-
+
function enano_safe_array_merge($arr1, $arr2)
{
$arr3 = $arr1;
@@ -34,7 +34,7 @@
* In Enano versions prior to 1.0.2, this class provided a search function that was keyword-based and allowed boolean searches. It was
* cut from Coblynau and replaced with perform_search(), later in this file, because of speed issues. Now mostly deprecated. The only
* thing remaining is the buildIndex function, which is still used by the path manager and the new search framework.
- *
+ *
* @package Enano
* @subpackage Page management frontend
* @license GNU General Public License
@@ -42,17 +42,17 @@
class Searcher
{
-
+
var $results;
var $index;
var $warnings;
var $match_case = false;
-
+
function buildIndex($texts)
{
$this->index = Array();
$stopwords = get_stopwords();
-
+
foreach($texts as $i => $l)
{
$seed = md5(microtime(true) . mt_rand());
@@ -119,15 +119,15 @@
{
global $db, $session, $paths, $template, $plugins; // Common objects
$warnings = array();
-
+
$query = parse_search_query($query, $warnings);
-
+
// Segregate search terms containing spaces
$query_phrase = array(
'any' => array(),
'req' => array()
);
-
+
foreach ( $query['any'] as $i => $_ )
{
$term =& $query['any'][$i];
@@ -141,7 +141,7 @@
}
unset($term);
$query['any'] = array_values($query['any']);
-
+
foreach ( $query['req'] as $i => $_ )
{
$term =& $query['req'][$i];
@@ -154,12 +154,13 @@
}
unset($term);
$query['req'] = array_values($query['req']);
-
+
$results = array();
$scores = array();
-
+ $ns_list = '(' . implode('|', array_keys($paths->nslist)) . ')';
+
// FIXME: Update to use FULLTEXT algo when available.
-
+
// Build an SQL query to load from the index table
if ( count($query['any']) < 1 && count($query['req']) < 1 && count($query_phrase['any']) < 1 && count($query_phrase['req']) < 1 )
{
@@ -167,14 +168,14 @@
$warnings[] = 'You need to have at least one keyword in your search query. Searching only for pages not containing a term is not allowed.';
return array();
}
-
+
//
// STAGE 1
// Get all possible result pages from the search index. Tally which pages have the most words, and later sort them by boolean relevance
//
-
+
// Skip this if no indexable words are included
-
+
if ( count($query['any']) > 0 || count($query['req']) > 0 )
{
$where_any = array();
@@ -192,18 +193,18 @@
$term = strtolower($term);
$where_any[] = $term;
}
-
+
$col_word = ( $case_sensitive ) ? 'word' : 'lcase(word)';
$where_any = ( count($where_any) > 0 ) ? '( ' . $col_word . ' = \'' . implode('\' OR ' . $col_word . ' = \'', $where_any) . '\' )' : '';
-
+
// generate query
// using a GROUP BY here ensures that the same word with a different case isn't counted as 2 words - it's all melted back
// into one later in the processing stages
- $group_by = ( $case_sensitive ) ? '' : ' GROUP BY lcase(word);';
- $sql = "SELECT word, page_names FROM " . table_prefix . "search_index WHERE {$where_any}{$group_by}";
+ // $group_by = ( $case_sensitive ) ? '' : ' GROUP BY lcase(word);';
+ $sql = "SELECT word, page_names FROM " . table_prefix . "search_index WHERE {$where_any}";
if ( !($q = $db->sql_unbuffered_query($sql)) )
$db->_die('Error is in perform_search(), includes/search.php, query 1');
-
+
$word_tracking = array();
if ( $row = $db->fetchrow() )
{
@@ -211,11 +212,10 @@
{
// get page list
$pages =& $row['page_names'];
- $ns_list = '(' . implode('|', array_keys($paths->nslist)) . ')';
if ( strpos($pages, ',') )
{
// the term occurs in more than one page
-
+
// Find page IDs that contain commas
// This should never happen because commas are escaped by sanitize_page_id(). Nevertheless for compatibility with older
// databases, and to alleviate the concerns of hackers, we'll accommodate for page IDs with commas here by checking for
@@ -235,62 +235,104 @@
$prev = $i;
}
unset($match);
-
+
// Iterate through each of the results, assigning scores based on how many times the page has shown up.
// This works because this phase of the search is strongly word-based not page-based. If a page shows up
// multiple times while fetching the result rows from the search_index table, it simply means that page
// contains more than one of the terms the user searched for.
-
+
foreach ( $matches as $match )
{
- if ( isset($scores[$match]) )
+ $word_cs = (( $case_sensitive ) ? $row['word'] : strtolower($row['word']));
+ if ( isset($word_tracking[$match]) && in_array($word_cs, $word_tracking[$match]) )
{
- $scores[$match]++;
+ continue;
+ }
+ if ( isset($word_tracking[$match]) )
+ {
+ if ( isset($word_tracking[$match]) )
+ {
+ $word_tracking[$match][] = ($word_cs);
+ }
}
else
{
- $scores[$match] = 1;
+ $word_tracking[$match] = array($word_cs);
}
- if ( isset($word_tracking[$match]) )
+ $inc = 1;
+
+ // Is this search term present in the page's title? If so, give extra points
+ preg_match("/^ns=$ns_list;pid=(.+)$/", $match, $piecesparts);
+ $pathskey = $paths->nslist[ $piecesparts[1] ] . sanitize_page_id($piecesparts[2]);
+ if ( isset($paths->pages[$pathskey]) )
{
- $word_tracking[$match][] = $row['word'];
+ $test_func = ( $case_sensitive ) ? 'strstr' : 'stristr';
+ if ( $test_func($paths->pages[$pathskey]['name'], $row['word']) || $test_func($paths->pages[$pathskey]['urlname_nons'], $row['word']) )
+ {
+ $inc = 1.5;
+ }
+ }
+ if ( isset($scores[$match]) )
+ {
+ $scores[$match] = $scores[$match] + $inc;
}
else
{
- $word_tracking[$match] = array($row['word']);
+ $scores[$match] = $inc;
}
}
}
else
{
// the term only occurs in one page
- if ( isset($scores[$pages]) )
+ $word_cs = (( $case_sensitive ) ? $row['word'] : strtolower($row['word']));
+ if ( isset($word_tracking[$pages]) && in_array($word_cs, $word_tracking[$pages]) )
{
- $scores[$pages]++;
+ continue;
+ }
+ if ( isset($word_tracking[$pages]) )
+ {
+ if ( isset($word_tracking[$pages]) )
+ {
+ $word_tracking[$pages][] = ($word_cs);
+ }
}
else
{
- $scores[$pages] = 1;
+ $word_tracking[$pages] = array($word_cs);
}
- if ( isset($word_tracking[$pages]) )
+ $inc = 1;
+
+ // Is this search term present in the page's title? If so, give extra points
+ preg_match("/^ns=$ns_list;pid=(.+)$/", $pages, $piecesparts);
+ $pathskey = $paths->nslist[ $piecesparts[1] ] . sanitize_page_id($piecesparts[2]);
+ if ( isset($paths->pages[$pathskey]) )
{
- $word_tracking[$pages][] = $row['word'];
+ $test_func = ( $case_sensitive ) ? 'strstr' : 'stristr';
+ if ( $test_func($paths->pages[$pathskey]['name'], $row['word']) || $test_func($paths->pages[$pathskey]['urlname_nons'], $row['word']) )
+ {
+ $inc = 1.5;
+ }
+ }
+ if ( isset($scores[$pages]) )
+ {
+ $scores[$pages] = $scores[$pages] + $inc;
}
else
{
- $word_tracking[$pages] = array($row['word']);
+ $scores[$pages] = $inc;
}
}
}
while ( $row = $db->fetchrow() );
}
$db->free_result();
-
+
//
// STAGE 2: FIRST ELIMINATION ROUND
// Iterate through the list of required terms. If a given page is not found to have the required term, eliminate it
//
-
+
foreach ( $query['req'] as $term )
{
foreach ( $word_tracking as $i => $page )
@@ -302,85 +344,108 @@
}
}
}
-
+
//
// STAGE 3: PHRASE SEARCHING
// Use LIKE to find pages with specified phrases. We can do a super-picky single query without another elimination round because
// at this stage we can search the full page_text column instead of relying on a word list.
//
-
+
// 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)';
+
if ( count($query_phrase['any']) > 0 || count($query_phrase['req']) > 0 )
{
-
+
$where_any = array();
foreach ( $query_phrase['any'] as $term )
{
$term = escape_string_like($term);
if ( !$case_sensitive )
$term = strtolower($term);
- $where_any[] = $term;
+ $where_any[] = "( $text_col LIKE '%$term%' OR $name_col LIKE '%$term%' )";
}
-
- $where_any = ( count($where_any) > 0 ) ? "( $text_col LIKE '%" . implode("%' OR $text_col LIKE '%", $where_any) . "%' )" : '';
-
- // Also do required columns, but use AND to ensure that all required terms are included
+
+ $where_any = ( count($where_any) > 0 ) ? implode(" OR\n ", $where_any) : '';
+
+ // Also do required terms, but use AND to ensure that all required terms are included
$where_req = array();
foreach ( $query_phrase['req'] as $term )
{
$term = escape_string_like($term);
if ( !$case_sensitive )
$term = strtolower($term);
- $where_req[] = $term;
+ $where_req[] = "( $text_col LIKE '%$term%' OR $name_col LIKE '%$term%' )";
}
$and_clause = ( $where_any != '' ) ? 'AND ' : '';
- $where_req = ( count($where_req) > 0 ) ? "{$and_clause}$text_col LIKE '%" . implode("%' AND $text_col LIKE '%", $where_req) . "%'" : '';
-
- $sql = 'SELECT CONCAT("ns=",namespace,";pid=",page_id) AS id FROM ' . table_prefix . "page_text WHERE $where_any $where_req;";
+ $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"
+ . " 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;";
if ( !($q = $db->sql_unbuffered_query($sql)) )
$db->_die('Error is in perform_search(), includes/search.php, query 2. Parsed query dump follows:
@@ -1554,7 +1560,7 @@
}
unset($_POST['_cont']);
require('config.new.php');
- $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE);
+ $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
if ( isset($crypto_key) )
{
$cryptkey = $crypto_key;
@@ -1579,7 +1585,7 @@
{
var frm = document.forms.login;
ret = true;
- if ( frm.admin_user.value.match(/^([A-z0-9 \\-\\.]+)$/) && !frm.admin_user.value.match(/^(?:(?:\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])$/) && frm.admin_user.value.toLowerCase() != \'anonymous\' )
+ if ( frm.admin_user.value.match(/^([^<>&\?\'"%\/]+)$/) && !frm.admin_user.value.match(/^(?:(?:\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])$/) && frm.admin_user.value.toLowerCase() != \'anonymous\' )
{
document.getElementById(\'s_user\').src = \'images/good.gif\';
}
@@ -1597,7 +1603,7 @@
document.getElementById(\'s_password\').src = \'images/bad.gif\';
ret = false;
}
- if(frm.admin_email.value.match(/^(?:[\\w\\d]+\\.?)+@(?:(?:[\\w\\d]\\-?)+\\.)+\\w{2,4}$/))
+ if(frm.admin_email.value.match(/^(?:[\\w\\d_-]+\\.?)+@(?:(?:[\\w\\d-]\\-?)+\\.)+\\w{2,4}$/))
{
document.getElementById(\'s_email\').src = \'images/good.gif\';
}
diff -r dc08c70ca550 -r e2cb5f1432c8 language/english/enano.json
--- a/language/english/enano.json Sun Dec 02 15:27:21 2007 -0500
+++ b/language/english/enano.json Sun Dec 02 16:00:10 2007 -0500
@@ -66,6 +66,7 @@
login_success_title: 'Login successful',
login_success_body: 'You have successfully logged into the %config.site_name% site as "%username%". Redirecting to %redir_target%...',
login_success_body_mainpage: 'the main page',
+ login_success_short: 'Success.',
login_ajax_fetching_key: 'Fetching an encryption key...',
login_ajax_prompt_title: 'Please enter your username and password to continue.',
@@ -76,6 +77,7 @@
login_ajax_loggingin: 'Logging in...',
err_key_not_found: 'Enano couldn\'t look up the encryption key used to encrypt your password. This most often happens if a cache rotation occurred during your login attempt, or if you refreshed the login page.',
+ err_key_not_found_cleared: 'It seems that the list of encryption keys used for login information has reached its maximum length, thus preventing new keys from being inserted. The list has been automatically cleared. Please try logging in again; if you are still unable to log in, please contact the site administration.',
err_key_wrong_length: 'The encryption key was the wrong length.',
err_too_big_for_britches: 'You are trying to authenticate at a level that your user account does not permit.',
err_invalid_credentials: 'You have entered an invalid username or password. Please enter your login details again.',
@@ -303,6 +305,8 @@
btn_cancel: 'Cancel and return to page',
btn_closeviewer: 'Close viewer',
preview_blurb: 'Reminder: This is only a preview - your changes to this page have not yet been saved.',
+ msg_save_success_title: 'Changes saved',
+ msg_save_success_body: 'Your changes to this page have been saved. Redirecting...',
},
history: {
summary_clearlogs: 'Automatic backup created when logs were purged',
@@ -349,6 +353,7 @@
rename_err_need_name: 'Error: you must enter a new name for this page.',
rename_lbl: 'Please enter a new name for this page:',
rename_btn_submit: 'Rename page',
+ rename_success_title: 'Page renamed',
flushlogs_warning_stern: '
You are about to destroy all logged edits and actions on this page.
Unlike deleting or editing this page, this action is not reversible! You should only do this if you are desparate for database space.
Do you really want to continue?
',
flushlogs_btn_submit: 'Flush logs',
diff -r dc08c70ca550 -r e2cb5f1432c8 language/english/install.json
--- a/language/english/install.json Sun Dec 02 15:27:21 2007 -0500
+++ b/language/english/install.json Sun Dec 02 16:00:10 2007 -0500
@@ -61,6 +61,7 @@
heading: 'Checking your server',
blurb: 'Enano has several requirements that must be met before it can be installed. If all is good then note any warnings and click Continue below.',
req_php: 'PHP Version >=4.3.0',
+ req_php5: 'PHP 5.2.0 or later',
req_mysql: 'MySQL extension for PHP',
req_uploads: 'File upload support',
req_apache: 'Apache HTTP Server',
@@ -70,6 +71,7 @@
req_fileswriteable: 'File uploads directory writable',
req_desc_php: 'It seems that the version of PHP that your server is running is too old to support Enano properly. If this is your server, please upgrade to the most recent version of PHP, remembering to use the --with-mysql configure option if you compile it yourself. If this is not your server, please contact your webhost and ask them if it would be possible to upgrade PHP. If this is not possible, you will need to switch to a different webhost in order to use Enano.',
+ req_desc_php5: 'Your server does not have support for PHP 5.2.0. While you may continue installing Enano, please be warned that as of December 31, 2007, all support for Enano on PHP 4 servers is discontinued. If you have at least PHP 5.0.0, support will still be available, but there are many security problems in PHP versions under 5.2.0 that Enano cannot effectively prevent.',
req_desc_mysql: 'It seems that your PHP installation does not have the MySQL extension enabled. If this is your own server, you may need to just enable the "libmysql.so" extension in php.ini. If you do not have the MySQL extension installed, you will need to either use your distribution\'s package manager to install it, or you will have to compile PHP from source. If you compile PHP from source, please remember to use the "--with-mysql" configure option, and you will have to have the MySQL development files installed (they usually are). If this is not your server, please contact your hosting company and ask them to install the PHP MySQL extension.',
req_desc_uploads: 'It seems that your server does not support uploading files. Enano *requires* this functionality in order to work properly. Please ask your server administrator to set the "file_uploads" option in php.ini to "On".',
req_desc_apache: 'Apparently your server is running a web server other than Apache. Enano will work nontheless, but there are some known bugs with non-Apache servers, and the "fancy" URLs will not work properly. The "Standard URLs" option will be set on the website configuration page, only change it if you are absolutely certain that your server is running Apache.',
@@ -151,6 +153,7 @@
field_urlscheme_ugly: 'Standard URLs - compatible with any web server (www.example.com/index.php?title=Page_name)',
field_urlscheme_short: 'Short URLs - requires Apache with a PHP module (www.example.com/index.php/Page_name)',
field_urlscheme_tiny: 'Tiny URLs - requires Apache on Linux/Unix/BSD with PHP module and mod_rewrite enabled (www.example.com/Page_name)',
+ field_urlscheme_helplink: 'Which URL scheme should I choose?',
objective_verify: 'Verify that your site information is correct. Again, all of the above settings can be changed from the administration panel.',
},
@@ -253,6 +256,23 @@
embed Javascript and arbitrary HTML and CSS.
If you don\'t have experience coding in PHP, you can safely disable this option. You may change this at any time
using the ACL editor by selecting the Administrators group and This Entire Website under the scope selection.
The URL scheme allows you to decide how the URLs to your Enano pages will look.
+
The first option (Standard URLs) works on any web server. You should select it if your server doesn\'t run Apache, or
+ if you are at all unsure of your server\'s configuration. With this scheme, URLs at your site will look like
+ http://yoursite.com/path-to-enano/index.php/Main_Page.
+
The second option, Small URLs, will be selected by default if Enano detects Apache. Small URLs are more friendly towards
+ search engines, but they don\'t work on very many non-Apache servers, or if PHP is set up through CGI on your server. Many
+ free and low-cost web hosts will configure PHP through CGI in order to keep your user account as the owner of any files that
+ Enano generates. With this scheme, URLs at your site will look like http://yoursite.com/path-to-enano/index.php/Main_Page.
+
+
The last option, Tiny URLs, is the most friendly URL scheme for search engines, because your URLs won\'t have any special characters
+ at all in them. However, this only works if your webhost has configured Apache with support for mod_rewrite. Most of the time if your
+ host supports this you will see a listing for it in their feature matrix. None of the popular Linux distributions (such as Ubuntu,
+ Debian, Red Hat Enterprise Linux™, Fedora, openSUSE™, or CentOS) come with mod_rewrite enabled, so if you run a
+ home-brew server, you should consult your distribution\'s documentation for enabling mod_rewrite before selecting this option.
+ With this scheme, URLs at your site will look like http://yoursite.com/path-to-enano/Main_Page.
'."\n ";
+ ksort($mime_types);
foreach($mime_types as $e => $m)
{
$c++;
diff -r dc08c70ca550 -r e2cb5f1432c8 plugins/SpecialPageFuncs.php
--- a/plugins/SpecialPageFuncs.php Sun Dec 02 15:27:21 2007 -0500
+++ b/plugins/SpecialPageFuncs.php Sun Dec 02 16:00:10 2007 -0500
@@ -172,6 +172,7 @@
exit;
}
$template->header();
+ /*
if ( !$session->get_permissions('create_page') )
{
echo 'Wiki mode is disabled, only admins can create pages.';
@@ -181,6 +182,7 @@
exit;
}
+ */
echo RenderMan::render('Using the form below you can create a page.');
?>
';
@@ -133,10 +134,10 @@
foreach ( $results as $i => $_ )
{
$result =& $results[$i];
- $result['page_text'] = str_replace(array('', ''), array('', ''), $result['page_text']);
+ $result['page_text'] = str_replace(array('', ''), array('', ''), $result['page_text']);
if ( !empty($result['page_text']) )
$result['page_text'] .= ' ';
- $result['page_name'] = str_replace(array('', ''), array('', ''), $result['page_name']);
+ $result['page_name'] = str_replace(array('', ''), array('', ''), $result['page_name']);
if ( $result['page_length'] >= 1048576 )
{
$result['page_length'] = round($result['page_length'] / 1048576, 1);
diff -r dc08c70ca550 -r e2cb5f1432c8 plugins/SpecialUpdownload.php
--- a/plugins/SpecialUpdownload.php Sun Dec 02 15:27:21 2007 -0500
+++ b/plugins/SpecialUpdownload.php Sun Dec 02 16:00:10 2007 -0500
@@ -218,12 +218,25 @@
global $do_gzip;
$filename = rawurldecode($paths->getParam(0));
$timeid = $paths->getParam(1);
- if($timeid && preg_match('#^([0-9]+)$#', (string)$timeid)) $tid = ' AND time_id='.$timeid;
- else $tid = '';
+ if ( $timeid && preg_match('#^([0-9]+)$#', (string)$timeid) )
+ {
+ $tid = ' AND time_id='.$timeid;
+ }
+ else
+ {
+ $tid = '';
+ }
$filename = $db->escape($filename);
$q = $db->sql_query('SELECT page_id,size,mimetype,time_id,file_extension,file_key FROM '.table_prefix.'files WHERE filename=\''.$filename.'\''.$tid.' ORDER BY time_id DESC;');
- if(!$q) $db->_die('The file data could not be selected.');
- if($db->numrows() < 1) { header('HTTP/1.1 404 Not Found'); die_friendly('File not found', '
The file "'.$filename.'" cannot be found.
'); }
+ if ( !$q )
+ {
+ $db->_die('The file data could not be selected.');
+ }
+ if ( $db->numrows() < 1 )
+ {
+ header('HTTP/1.1 404 Not Found');
+ die_friendly('File not found', '
The file "'.$filename.'" cannot be found.
');
+ }
$row = $db->fetchrow();
$db->free_result();
diff -r dc08c70ca550 -r e2cb5f1432c8 plugins/SpecialUserFuncs.php
--- a/plugins/SpecialUserFuncs.php Sun Dec 02 15:27:21 2007 -0500
+++ b/plugins/SpecialUserFuncs.php Sun Dec 02 16:00:10 2007 -0500
@@ -525,7 +525,7 @@
if ( $_POST['use_crypt'] == 'yes' )
{
- $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE);
+ $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
$crypt_key = $session->fetch_public_key($_POST['crypt_key']);
if ( !$crypt_key )
{
@@ -1235,7 +1235,7 @@
if ( isset($_POST['do_stage2']) )
{
- $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE);
+ $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
if($_POST['use_crypt'] == 'yes')
{
$crypt_key = $session->fetch_public_key($_POST['crypt_key']);
diff -r dc08c70ca550 -r e2cb5f1432c8 plugins/SpecialUserPrefs.php
--- a/plugins/SpecialUserPrefs.php Sun Dec 02 15:27:21 2007 -0500
+++ b/plugins/SpecialUserPrefs.php Sun Dec 02 16:00:10 2007 -0500
@@ -25,7 +25,7 @@
function userprefs_menu_add($section, $text, $link)
{
global $userprefs_menu;
- if ( is_array($userprefs_menu[$section]) )
+ if ( isset($userprefs_menu[$section]) && is_array($userprefs_menu[$section]) )
{
$userprefs_menu[$section][] = Array(
'text' => $text,
@@ -133,7 +133,7 @@
$uid = intval($session->user_id);
// Instanciate the AES encryptor
- $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE);
+ $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
// Basic user info
$q = $db->sql_query('SELECT username, password, email, real_name, signature, theme, style FROM '.table_prefix.'users WHERE user_id='.$uid.';');
diff -r dc08c70ca550 -r e2cb5f1432c8 plugins/admin/UserManager.php
--- a/plugins/admin/UserManager.php Sun Dec 02 15:27:21 2007 -0500
+++ b/plugins/admin/UserManager.php Sun Dec 02 16:00:10 2007 -0500
@@ -68,7 +68,7 @@
$password = false;
if ( $_POST['changing_pw'] == 'yes' )
{
- $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE);
+ $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
$key_hex_md5 = $_POST['crypt_key'];
$key_hex = $session->fetch_public_key($key_hex_md5);
if ( $key_hex )
@@ -348,7 +348,7 @@
else
{
// Get the current session information so the user doesn't get logged out
- $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE);
+ $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
$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 )
@@ -544,21 +544,12 @@
* Constructor.
*/
- function __construct()
+ function Admin_UserManager_SmartForm()
{
$this->uuid = md5( mt_rand() . microtime() );
}
/**
- * PHP4 constructor.
- */
-
- function Admin_UserManager_SmartForm()
- {
- $this->__construct();
- }
-
- /**
* Renders and returns the finished form.
* @return string
*/
diff -r dc08c70ca550 -r e2cb5f1432c8 schema.sql
--- a/schema.sql Sun Dec 02 15:27:21 2007 -0500
+++ b/schema.sql Sun Dec 02 16:00:10 2007 -0500
@@ -49,7 +49,7 @@
) CHARACTER SET `utf8` COLLATE `utf8_bin`;
CREATE TABLE {{TABLE_PREFIX}}page_text(
- page_id varchar(63),
+ page_id varchar(255),
namespace varchar(16) NOT NULL default 'Article',
page_text text,
char_tag varchar(63),
@@ -58,8 +58,8 @@
CREATE TABLE {{TABLE_PREFIX}}pages(
page_order int(8),
- name varchar(127),
- urlname varchar(63),
+ name varchar(255),
+ urlname varchar(255),
namespace varchar(16) NOT NULL default 'Article',
special tinyint(1) default '0',
visible tinyint(1) default '1',
@@ -304,7 +304,7 @@
('copyright_notice', '{{COPYRIGHT}}'),
('wiki_edit_notice_text', '== Why can I edit this page? ==\n\nEveryone can edit almost any page in this website. This concept is called a wiki. It gives everyone the opportunity to make a change for the best. While some spam and vandalism may occur, it is believed that most contributions will be legitimate and helpful.\n\nFor security purposes, a history of all page edits is kept, and administrators are able to restore vandalized or spammed pages with just a few clicks.'),
('cache_thumbs', '{{ENABLE_CACHE}}'),
- ('max_file_size', '256000'),('enano_version', '{{VERSION}}'),( 'allowed_mime_types', 'cbf:len=168;crc=c3dcad3f;data=0[1],1[4],0[3],1[1],0[2],1[1],0[11],1[1],0[7],1[1],0[9],1[1],0[6],1[3],0[10],1[1],0[2],1[2],0[1],1[1],0[1],1[2],0[6],1[3],0[1],1[1],0[2],1[4],0[1],1[2],0[3],1[1],0[4],1[2],0[26],1[5],0[6],1[2],0[2],1[1],0[4],1[1],0[10],1[2],0[1],1[1],0[6]|end' ),
+ ('max_file_size', '256000'),('enano_version', '{{VERSION}}'),( 'allowed_mime_types', 'cbf:len=185;crc=55fb6f14;data=0[1],1[4],0[3],1[1],0[22],1[1],0[16],1[3],0[16],1[1],0[1],1[2],0[6],1[1],0[1],1[1],0[4],1[2],0[3],1[1],0[48],1[2],0[2],1[1],0[4],1[1],0[37]|end' ),
('contact_email', '{{ADMIN_EMAIL}}'),
('powered_btn', '1');
diff -r dc08c70ca550 -r e2cb5f1432c8 themes/oxygen/footer.tpl
--- a/themes/oxygen/footer.tpl Sun Dec 02 15:27:21 2007 -0500
+++ b/themes/oxygen/footer.tpl Sun Dec 02 16:00:10 2007 -0500
@@ -12,7 +12,7 @@
-->