# HG changeset patch # User Dan # Date 1188175533 14400 # Node ID a8891e108c95ba26d90d493550149af5b8ac215c # Parent d807dcd7aed74577e99bf46124174c427cdd557b Several major improvements: Memberlist page added (planned since about beta 2), page group support added for non-JS ACL editor (oops!), and attempting to view a page for which you lack read permissions will get you logged. diff -r d807dcd7aed7 -r a8891e108c95 includes/clientside/static/ajax.js --- a/includes/clientside/static/ajax.js Sun Aug 26 16:48:15 2007 -0400 +++ b/includes/clientside/static/ajax.js Sun Aug 26 20:45:33 2007 -0400 @@ -812,6 +812,28 @@ window.location = loc; } +function ajaxAdminUser(username) +{ + // IE <6 pseudo-compatibility + if ( KILL_SWITCH ) + return true; + if ( auth_level < USER_LEVEL_ADMIN ) + { + ajaxPromptAdminAuth(function(k) { + ENANO_SID = k; + auth_level = USER_LEVEL_ADMIN; + var loc = String(window.location + ''); + window.location = append_sid(loc); + var loc = makeUrlNS('Special', 'Administration', 'module=' + namespace_list['Admin'] + 'UserManager&src=get&user=' + ajaxEscape(username)); + if ( (ENANO_SID + ' ').length > 1 ) + window.location = loc; + }, 9); + return false; + } + var loc = makeUrlNS('Special', 'Administration', 'module=' + namespace_list['Admin'] + 'UserManager&src=get&user=' + ajaxEscape(username)); + window.location = loc; +} + function ajaxDisableEmbeddedPHP() { // IE <6 pseudo-compatibility diff -r d807dcd7aed7 -r a8891e108c95 includes/pageprocess.php --- a/includes/pageprocess.php Sun Aug 26 16:48:15 2007 -0400 +++ b/includes/pageprocess.php Sun Aug 26 20:45:33 2007 -0400 @@ -969,14 +969,39 @@ { global $db, $session, $paths, $template, $plugins; // Common objects + // Log it for crying out loud + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'illegal_page\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($session->username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', \'' . $db->escape(serialize(array($this->page_id, $this->namespace))) . '\')'); + $ob = ''; - $template->tpl_strings['PAGE_NAME'] = 'Access denied'; + //$template->tpl_strings['PAGE_NAME'] = 'Access denied'; + $template->tpl_strings['PAGE_NAME'] = htmlspecialchars( $this->title ); if ( $this->send_headers ) { $ob .= $template->getHeader(); } + if ( count($this->redirect_stack) > 0 ) + { + $stack = array_reverse($this->redirect_stack); + foreach ( $stack as $oldtarget ) + { + $url = makeUrlNS($oldtarget[1], $oldtarget[0], 'redirect=no', true); + $page_id_key = $paths->nslist[ $oldtarget[1] ] . $oldtarget[0]; + $page_data = $paths->pages[$page_id_key]; + $title = ( isset($page_data['name']) ) ? $page_data['name'] : $paths->nslist[$oldtarget[1]] . htmlspecialchars( str_replace('_', ' ', dirtify_page_id( $oldtarget[0] ) ) ); + $a = '' . $title . ''; + + $url = makeUrlNS($this->namespace, $this->page_id, 'redirect=no', true); + $page_id_key = $paths->nslist[ $this->namespace ] . $this->page_id; + $page_data = $paths->pages[$page_id_key]; + $title = ( isset($page_data['name']) ) ? $page_data['name'] : $paths->nslist[$this->namespace] . htmlspecialchars( str_replace('_', ' ', dirtify_page_id( $this->page_id ) ) ); + $b = '' . $title . ''; + + $ob .= '(Redirected to ' . $b . ' from ' . $a . ')
'; + } + } + $ob .= '
Access to this page is denied.
This may be because you are not logged in or you have not met certain criteria for viewing this page.
'; if ( $this->send_headers ) diff -r d807dcd7aed7 -r a8891e108c95 includes/pageutils.php --- a/includes/pageutils.php Sun Aug 26 16:48:15 2007 -0400 +++ b/includes/pageutils.php Sun Aug 26 20:45:33 2007 -0400 @@ -1943,11 +1943,25 @@ { echo ''; } + // page group selector + $groupsel = ''; + if ( count($response['page_groups']) > 0 ) + { + $groupsel = '

+

'; + } + echo '

