# HG changeset patch # User Dan # Date 1198279280 18000 # Node ID 0437a7cf1accbca35ae3483a822f8215ed7b1661 # Parent dc838fd61a06b0f078dc2990924a23d99c30058c Added update-checking function (still a little rough around the edges); added support into admin user CP for changing avatars diff -r dc838fd61a06 -r 0437a7cf1acc files/avatars/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/files/avatars/.htaccess Fri Dec 21 18:21:20 2007 -0500 @@ -0,0 +1,1 @@ +Allow from all diff -r dc838fd61a06 -r 0437a7cf1acc includes/clientside/css/enano-shared.css --- a/includes/clientside/css/enano-shared.css Thu Dec 20 22:23:07 2007 -0500 +++ b/includes/clientside/css/enano-shared.css Fri Dec 21 18:21:20 2007 -0500 @@ -163,6 +163,14 @@ 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%; } +/* Colored table cells */ +div.tblholder td.row1_red { padding: 4px; background-color: #F8E0E0; } +div.tblholder td.row2_red { padding: 4px; background-color: #FFF0F0; } +div.tblholder td.row3_red { padding: 4px; background-color: #FFE8E8; } +div.tblholder td.row1_green { padding: 4px; background-color: #E0F8E0; } +div.tblholder td.row2_green { padding: 4px; background-color: #F0FFF0; } +div.tblholder td.row3_green { padding: 4px; background-color: #E8FFE8; } + /* Well, not Midget and not comments (usually), but that's what the class is called ;-). Basically an informational window or used as a wrapper for tables. */ .mdg-comment, .mdg-infobox { margin-left: 1em; padding: 7px; border: 1px solid #AAAAAA; background-color: #E8E8E8; } diff -r dc838fd61a06 -r 0437a7cf1acc includes/clientside/static/ajax.js --- a/includes/clientside/static/ajax.js Thu Dec 20 22:23:07 2007 -0500 +++ b/includes/clientside/static/ajax.js Fri Dec 21 18:21:20 2007 -0500 @@ -1289,3 +1289,179 @@ body.appendChild(mydiv); } +function ajaxUpdateCheck(targetelement) +{ + if ( !document.getElementById(targetelement) ) + { + return false; + } + var target = document.getElementById(targetelement); + target.innerHTML = ''; + var img = document.createElement('img'); + img.src = scriptPath + '/images/loading.gif'; + img.alt = 'Loading...'; + target.appendChild(img); + ajaxGet(makeUrlNS('Admin', 'Home/updates.xml'), function() + { + if ( ajax.readyState == 4 ) + { + var releases = new Array(); + var update_available = false; + if ( ajax.responseXML == null ) + { + alert("Error fetching updates list:\n" + ajax.responseText); + return false; + } + if ( ajax.responseXML.firstChild.tagName == 'enano' ) + { + var enanotag = ajax.responseXML.firstChild; + for ( var i in enanotag.childNodes ) + { + if ( enanotag.childNodes[i].tagName == 'error' ) + { + alert(enanotag.childNodes[i].firstChild.nodeValue); + } + else if ( enanotag.childNodes[i].tagName == 'latest' ) + { + // got + var latesttag = enanotag.childNodes[i]; + for ( var i in latesttag.childNodes ) + { + var node = latesttag.childNodes[i]; + if ( node.tagName == 'release' ) + { + var releasedata = new Object(); + for ( var i in node.attributes ) + { + releasedata[node.attributes[i].nodeName] = node.attributes[i].nodeValue; + } + releases.push(releasedata); + } + else if ( node.tagName == 'haveupdates' ) + { + update_available = true; + } + } + break; + } + } + } + else + { + if ( window.console ) + window.console.error('Invalid XML response'); + return false; + } + var thediv = document.getElementById(targetelement); + thediv.innerHTML = ''; + if ( !thediv ) + { + if ( window.console ) + window.console.error('Can\'t get the div'); + return false; + } + if ( releases.length > 0 ) + { + thediv.className = 'tblholder'; + if ( update_available ) + { + var infobox = document.createElement('div'); + infobox.className = 'info-box-mini'; + infobox.appendChild(document.createTextNode('An update for Enano is available.')); + infobox.style.borderWidth = '0'; + infobox.style.margin = '0 0 0 0'; + thediv.appendChild(infobox); + } + else + { + var infobox = document.createElement('div'); + infobox.className = 'info-box-mini'; + infobox.appendChild(document.createTextNode('No new updates are available.')); + infobox.style.borderWidth = '0'; + infobox.style.margin = '0 0 0 0'; + thediv.appendChild(infobox); + } + var table = document.createElement('table'); + table.border = '0'; + table.cellspacing = '1'; + table.cellpadding = '4'; + + var tr = document.createElement('tr'); + + var td1 = document.createElement('th'); + var td2 = document.createElement('th'); + var td3 = document.createElement('th'); + var td4 = document.createElement('th'); + + td1.appendChild( document.createTextNode('Release type') ); + td2.appendChild( document.createTextNode('Version') ); + td3.appendChild( document.createTextNode('Code name') ); + td4.appendChild( document.createTextNode('Release notes') ); + + tr.appendChild(td1); + tr.appendChild(td2); + tr.appendChild(td3); + tr.appendChild(td4); + + table.appendChild(tr); + + var cls = 'row2'; + + var j = 0; + for ( var i in releases ) + { + j++; + if ( j > 5 ) + break; + if ( update_available && j == 1 ) + cls = 'row1_green'; + else + cls = ( cls == 'row1' ) ? 'row2' : 'row1'; + var release = releases[i]; + var tr = document.createElement('tr'); + window.console.debug(release); + + var td1 = document.createElement('td'); + var td2 = document.createElement('td'); + var td3 = document.createElement('td'); + var td4 = document.createElement('td'); + + td1.className = cls; + td2.className = cls; + td3.className = cls; + td4.className = cls; + + if ( release.tag ) + td1.appendChild( document.createTextNode(release.tag) ); + + if ( release.version ) + td2.appendChild( document.createTextNode(release.version) ); + + if ( release.codename ) + td3.appendChild( document.createTextNode(release.codename) ); + + if ( release.relnotes ) + { + var a = document.createElement('a'); + a.href = release.relnotes; + a.appendChild(document.createTextNode('View')); + td4.appendChild( a ); + } + + tr.appendChild(td1); + tr.appendChild(td2); + tr.appendChild(td3); + tr.appendChild(td4); + + table.appendChild(tr); + } + thediv.appendChild(table); + } + else + { + thediv.appendChild(document.createTextNode('No releases available.')); + } + } + }); +} + diff -r dc838fd61a06 -r 0437a7cf1acc includes/pageprocess.php --- a/includes/pageprocess.php Thu Dec 20 22:23:07 2007 -0500 +++ b/includes/pageprocess.php Fri Dec 21 18:21:20 2007 -0500 @@ -169,6 +169,15 @@ } $pathskey = $paths->nslist[ $this->namespace ] . $this->page_id; $strict_no_headers = false; + if ( $this->namespace == 'Admin' && strstr($this->page_id, '/') ) + { + $this->page_id = substr($this->page_id, 0, strpos($this->page_id, '/')); + $funcname = "page_{$this->namespace}_{$this->page_id}"; + if ( function_exists($funcname) ) + { + $this->page_exists = true; + } + } if ( isset($paths->pages[$pathskey]) ) { if ( $paths->pages[$pathskey]['special'] == 1 ) diff -r dc838fd61a06 -r 0437a7cf1acc language/english/enano.json --- a/language/english/enano.json Thu Dec 20 22:23:07 2007 -0500 +++ b/language/english/enano.json Fri Dec 21 18:21:20 2007 -0500 @@ -18,7 +18,7 @@ var enano_lang = { categories: [ 'adm', 'meta', 'user', 'page', 'comment', 'onpage', 'etc', 'editor', 'history', 'catedit', 'tags', 'delvote', 'ajax', 'sidebar', 'acl', - 'perm', 'usercp', + 'perm', 'usercp', 'adminusers', ], strings: { meta: { @@ -38,6 +38,8 @@ sidebar: 'Default sidebar blocks and buttons', acl: 'Access control list editor', perm: 'Page actions (for ACLs)', + usercp: 'User control panel', + adminusers: 'ACP: User management', plural: 's', enano_about_poweredby: '

