# 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 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. 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., Alternatively, you can read it online.
51 Franklin Street, Fifth Floor
Boston, MA 02110-1301, USA
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 '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_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 '