' . $template->username_field('data[target_id_user]') . '

What should this access rule control?

+ ' . $groupsel . '

@@ -1999,7 +2013,7 @@ echo '

Create new rule

'; } $type = ( $response['target_type'] == ACL_TYPE_GROUP ) ? 'group' : 'user'; - $scope = ( $response['page_id'] ) ? 'this page' : 'this entire site'; + $scope = ( $response['page_id'] ) ? ( $response['namespace'] == '__PageGroup' ? 'this group of pages' : 'this page' ) : 'this entire site'; echo 'This panel allows you to edit what the '.$type.' "'.$response['target_name'].'" can do on '.$scope.'. Unless you set a permission to "Deny", these permissions may be overridden by other rules.'; echo $formstart; $parser = $template->makeParserText( $response['template']['acl_field_begin'] ); @@ -2047,7 +2061,7 @@ -    + ' . ( ( $response['type'] == 'edit' ) ? '  ' : '' ) . '
'; echo $formend; break; @@ -2097,6 +2111,11 @@ $parms['page_id'] = false; $parms['namespace'] = false; } + else if ( $parms['scope'] == 'page_group' ) + { + $parms['page_id'] = $parms['pg_id']; + $parms['namespace'] = '__PageGroup'; + } break; } diff -r d807dcd7aed7 -r a8891e108c95 index.php --- a/index.php Sun Aug 26 16:48:15 2007 -0400 +++ b/index.php Sun Aug 26 20:45:33 2007 -0400 @@ -15,7 +15,7 @@ // Set up gzip encoding before any output is sent - $aggressive_optimize_html = false; + $aggressive_optimize_html = true; global $do_gzip; $do_gzip = true; diff -r d807dcd7aed7 -r a8891e108c95 plugins/SpecialAdmin.php --- a/plugins/SpecialAdmin.php Sun Aug 26 16:48:15 2007 -0400 +++ b/plugins/SpecialAdmin.php Sun Aug 26 20:45:33 2007 -0400 @@ -128,10 +128,19 @@ $q = $db->sql_query($l); while($r = $db->fetchrow()) { + if ( $r['action'] == 'illegal_page' ) + { + list($illegal_id, $illegal_ns) = unserialize($r['page_text']); + $url = makeUrlNS($illegal_ns, $illegal_id, false, true); + $title = get_page_title_ns($illegal_id, $illegal_ns); + $class = ( isPage($paths->nslist[$illegal_ns] . $illegal_id) ) ? '' : ' class="wikilink-nonexistent"'; + $illegal_link = '' . $title . ''; + } if($cls == 'row2') $cls = 'row1'; else $cls = 'row2'; echo ''; - switch($r['action']) { + switch($r['action']) + { case "admin_auth_good": echo 'Successful elevated authentication'; if ( !empty($r['page_text']) ) { $level = $session->userlevel_to_string( intval($r['page_text']) ); echo "
Authentication level: $level"; } break; case "admin_auth_bad": echo 'Failed elevated authentication'; if ( !empty($r['page_text']) ) { $level = $session->userlevel_to_string( intval($r['page_text']) ); echo "
Attempted auth level: $level"; } break; case "activ_good": echo 'Successful account activation'; break; @@ -142,6 +151,7 @@ case "db_backup": echo 'Database backup created
Tables: ' . $r['page_text'] . ''; break; case "install_enano": echo "Installed Enano version {$r['page_text']}"; break; case "upgrade_enano": echo "Upgraded Enano to version {$r['page_text']}"; break; + case "illegal_page": echo "Unauthorized viewing attempt
Page: {$illegal_link}"; break; } echo ''.date('d M Y h:i a', $r['time_id']).''.$r['author'].''.$r['edit_summary'].''; } @@ -790,6 +800,12 @@ return; } + if ( isset($_GET['src']) && $_GET['src'] == 'get' && !empty($_GET['user']) ) + { + $_POST['go'] = true; + $_POST['username'] = $_GET['user']; + } + if(isset($_POST['go'])) { // We need the user ID before we can do anything @@ -2312,7 +2328,7 @@ @set_time_limit(300); // five minutes // Do the actual export $aesext = ( defined('SQL_BACKUP_CRYPT') ) ? '.tea' : ''; - $filename = 'enano_backup_' . date('dmy') . '.sql' . $aesext; + $filename = 'enano_backup_' . date('ymd') . '.sql' . $aesext; ob_start(); header('Content-disposition: attachment, filename="'.$filename.'";'); header('Content-type: application/transact-sql'); @@ -2342,6 +2358,7 @@ } foreach($tables as $t) { + // THE FOLLOWING COMMENT DOES NOT APPLY AS OF 1.0. // Sorry folks - this script CAN'T backup enano_files, enano_search_index, and enano_search_cache due to the sheer size of the tables. // If encryption is enabled the log data will be excluded too. echo export_table( diff -r d807dcd7aed7 -r a8891e108c95 plugins/SpecialUserFuncs.php --- a/plugins/SpecialUserFuncs.php Sun Aug 26 16:48:15 2007 -0400 +++ b/plugins/SpecialUserFuncs.php Sun Aug 26 20:45:33 2007 -0400 @@ -83,6 +83,13 @@ \'namespace\'=>\'Special\', \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\', )); + + $paths->add_page(Array( + \'name\'=>\'Member list\', + \'urlname\'=>\'Memberlist\', + \'namespace\'=>\'Special\', + \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\', + )); '); // function names are IMPORTANT!!! The name pattern is: page__ @@ -1066,4 +1073,185 @@ $template->footer(); } +function page_Special_Memberlist() +{ + global $db, $session, $paths, $template, $plugins; // Common objects + $template->header(); + + $startletters = 'abcdefghijklmnopqrstuvwxyz'; + $startletters = enano_str_split($startletters); + $startletter = ( isset($_GET['letter']) ) ? strtolower($_GET['letter']) : ''; + if ( !in_array($startletter, $startletters) && $startletter != 'chr' ) + { + $startletter = ''; + } + + $startletter_sql = $startletter; + if ( $startletter == 'chr' ) + { + $startletter_sql = '([^a-z])'; + } + + // determine number of rows + $q = $db->sql_query('SELECT u.user_id FROM '.table_prefix.'users AS u WHERE u.username REGEXP "^' . $startletter_sql . '" AND u.username != "Anonymous";'); + if ( !$q ) + $db->_die(); + + $num_rows = $db->numrows(); + $db->free_result(); + + // offset + $offset = ( isset($_GET['offset']) && strval(intval($_GET['offset'])) === $_GET['offset']) ? intval($_GET['offset']) : 0; + + // sort order + $sortkeys = array( + 'uid' => 'u.user_id', + 'username' => 'u.username', + 'email' => 'u.email' + ); + + $sortby = ( isset($_GET['sort']) && isset($sortkeys[$_GET['sort']]) ) ? $_GET['sort'] : 'username'; + $sort_sqllet = $sortkeys[$sortby]; + + $target_order = ( isset($_GET['orderby']) && in_array($_GET['orderby'], array('ASC', 'DESC')) )? $_GET['orderby'] : 'ASC'; + + $sortorders = array(); + foreach ( $sortkeys as $k => $_unused ) + { + $sortorders[$k] = ( $sortby == $k ) ? ( $target_order == 'ASC' ? 'DESC' : 'ASC' ) : 'ASC'; + } + + // Why 3.3714%? 100 percent / 28 cells, minus a little (0.2% / cell) to account for cell spacing + + echo '
+ + '; + echo ''; + echo ''; + foreach ( $startletters as $letter ) + { + echo ''; + } + echo ' +
All#' . strtoupper($letter) . '
+
'; + + // formatter parameters + $formatter = new MemberlistFormatter(); + $formatters = array( + 'username' => array($formatter, 'username'), + 'user_level' => array($formatter, 'user_level'), + 'email' => array($formatter, 'email') + ); + + // Column markers + $headings = ' + + # + + + Username + + + E-mail + + '; + + $q = $db->sql_unbuffered_query('SELECT u.user_id, u.username, u.reg_time, u.email, u.user_level, x.email_public FROM '.table_prefix.'users AS u + LEFT JOIN '.table_prefix.'users_extra AS x + ON ( u.user_id = x.user_id ) + WHERE u.username REGEXP "^' . $startletter_sql . '" AND u.username != "Anonymous" + ORDER BY ' . $sort_sqllet . ' ' . $target_order . ';'); + if ( !$q ) + $db->_die(); + + $html = paginate( + $q, // MySQL result resource + ' + {user_id} + {username}
{user_level} + {email} + + ', // TPL code for rows + $num_rows, // Number of results + makeUrlNS('Special', 'Memberlist', 'letter=' . $startletter . '&offset=%s&sort=' . $sortby . '&orderby=' . $target_order ), // Result URL + $offset, // Start at this number + 25, // Results per page + $formatters, // Formatting hooks + '
+ + ' . $headings . ' + ', // Header (printed before rows) + ' ' . $headings . ' +
+
+ ' // Footer (printed after rows) + ); + + if ( $num_rows < 1 ) + { + echo '