This website is powered by Enano, the lightweight and open source CMS that everyone can use. Enano is copyright © 2006-2007 Dan Fuhry. For legal information, along with a list of libraries that Enano uses, please see Legal Information.

The developers and maintainers of Enano strongly believe that software should not only be free to use, but free to be modified, distributed, and used to create derivative works. For more information about Free Software, check out the Wikipedia page or the Free Software Foundation\'s homepage.

', enano_about_gpl: '

This program is Free Software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.

You should have received a copy of the GNU General Public License along with this program; if not, write to:

Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor
Boston, MA 02110-1301, USA

Alternatively, you can read it online.

', @@ -596,6 +598,15 @@ php_in_pages: 'Embed PHP code in pages', edit_acl: 'Edit access control lists', }, + adminusers: { + avatar_heading: 'Avatar settings', + avatar_image_none: 'This user does not currently have an avatar.', + avatar_lbl_change: 'Change avatar:', + avatar_lbl_keep: 'Keep current setting', + avatar_lbl_remove: 'Delete this user\'s avatar', + avatar_lbl_set_http: 'Replace avatar using a new image from a URL', + avatar_lbl_set_file: 'Replace avatar using a new image from my computer', + }, etc: { redirect_title: 'Redirecting...', redirect_body: 'Please wait while you are redirected.', diff -r dc838fd61a06 -r 0437a7cf1acc plugins/SpecialAdmin.php --- a/plugins/SpecialAdmin.php Thu Dec 20 22:23:07 2007 -0500 +++ b/plugins/SpecialAdmin.php Fri Dec 21 18:21:20 2007 -0500 @@ -57,6 +57,38 @@ return; } + if ( $paths->getParam(0) == 'updates.xml' ) + { + require_once(ENANO_ROOT . '/includes/http.php'); + $req = new Request_HTTP('germantown.enanocms.org', '/meta/updates.xml'); + $response = $req->get_response_body(); + header('Content-type: application/xml'); + if ( $req->response_code != HTTP_OK ) + { + // Error in response + echo 'response_code . ' ' . $req->response_string . ' +]]>'; + } + else + { + // Retrieve first update + $first_update = preg_match('//', $response, $match); + if ( !$first_update ) + { + echo ''; + } + if ( version_compare(enano_version(true), $match[2], '<') ) + { + $response = str_replace_once('
', " \n ", $response); + } + echo $response; + } + return; + } + // Basic information echo RenderMan::render( '== Welcome to Runt, the Enano administration panel. == @@ -78,6 +110,10 @@ echo '
NOTE: It appears that your install.php and/or schema.sql files still exist. It is HIGHLY RECOMMENDED that you delete or rename these files, to prevent getting your server hacked.
'; } + echo '

Check for updates

'; + echo '

Periodically, new releases of Enano will be made available. Click the button below to check for updates to Enano. During this process, a request will be sent to the Enano CMS server (germantown.enanocms.org) over HTTP. No information about your Enano installation will be transmitted.

'; + echo '
'; + // Inactive users $q = $db->sql_query('SELECT * FROM '.table_prefix.'logs WHERE log_type=\'admin\' AND action=\'activ_req\';'); if($q) diff -r dc838fd61a06 -r 0437a7cf1acc plugins/SpecialUserPrefs.php --- a/plugins/SpecialUserPrefs.php Thu Dec 20 22:23:07 2007 -0500 +++ b/plugins/SpecialUserPrefs.php Fri Dec 21 18:21:20 2007 -0500 @@ -708,6 +708,8 @@ break; } + $avi_path_new = ENANO_ROOT . '/' . getConfig('avatar_directory') . '/' . $session->user_id . '.' . $file_type; + // The file type is good - validate dimensions and animation switch($file_type) { @@ -752,7 +754,8 @@ break; } // All good! - if ( rename($tempfile, $avi_path) ) + @unlink($avi_path); + if ( rename($tempfile, $avi_path_new) ) { $q = $db->sql_query('UPDATE ' . table_prefix . "users SET user_has_avatar = 1, avatar_type = '$file_type' WHERE user_id = {$session->user_id};"); if ( !$q ) diff -r dc838fd61a06 -r 0437a7cf1acc plugins/admin/UserManager.php --- a/plugins/admin/UserManager.php Thu Dec 20 22:23:07 2007 -0500 +++ b/plugins/admin/UserManager.php Fri Dec 21 18:21:20 2007 -0500 @@ -15,9 +15,12 @@ function page_Admin_UserManager() { global $db, $session, $paths, $template, $plugins; // Common objects + global $lang; if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN ) { - echo '

