--- a/ajax.php Mon Sep 29 08:24:26 2008 -0400
+++ b/ajax.php Sun Nov 09 14:22:03 2008 -0500
@@ -469,6 +469,7 @@
break;
case "preview":
require_once(ENANO_ROOT.'/includes/pageutils.php');
+ $template->init_vars();
echo PageUtils::genPreview($_POST['text']);
break;
case "pagediff":
--- a/includes/clientside/static/editor.js Mon Sep 29 08:24:26 2008 -0400
+++ b/includes/clientside/static/editor.js Sun Nov 09 14:22:03 2008 -0500
@@ -162,7 +162,7 @@
}
// Draft notice
- if ( response.have_draft )
+ if ( response.have_draft && !readonly )
{
var dn = document.createElement('div');
dn.className = 'warning-box';
--- a/includes/clientside/static/login.js Mon Sep 29 08:24:26 2008 -0400
+++ b/includes/clientside/static/login.js Sun Nov 09 14:22:03 2008 -0500
@@ -72,6 +72,7 @@
var AJAX_STATUS_GENERATING_KEY = 2;
var AJAX_STATUS_LOGGING_IN = 3;
var AJAX_STATUS_SUCCESS = 4;
+var AJAX_STATUS_ERROR = 5;
var AJAX_STATUS_DESTROY = 65535;
/**
@@ -297,6 +298,53 @@
logindata.mb_inner.innerHTML = '';
logindata.mb_inner.appendChild(div);
+ break;
+
+ case AJAX_STATUS_ERROR:
+ // Create the status div
+ var div = document.createElement('div');
+ div.id = 'ajax_login_status';
+ div.style.marginTop = '10px';
+ div.style.textAlign = 'center';
+
+ // The circly ball ajaxy image + status message
+ var status_msg = $lang.get('user_login_ajax_err_crypto');
+
+ // Insert the status message
+ div.appendChild(document.createTextNode(status_msg));
+
+ // Append a br or two to space things properly
+ div.appendChild(document.createElement('br'));
+ div.appendChild(document.createElement('br'));
+
+ var img = document.createElement('img');
+ img.src = ( ajax_login_successimg_path ) ? ajax_login_successimg_path : scriptPath + '/images/checkbad.png';
+ div.appendChild(img);
+
+ // Append a br or two to space things properly
+ div.appendChild(document.createElement('br'));
+ div.appendChild(document.createElement('br'));
+
+ // The circly ball ajaxy image + status message
+ var detail_msg = $lang.get('user_login_ajax_err_crypto_details');
+ var full_link = $lang.get('user_login_ajax_err_crypto_link');
+ var link = document.createElement('a');
+ link.href = makeUrlNS('Special', 'Login/' + title);
+ link.appendChild(document.createTextNode(full_link));
+ var span = document.createElement('span');
+ span.style.fontSize = 'smaller';
+
+ // Insert the message
+ span.appendChild(document.createTextNode(detail_msg + ' '));
+ span.appendChild(link);
+ div.appendChild(span);
+
+ // Insert the entire message into the login window
+ logindata.mb_inner.innerHTML = '';
+ logindata.mb_inner.appendChild(div);
+
+ break;
+
case AJAX_STATUS_DESTROY:
case null:
case undefined:
@@ -588,6 +636,14 @@
lbl_dh.innerHTML = $lang.get('user_login_ajax_check_dh_ie');
form.appendChild(lbl_dh);
}
+ else if ( !data.allow_diffiehellman )
+ {
+ // create hidden control - server requested that DiffieHellman be disabled (usually means not supported)
+ var check_dh = document.createElement('input');
+ check_dh.type = 'hidden';
+ check_dh.id = 'ajax_login_field_dh';
+ form.appendChild(check_dh);
+ }
else
{
var lbl_dh = document.createElement('label');
@@ -744,6 +800,7 @@
return false;
}
}
+
if ( !username )
{
var username = document.getElementById('ajax_login_field_username').value;
@@ -757,6 +814,9 @@
var captcha = document.getElementById('ajax_login_field_captcha').value;
}
+ try
+ {
+
if ( do_dh )
{
ajaxLoginSetStatus(AJAX_STATUS_GENERATING_KEY);
@@ -836,6 +896,14 @@
remember: remember_session
}
}
+ }
+ catch(e)
+ {
+ ajaxLoginSetStatus(AJAX_STATUS_ERROR);
+ console.error('Exception caught in login process; backtrace follows');
+ console.debug(e);
+ return false;
+ }
ajaxLoginPerformRequest(json_packet);
}
--- a/includes/clientside/static/userpage.js Mon Sep 29 08:24:26 2008 -0400
+++ b/includes/clientside/static/userpage.js Sun Nov 09 14:22:03 2008 -0500
@@ -7,6 +7,9 @@
var wrapper = document.getElementById('userpage_wrap');
var links = document.getElementById('userpage_links');
+ if ( !wrapper )
+ return false;
+
wrapper.className = 'userpage_wrap';
links.className = 'userpage_links';
--- a/includes/common.php Mon Sep 29 08:24:26 2008 -0400
+++ b/includes/common.php Sun Nov 09 14:22:03 2008 -0500
@@ -170,6 +170,10 @@
global $timezone;
$timezone = 0;
+// DST settings
+global $dst_params;
+$dst_params = array(0, 0, 0, 0, 60);
+
// Divert to CLI loader if running from CLI
if ( isset($argc) && isset($argv) )
{
@@ -390,7 +394,7 @@
// One quick security check...
if ( !is_valid_ip($_SERVER['REMOTE_ADDR']) )
{
- die('SECURITY: spoofed IP address');
+ die('SECURITY: spoofed IP address: ' . htmlspecialchars($_SERVER['REMOTE_ADDR']));
}
// All checks passed! Start the main components up.
--- a/includes/constants.php Mon Sep 29 08:24:26 2008 -0400
+++ b/includes/constants.php Sun Nov 09 14:22:03 2008 -0500
@@ -92,6 +92,12 @@
define('TOKEN_PARENTHRIGHT', 4);
define('TOKEN_NOT', 5);
+// DST constants
+define('FIRST_SUNDAY', 1);
+define('SECOND_SUNDAY', 2);
+define('THIRD_SUNDAY', 3);
+define('LAST_SUNDAY', 4);
+
//
// User types - don't touch these
//
@@ -617,3 +623,12 @@
0xFE => "COM", 0x01 => "TEM", 0x02 => "RES",
);
+// DST profiles
+global $dst_profiles;
+$dst_profiles = array(
+ 'off' => '0;0;0;0;60',
+ 'usa' => '3;' . SECOND_SUNDAY . ';11;' . FIRST_SUNDAY . ';60',
+ 'europe' => '3;' . LAST_SUNDAY . ';10;' . LAST_SUNDAY . ';60',
+ 'australia' => '10;' . LAST_SUNDAY . ';3;' . LAST_SUNDAY . ';60',
+ 'tasmania' => '10;' . FIRST_SUNDAY . ';3;' . LAST_SUNDAY . ';60'
+ );
--- a/includes/functions.php Mon Sep 29 08:24:26 2008 -0400
+++ b/includes/functions.php Sun Nov 09 14:22:03 2008 -0500
@@ -271,31 +271,117 @@
if ( !is_int($timestamp) && !is_double($timestamp) && strval(intval($timestamp)) !== $timestamp )
$timestamp = time();
- /*
- // List of valid characters for date()
- $date_chars = 'dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZFcrU';
- // Split them into an array
- $date_chars = enano_str_split($date_chars);
- // Emulate date() formatting by replacing date characters with their
- // percentage-signed counterparts, but not escaped characters which
- // shouldn't be parsed.
- foreach ( $date_chars as $char )
- {
- $string = str_replace($char, "%$char", $string);
- $string = str_replace("\\%$char", $char, $string);
- }
- */
-
// perform timestamp offset
global $timezone;
// it's gonna be in minutes, so multiply by 60 to offset the unix timestamp
$timestamp = $timestamp + ( $timezone * 60 );
+ // are we in DST?
+ global $dst_params;
+ if ( check_timestamp_dst($timestamp, $dst_params[0], $dst_params[1], $dst_params[2], $dst_params[3]) )
+ {
+ // offset for DST
+ $timestamp += ( $dst_params[4] * 60 );
+ }
+
// Let PHP do the work for us =)
return gmdate($string, $timestamp);
}
/**
+ * Determine if a timestamp is within DST.
+ * @param int Timestamp
+ * @param int Start month (1-12) of DST
+ * @param int Which Sunday DST starts on (*_SUNDAY constants)
+ * @param int End month of DST
+ * @param int Which Sunday DST ends on
+ * @return bool
+ */
+
+function check_timestamp_dst($time, $start_month, $start_sunday, $end_month, $end_sunday)
+{
+ static $sundays = array(FIRST_SUNDAY, SECOND_SUNDAY, THIRD_SUNDAY, LAST_SUNDAY);
+
+ // perform timestamp offset
+ global $timezone;
+ // it's gonna be in minutes, so multiply by 60 to offset the unix timestamp
+ $time = $time + ( $timezone * 60 );
+ $year = intval(gmdate('Y', $time));
+
+ // one-pass validation
+ if ( !in_array($start_sunday, $sundays) || !in_array($end_sunday, $sundays) ||
+ $start_month < 1 || $start_month > 12 || $end_month < 1 || $end_month > 12 )
+ return false;
+
+ // get timestamp of the selected sunday (start)
+ $dst_start = get_sunday_timestamp($start_month, $start_sunday, $year);
+ $dst_end = get_sunday_timestamp($end_month, $end_sunday, $year);
+
+ if ( $dst_start > $dst_end )
+ {
+ // start time is past the end time, this means we're in the southern hemisphere
+ // as a result, if we're within the range, DST is NOT in progress.
+ return !( $time >= $dst_start && $time <= $dst_end );
+ }
+
+ return $time >= $dst_start && $time <= $dst_end;
+}
+
+/**
+ * Returns a timestamp for the given *_SUNDAY index.
+ * @param int Month
+ * @param int Which Sunday (FIRST, SECOND, THIRD, or LAST)
+ * @param int Year that we're doing our calculations in
+ * @return int
+ */
+
+function get_sunday_timestamp($month, $sunday, $year)
+{
+ $days_in_month = array(
+ 1 => 31,
+ 2 => $year % 4 == 0 && ( $year % 100 != 0 || ( $year % 100 == 0 && $year % 400 == 0 ) ) ? 29 : 28,
+ 3 => 31,
+ 4 => 30,
+ 5 => 31,
+ 6 => 30,
+ 7 => 31,
+ 8 => 31,
+ 9 => 30,
+ 10 => 31,
+ 11 => 30,
+ 12 => 31
+ );
+
+ $result = mktime(0, 0, 0, $month, 1, $year);
+
+ // hack. allows a specific day of the month to be set instead of a sunday. not a good place to do this.
+ if ( is_string($sunday) && substr($sunday, -1) === 'd' )
+ {
+ $result += 86400 * ( intval($sunday) - 1);
+ return $result;
+ }
+
+ $tick = 0;
+ $days_remaining = $days_in_month[$month];
+ while ( true )
+ {
+ if ( date('D', $result) == 'Sun' )
+ {
+ $tick++;
+ if ( ( $tick == 1 && $sunday == FIRST_SUNDAY ) ||
+ ( $tick == 2 && $sunday == SECOND_SUNDAY ) ||
+ ( $tick == 3 && $sunday == THIRD_SUNDAY ) ||
+ ( $sunday == LAST_SUNDAY && $days_remaining < 7 ) )
+ break;
+ }
+ $days_remaining--;
+ $result += 86400;
+ }
+
+ return $result;
+}
+
+/**
* 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.
@@ -2851,9 +2937,9 @@
function is_valid_ip($ip)
{
- // These came from phpBB3.
+ // This next one came from phpBB3.
$ipv4 = '(?:(?:\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])';
- $ipv6 = '(?:(?:(?:[\dA-F]{1,4}:){6}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\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])))|(?:::(?:[\dA-F]{1,4}:){5}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\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])))|(?:(?:[\dA-F]{1,4}:):(?:[\dA-F]{1,4}:){4}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\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])))|(?:(?:[\dA-F]{1,4}:){1,2}:(?:[\dA-F]{1,4}:){3}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\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])))|(?:(?:[\dA-F]{1,4}:){1,3}:(?:[\dA-F]{1,4}:){2}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\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])))|(?:(?:[\dA-F]{1,4}:){1,4}:(?:[\dA-F]{1,4}:)(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\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])))|(?:(?:[\dA-F]{1,4}:){1,5}:(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\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])))|(?:(?:[\dA-F]{1,4}:){1,6}:[\dA-F]{1,4})|(?:(?:[\dA-F]{1,4}:){1,7}:))';
+ $ipv6 = '(?:[a-f0-9]{0,4}):(?:[a-f0-9]{0,4}):(?:[a-f0-9]{0,4}:|:)?(?:[a-f0-9]{0,4}:|:)?(?:[a-f0-9]{0,4}:|:)?(?:[a-f0-9]{0,4}:|:)?(?:[a-f0-9]{0,4}:|:)?(?:[a-f0-9]{1,4})';
if ( preg_match("/^{$ipv4}$/", $ip) || preg_match("/^{$ipv6}$/", $ip) )
return true;
--- a/includes/render.php Mon Sep 29 08:24:26 2008 -0400
+++ b/includes/render.php Sun Nov 09 14:22:03 2008 -0500
@@ -145,6 +145,7 @@
$p = '<b>Notice:</b> RenderMan::getTemplate(): Parameter '.$m.' is not set';
}
$text = str_replace('(_'.$m.'_)', $p, $text);
+ $text = str_replace('{{' . ( $m + 1 ) . '}}', $p, $text);
}
$text = RenderMan::include_templates($text);
return $text;
@@ -252,7 +253,7 @@
$text = preg_replace('/<nodisplay>(.*?)<\/nodisplay>/is', '', $text);
}
- preg_match_all('/<lang code="([a-z0-9_]+)">([\w\W]+?)<\/lang>/', $text, $langmatch);
+ preg_match_all('/<lang code="([a-z0-9_-]+)">([\w\W]+?)<\/lang>/', $text, $langmatch);
foreach ( $langmatch[0] as $i => $match )
{
if ( $langmatch[1][$i] == $lang->lang_code )
@@ -271,6 +272,17 @@
eval($cmd);
}
+ //$template_regex = "/\{\{([^\]]+?)((\n([ ]*?)[A-z0-9]+([ ]*?)=([ ]*?)(.+?))*)\}\}/is";
+ $template_regex = "/\{\{(.+)((\n|\|[ ]*([A-z0-9]+)[ ]*=[ ]*(.+))*)\}\}/isU";
+ $i = 0;
+ while ( preg_match($template_regex, $text) )
+ {
+ $i++;
+ if ( $i == 5 )
+ break;
+ $text = RenderMan::include_templates($text);
+ }
+
if ( !$plaintext )
{
// Process images
@@ -287,17 +299,6 @@
}
}
- //$template_regex = "/\{\{([^\]]+?)((\n([ ]*?)[A-z0-9]+([ ]*?)=([ ]*?)(.+?))*)\}\}/is";
- $template_regex = "/\{\{(.+)((\n|\|[ ]*([A-z0-9]+)[ ]*=[ ]*(.+))*)\}\}/isU";
- $i = 0;
- while ( preg_match($template_regex, $text) )
- {
- $i++;
- if ( $i == 5 )
- break;
- $text = RenderMan::include_templates($text);
- }
-
// Before shipping it out to the renderer, replace spaces in between headings and paragraphs:
$text = preg_replace('/<\/(h[0-9]|div|p)>([\s]+)<(h[0-9]|div|p)( .+?)?>/i', '</\\1><\\3\\4>', $text);
@@ -495,9 +496,18 @@
foreach ( $matches[0] as $i => $match )
{
list($page_id, $namespace) = RenderMan::strToPageID($matches[1][$i]);
+ if ( ($pos = strrpos($page_id, '#')) !== false )
+ {
+ $hash = substr($page_id, $pos);
+ $page_id = substr($page_id, 0, $pos);
+ }
+ else
+ {
+ $hash = '';
+ }
$pid_clean = $paths->nslist[$namespace] . sanitize_page_id($page_id);
- $url = makeUrl($pid_clean, false, true);
+ $url = makeUrl($pid_clean, false, true) . $hash;
$inner_text = $matches[2][$i];
$quot = '"';
$exists = ( isPage($pid_clean) ) ? '' : ' class="wikilink-nonexistent"';
@@ -564,54 +574,43 @@
* [bar] => dolor sit amet
*/
- public static function parse_template_vars($input)
+ public static function parse_template_vars($input, $newlinemode = true)
{
- if ( !preg_match('/^(\|[ ]*([A-z0-9_]+)([ ]*)=([ ]*)(.+?))*$/is', trim($input)) )
+ $parms = array();
+ $input = trim($input);
+ if ( $newlinemode )
{
- $using_pipes = false;
- $input = explode("\n", trim( $input ));
+ $result = preg_match_all('/
+ (?:^|[\s]*)\|? # start of parameter - string start or series of spaces
+ [ ]*
+ (?:
+ ([A-z0-9_]+) # variable name
+ [ ]* = [ ]* # assignment
+ )? # this is optional - if the parameter name is not given, a numerical index is assigned
+ (.+) # value
+ /x', trim($input), $matches);
}
else
{
- $using_pipes = true;
- $input = substr($input, 1);
- $input = explode("|", trim( $input ));
- }
- $parms = Array();
- $current_line = '';
- $current_parm = '';
- foreach ( $input as $num => $line )
+ $result = preg_match_all('/
+ (?:^|[ ]*)\| # start of parameter - string start or series of spaces
+ [ ]*
+ (?:
+ ([A-z0-9_]+) # variable name
+ [ ]* = [ ]* # assignment
+ )? # name section is optional - if the parameter name is not given, a numerical index is assigned
+ ([^\|]+|.+?\n[ ]*\|) # value
+ /x', trim($input), $matches);
+ }
+ if ( $result )
{
- if ( preg_match('/^[ ]*([A-z0-9_]+)([ ]*)=([ ]*)(.+?)$/is', $line, $matches) )
+ $pi = 0;
+ for ( $i = 0; $i < count($matches[0]); $i++ )
{
- $parm =& $matches[1];
- $text =& $matches[4];
- if ( $parm == $current_parm )
- {
- $current_line .= $text;
- }
- else
- {
- // New parameter
- if ( $current_parm != '' )
- $parms[$current_parm] = $current_line;
- $current_line = $text;
- $current_parm = $parm;
- }
+ $matches[1][$i] = trim($matches[1][$i]);
+ $parmname = !empty($matches[1][$i]) ? $matches[1][$i] : strval(++$pi);
+ $parms[ $parmname ] = $matches[2][$i];
}
- else if ( $num == 0 )
- {
- // Syntax error
- return false;
- }
- else
- {
- $current_line .= "\n$line";
- }
- }
- if ( !empty($current_parm) && !empty($current_line) )
- {
- $parms[$current_parm] = $current_line;
}
return $parms;
}
@@ -624,8 +623,8 @@
* @example
* <code>
$text = '{{Template
- parm1 = Foo
- parm2 = Bar
+ | parm1 = Foo
+ | parm2 = Bar
}}';
$text = RenderMan::include_templates($text);
* </code>
@@ -635,17 +634,26 @@
{
global $db, $session, $paths, $template, $plugins; // Common objects
// $template_regex = "/\{\{([^\]]+?)((\n([ ]*?)[A-z0-9]+([ ]*?)=([ ]*?)(.+?))*)\}\}/is";
- $template_regex = "/\{\{(.+)(((\n|[ ]*\|)[ ]*([A-z0-9]+)[ ]*=[ ]*(.+))*)\}\}/isU";
+ // matches:
+ // 1 - template name
+ // 2 - parameter section
+ $template_regex = "/
+ \{\{ # opening
+ ([^\n\t\a\r]+) # template name
+ ((?:(?:[\s]+\|?)[ ]*(?:[A-z0-9_]+)[ ]*=[ ]*?(?:.+))*) # parameters
+ \}\} # closing
+ /isxU";
if ( $count = preg_match_all($template_regex, $text, $matches) )
{
//die('<pre>' . print_r($matches, true) . '</pre>');
for ( $i = 0; $i < $count; $i++ )
{
$matches[1][$i] = sanitize_page_id($matches[1][$i]);
+ $newlinemode = ( substr($matches[2][$i], 0, 1) == "\n" );
$parmsection = trim($matches[2][$i]);
if ( !empty($parmsection) )
{
- $parms = RenderMan::parse_template_vars($parmsection);
+ $parms = RenderMan::parse_template_vars($parmsection, $newlinemode);
if ( !is_array($parms) )
// Syntax error
$parms = array();
--- a/includes/sessions.php Mon Sep 29 08:24:26 2008 -0400
+++ b/includes/sessions.php Sun Nov 09 14:22:03 2008 -0500
@@ -473,7 +473,15 @@
}
}
$user = true;
+
+ // set timezone params
$GLOBALS['timezone'] = $userdata['user_timezone'];
+ $GLOBALS['dst_params'] = explode(';', $userdata['user_dst']);
+ foreach ( $GLOBALS['dst_params'] as &$parm )
+ {
+ if ( substr($parm, -1) != 'd' )
+ $parm = intval($parm);
+ }
// Set language
if ( !defined('ENANO_ALLOW_LOAD_NOLANG') )
@@ -1038,7 +1046,7 @@
// using a normal call to $db->sql_query to avoid failing on errors here
$query = $db->sql_query('SELECT u.user_id AS uid,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,' . "\n"
. ' u.reg_time,u.account_active,u.activation_key,u.user_lang,u.user_title,k.source_ip,k.time,k.auth_level,k.key_type,COUNT(p.message_id) AS num_pms,' . "\n"
- . ' u.user_timezone, x.* FROM '.table_prefix.'session_keys AS k' . "\n"
+ . ' u.user_timezone, u.user_dst, x.* FROM '.table_prefix.'session_keys AS k' . "\n"
. ' LEFT JOIN '.table_prefix.'users AS u' . "\n"
. ' ON ( u.user_id=k.user_id )' . "\n"
. ' LEFT JOIN '.table_prefix.'users_extra AS x' . "\n"
@@ -1051,7 +1059,7 @@
if ( !$query && ( defined('IN_ENANO_INSTALL') or defined('IN_ENANO_UPGRADE') ) )
{
- $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, 1440 AS user_timezone, ' . SK_SHORT . ' AS key_type FROM '.table_prefix.'session_keys AS k
+ $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, 1440 AS user_timezone, \'0;0;0;0;60\' AS user_dst, ' . SK_SHORT . ' AS key_type FROM '.table_prefix.'session_keys AS k
LEFT JOIN '.table_prefix.'users AS u
ON ( u.user_id=k.user_id )
LEFT JOIN '.table_prefix.'privmsgs AS p
@@ -2707,7 +2715,8 @@
if ( !$q )
$db->_die();
- $groups = array();
+ // The l10n engine takes care of this later.
+ $groups = array(1 => 'Everyone');
if ( $row = $db->fetchrow() )
{
@@ -2983,7 +2992,7 @@
{
if ( isset($perm2[$i]) )
{
- if ( $is_everyone && !$defaults_used[$i] )
+ if ( $is_everyone && isset($defaults_used[$i]) && $defaults_used[$i] === false )
continue;
// Decide precedence
if ( isset($defaults_used[$i]) )
@@ -3396,17 +3405,20 @@
global $db, $session, $paths, $template, $plugins; // Common objects
// Setup EnanoMath and Diffie-Hellman
- require_once(ENANO_ROOT.'/includes/math.php');
-
global $dh_supported;
- $dh_supported = true;
- try
+ if ( !function_exists('dh_gen_private') )
{
- require_once(ENANO_ROOT . '/includes/diffiehellman.php');
- }
- catch ( Exception $e )
- {
- $dh_supported = false;
+ require_once(ENANO_ROOT.'/includes/math.php');
+
+ $dh_supported = true;
+ try
+ {
+ require_once(ENANO_ROOT . '/includes/diffiehellman.php');
+ }
+ catch ( Exception $e )
+ {
+ $dh_supported = false;
+ }
}
global $_math;
--- a/includes/template.php Mon Sep 29 08:24:26 2008 -0400
+++ b/includes/template.php Sun Nov 09 14:22:03 2008 -0500
@@ -2051,84 +2051,59 @@
/**
* Fetches the contents of both sidebars.
- * @return array - key 0 is left, key 1 is right
+ * @return array - key 0 is left, key 1 is right, key 2 is the HTML that makes up an empty sidebar
* @example list($left, $right) = $template->fetch_sidebar();
*/
function fetch_sidebar()
{
global $db, $session, $paths, $template, $plugins; // Common objects
- global $cache;
+ // first, check the cache
+ if ( $result = $this->fetch_cached_sidebar() )
+ {
+ return $result;
+ }
+
+ profiler_log('Started sidebar parsing');
+
+ // init our block contents
$left = '';
$right = '';
+ $min = '';
- // check the cache
- if ( !$session->user_logged_in && $data = $cache->fetch('anon_sidebar') )
- {
- if ( @$data['_theme_'] === $this->theme )
- {
- unset($data['_theme_']);
- foreach ( $data as &$md )
- {
- $md = str_replace('$USERNAME$', $session->username, $md);
- $md = str_replace('$PAGEID$', $paths->page, $md);
- $md = str_replace('$MAIN_PAGE$', getConfig('main_page'), $md);
- }
- return $data;
- }
- }
-
+ // also might want the links block
if ( !$this->fetch_block('Links') )
$this->initLinksWidget();
- $q = $db->sql_query('SELECT item_id,sidebar_id,block_name,block_type,block_content FROM '.table_prefix.'sidebar' . "\n"
- . ' WHERE item_enabled=1 ORDER BY sidebar_id ASC, item_order ASC;');
- if(!$q) $db->_die('The sidebar text data could not be selected.');
-
+ // templates to work with
$vars = $this->extract_vars('elements.tpl');
- if(isset($vars['sidebar_top']))
+ // sidebar_top and sidebar_bottom are HTML that is prepended/appended to sidebar content. Themes can
+ // choose whether or not to display a sidebar depending on whether the sidebar is empty ( $left == $min )
+ // or not using the sidebar_left and sidebar_right template booleans (the oxygen theme does this).
+ if ( isset($vars['sidebar_top']) )
{
$top = $this->parse($vars['sidebar_top']);
$left .= $top;
$right .= $top;
+ $min .= $top;
}
- while($row = $db->fetchrow())
+ // grab the blocks from the DB
+ $q = $db->sql_query('SELECT item_id,sidebar_id,block_name,block_type,block_content FROM '.table_prefix.'sidebar' . "\n"
+ . ' WHERE item_enabled=1 ORDER BY sidebar_id ASC, item_order ASC;');
+ if ( !$q )
+ $db->_die('The sidebar text data could not be selected.');
+
+ // explicitly specify $q in case a plugin or PHP block makes a query
+ while ( $row = $db->fetchrow($q) )
{
- switch($row['block_type'])
- {
- case BLOCK_WIKIFORMAT:
- default:
- $parser = $this->makeParserText($vars['sidebar_section']);
- $c = RenderMan::render($row['block_content']);
- break;
- case BLOCK_TEMPLATEFORMAT:
- $parser = $this->makeParserText($vars['sidebar_section']);
- $c = $this->tplWikiFormat($row['block_content']);
- break;
- case BLOCK_HTML:
- $parser = $this->makeParserText($vars['sidebar_section_raw']);
- $c = $row['block_content'];
- break;
- case BLOCK_PHP:
- $parser = $this->makeParserText($vars['sidebar_section_raw']);
- ob_start();
- @eval($row['block_content']);
- $c = ob_get_contents();
- ob_end_clean();
- break;
- case BLOCK_PLUGIN:
- $parser = $this->makeParserText('{CONTENT}');
- $c = '<!-- PLUGIN -->' . (gettype($this->fetch_block($row['block_content'])) == 'string') ?
- $this->fetch_block($row['block_content']) :
- // This used to say "can't find plugin block" but I think it's more friendly to just silently hide it.
- '';
- break;
- }
+ // format the block
+ $block_content = $this->format_sidebar_block($row, $vars, $parser);
+
// is there a {restrict} or {hideif} block?
- if ( preg_match('/\{(restrict|hideif) ([a-z0-9_\(\)\|&! ]+)\}/', $c, $match) )
+ if ( preg_match('/\{(restrict|hideif) ([a-z0-9_\(\)\|&! ]+)\}/', $block_content, $match) )
{
// we have one, check the condition
$type =& $match[1];
@@ -2140,53 +2115,253 @@
continue;
}
// didn't get a match, so hide the conditional logic
- $c = str_replace_once($match[0], '', $c);
+ // FIXME: this needs to be verbose about syntax errors
+ $block_content = str_replace_once($match[0], '', $block_content);
}
- $parser->assign_vars(Array( 'TITLE'=>$this->tplWikiFormat($row['block_name']), 'CONTENT'=>$c ));
- $run = $parser->run();
+ // if we made it here, this block definitely needs to be displayed. send it to the
+ // parser (set by format_sidebar_block) and decide where to append it (but not in that order ;))
+ $appender = false;
+
+ if ( $row['sidebar_id'] == SIDEBAR_LEFT )
+ {
+ $appender =& $left;
+ }
+ else if ( $row['sidebar_id'] == SIDEBAR_RIGHT )
+ {
+ $appender =& $right;
+ }
+ else
+ {
+ // uhoh, block_id isn't valid. maybe a plugin wants to put this block somewhere else?
+ $code = $plugins->setHook('sidebar_block_id');
+ foreach ( $code as $cmd )
+ {
+ eval($cmd);
+ }
+ // if $appender wasn't set by a plugin, don't parse this block to save some CPU cycles
+ if ( !$appender )
+ {
+ continue;
+ }
+ }
+
+ // assign variables to parser
+ $block_name = $this->tplWikiFormat($row['block_name']);
+ $parser->assign_vars(array(
+ // be nice and format the title (FIXME, does this use a lot of CPU time? still needs l10n in some cases though)
+ 'TITLE' => $block_name,
+ 'CONTENT' => $block_content
+ ));
+ $parsed = $parser->run();
+
+ // plugins are parsed earlier due to the way disabled/missing plugins that add sidebar blocks are
+ // handled, so the {TITLE} var won't be replaced until now. this allows completely eliminating a
+ // block if it's not available
if ( $row['block_type'] == BLOCK_PLUGIN )
{
- $run = str_replace('{TITLE}', $this->tplWikiFormat($row['block_name']), $run);
+ $parsed = str_replace('{TITLE}', $block_name, $parsed);
}
- if ($row['sidebar_id'] == SIDEBAR_LEFT ) $left .= $run;
- elseif($row['sidebar_id'] == SIDEBAR_RIGHT) $right .= $run;
- unset($parser);
+
+ // done parsing - append and continue
+ $appender .= $parsed;
+
+ // we're done with this - unset it because it's a reference and we don't want it overwritten.
+ // also free the parser to get some RAM back
+ unset($appender, $parser);
}
- $db->free_result();
+
+ // lastly, append any footer HTML
if(isset($vars['sidebar_bottom']))
{
$bottom = $this->parse($vars['sidebar_bottom']);
$left .= $bottom;
$right .= $bottom;
+ $min .= $bottom;
}
- $min = '';
- if(isset($vars['sidebar_top']))
+
+ $return = array($left, $right, $min);
+
+ // allow any plugins to append what they want to the return
+ $code = $plugins->setHook('sidebar_fetch_return');
+ foreach ( $code as $cmd )
{
- $min .= $top;
+ eval($cmd);
}
- if(isset($vars['sidebar_bottom']))
- {
- $min .= $bottom;
- }
- $return = Array($left, $right, $min);
- if ( getConfig('cache_thumbs') == '1' && !$session->user_logged_in )
+
+ // cache the result if appropriate
+ $this->cache_compiled_sidebar($return);
+
+ profiler_log('Finished sidebar parsing');
+
+ return $return;
+ }
+
+ /**
+ * Runs the appropriate formatting routine on a sidebar row.
+ * @param array Row in sidebar table
+ * @param array Template variable set from elements.tpl
+ * @param null Pass by reference, will be filled with the parser according to the block's type (sidebar_section or sidebar_section_raw)
+ * @return string HTML + directives like {restrict} or {hideif}
+ */
+
+ function format_sidebar_block($row, $vars, &$parser)
+ {
+ // import globals in case a PHP block wants to call the Enano API
+ global $db, $session, $paths, $template, $plugins; // Common objects
+
+ $parser = null;
+
+ switch($row['block_type'])
{
- $cachestore = enano_json_encode($return);
- $cachestore = str_replace($session->username, '$USERNAME$', $cachestore);
- $cachestore = str_replace($paths->page, '$PAGEID$', $cachestore);
- $cachestore = str_replace('__STATICLINK__', $paths->page, $cachestore);
- $cachestore = str_replace('__MAINPAGELINK__', '$MAIN_PAGE$', $cachestore);
- $cachestore = enano_json_decode($cachestore);
- $cachestore['_theme_'] = $this->theme;
- $cache->store('anon_sidebar', $cachestore, 10);
-
- foreach ( $return as &$el )
+ case BLOCK_WIKIFORMAT:
+ $parser = $this->makeParserText($vars['sidebar_section']);
+ $c = RenderMan::render($row['block_content']);
+ break;
+
+ case BLOCK_TEMPLATEFORMAT:
+ $parser = $this->makeParserText($vars['sidebar_section']);
+ $c = $this->tplWikiFormat($row['block_content']);
+ break;
+
+ case BLOCK_HTML:
+ $parser = $this->makeParserText($vars['sidebar_section_raw']);
+ $c = $row['block_content'];
+ break;
+
+ case BLOCK_PHP:
+ // PHP blocks need to be sent directly to eval()
+ $parser = $this->makeParserText($vars['sidebar_section_raw']);
+ ob_start();
+ @eval($row['block_content']);
+ $c = ob_get_contents();
+ ob_end_clean();
+ break;
+
+ case BLOCK_PLUGIN:
+ $parser = $this->makeParserText('{CONTENT}');
+ $c = '<!-- PLUGIN -->' . (gettype($this->fetch_block($row['block_content'])) == 'string') ?
+ $this->fetch_block($row['block_content']) :
+ // This used to say "can't find plugin block" but I think it's more friendly to just silently hide it.
+ '';
+ break;
+ default:
+ // unknown block type - can a plugin handle it?
+ $code = $plugins->setHook('format_sidebar_block');
+ foreach ( $code as $cmd )
+ {
+ eval($cmd);
+ }
+ if ( !isset($c) )
+ {
+ // default to wiki formatting (this was going to be straight HTML but this is done for backwards compatibility reasons)
+ $c = RenderMan::render($row['block_content']);
+ }
+ if ( !$parser )
+ {
+ // no parser defined, use the "raw" section by default (plugins are more likely to want raw content
+ // rather than a list of links, and they can set the parser to use sidebar_section if they want)
+ $parser = $this->makeParserText($vars['sidebar_section_raw']);
+ }
+
+ break;
+ }
+
+ return $c;
+ }
+
+ /**
+ * Returns the list of things that should not be cached (sorry, I was listening to "The Thing That Should Not Be" by Metallica when I
+ * wrote this routine. You should get a copy of Master of Puppets, it's a damn good album.)
+ * @return array
+ */
+
+ function get_cache_replacements()
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+
+ return array(
+ '$LOGIN_LINK$' => $this->tpl_strings['LOGIN_LINK'],
+ '$MAIN_PAGE$' => $this->tpl_strings['MAIN_PAGE'],
+ '$USERNAME$' => $session->username
+ );
+ }
+
+ /**
+ * Attempts to load a cached compiled sidebar.
+ * @return array Same format as fetch_sidebar()
+ */
+
+ function fetch_cached_sidebar()
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ global $cache;
+
+ $cached = false;
+ if ( ($result = $cache->fetch('anon_sidebar')) && !$session->user_logged_in )
+ {
+ if ( isset($result[$this->theme]) )
{
- $el = str_replace('__STATICLINK__', $paths->page, $el);
+ $cached = $result[$this->theme];
}
}
- return $return;
+
+ // if we haven't been able to fetch yet, see if a plugin wants to give us something
+ if ( !$cached )
+ {
+ $code = $plugins->setHook('fetch_cached_sidebar');
+ foreach ( $code as $cmd )
+ {
+ eval($cmd);
+ }
+ }
+
+ if ( is_array($cached) )
+ {
+ // fetch certain variables that can't be stored in the cache and quickly substitute
+ $replace = $this->get_cache_replacements();
+ foreach ( $cached as &$val )
+ {
+ $val = strtr($val, $replace);
+ }
+
+ // done processing, send it back
+ return $cached;
+ }
+
+ return false;
+ }
+
+ /**
+ * Caches a completely compiled sidebar, if appropriate
+ * @param array Effectively, return from fetch_sidebar()
+ */
+
+ function cache_compiled_sidebar($sidebar)
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ global $cache;
+
+ // check if conditions are right
+ if ( !$session->user_logged_in && getConfig('cache_thumbs') === '1' )
+ {
+ // load any existing cache to make sure other themes' cached sidebars aren't discarded
+ $cached = ( $_ = $cache->fetch('anon_sidebar') ) ? $_ : array();
+
+ // replace variables
+ $replace = array_flip($this->get_cache_replacements());
+
+ foreach ( $sidebar as &$section )
+ {
+ $section = strtr($section, $replace);
+ }
+
+ // compile
+ $cached[$this->theme] = $sidebar;
+
+ // store
+ $cache->store('anon_sidebar', $cached, 15);
+ }
}
function initLinksWidget()
--- a/includes/wikiengine/Render/Xhtml/Wikilink.php Mon Sep 29 08:24:26 2008 -0400
+++ b/includes/wikiengine/Render/Xhtml/Wikilink.php Sun Nov 09 14:22:03 2008 -0500
@@ -56,6 +56,11 @@
function token($options)
{
+ ##
+ ## THIS IS NOT WHAT YOU ARE LOOKING FOR!!
+ ## All of this code is deprecated. Patch RenderMan::parse_internal_links() instead!
+ ##
+
global $session;
if ( $session->sid_super )
{
@@ -120,16 +125,8 @@
// the HREF. we support both the old form where
// the page always comes at the end, and the new
// form that uses %s for sprintf()
- $href = $this->getConf('view_url');
-
- if (strpos($href, '%s') === false) {
- // use the old form (page-at-end)
- $href = $href . $page . $anchor;
- } else {
- // use the new form (sprintf format string)
- $href = sprintf($href, $page . $anchor);
- }
-
+ $href = makeUrl($page, false, true);
+
// get the CSS class and generate output
$css = $this->formatConf(' class="%s"', 'css');
@@ -143,22 +140,13 @@
// the HREF. we support both the old form where
// the page always comes at the end, and the new
// form that uses %s for sprintf()
- $href = $this->getConf('view_url');
-
- if (strpos($href, '%s') === false) {
- // use the old form (page-at-end)
- $href = $href . $page . $anchor;
- } else {
- // use the new form (sprintf format string)
- $href = sprintf($href, $page . $anchor);
- }
+ $href = makeUrl($page, false, true);
// get the CSS class and generate output
$css = $this->formatConf(' class="%s"', 'css');
- $start = '<a'.$css.' href="'.$href.$as.'"'.$nobg.' class="wikilink-nonexistent">';
+ $start = '<a'.$css.' href="'.$href.'"'.$nobg.' class="wikilink-nonexistent">';
$end = '</a>';
-
}
if (!strlen($text)) {
$start .= $this->textEncode($options['page']);
--- a/install/schemas/mysql_stage2.sql Mon Sep 29 08:24:26 2008 -0400
+++ b/install/schemas/mysql_stage2.sql Sun Nov 09 14:22:03 2008 -0500
@@ -115,6 +115,7 @@
user_timezone int(12) UNSIGNED NOT NULL DEFAULT 0,
user_title varchar(64) DEFAULT NULL,
user_group mediumint(5) NOT NULL DEFAULT 1,
+ user_dst varchar(11) NOT NULL DEFAULT '0;0;0;0;60',
PRIMARY KEY (user_id)
) CHARACTER SET `utf8` COLLATE `utf8_bin`;
--- a/install/schemas/postgresql_stage2.sql Mon Sep 29 08:24:26 2008 -0400
+++ b/install/schemas/postgresql_stage2.sql Sun Nov 09 14:22:03 2008 -0500
@@ -115,6 +115,7 @@
user_timezone int NOT NULL DEFAULT 0,
user_title varchar(64) DEFAULT NULL,
user_group int NOT NULL DEFAULT 1,
+ user_dst varchar(11) NOT NULL DEFAULT '0;0;0;0;60',
CHECK (avatar_type IN ('jpg', 'png', 'gif', 'grv')),
PRIMARY KEY (user_id)
);
--- a/install/schemas/upgrade/1.1.4-1.1.5-mysql.sql Mon Sep 29 08:24:26 2008 -0400
+++ b/install/schemas/upgrade/1.1.4-1.1.5-mysql.sql Sun Nov 09 14:22:03 2008 -0500
@@ -1,2 +1,3 @@
ALTER TABLE {{TABLE_PREFIX}}session_keys ADD COLUMN key_type tinyint(1) NOT NULL DEFAULT 0;
UPDATE {{TABLE_PREFIX}}session_keys SET key_type = 2 WHERE auth_level > 2;
+ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_dst varchar(11) NOT NULL DEFAULT '0;0;0;0;60';
--- a/install/schemas/upgrade/1.1.4-1.1.5-postgresql.sql Mon Sep 29 08:24:26 2008 -0400
+++ b/install/schemas/upgrade/1.1.4-1.1.5-postgresql.sql Sun Nov 09 14:22:03 2008 -0500
@@ -1,3 +1,4 @@
ALTER TABLE {{TABLE_PREFIX}}session_keys ADD COLUMN key_type smallint NOT NULL DEFAULT 0;
UPDATE {{TABLE_PREFIX}}session_keys SET key_type = 2 WHERE auth_level > 2;
+ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_dst varchar(11) NOT NULL DEFAULT '0;0;0;0;60';
--- a/language/english/core.json Mon Sep 29 08:24:26 2008 -0400
+++ b/language/english/core.json Sun Nov 09 14:22:03 2008 -0500
@@ -692,7 +692,14 @@
title_13: '[UTC + 13] Tonga Time, Phoenix Islands Time',
title_14: '[UTC + 14] Line Island Time',
// This is a JSON string that lists all the timezones that are defined here.
- list: '{"n12":-12,"n11":-11,"n10":-10,"n9p5":-9.5,"n9":-9,"n8":-8,"n7":-7,"n6":-6,"n5":-5,"n4":-4,"n3p5":-3.5,"n3":-3,"n2":-2,"n1":-1,"0":0,"1":1,"2":2,"3":3,"3p5":3.5,"4":4,"4p5":4.5,"5":5,"5p5":5.5,"5p75":5.75,"6":6,"6p5":6.5,"7":7,"8":8,"8p75":8.75,"9":9,"9p5":9.5,"10":10,"10p5":10.5,"11":11,"11p5":11.5,"12":12,"12p75":12.75,"13":13,"14":14}'
+ list: '{"n12":-12,"n11":-11,"n10":-10,"n9p5":-9.5,"n9":-9,"n8":-8,"n7":-7,"n6":-6,"n5":-5,"n4":-4,"n3p5":-3.5,"n3":-3,"n2":-2,"n1":-1,"0":0,"1":1,"2":2,"3":3,"3p5":3.5,"4":4,"4p5":4.5,"5":5,"5p5":5.5,"5p75":5.75,"6":6,"6p5":6.5,"7":7,"8":8,"8p75":8.75,"9":9,"9p5":9.5,"10":10,"10p5":10.5,"11":11,"11p5":11.5,"12":12,"12p75":12.75,"13":13,"14":14}',
+
+ // DST profiles
+ dst_off: 'My region doesn\'t use DST',
+ dst_usa: 'United States: second Sunday of March to first Sunday of November',
+ dst_europe: 'Europe: last Sunday of March to last Sunday of October',
+ dst_australia: 'Australia (except Tasmania): last Sunday of October to last Sunday of March',
+ dst_tasmania: 'Tasmania: first Sunday of October to last Sunday of March'
},
etc: {
redirect_title: 'Redirecting...',
--- a/language/english/user.json Mon Sep 29 08:24:26 2008 -0400
+++ b/language/english/user.json Sun Nov 09 14:22:03 2008 -0500
@@ -75,6 +75,9 @@
login_ajax_check_dh_ie: 'Use a standards-compliant browser to help protect your password. <a href="http://docs.enanocms.org/Help:Appendix_B#dh" onclick="window.open(this.href); return false;">Learn more</a>',
login_ajax_check_remember: 'Keep me logged in on this computer for %session_length% %length_units% unless I log out',
login_ajax_check_remember_infinite: 'Keep me logged in on this computer until I log out',
+ login_ajax_err_crypto: 'Encryption failed.',
+ login_ajax_err_crypto_details: 'Details available on console.',
+ login_ajax_err_crypto_link: 'Use full login form',
err_login_generic_title: 'There was an error in the login process',
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.',
@@ -308,6 +311,7 @@
publicinfo_field_changetheme: 'Change my theme...',
publicinfo_field_timezone: 'Time zone:',
publicinfo_field_timezone_hint: 'Select the time zone you live in and when Daylight Savings Time occurs, if at all.',
+ publicinfo_field_dst: 'Daylight saving time:',
publicinfo_field_usertitle_title: 'User title:',
publicinfo_field_usertitle_hint: 'This can be some text that will be displayed underneath your username.',
publicinfo_th_im: 'Instant messenger contact information',
--- a/plugins/SpecialAdmin.php Mon Sep 29 08:24:26 2008 -0400
+++ b/plugins/SpecialAdmin.php Sun Nov 09 14:22:03 2008 -0500
@@ -44,8 +44,26 @@
));
}
+$plugins->attachHook('session_started', 'SpecialAdmin_theme_init();');
$plugins->attachHook('common_post', 'SpecialAdmin_include();');
+function SpecialAdmin_theme_init()
+{
+ global $db, $session, $paths, $template, $plugins; // Common objects
+
+ // Admin pages that were too enormous to be in this file were split off into the plugins/admin/ directory in 1.0.1.
+ // Only load these files if we're looking to load the admin panel
+ list($pid, $ns) = RenderMan::strToPageID($paths->get_pageid_from_url());
+ if ( $ns == 'Admin' || ( $pid == 'Administration' && $ns == 'Special' ) )
+ {
+ // Set the theme
+ $session->theme = 'admin';
+ $session->style = 'default';
+
+ $template->add_header('<script type="text/javascript" src="' . cdnPath . '/includes/clientside/static/admin-menu.js"></script>');
+ }
+}
+
function SpecialAdmin_include()
{
global $db, $session, $paths, $template, $plugins; // Common objects
@@ -66,12 +84,6 @@
require(ENANO_ROOT . '/plugins/admin/ThemeManager.php');
require(ENANO_ROOT . '/plugins/admin/PluginManager.php');
require(ENANO_ROOT . '/plugins/admin/CacheManager.php');
-
- // Set the theme
- $session->theme = 'admin';
- $session->style = 'default';
-
- $template->add_header('<script type="text/javascript" src="' . cdnPath . '/includes/clientside/static/admin-menu.js"></script>');
}
}
@@ -2093,7 +2105,7 @@
onclick: function()
{
var tigraentry = document.getElementById('i_div0_0').parentNode;
- var tigraobj = $(tigraentry);
+ var tigraobj = $dynano(tigraentry);
var div = document.createElement('div');
div.style.backgroundColor = '#FFFFFF';
domObjChangeOpac(70, div);
--- a/plugins/SpecialUserPrefs.php Mon Sep 29 08:24:26 2008 -0400
+++ b/plugins/SpecialUserPrefs.php Sun Nov 09 14:22:03 2008 -0500
@@ -652,6 +652,22 @@
<td class="row2"><?php echo $lang->get('usercp_publicinfo_field_timezone'); ?><br /><small><?php echo $lang->get('usercp_publicinfo_field_timezone_hint'); ?></small></td>
<td class="row1"><?php echo $tz_select; ?></td>
</tr>
+ <tr>
+ <td class="row2"><?php echo $lang->get('usercp_publicinfo_field_dst'); ?></td>
+ <td class="row1">
+ <select name="dst">
+ <?php
+ global $dst_profiles, $dst_params;
+ $user_dst = implode(';', $dst_params);
+ foreach ( $dst_profiles as $region => $data )
+ {
+ $selected = ( $data === $user_dst ) ? ' selected="selected"' : '';
+ echo '<option value="' . $data . '"' . $selected . '>' . $lang->get("tz_dst_$region") . '</option>';
+ }
+ ?>
+ </select>
+ </td>
+ </tr>
<?php
if ( $session->get_permissions('custom_user_title') ):
?>