Sorry - no users with usernames that start with that letter could be found.

'; + } + else + { + echo $html; + } + + $template->footer(); +} + +/** + * Class for formatting results for the memberlist. + * @access private + */ + +class MemberlistFormatter +{ + function username($username, $row) + { + global $db, $session, $paths, $template, $plugins; // Common objects + $userpage = $paths->nslist['User'] . sanitize_page_id($username); + $class = ( isPage($userpage) ) ? ' title="Click to view this user\'s userpage"' : ' class="wikilink-nonexistent" title="This user hasn\'t created a userpage yet, but you can still view profile details by clicking this link."'; + $anchor = '' . htmlspecialchars($username) . ''; + if ( $session->user_level >= USER_LEVEL_ADMIN ) + { + $anchor .= ' - Administer user'; + } + return $anchor; + } + function user_level($level, $row) + { + global $db, $session, $paths, $template, $plugins; // Common objects + switch ( $level ) + { + case USER_LEVEL_GUEST: + $s_level = 'Guest'; break; + case USER_LEVEL_MEMBER: + case USER_LEVEL_CHPREF: + $s_level = 'Member'; break; + case USER_LEVEL_MOD: + $s_level = 'Moderator'; break; + case USER_LEVEL_ADMIN: + $s_level = 'Site administrator'; break; + default: + $s_level = 'Unknown (level ' . $level . ')'; + } + return $s_level; + } + function email($addy, $row) + { + if ( $row['email_public'] == '1' ) + { + global $email; + $addy = $email->encryptEmail($addy); + return $addy; + } + else + { + return '<Non-public>'; + } + } +} + ?> \ No newline at end of file diff -r d807dcd7aed7 -r a8891e108c95 plugins/SpecialUserPrefs.php --- a/plugins/SpecialUserPrefs.php Sun Aug 26 16:48:15 2007 -0400 +++ b/plugins/SpecialUserPrefs.php Sun Aug 26 20:45:33 2007 -0400 @@ -41,6 +41,28 @@ } } +$plugins->attachHook('compile_template', 'userprefs_jbox_setup($button, $tb, $menubtn);'); + +function userprefs_jbox_setup(&$button, &$tb, &$menubtn) +{ + global $db, $session, $paths, $template, $plugins; // Common objects + + if ( $paths->namespace != 'Special' || $paths->cpage['urlname_nons'] != 'Preferences' ) + return false; + + $tb .= ""; + $template->toolbar_menu = ''; + + $button->assign_vars(array( + 'TEXT' => 'list of registered members', + 'FLAGS' => '', + 'PARENTFLAGS' => '', + 'HREF' => makeUrlNS('Special', 'Memberlist') + )); + + $tb .= $button->run(); +} + function userprefs_menu_html() { global $userprefs_menu; diff -r d807dcd7aed7 -r a8891e108c95 themes/oxygen/css/bleu.css --- a/themes/oxygen/css/bleu.css Sun Aug 26 16:48:15 2007 -0400 +++ b/themes/oxygen/css/bleu.css Sun Aug 26 20:45:33 2007 -0400 @@ -71,6 +71,16 @@ div.tblholder th.subhead { padding: 4px; background-color: #90A0B0; font-weight: bold; text-align: center; color: #FFFFFF; } div.tblholder table { background-color: #FFFFFF; width: 100%; } +div.tblholder th a { + color: #FFFFFF !important; + text-decoration: underline !important; +} + +div.tblholder th a:hover { + color: #FFFF00 !important; + text-decoration: underline !important; +} + /* The "page tools" bar below the site logo but above the page content div.pagebar { background-color: #B0D0F0; margin-top: 0px; padding: 3px; font-size: 7pt; } div.pagebar a { cursor: pointer; padding: 3px; margin-left: 3px; margin-right: 3px; text-decoration: none; color: #406080; } @@ -222,6 +232,7 @@ input[type ^="button"], input[type ^="submit"] { background-image: url(../images/buttonbg.gif); background-repeat: repeat-x; + color: #202020; } /* JWS window theming */