Error: Not authenticated

It looks like your administration session is invalid or you are not authorized to access this administration page. Please re-authenticate to continue.

'; + $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true); + echo '

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

'; + echo '

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

'; return; } @@ -123,7 +126,7 @@ if ( count($errors) < 1 ) { - $q = $db->sql_query('SELECT u.user_level FROM '.table_prefix.'users AS u WHERE u.user_id = ' . $user_id . ';'); + $q = $db->sql_query('SELECT u.user_level, u.user_has_avatar, u.avatar_type FROM '.table_prefix.'users AS u WHERE u.user_id = ' . $user_id . ';'); if ( !$q ) $db->_die(); @@ -134,8 +137,10 @@ $row = $db->fetchrow(); $existing_level =& $row['user_level']; + $avi_type =& $row['avatar_type']; + $has_avi = ( $row['user_has_avatar'] == 1 ); $db->free_result(); - + $to_update_users = array(); if ( $user_id != $session->user_id ) { @@ -161,80 +166,231 @@ $to_update_users['activation_key'] = sha1($session->dss_rand()); } - $to_update_users_extra = array(); - $to_update_users_extra['user_aim'] = $imaddr_aim; - $to_update_users_extra['user_msn'] = $imaddr_msn; - $to_update_users_extra['user_yahoo'] = $imaddr_yahoo; - $to_update_users_extra['user_xmpp'] = $imaddr_xmpp; - $to_update_users_extra['user_homepage'] = $homepage; - $to_update_users_extra['user_location'] = $location; - $to_update_users_extra['user_job'] = $occupation; - $to_update_users_extra['user_hobbies'] = $hobbies; - $to_update_users_extra['email_public'] = ( $email_public ) ? '1' : '0'; - - $update_sql = ''; - - foreach ( $to_update_users as $key => $unused_crap ) + // Avatar validation + $action = ( isset($_POST['avatar_action']) ) ? $_POST['avatar_action'] : 'keep'; + $avi_path = ENANO_ROOT . '/' . getConfig('avatar_directory') . '/' . $user_id . '.' . $avi_type; + switch($action) { - $value =& $to_update_users[$key]; - $value = $db->escape($value); - $update_sql .= ( empty($update_sql) ? '' : ',' ) . "$key='$value'"; - } - - $update_sql = 'UPDATE '.table_prefix."users SET $update_sql WHERE user_id=$user_id;"; - - $update_sql_extra = ''; - - foreach ( $to_update_users_extra as $key => $unused_crap ) - { - $value =& $to_update_users_extra[$key]; - $value = $db->escape($value); - $update_sql_extra .= ( empty($update_sql_extra) ? '' : ',' ) . "$key='$value'"; + case 'keep': + default: + break; + case 'remove': + if ( $has_avi ) + { + // First switch the avatar off + $to_update_users['user_has_avatar'] = '0'; + @unlink($avi_path); + } + break; + case 'set_http': + case 'set_file': + // Hackish way to preserve the UNIX philosophy of reusing as much code as possible + if ( $action == 'set_http' ) + { + // Check if this action is enabled + if ( getConfig('avatar_upload_http') !== '1' ) + { + // non-localized, only appears on hack attempt + $errors[] = 'Uploads over HTTP are disabled.'; + break; + } + // Download the file + require_once( ENANO_ROOT . '/includes/http.php' ); + + if ( !preg_match('/^http:\/\/([a-z0-9-\.]+)(:([0-9]+))?\/(.+)$/', $_POST['avatar_http_url'], $match) ) + { + $errors[] = $lang->get('usercp_avatar_invalid_url'); + break; + } + + $hostname = $match[1]; + $uri = '/' . $match[4]; + $port = ( $match[3] ) ? intval($match[3]) : 80; + $max_size = intval(getConfig('avatar_max_size')); + + // Get temporary file + $tempfile = tempnam(false, "enanoavatar_{$user_id}"); + if ( !$tempfile ) + $errors[] = 'Error getting temp file.'; + + @unlink($tempfile); + $request = new Request_HTTP($hostname, $uri, 'GET', $port); + $result = $request->write_response_to_file($tempfile, 50, $max_size); + if ( !$result || $request->response_code != HTTP_OK ) + { + @unlink($tempfile); + $errors[] = $lang->get('usercp_avatar_bad_write'); + break; + } + + // Response written. Proceed to validation... + } + else + { + // Check if this action is enabled + if ( getConfig('avatar_upload_file') !== '1' ) + { + // non-localized, only appears on hack attempt + $errors[] = 'Uploads from the browser are disabled.'; + break; + } + + $max_size = intval(getConfig('avatar_max_size')); + + $file =& $_FILES['avatar_file']; + $tempfile =& $file['tmp_name']; + if ( filesize($tempfile) > $max_size ) + { + @unlink($tempfile); + $errors[] = $lang->get('usercp_avatar_file_too_large'); + break; + } + } + $file_type = get_image_filetype($tempfile); + if ( !$file_type ) + { + unlink($tempfile); + $errors[] = $lang->get('usercp_avatar_bad_filetype'); + break; + } + + $avi_path_new = ENANO_ROOT . '/' . getConfig('avatar_directory') . '/' . $user_id . '.' . $file_type; + + // The file type is good - validate dimensions and animation + switch($file_type) + { + case 'png': + $is_animated = is_png_animated($tempfile); + $dimensions = png_get_dimensions($tempfile); + break; + case 'gif': + $is_animated = is_gif_animated($tempfile); + $dimensions = gif_get_dimensions($tempfile); + break; + case 'jpg': + $is_animated = false; + $dimensions = jpg_get_dimensions($tempfile); + break; + default: + $errors[] = 'API mismatch'; + break 2; + } + // Did we get invalid size data? If so the image is probably corrupt. + if ( !$dimensions ) + { + @unlink($tempfile); + $errors[] = $lang->get('usercp_avatar_corrupt_image'); + break; + } + // Is the image animated? + if ( $is_animated && getConfig('avatar_enable_anim') !== '1' ) + { + @unlink($tempfile); + $errors[] = $lang->get('usercp_avatar_disallowed_animation'); + break; + } + // Check image dimensions + list($image_x, $image_y) = $dimensions; + $max_x = intval(getConfig('avatar_max_width')); + $max_y = intval(getConfig('avatar_max_height')); + if ( $image_x > $max_x || $image_y > $max_y ) + { + @unlink($tempfile); + $errors[] = $lang->get('usercp_avatar_too_large'); + break; + } + // All good! + @unlink($avi_path); + if ( rename($tempfile, $avi_path_new) ) + { + $to_update_users['user_has_avatar'] = '1'; + $to_update_users['avatar_type'] = $file_type; + } + else + { + // move failed - turn avatar off + $to_update_users['user_has_avatar'] = '0'; + } + break; } - $update_sql_extra = 'UPDATE '.table_prefix."users_extra SET $update_sql_extra WHERE user_id=$user_id;"; - - if ( !$db->sql_query($update_sql) ) - $db->_die(); - - if ( !$db->sql_query($update_sql_extra) ) - $db->_die(); - - if ( $existing_level != $user_level ) + if ( count($errors) < 1 ) { - // We need to update group memberships - if ( $existing_level == USER_LEVEL_ADMIN ) + $to_update_users_extra = array(); + $to_update_users_extra['user_aim'] = $imaddr_aim; + $to_update_users_extra['user_msn'] = $imaddr_msn; + $to_update_users_extra['user_yahoo'] = $imaddr_yahoo; + $to_update_users_extra['user_xmpp'] = $imaddr_xmpp; + $to_update_users_extra['user_homepage'] = $homepage; + $to_update_users_extra['user_location'] = $location; + $to_update_users_extra['user_job'] = $occupation; + $to_update_users_extra['user_hobbies'] = $hobbies; + $to_update_users_extra['email_public'] = ( $email_public ) ? '1' : '0'; + + $update_sql = ''; + + foreach ( $to_update_users as $key => $unused_crap ) { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_from_admin\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); - if ( !$q ) - $db->_die(); - $session->remove_user_from_group($user_id, GROUP_ID_ADMIN); + $value =& $to_update_users[$key]; + $value = $db->escape($value); + $update_sql .= ( empty($update_sql) ? '' : ',' ) . "$key='$value'"; } - else if ( $existing_level == USER_LEVEL_MOD ) + + $update_sql = 'UPDATE '.table_prefix."users SET $update_sql WHERE user_id=$user_id;"; + + $update_sql_extra = ''; + + foreach ( $to_update_users_extra as $key => $unused_crap ) { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_from_mod\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); - if ( !$q ) - $db->_die(); - $session->remove_user_from_group($user_id, GROUP_ID_MOD); + $value =& $to_update_users_extra[$key]; + $value = $db->escape($value); + $update_sql_extra .= ( empty($update_sql_extra) ? '' : ',' ) . "$key='$value'"; } - if ( $user_level == USER_LEVEL_ADMIN ) - { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_to_admin\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); - if ( !$q ) - $db->_die(); - $session->add_user_to_group($user_id, GROUP_ID_ADMIN, false); - } - else if ( $user_level == USER_LEVEL_MOD ) + $update_sql_extra = 'UPDATE '.table_prefix."users_extra SET $update_sql_extra WHERE user_id=$user_id;"; + + if ( !$db->sql_query($update_sql) ) + $db->_die(); + + if ( !$db->sql_query($update_sql_extra) ) + $db->_die(); + + if ( $existing_level != $user_level ) { - $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_to_mod\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); - if ( !$q ) - $db->_die(); - $session->add_user_to_group($user_id, GROUP_ID_MOD, false); + // We need to update group memberships + if ( $existing_level == USER_LEVEL_ADMIN ) + { + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_from_admin\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); + if ( !$q ) + $db->_die(); + $session->remove_user_from_group($user_id, GROUP_ID_ADMIN); + } + else if ( $existing_level == USER_LEVEL_MOD ) + { + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_from_mod\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); + if ( !$q ) + $db->_die(); + $session->remove_user_from_group($user_id, GROUP_ID_MOD); + } + + if ( $user_level == USER_LEVEL_ADMIN ) + { + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_to_admin\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); + if ( !$q ) + $db->_die(); + $session->add_user_to_group($user_id, GROUP_ID_ADMIN, false); + } + else if ( $user_level == USER_LEVEL_MOD ) + { + $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_to_mod\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");'); + if ( !$q ) + $db->_die(); + $session->add_user_to_group($user_id, GROUP_ID_MOD, false); + } } + + echo '
Your changes have been saved.
'; } - - echo '
Your changes have been saved.
'; } } @@ -290,7 +446,7 @@ echo 'No username provided'; return false; } - $q = $db->sql_query('SELECT u.user_id AS authoritative_uid, u.username, u.email, u.real_name, u.signature, u.account_active, u.user_level, x.* FROM '.table_prefix.'users AS u + $q = $db->sql_query('SELECT u.user_id AS authoritative_uid, u.username, u.email, u.real_name, u.signature, u.account_active, u.user_level, u.user_has_avatar, u.avatar_type, x.* FROM '.table_prefix.'users AS u LEFT JOIN '.table_prefix.'users_extra AS x ON ( u.user_id = x.user_id OR x.user_id IS NULL ) WHERE ( ' . ENANO_SQLFUNC_LOWERCASE . '(u.username) = \'' . $db->escape(strtolower($username)) . '\' OR u.username = \'' . $db->escape($username) . '\' ) AND u.user_id != 1;'); @@ -314,6 +470,8 @@ $form->user_level= $row['user_level']; $form->account_active = ( $row['account_active'] == 1 ); $form->email_public = ( $row['email_public'] == 1 ); + $form->has_avatar = ( $row['user_has_avatar'] == 1 ); + $form->avi_type = $row['avatar_type']; $form->im = array( 'aim' => $row['user_aim'], 'yahoo' => $row['user_yahoo'], @@ -541,6 +699,20 @@ var $email_public = false; /** + * Whether the user has an avatar or not. + * @var bool + */ + + var $has_avatar = false; + + /** + * The type of avatar the user has. One of "jpg", "png", or "gif". + * @var string + */ + + var $avi_type = 'png'; + + /** * Constructor. */ @@ -557,6 +729,7 @@ function render() { global $db, $session, $paths, $template, $plugins; // Common objects + global $lang; if ( file_exists( ENANO_ROOT . "/themes/$template->theme/admin_usermanager_form.tpl" ) ) { $parser = $template->makeParser('admin_usermanager_form.tpl'); @@ -768,6 +941,70 @@ + + + + + {lang:adminusers_avatar_heading} + + + + + + {lang:usercp_avatar_label_current} + + + + {AVATAR_ALT} + + {lang:adminusers_avatar_image_none} + + + + + + + {lang:adminusers_avatar_lbl_change} + + + +
+
+
+ + + + + + + + @@ -895,6 +1132,14 @@ 'FORM_ACTION' => $form_action )); + if ( $this->has_avatar ) + { + $parser->assign_vars(array( + 'AVATAR_SRC' => make_avatar_url($this->user_id, $this->avi_type), + 'AVATAR_ALT' => $lang->get('usercp_avatar_image_alt', array('username' => $this->username)) + )); + } + $parser->assign_bool(array( 'password_meter' => ( getConfig('pw_strength_enable') == '1' ), 'ul_member' => ( $this->user_level == USER_LEVEL_CHPREF ), @@ -902,7 +1147,8 @@ 'ul_admin' => ( $this->user_level == USER_LEVEL_ADMIN ), 'account_active' => ( $this->account_active === true ), 'email_public' => ( $this->email_public === true ), - 'same_user' => ( $this->user_id == $session->user_id ) + 'same_user' => ( $this->user_id == $session->user_id ), + 'user_has_avatar' => ( $this->has_avatar ) )); $parsed = $parser->run();