--- a/includes/clientside/css/enano-shared.css Sun Aug 12 14:56:52 2007 -0400
+++ b/includes/clientside/css/enano-shared.css Tue Aug 14 15:13:40 2007 -0400
@@ -150,6 +150,8 @@
padding-right: 5px;
}
+div.breadcrumbs { margin: 10px 0; padding: 5px; border: 1px solid #AAAAAA; background-color: #E8E8E8; font-size: smaller; font-weight: bold; }
+
/* Tables */
.tblholder { margin: 10px 0 0 0; padding: 0; border: 1px solid #AAAAAA; background-color: #E8E8E8; }
--- a/includes/dbal.php Sun Aug 12 14:56:52 2007 -0400
+++ b/includes/dbal.php Tue Aug 14 15:13:40 2007 -0400
@@ -83,8 +83,17 @@
$bt = $this->latest_query; // $this->sql_backtrace();
$e = htmlspecialchars(mysql_error());
if($e=='') $e='<none>';
- if(defined('ENANO_CONFIG_FETCHED')) die_semicritical('Database error', '<h3>An error occurred during a database query.</h3><p>'.$t.'<br />Error returned by MySQL: '.$e.'<br />SQL Backtrace:</p><pre>'.$bt.'</pre>');
- else grinding_halt('Database error', '<h3>An error occurred during a database query.</h3><p>'.$t.'<br />Error returned by MySQL: '.$e.'<br />SQL Backtrace:</p><pre>'.$bt.'</pre>');
+ $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 = '<h3>The site was unable to finish serving your request.</h3>
+ <p>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 . '.</p>
+ <p>Description or location of error: '.$t.'<br />
+ Error returned by MySQL extension: ' . $e . '<br />
+ Most recent SQL query:</p>
+ <pre>'.$bt.'</pre>';
+ if(defined('ENANO_CONFIG_FETCHED')) die_semicritical('Database error', $internal_text);
+ else grinding_halt('Database error', $internal_text);
exit;
}
@@ -101,8 +110,15 @@
$bt = $this->sql_backtrace();
$e = htmlspecialchars(mysql_error());
if($e=='') $e='<none>';
- $text = '<h3>An error occurred during a database query.</h3><p>'.$t.'<br />Error returned by MySQL: '.$e.'<br />SQL Backtrace:</p><pre>'.$bt.'</pre>';
- return $text;
+ global $email;
+ $email_info = ( defined('ENANO_CONFIG_FETCHED') && is_object($email) ) ? ', at <' . $email->jscode() . $email->encryptEmail(getConfig('contact_email')) . '>' : '';
+ $internal_text = '<h3>The site was unable to finish serving your request.</h3>
+ <p>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 . '.</p>
+ <p>Description or location of error: '.$t.'<br />
+ Error returned by MySQL extension: ' . $e . '<br />
+ Most recent SQL query:</p>
+ <pre>'.$bt.'</pre>';
+ return $internal_text;
}
function connect() {
--- a/includes/functions.php Sun Aug 12 14:56:52 2007 -0400
+++ b/includes/functions.php Tue Aug 14 15:13:40 2007 -0400
@@ -71,6 +71,7 @@
global $db, $session, $paths, $template, $plugins; // Common objects
$flags = '';
$sep = urlSeparator;
+ $t = sanitize_page_id($t);
if ( isset($_GET['printable'] ) )
{
$flags .= $sep . 'printable=yes';
@@ -226,17 +227,24 @@
/**
* Tells you the title for the given page ID string
* @param string Page ID string (ex: Special:Administration)
+ * @param bool Optional. If true, and if the namespace turns out to be something other than Article, the namespace prefix will be prepended to the return value.
* @return string
*/
-function get_page_title($page_id)
+function get_page_title($page_id, $show_ns = true)
{
global $db, $session, $paths, $template, $plugins; // Common objects
$idata = RenderMan::strToPageID($page_id);
$page_id_key = $paths->nslist[ $idata[1] ] . $idata[0];
+ $page_id_key = sanitize_page_id($page_id_key);
$page_data = $paths->pages[$page_id_key];
- $title = ( isset($page_data['name']) ) ? ( $page_data['namespace'] == 'Article' ? '' : $paths->nslist[ $idata[1] ] ) . $page_data['name'] : $paths->nslist[$idata[1]] . str_replace('_', ' ', dirtify_page_id( $idata[0] ) );
+ $title = ( isset($page_data['name']) ) ?
+ ( ( $page_data['namespace'] == 'Article' || !$show_ns ) ?
+ '' :
+ $paths->nslist[ $idata[1] ] )
+ . $page_data['name'] :
+ ( $show_ns ? $paths->nslist[$idata[1]] : '' ) . str_replace('_', ' ', dirtify_page_id( $idata[0] ) );
return $title;
}
--- a/includes/pageprocess.php Sun Aug 12 14:56:52 2007 -0400
+++ b/includes/pageprocess.php Tue Aug 14 15:13:40 2007 -0400
@@ -212,7 +212,7 @@
return false;
}
}
- else if ( $this->namespace == 'User' )
+ else if ( $this->namespace == 'User' && strpos($this->page_id, '/') === false )
{
$this->_handle_userpage();
}
@@ -371,6 +371,8 @@
global $db, $session, $paths, $template, $plugins; // Common objects
$text = $this->fetch_text();
+ $text = preg_replace('/([\s]*)__NOBREADCRUMBS__([\s]*)/', '', $text);
+ $text = preg_replace('/([\s]*)__NOTOC__([\s]*)/', '', $text);
$redir_enabled = false;
if ( preg_match('/^#redirect \[\[([^\]]+?)\]\]/i', $text, $match ) )
@@ -418,6 +420,7 @@
$template->tpl_strings['PAGE_NAME'] = htmlspecialchars( $this->title );
$this->header();
+ $this->do_breadcrumbs();
if ( $_errormsg )
{
@@ -631,6 +634,8 @@
));
$target_username = preg_replace('/^' . preg_quote($paths->nslist['User']) . '/', '', $target_username);
+ $target_username = explode('/', $target_username);
+ $target_username = $target_username[0];
if ( ( $page_name == str_replace('_', ' ', $this->page_id) || $page_name == $paths->nslist['User'] . str_replace('_', ' ', $this->page_id) ) || !$this->page_exists )
{
@@ -1044,8 +1049,11 @@
{
global $db, $session, $paths, $template, $plugins; // Common objects
+ header('HTTP/1.1 404 Not Found');
+
$this->header();
- header('HTTP/1.1 404 Not Found');
+ $this->do_breadcrumbs();
+
if ( $userpage )
{
echo '<h3>There is no page with this title yet.</h3>
@@ -1078,6 +1086,10 @@
}
$db->free_result();
}
+ if ( $session->user_level >= USER_LEVEL_ADMIN )
+ {
+ echo '<p>Additional admin options: <a href="' . makeUrl($paths->page, 'do=detag', true) . '" title="Remove any tags on this page">detag page</a></p>';
+ }
echo '<p>
HTTP Error: 404 Not Found
</p>';
@@ -1085,6 +1097,58 @@
}
/**
+ * Echoes out breadcrumb data, if appropriate.
+ * @access private
+ */
+
+ function do_breadcrumbs()
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ if ( strpos($this->text_cache, '__NOBREADCRUMBS__') !== false )
+ return false;
+ $breadcrumb_data = explode('/', $this->page_id);
+ if ( count($breadcrumb_data) > 1 )
+ {
+ echo '<!-- Start breadcrumbs -->
+ <div class="breadcrumbs">
+ ';
+ foreach ( $breadcrumb_data as $i => $higherpage )
+ {
+ $higherpage = $paths->nslist[$this->namespace] . sanitize_page_id(implode('/', array_slice($breadcrumb_data, 0, ($i+1))));
+ if ( ($i + 1) == count($breadcrumb_data) )
+ {
+ $title = get_page_title($higherpage, false);
+ if ( !$this->page_exists )
+ {
+ $title = explode('/', $title);
+ $title = array_reverse($title);
+ $title = $title[0];
+ }
+ echo htmlspecialchars($title);
+ break;
+ }
+ else if ( isPage($higherpage) )
+ {
+ $title = get_page_title($higherpage, false);
+ echo '<a href="' . makeUrl($higherpage, false, true) . '">' . htmlspecialchars($title) . '</a>';
+ }
+ else
+ {
+ $title = get_page_title($higherpage, false);
+ $title = explode('/', $title);
+ $title = array_reverse($title);
+ $title = $title[0];
+ echo '<a href="' . makeUrl($higherpage, false, true) . '" class="wikilink-nonexistent">' . htmlspecialchars($title) . '</a>';
+ }
+ echo ' » ';
+ }
+ echo '</div>
+ <!-- End breadcrumbs -->
+ ';
+ }
+ }
+
+ /**
* PHP 4 constructor.
* @see PageProcessor::__construct()
*/
--- a/includes/render.php Sun Aug 12 14:56:52 2007 -0400
+++ b/includes/render.php Tue Aug 14 15:13:40 2007 -0400
@@ -408,7 +408,7 @@
function sanitize_html($text)
{
$text = htmlspecialchars($text);
- $allowed_tags = Array('b', 'i', 'u', 'pre', 'code', 'tt', 'br', 'p', 'nowiki', '!--([^.]+)--');
+ $allowed_tags = Array('b', 'i', 'u', 'pre', 'code', 'tt', 'br', 'p', 'nowiki', '!--([\w\W]+)--');
foreach($allowed_tags as $t)
{
$text = preg_replace('#<'.$t.'>(.*?)</'.$t.'>#is', '<'.$t.'>\\1</'.$t.'>', $text);
@@ -418,6 +418,52 @@
return $text;
}
+ /**
+ * Parses internal links (wikilinks) in a block of text.
+ * @param string Text to process
+ * @return string
+ */
+
+ function parse_internal_links($text)
+ {
+
+ // stage 1 - links with alternate text
+ preg_match_all('/\[\[([^\[\]<>\{\}\|]+)\|(.+?)\]\]/', $text, $matches);
+ foreach ( $matches[0] as $i => $match )
+ {
+ list($page_id, $namespace) = RenderMan::strToPageID($matches[1][$i]);
+ $pid_clean = $paths->nslist[$namespace] . sanitize_page_id($page_id);
+
+ $url = makeUrl($pid_clean, false, true);
+ $inner_text = $matches[2][$i];
+ $quot = '"';
+ $exists = ( isPage($pid_clean) ) ? '' : ' class="wikilink-nonexistent"';
+
+ $link = "<a href={$quot}{$url}{$quot}{$exists}>{$inner_text}</a>";
+
+ $text = str_replace($match, $link, $text);
+ }
+
+ // stage 2 - links with no alternate text
+ preg_match_all('/\[\[([^\[\]<>\{\}\|]+)\]\]/', $text, $matches);
+ foreach ( $matches[0] as $i => $match )
+ {
+ list($page_id, $namespace) = RenderMan::strToPageID($matches[1][$i]);
+ $pid_clean = $paths->nslist[$namespace] . sanitize_page_id($page_id);
+
+ $url = makeUrl($matches[1][$i], false, true);
+ $inner_text = htmlspecialchars(get_page_title($pid_clean));
+ $quot = '"';
+ $exists = ( isPage($pid_clean) ) ? '' : ' class="wikilink-nonexistent"';
+
+ $link = "<a href={$quot}{$url}{$quot}{$exists}>{$inner_text}</a>";
+
+ $text = str_replace($match, $link, $text);
+ }
+
+ return $text;
+ }
+
/* *
* Replaces template inclusions with the templates
* @param string $message The text to format
--- a/includes/template.php Sun Aug 12 14:56:52 2007 -0400
+++ b/includes/template.php Tue Aug 14 15:13:40 2007 -0400
@@ -732,7 +732,7 @@
'ADMIN_SID_AMP_HTML'=>$ash,
'ADMIN_SID_AUTO'=>$as2,
'ADDITIONAL_HEADERS'=>$this->additional_headers,
- 'COPYRIGHT'=>getConfig('copyright_notice'),
+ 'COPYRIGHT'=>RenderMan::parse_internal_links(getConfig('copyright_notice')),
'TOOLBAR_EXTRAS'=>$this->toolbar_menu,
'REQUEST_URI'=>$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'],
'STYLE_LINK'=>makeUrlNS('Special', 'CSS'.$p, null, true), //contentPath.$paths->nslist['Special'].'CSS' . $p,
@@ -1672,6 +1672,7 @@
global $db, $session, $paths, $template, $plugins; // Common objects
if(!$this->no_headers) {
global $_starttime;
+
$f = microtime(true);
$f = $f - $_starttime;
$f = round($f, 4);
@@ -1681,6 +1682,9 @@
$dbg = 'Time: '.$f.'s | Queries: '.$nq;
$t = $this->process_template('footer.tpl');
$t = str_replace('[[Stats]]', $dbg, $t);
+ $t = str_replace('[[NumQueries]]', (string)$db->num_queries, $t);
+ $t = str_replace('[[GenTime]]', (string)$f, $t);
+
echo $t;
}
else return '';
--- a/index.php Sun Aug 12 14:56:52 2007 -0400
+++ b/index.php Tue Aug 14 15:13:40 2007 -0400
@@ -359,6 +359,20 @@
echo PageUtils::pagediff($paths->cpage['urlname_nons'], $paths->namespace, $id1, $id2);
$template->footer();
break;
+ case 'detag':
+ if ( $session->user_level < USER_LEVEL_ADMIN )
+ {
+ die_friendly('Access denied', '<p>You need to be an administrator to detag pages.</p>');
+ }
+ if ( $paths->page_exists )
+ {
+ die_friendly('Invalid request', '<p>The detag action is only valid for pages that have been deleted in the past.</p>');
+ }
+ $q = $db->sql_query('DELETE FROM '.table_prefix.'tags WHERE page_id=\'' . $db->escape($paths->cpage['urlname_nons']) . '\' AND namespace=\'' . $paths->namespace . '\';');
+ if ( !$q )
+ $db->_die('Detag query, index.php:'.__LINE__);
+ die_friendly('Page detagged', '<p>All stale tags have been removed from this page.</p>');
+ break;
case 'aclmanager':
$data = ( isset($_POST['data']) ) ? $_POST['data'] : Array('mode' => 'listgroups');
PageUtils::aclmanager($data);
--- a/themes/oxygen/css/bleu.css Sun Aug 12 14:56:52 2007 -0400
+++ b/themes/oxygen/css/bleu.css Tue Aug 14 15:13:40 2007 -0400
@@ -28,7 +28,7 @@
.dbx-handle { cursor: move !important; }
/* The credits thingy at the bottom */
-div#credits { margin: 0; padding: 10px; padding-bottom: 0px; padding-top: 12px; background-color: #E8E8E8; color: #AAA; font-size: 7pt; }
+div#credits { margin: 0; padding: 10px; padding-bottom: 0px; padding-top: 12px; background-color: #E8E8E8; color: #AAA; font-size: 7pt; font-family: lucida grande, verdana, arial, sans-serif; }
div#credits a { color: #90B0D0; text-decoration: none; }
div#credits a:hover { color: #80A0C0; text-decoration: underline; }
--- a/themes/oxygen/css/mint.css Sun Aug 12 14:56:52 2007 -0400
+++ b/themes/oxygen/css/mint.css Tue Aug 14 15:13:40 2007 -0400
@@ -28,7 +28,7 @@
.dbx-handle { cursor: move !important; }
/* The credits thingy at the bottom */
-div#credits { margin: 0; padding: 10px; padding-bottom: 0px; padding-top: 12px; background-color: #E8E8E8; color: #AAA; font-size: 7pt; }
+div#credits { margin: 0; padding: 10px; padding-bottom: 0px; padding-top: 12px; background-color: #E8E8E8; color: #AAA; font-size: 7pt; font-family: lucida grande, verdana, arial, sans-serif; }
div#credits a { color: #90D0B0; text-decoration: none; }
div#credits a:hover { color: #80C0A0; text-decoration: underline; }
--- a/themes/oxygen/footer.tpl Sun Aug 12 14:56:52 2007 -0400
+++ b/themes/oxygen/footer.tpl Tue Aug 14 15:13:40 2007 -0400
@@ -11,8 +11,8 @@
-Dan
-->
<div id="credits">
- {COPYRIGHT}<br />
- Powered by <a href="<!-- BEGIN stupid_mode -->http://enanocms.org/<!-- BEGINELSE stupid_mode -->{URL_ABOUT_ENANO}<!-- END stupid_mode -->">Enano</a> | <a href="http://validator.w3.org/check?uri=referer">Valid XHTML 1.1</a> | <a href="http://jigsaw.w3.org/css-validator/validator?uri=referer">Valid CSS</a> | [[Stats]]
+ <b>{COPYRIGHT}</b><br />
+ Website engine powered by <a href="<!-- BEGIN stupid_mode -->http://enanocms.org/<!-- BEGINELSE stupid_mode -->{URL_ABOUT_ENANO}<!-- END stupid_mode -->">Enano</a> | <a href="http://validator.w3.org/check?uri=referer">Valid XHTML 1.1</a> | <a href="http://jigsaw.w3.org/css-validator/validator?uri=referer">Valid CSS</a> | Generated in [[GenTime]]sec
</div>
</td><td id="mdg-btr"></td></tr>
--- a/upgrade.php Sun Aug 12 14:56:52 2007 -0400
+++ b/upgrade.php Tue Aug 14 15:13:40 2007 -0400
@@ -493,6 +493,7 @@
<li>You have completely backed up your database (<b><?php echo "$dbhost:$dbname"; ?></b>)</li>
<li>You have backed up the entire Enano directory (<b><?php echo ENANO_ROOT; ?></b>)</li>
<li>You have reviewed the release notes for this version, and you<br />are comfortable with any known bugs or issues</li>
+ <li>If you've configured Enano to work using a MySQL user with restricted<br />privileges, you need to enable ALTER, CREATE TABLE, and CREATE INDEX privileges<br />for this upgrade to work.</li>
</ul>
</div>
<div style="text-align: center; margin-top: 10px;">