author | Dan |
Sun, 21 Dec 2008 06:32:06 -0500 | |
changeset 773 | 7b1ac402b451 |
parent 743 | 0acb5d0f8328 |
child 782 | 96848f04bbba |
permissions | -rw-r--r-- |
<?php /**!info** { "Plugin Name" : "plugin_specialuserfuncs_title", "Plugin URI" : "http://enanocms.org/", "Description" : "plugin_specialuserfuncs_desc", "Author" : "Dan Fuhry", "Version" : "1.1.5", "Author URI" : "http://enanocms.org/" } **!*/ /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between * Version 1.1.5 (Caoineag alpha 5) * Copyright (C) 2006-2008 Dan Fuhry * * This program is Free Software; you can redistribute 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. */ global $db, $session, $paths, $template, $plugins; // Common objects // $plugins->attachHook('session_started', 'SpecialUserFuncs_paths_init();'); function SpecialUserFuncs_paths_init() { global $paths; $paths->add_page(Array( 'name'=>'specialpage_log_in', 'urlname'=>'Login', 'namespace'=>'Special', 'special'=>0,'visible'=>1,'comments_on'=>0,'protected'=>1,'delvotes'=>0,'delvote_ips'=>'', )); $paths->add_page(Array( 'name'=>'specialpage_log_out', 'urlname'=>'Logout', 'namespace'=>'Special', 'special'=>0,'visible'=>1,'comments_on'=>0,'protected'=>1,'delvotes'=>0,'delvote_ips'=>'', )); $paths->add_page(Array( 'name'=>'specialpage_register', 'urlname'=>'Register', 'namespace'=>'Special', 'special'=>0,'visible'=>1,'comments_on'=>0,'protected'=>1,'delvotes'=>0,'delvote_ips'=>'', )); $paths->add_page(Array( 'name'=>'specialpage_preferences', 'urlname'=>'Preferences', 'namespace'=>'Special', 'special'=>0,'visible'=>1,'comments_on'=>0,'protected'=>1,'delvotes'=>0,'delvote_ips'=>'', )); $paths->add_page(Array( 'name'=>'specialpage_contributions', 'urlname'=>'Contributions', 'namespace'=>'Special', 'special'=>0,'visible'=>1,'comments_on'=>0,'protected'=>1,'delvotes'=>0,'delvote_ips'=>'', )); $paths->add_page(Array( 'name'=>'specialpage_change_theme', 'urlname'=>'ChangeStyle', 'namespace'=>'Special', 'special'=>0,'visible'=>1,'comments_on'=>0,'protected'=>1,'delvotes'=>0,'delvote_ips'=>'', )); $paths->add_page(Array( 'name'=>'specialpage_activate_account', 'urlname'=>'ActivateAccount', 'namespace'=>'Special', 'special'=>0,'visible'=>1,'comments_on'=>0,'protected'=>1,'delvotes'=>0,'delvote_ips'=>'', )); $paths->add_page(Array( 'name'=>'specialpage_captcha', 'urlname'=>'Captcha', 'namespace'=>'Special', 'special'=>0,'visible'=>1,'comments_on'=>0,'protected'=>1,'delvotes'=>0,'delvote_ips'=>'', )); $paths->add_page(Array( 'name'=>'specialpage_password_reset', 'urlname'=>'PasswordReset', 'namespace'=>'Special', 'special'=>0,'visible'=>1,'comments_on'=>0,'protected'=>1,'delvotes'=>0,'delvote_ips'=>'', )); $paths->add_page(Array( 'name'=>'specialpage_member_list', 'urlname'=>'Memberlist', 'namespace'=>'Special', 'special'=>0,'visible'=>1,'comments_on'=>0,'protected'=>1,'delvotes'=>0,'delvote_ips'=>'', )); $paths->add_page(Array( 'name'=>'specialpage_language_export', 'urlname'=>'LangExportJSON', 'namespace'=>'Special', 'special'=>0,'visible'=>0,'comments_on'=>0,'protected'=>1,'delvotes'=>0,'delvote_ips'=>'', )); $paths->add_page(Array( 'name'=>'specialpage_avatar', 'urlname'=>'Avatar', 'namespace'=>'Special', 'special'=>0,'visible'=>0,'comments_on'=>0,'protected'=>1,'delvotes'=>0,'delvote_ips'=>'', )); } // function names are IMPORTANT!!! The name pattern is: page_<namespace ID>_<page URLname, without namespace> $__login_status = ''; function page_Special_Login() { global $db, $session, $paths, $template, $plugins; // Common objects global $__login_status; global $lang; require_once( ENANO_ROOT . '/includes/diffiehellman.php' ); global $dh_supported, $_math; $pubkey = $session->rijndael_genkey(); $challenge = $session->dss_rand(); $locked_out = false; // are we locked out? $threshold = ( $_ = getConfig('lockout_threshold') ) ? intval($_) : 5; $duration = ( $_ = getConfig('lockout_duration') ) ? intval($_) : 15; // convert to minutes $duration = $duration * 60; $policy = ( $x = getConfig('lockout_policy') && in_array(getConfig('lockout_policy'), array('lockout', 'disable', 'captcha')) ) ? getConfig('lockout_policy') : 'lockout'; if ( $policy != 'disable' ) { $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']); $timestamp_cutoff = time() - $duration; $q = $session->sql('SELECT timestamp FROM '.table_prefix.'lockout WHERE timestamp > ' . $timestamp_cutoff . ' AND ipaddr = \'' . $ipaddr . '\' ORDER BY timestamp DESC;'); $fails = $db->numrows(); if ( $fails >= $threshold ) { $row = $db->fetchrow(); $locked_out = true; $lockdata = array( 'locked_out' => true, 'lockout_threshold' => $threshold, 'lockout_duration' => ( $duration / 60 ), 'lockout_fails' => $fails, 'lockout_policy' => $policy, 'lockout_last_time' => $row['timestamp'], 'time_rem' => ( $duration / 60 ) - round( ( time() - $row['timestamp'] ) / 60 ), 'captcha' => '' ); if ( $policy == 'captcha' ) { $lockdata['captcha'] = $session->make_captcha(); } } $db->free_result(); } if ( isset($_GET['act']) && $_GET['act'] == 'getkey' ) { header('Content-type: text/javascript'); $username = ( $session->user_logged_in ) ? $session->username : false; $response = Array( 'username' => $username, 'key' => $pubkey, 'challenge' => $challenge, 'locked_out' => false ); if ( $locked_out ) { foreach ( $lockdata as $x => $y ) { $response[$x] = $y; } unset($x, $y); } // 1.1.3: generate diffie hellman key $response['dh_supported'] = $dh_supported; if ( $dh_supported ) { $dh_key_priv = dh_gen_private(); $dh_key_pub = dh_gen_public($dh_key_priv); $dh_key_priv = $_math->str($dh_key_priv); $dh_key_pub = $_math->str($dh_key_pub); $response['dh_public_key'] = $dh_key_pub; // store the keys in the DB $q = $db->sql_query('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );"); if ( !$q ) $db->die_json(); } $response = enano_json_encode($response); echo $response; return null; } $level = ( isset($_GET['level']) && in_array($_GET['level'], array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') ) ) ? intval($_GET['level']) : USER_LEVEL_MEMBER; if ( isset($_POST['login']) ) { if ( in_array($_POST['auth_level'], array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') ) ) { $level = intval($_POST['auth_level']); } } if ( $level > USER_LEVEL_MEMBER && !$session->user_logged_in ) { $level = USER_LEVEL_MEMBER; } if ( $level <= USER_LEVEL_MEMBER && $session->user_logged_in ) $paths->main_page(); $template->header(); echo '<form action="'.makeUrl($paths->nslist['Special'].'Login').'" method="post" name="loginform" onsubmit="try{runEncryption();}catch(e){};">'; $header = ( $level > USER_LEVEL_MEMBER ) ? $lang->get('user_login_message_short_elev') : $lang->get('user_login_message_short'); if ( isset($_POST['login']) ) { $errstring = $__login_status['error']; switch($__login_status['error']) { case 'key_not_found': $errstring = $lang->get('user_err_key_not_found'); break; case 'ERR_DH_KEY_NOT_FOUND': $errstring = $lang->get('user_err_dh_key_not_found'); // . " -- {$__login_status['debug']}"; break; case 'ERR_DH_KEY_NOT_INTEGER': $errstring = $lang->get('user_err_dh_key_not_numeric'); break; case 'key_wrong_length': $errstring = $lang->get('user_err_key_wrong_length'); break; case 'too_big_for_britches': $errstring = $lang->get('user_err_too_big_for_britches'); break; case 'invalid_credentials': $errstring = $lang->get('user_err_invalid_credentials'); if ( $__login_status['lockout_policy'] == 'lockout' ) { $errstring .= $lang->get('err_invalid_credentials_lockout', array('fails' => $__login_status['lockout_fails'])); } else if ( $__login_status['lockout_policy'] == 'captcha' ) { $errstring .= $lang->get('user_err_invalid_credentials_lockout_captcha', array('fails' => $__login_status['lockout_fails'])); } break; case 'backend_fail': $errstring = $lang->get('user_err_backend_fail'); break; case 'locked_out': $attempts = intval($__login_status['lockout_fails']); if ( $attempts > $__login_status['lockout_threshold']) $attempts = $__login_status['lockout_threshold']; $server_time = time(); $time_rem = ( intval(@$__login_status['lockout_last_time']) == time() ) ? $__login_status['lockout_duration'] : $__login_status['lockout_duration'] - round( ( $server_time - $__login_status['lockout_last_time'] ) / 60 ); if ( $time_rem < 1 ) $time_rem = $__login_status['lockout_duration']; $s = ( $time_rem == 1 ) ? '' : $lang->get('meta_plural'); $captcha_string = ( $__login_status['lockout_policy'] == 'captcha' ) ? $lang->get('user_err_locked_out_captcha_blurb') : ''; $errstring = $lang->get('user_err_locked_out', array('plural' => $s, 'captcha_blurb' => $captcha_string, 'time_rem' => $time_rem)); break; } echo '<div class="error-box-mini">'.$errstring.'</div>'; } if ( $p = $paths->getAllParams() ) { echo '<input type="hidden" name="return_to" value="'.$p.'" />'; } else if ( isset($_POST['login']) && isset($_POST['return_to']) ) { echo '<input type="hidden" name="return_to" value="'.htmlspecialchars($_POST['return_to']).'" />'; } ?> <div class="tblholder"> <table border="0" style="width: 100%;" cellspacing="1" cellpadding="4"> <tr> <th colspan="3"><?php echo $header; ?></th> </tr> <tr> <td colspan="3" class="row1"> <?php if ( $level <= USER_LEVEL_MEMBER ) { echo '<p>' . $lang->get('user_login_body', array('reg_link' => makeUrlNS('Special', 'Register'))) . '</p>'; } else { echo '<p>' . $lang->get('user_login_body_elev') . '</p>'; } ?> </td> </tr> <tr> <td class="row2"> <?php echo $lang->get('user_login_field_username'); ?>: </td> <td class="row1"> <input name="username" size="25" type="text" <?php if ( $level <= USER_LEVEL_MEMBER ) { echo 'tabindex="1" '; } else { echo 'tabindex="3" '; } if ( $session->user_logged_in ) { echo 'value="' . $session->username . '"'; } ?> /> </td> <?php if ( $level <= USER_LEVEL_MEMBER ) { ?> <td rowspan="<?php echo ( ( $locked_out && $lockdata['lockout_policy'] == 'captcha' ) ) ? '4' : '2'; ?>" class="row3"> <small><?php echo $lang->get('user_login_forgotpass_blurb', array('forgotpass_link' => makeUrlNS('Special', 'PasswordReset'))); ?><br /> <?php echo $lang->get('user_login_createaccount_blurb', array('reg_link' => makeUrlNS('Special', 'Register'))); ?></small> </td> <?php } ?> </tr> <tr> <td class="row2"> <?php echo $lang->get('user_login_field_password'); ?>: </td><td class="row1"><input name="pass" size="25" type="password" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '2' : '1'; ?>" /></td> </tr> <?php if ( $locked_out && $lockdata['lockout_policy'] == 'captcha' ) { ?> <tr> <td class="row2" rowspan="2"><?php echo $lang->get('user_login_field_captcha'); ?>:<br /></td><td class="row1"><input type="hidden" name="captcha_hash" value="<?php echo $lockdata['captcha']; ?>" /><input name="captcha_code" size="25" type="text" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '3' : '4'; ?>" /></td> </tr> <tr> <td class="row3"> <img src="<?php echo makeUrlNS('Special', 'Captcha/' . $lockdata['captcha']) ?>" onclick="this.src=this.src+'/a';" style="cursor: pointer;" /> </td> </tr> <?php } ?> <?php if ( $level <= USER_LEVEL_MEMBER ) { // "remember me" switch // first order of business is to determine what the checkbox should say $session_time = intval(getConfig('session_remember_time', '30')); if ( $session_time === 0 ) { // sessions are infinite $text_remember = $lang->get('user_login_check_remember_infinite'); } else { // is the number of days evenly divisible by 7? if so, use weeks if ( $session_time % 7 == 0 ) { $session_time = $session_time / 7; $unit = 'week'; } else { $unit = 'day'; } // if it's not equal to 1, pluralize it if ( $session_time != 1 ) { $unit .= 's'; } $text_remember = $lang->get('user_login_check_remember', array( 'session_length' => $session_time, 'length_units' => $lang->get("etc_unit_$unit") )); } ?> <tr> <td class="row2"> <?php echo $lang->get('user_login_field_remember'); ?> </td> <td class="row1" colspan="2"> <label> <input type="checkbox" name="remember" tabindex="3" /> <?php echo $text_remember; ?> </label> </td> </tr> <?php } if ( $level <= USER_LEVEL_MEMBER && ( !isset($_GET['use_crypt']) || ( isset($_GET['use_crypt']) && $_GET['use_crypt']!='0' ) ) ) { echo '<tr> <td class="row3" colspan="3">'; $returnpage_link = ( $return = $paths->getAllParams() ) ? '/' . $return : ''; $nocrypt_link = makeUrlNS('Special', "Login$returnpage_link", "level=$level&use_crypt=0", true); echo '<p><b>' . $lang->get('user_login_nocrypt_title') . '</b> ' . $lang->get('user_login_nocrypt_body', array('nocrypt_link' => $nocrypt_link)) . '</p>'; echo '<p>' . $lang->get('user_login_nocrypt_countrylist') . '</p>'; echo ' </td> </tr>'; } else if ( $level <= USER_LEVEL_MEMBER && ( isset($_GET['use_crypt']) && $_GET['use_crypt']=='0' ) ) { echo '<tr> <td class="row3" colspan="3">'; $returnpage_link = ( $return = $paths->getAllParams() ) ? '/' . $return : ''; $usecrypt_link = makeUrlNS('Special', "Login$returnpage_link", "level=$level&use_crypt=1", true); echo '<p><b>' . $lang->get('user_login_usecrypt_title') . '</b> ' . $lang->get('user_login_usecrypt_body', array('usecrypt_link' => $usecrypt_link)) . '</p>'; echo '<p>' . $lang->get('user_login_usecrypt_countrylist') . '</p>'; echo ' </td> </tr>'; } else if ( $level > USER_LEVEL_MEMBER && !strstr($_SERVER['HTTP_USER_AGENT'], 'iPhone') && $dh_supported ) { echo '<tr>'; echo '<td class="row3" colspan="3">'; echo '<p>' . $lang->get('user_login_dh_notice') . '</p>'; echo '</td>'; echo '</tr>'; } ?> <tr> <th colspan="3" style="text-align: center" class="subhead"><input type="submit" name="login" value="Log in" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '4' : '2'; ?>" /></th> </tr> </table> </div> <input type="hidden" name="challenge_data" value="<?php echo $challenge; ?>" /> <input type="hidden" name="use_crypt" value="no" /> <input type="hidden" name="crypt_key" value="<?php echo $pubkey; ?>" /> <input type="hidden" name="crypt_data" value="" /> <input type="hidden" name="auth_level" value="<?php echo (string)$level; ?>" /> <?php if ( $level <= USER_LEVEL_MEMBER ): ?> <script type="text/javascript"> document.forms.loginform.username.focus(); </script> <?php else: ?> <script type="text/javascript"> document.forms.loginform.pass.focus(); </script> <?php endif; ?> <?php // 1.1.4 require_once( ENANO_ROOT . '/includes/diffiehellman.php' ); global $dh_supported, $_math; if ( $dh_supported ) { $dh_key_priv = dh_gen_private(); $dh_key_pub = dh_gen_public($dh_key_priv); $dh_key_priv = $_math->str($dh_key_priv); $dh_key_pub = $_math->str($dh_key_pub); // store the keys in the DB $q = $db->sql_query('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );"); if ( !$q ) $db->_die(); echo "<input type=\"hidden\" name=\"dh_supported\" value=\"true\" /> <input type=\"hidden\" name=\"dh_public_key\" value=\"$dh_key_pub\" /> <input type=\"hidden\" name=\"dh_client_public_key\" value=\"\" />"; } else { echo "<input type=\"hidden\" name=\"dh_supported\" value=\"false\" />"; } ?> </form> <?php echo $session->aes_javascript('loginform', 'pass', 'use_crypt', 'crypt_key', 'crypt_data', 'challenge_data', 'dh_supported', 'dh_public_key', 'dh_client_public_key'); ?> <?php $template->footer(); } function page_Special_Login_preloader() // adding _preloader to the end of the function name calls the function before $session and $paths setup routines are called { global $db, $session, $paths, $template, $plugins; // Common objects global $__login_status; global $lang; require_once( ENANO_ROOT . '/includes/math.php' ); if ( $paths->getParam(0) === 'action.json' ) { if ( !isset($_POST['r']) ) die('No request.'); $request = $_POST['r']; try { $request = enano_json_decode($request); } catch ( Exception $e ) { die(enano_json_encode(array( 'mode' => 'error', 'error' => 'ERR_JSON_PARSE_FAILED' ))); } echo enano_json_encode($session->process_login_request($request)); $db->close(); exit; } if ( isset($_GET['act']) && $_GET['act'] == 'ajaxlogin' ) { echo 'This version of the Enano LoginAPI is deprecated. Please use the action.json method instead.'; return true; } if(isset($_POST['login'])) { $captcha_hash = ( isset($_POST['captcha_hash']) ) ? $_POST['captcha_hash'] : false; $captcha_code = ( isset($_POST['captcha_code']) ) ? $_POST['captcha_code'] : false; if ( $_POST['use_crypt'] == 'yes' ) { $result = $session->login_with_crypto($_POST['username'], $_POST['crypt_data'], $_POST['crypt_key'], $_POST['challenge_data'], intval($_POST['auth_level']), $captcha_hash, $captcha_code, isset($_POST['remember'])); } else if ( $_POST['use_crypt'] == 'yes_dh' ) { // retrieve and decrypt the password using DiffieHellman require_once( ENANO_ROOT . '/includes/diffiehellman.php' ); global $dh_supported, $_math; if ( !$dh_supported ) { die_semicritical('DiffieHellman error', 'Server does not support DiffieHellman, denying logon request'); } // Fetch private key $dh_public = $_POST['dh_public_key']; if ( !preg_match('/^[0-9]+$/', $dh_public) ) { $__login_status = array( 'success' => false, 'error' => 'ERR_DH_KEY_NOT_INTEGER', 'debug' => "public key: $dh_public" ); return false; } $q = $db->sql_query('SELECT private_key, key_id FROM ' . table_prefix . "diffiehellman WHERE public_key = '$dh_public';"); if ( !$q ) $db->die_json(); if ( $db->numrows() < 1 ) { $__login_status = array( 'success' => false, 'error' => 'ERR_DH_KEY_NOT_FOUND', 'debug' => "public key: $dh_public" ); return false; } list($dh_private, $dh_key_id) = $db->fetchrow_num(); $db->free_result(); // We have the private key, now delete the key pair, we no longer need it $q = $db->sql_query('DELETE FROM ' . table_prefix . "diffiehellman WHERE key_id = $dh_key_id;"); if ( !$q ) $db->die_json(); // Generate the shared secret $dh_secret = dh_gen_shared_secret($dh_private, $_POST['dh_client_public_key']); $dh_secret = $_math->str($dh_secret); // Did we get all our math right? $dh_secret_check = sha1($dh_secret); $dh_hash = $_POST['crypt_key']; if ( $dh_secret_check !== $dh_hash ) { $__login_status = array( 'success' => false, 'error' => 'ERR_DH_HASH_NO_MATCH', 'debug' => "dh_secret_check = $dh_secret_check\ndh_hash_input = $dh_hash" ); return false; } // All good! Generate the AES key $aes_key = substr(sha256($dh_secret), 0, ( AES_BITS / 4 )); // decrypt user info $aes_key = hexdecode($aes_key); $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); $password = $aes->decrypt($_POST['crypt_data'], $aes_key, ENC_HEX); $result = $session->login_without_crypto($_POST['username'], $password, false, intval($_POST['auth_level']), $captcha_hash, $captcha_code, isset($_POST['remember'])); } else { $result = $session->login_without_crypto($_POST['username'], $_POST['pass'], false, intval($_POST['auth_level']), $captcha_hash, $captcha_code, isset($_POST['remember'])); } if($result['success']) { $session->start(); $template->load_theme($session->theme, $session->style); if(isset($_POST['return_to'])) { $name = ( isset($paths->pages[$_POST['return_to']]['name']) ) ? $paths->pages[$_POST['return_to']]['name'] : $_POST['return_to']; $subst = array( 'username' => $session->username, 'redir_target' => $name ); redirect( makeUrl($_POST['return_to'], false, true), $lang->get('user_login_success_title'), $lang->get('user_login_success_body', $subst) ); } else { $subst = array( 'username' => $session->username, 'redir_target' => $lang->get('user_login_success_body_mainpage') ); redirect( makeUrl(get_main_page(), false, true), $lang->get('user_login_success_title'), $lang->get('user_login_success_body', $subst) ); } } else { if ( $result['error'] === 'valid_reset' ) { header('HTTP/1.1 302 Temporary Redirect'); header('Location: ' . $result['redirect_url']); $db->close(); exit(); } $GLOBALS['__login_status'] = $result; } } } function SpecialLogin_SendResponse_PasswordReset($user_id, $passkey) { $response = Array( 'result' => 'success_reset', 'user_id' => $user_id, 'temppass' => $passkey ); $response = enano_json_encode($response); echo $response; $db->close(); exit; } function page_Special_Logout() { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; if ( !$session->user_logged_in ) $paths->main_page(); $token = $paths->getParam(0); if ( $token !== $session->csrf_token ) { csrf_request_confirm(); } $l = $session->logout(); if ( $l == 'success' ) { $url = makeUrl(get_main_page(), false, true); if ( $paths->getParam(1) ) { $pi = explode('/', $paths->getAllParams()); $pi = implode('/', array_values(array_slice($pi, 1))); list($pid, $ns) = RenderMan::strToPageID($pi); $perms = $session->fetch_page_acl($pid, $ns); if ( $perms->get_permissions('read') ) { $url = makeUrl($pi, false, true); } } redirect($url, $lang->get('user_logout_success_title'), $lang->get('user_logout_success_body'), 3); } $template->header(); echo '<h3>' . $lang->get('user_logout_err_title') . '</h3>'; echo '<p>' . $l . '</p>'; $template->footer(); } function page_Special_Register() { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; if ( $session->user_logged_in ) { $paths->main_page(); } // form field trackers $username = ''; $email = ''; $realname = ''; $terms = getConfig('register_tou'); if(getConfig('account_activation') == 'disable' && ( ( $session->user_level >= USER_LEVEL_ADMIN && !isset($_GET['IWannaPlayToo']) ) || $session->user_level < USER_LEVEL_ADMIN || !$session->user_logged_in )) { $s = ($session->user_level >= USER_LEVEL_ADMIN) ? '<p>' . $lang->get('user_reg_err_disabled_body_adminblurb', array( 'reg_link' => makeUrl($paths->page, 'IWannaPlayToo&coppa=no', true) )) . '</p>' : ''; die_friendly($lang->get('user_reg_err_disabled_title'), '<p>' . $lang->get('user_reg_err_disabled_body') . '</p>' . $s); } // are we locked out from logging in? if so, also lock out registration if ( getConfig('lockout_policy') === 'lockout' ) { $ip = $db->escape($_SERVER['REMOTE_ADDR']); $threshold = time() - ( 60 * intval(getConfig('lockout_duration')) ); $limit = intval(getConfig('lockout_threshold')); $q = $db->sql_query('SELECT * FROM ' . table_prefix . "lockout WHERE timestamp >= $threshold ORDER BY timestamp DESC;"); if ( !$q ) $db->_die(); if ( $db->numrows() >= $limit ) { $row = $db->fetchrow(); $db->free_result(); $time_rem = intval(getConfig('lockout_duration')) - round((time() - $row['timestamp']) / 60); die_friendly($lang->get('user_reg_err_disabled_title'), '<p>' . $lang->get('user_reg_err_locked_out', array('time' => $time_rem)) . '</p>'); } $db->free_result(); } if ( $session->user_level < USER_LEVEL_ADMIN && $session->user_logged_in ) { $paths->main_page(); } if(isset($_POST['submit'])) { $_GET['coppa'] = ( isset($_POST['coppa']) ) ? $_POST['coppa'] : 'x'; $captcharesult = $session->get_captcha($_POST['captchahash']); $session->kill_captcha(); if ( strtolower($captcharesult) != strtolower($_POST['captchacode']) ) { $s = $lang->get('user_reg_err_captcha'); } else { if ( getConfig('enable_coppa') == '1' && ( !isset($_POST['coppa']) || ( isset($_POST['coppa']) && !in_array($_POST['coppa'], array('yes', 'no')) ) ) ) { $s = 'Invalid COPPA input'; } else if ( !empty($terms) && !isset($_POST['tou_agreed']) ) { $s = $lang->get('user_reg_err_accept_tou'); } else { $coppa = ( isset($_POST['coppa']) && $_POST['coppa'] == 'yes' ); $s = false; // decrypt password // as with the change pass form, we aren't going to bother checking the confirmation code because if the passwords didn't match // and yet the password got encrypted, that means the user screwed with the code, and if the user screwed with the code and thus // forgot his password, that's his problem. if ( $_POST['use_crypt'] == 'yes' ) { $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); $crypt_key = $session->fetch_public_key($_POST['crypt_key']); if ( !$crypt_key ) { $s = $lang->get('user_reg_err_missing_key'); } else { $data = $_POST['crypt_data']; $bin_key = hexdecode($crypt_key); //die("Decrypting with params: key $crypt_key, data $data"); $password = $aes->decrypt($data, $bin_key, ENC_HEX); } } else { $password = $_POST['password']; } // CAPTCHA code was correct, create the account // ... and check for errors returned from the crypto API if ( !$s ) $s = $session->create_user($_POST['username'], $password, $_POST['email'], $_POST['real_name'], $coppa); } } if($s == 'success' && !$coppa) { switch(getConfig('account_activation')) { case "none": default: $str = $lang->get('user_reg_msg_success_activ_none', array('login_link' => makeUrlNS('Special', 'Login', false, true))); break; case "user": $str = $lang->get('user_reg_msg_success_activ_user'); break; case "admin": $str = $lang->get('user_reg_msg_success_activ_admin'); break; } die_friendly($lang->get('user_reg_msg_success_title'), '<p>' . $lang->get('user_reg_msg_success_body') . ' ' . $str . '</p>'); } else if ( $s == 'success' && $coppa ) { $str = $lang->get('user_reg_msg_success_activ_coppa'); die_friendly($lang->get('user_reg_msg_success_title'), '<p>' . $lang->get('user_reg_msg_success_body') . ' ' . $str . '</p>'); } $username = htmlspecialchars($_POST['username']); $email = htmlspecialchars($_POST['email']); $realname = htmlspecialchars($_POST['real_name']); } $template->header(); echo $lang->get('user_reg_msg_greatercontrol'); if ( getConfig('enable_coppa') != '1' || ( isset($_GET['coppa']) && in_array($_GET['coppa'], array('yes', 'no')) ) ) { $coppa = ( isset($_GET['coppa']) && $_GET['coppa'] == 'yes' ); $session->kill_captcha(); $captchacode = $session->make_captcha(); $pubkey = $session->rijndael_genkey(); $challenge = $session->dss_rand(); ?> <h3><?php echo $lang->get('user_reg_msg_table_title'); ?></h3> <form name="regform" action="<?php echo makeUrl($paths->page); ?>" method="post" onsubmit="return runEncryption();"> <div class="tblholder"> <table border="0" width="100%" cellspacing="1" cellpadding="4"> <tr><th class="subhead" colspan="3"><?php echo $lang->get('user_reg_msg_table_subtitle'); ?></th></tr> <?php if(isset($_POST['submit'])) echo '<tr><td colspan="3" class="row2" style="color: red;">'.$s.'</td></tr>'; ?> <!-- FIELD: Username --> <tr> <td class="row1" style="width: 50%;"> <?php echo $lang->get('user_reg_lbl_field_username'); ?> <span id="e_username"></span> </td> <td class="row1" style="width: 50%;"> <input tabindex="1" type="text" name="username" size="30" value="<?php echo $username; ?>" onkeyup="namegood = false; validateForm(this);" onblur="checkUsername();" /> </td> <td class="row1" style="width: 1px;"> <img alt="Good/bad icon" src="<?php echo scriptPath; ?>/images/checkbad.png" id="s_username" /> </td> </tr> <!-- FIELD: Password --> <tr> <td class="row3" style="width: 50%;" rowspan="<?php echo ( getConfig('pw_strength_enable') == '1' ) ? '3' : '2'; ?>"> <?php echo $lang->get('user_reg_lbl_field_password'); ?> <span id="e_password"></span> <?php if ( getConfig('pw_strength_enable') == '1' && getConfig('pw_strength_minimum') > -10 ): ?> <small><?php echo $lang->get('user_reg_msg_password_score'); ?></small> <?php endif; ?> </td> <td class="row3" style="width: 50%;"> <input tabindex="2" type="password" name="password" size="15" onkeyup="<?php if ( getConfig('pw_strength_enable') == '1' ): ?>password_score_field(this); <?php endif; ?>validateForm(this);" /><?php if ( getConfig('pw_strength_enable') == '1' ): ?><span class="password-checker" style="font-weight: bold; color: #aaaaaa;"> Loading...</span><?php endif; ?> </td> <td rowspan="<?php echo ( getConfig('pw_strength_enable') == '1' ) ? '3' : '2'; ?>" class="row3" style="max-width: 24px;"> <img alt="Good/bad icon" src="<?php echo scriptPath; ?>/images/checkbad.png" id="s_password" /> </td> </tr> <!-- FIELD: Password confirmation --> <tr> <td class="row3" style="width: 50%;"> <input tabindex="3" type="password" name="password_confirm" size="15" onkeyup="validateForm(this);" /> <small><?php echo $lang->get('user_reg_lbl_field_password_confirm'); ?></small> </td> </tr> <!-- FIELD: Password strength meter --> <?php if ( getConfig('pw_strength_enable') == '1' ): ?> <tr> <td class="row3" style="width: 50%;"> <div id="pwmeter"></div> </td> </tr> <?php endif; ?> <!-- FIELD: E-mail address --> <tr> <td class="row1" style="width: 50%;"> <?php if ( $coppa ) { echo $lang->get('user_reg_lbl_field_email_coppa'); } else { echo $lang->get('user_reg_lbl_field_email'); } ?> <?php if ( ( $x = getConfig('account_activation') ) == 'user' ) { echo '<br /><small>' . $lang->get('user_reg_msg_email_activuser') . '</small>'; } ?> </td> <td class="row1" style="width: 50%;"> <input tabindex="4" type="text" name="email" size="30" value="<?php echo $email; ?>" onkeyup="validateForm(this);" /> </td> <td class="row1" style="max-width: 24px;"> <img alt="Good/bad icon" src="<?php echo scriptPath; ?>/images/checkbad.png" id="s_email" /> </td> </tr> <!-- FIELD: Real name --> <tr> <td class="row3" style="width: 50%;"> <?php echo $lang->get('user_reg_lbl_field_realname'); ?><br /> <small><?php echo $lang->get('user_reg_msg_realname_optional'); ?></small> </td> <td class="row3" style="width: 50%;"> <input tabindex="5" type="text" name="real_name" size="30" value="<?php echo $realname; ?>" /></td><td class="row3" style="max-width: 24px;"> </td> </tr> <!-- FIELD: CAPTCHA image --> <tr> <td class="row1" style="width: 50%;" rowspan="2"> <?php echo $lang->get('user_reg_lbl_field_captcha'); ?><br /> <small> <?php echo $lang->get('user_reg_msg_captcha_pleaseenter', array('regen_flags' => 'href="#" onclick="regenCaptcha(); return false;"')); ?><br /> <br /> <?php echo $lang->get('user_reg_msg_captcha_blind'); ?> </small> </td> <td colspan="2" class="row1"> <img id="captchaimg" alt="CAPTCHA image" src="<?php echo makeUrlNS('Special', 'Captcha/'.$captchacode); ?>" /> <span id="b_username"></span> </td> </tr> <!-- FIELD: CAPTCHA input field --> <tr> <td class="row1" colspan="2"> <?php echo $lang->get('user_reg_lbl_field_captcha_code'); ?> <input tabindex="6" name="captchacode" type="text" size="10" /> <input type="hidden" name="captchahash" value="<?php echo $captchacode; ?>" /> </td> </tr> <!-- FIELD: TOU --> <?php if ( !empty($terms) ): ?> <tr> <td class="row1" colspan="3"> <?php echo $lang->get('user_reg_msg_please_read_tou'); ?> </td> </tr> <tr> <td class="row3" colspan="3"> <div style="border: 1px solid #000000; height: 75px; width: 60%; clip: rect(0px,auto,auto,0px); overflow: auto; background-color: #FFF; margin: 0 auto; padding: 4px;"> <?php echo RenderMan::render($terms); ?> </div> <p style="text-align: center;"> <label> <input tabindex="7" type="checkbox" name="tou_agreed" /> <b><?php echo $lang->get('user_reg_lbl_field_tou'); ?></b> </label> </p> </td> </tr> <?php endif; ?> <!-- FIELD: submit button --> <tr> <th class="subhead" colspan="3" style="text-align: center;"> <input tabindex="8" type="submit" name="submit" value="<?php echo $lang->get('user_reg_btn_create_account'); ?>" /> </td> </tr> </table> </div> <?php $val = ( $coppa ) ? 'yes' : 'no'; echo '<input type="hidden" name="coppa" value="' . $val . '" />'; ?> <input type="hidden" name="challenge_data" value="<?php echo $challenge; ?>" /> <input type="hidden" name="use_crypt" value="no" /> <input type="hidden" name="crypt_key" value="<?php echo $pubkey; ?>" /> <input type="hidden" name="crypt_data" value="" /> <script type="text/javascript"> // ENCRYPTION CODE function runEncryption() { var frm = document.forms.regform; if ( frm.password.value.length < 1 ) return true; pass1 = frm.password.value; pass2 = frm.password_confirm.value; if ( pass1 != pass2 ) { alert($lang.get('user_reg_err_alert_password_nomatch')); return false; } if ( pass1.length < 6 && pass1.length > 0 ) { alert($lang.get('user_reg_err_alert_password_tooshort')); return false; } if(aes_self_test()) { frm.use_crypt.value = 'yes'; var cryptkey = frm.crypt_key.value; frm.crypt_key.value = hex_md5(cryptkey); cryptkey = hexToByteArray(cryptkey); if(!cryptkey || ( ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ) && cryptkey.length != keySizeInBits / 8 ) { frm.submit.disabled = true; len = ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ? '\nLen: '+cryptkey.length : ''; alert('The key is messed up\nType: '+typeof(cryptkey)+len); } pass = frm.password.value; pass = stringToByteArray(pass); cryptstring = rijndaelEncrypt(pass, cryptkey, 'ECB'); if(!cryptstring) { return false; } cryptstring = byteArrayToHex(cryptstring); frm.crypt_data.value = cryptstring; frm.password.value = ""; frm.password_confirm.value = ""; } return true; } </script> </form> <!-- Don't optimize this script, it fails when compressed --> <enano:no-opt> <script type="text/javascript"> // <![CDATA[ var namegood = false; function validateForm(field) { if ( typeof(field) != 'object' ) { field = { name: '_nil', value: '_nil' } } // wait until $lang is initted if ( typeof($lang) != 'object' ) { setTimeout('validateForm();', 200); return false; } var frm = document.forms.regform; failed = false; // Username if(!namegood && ( field.name == 'username' || field.name == '_nil' ) ) { //if(frm.username.value.match(/^([A-z0-9 \!@\-\(\)]+){2,}$/ig)) var regex = new RegExp('^([^<>&\?]+){2,}$', 'ig'); if ( frm.username.value.match(regex) ) { document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/checkunk.png'; document.getElementById('e_username').innerHTML = ' '; } else { failed = true; document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/checkbad.png'; document.getElementById('e_username').innerHTML = '<br /><small>' + $lang.get('user_reg_err_username_invalid') + '</small>'; } } document.getElementById('b_username').innerHTML = ''; if(hex_md5(frm.real_name.value) == '5a397df72678128cf0e8147a2befd5f1') { document.getElementById('b_username').innerHTML = '<br /><br />Hey...I know you!<br /><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/Bill_Gates_2004_cr.jpg/220px-Bill_Gates_2004_cr.jpg" />'; } // Password if ( field.name == 'password' || field.name == 'password_confirm' || field.name == '_nil' ) { if(frm.password.value.match(/^(.+){6,}$/ig) && frm.password_confirm.value.match(/^(.+){6,}$/ig) && frm.password.value == frm.password_confirm.value ) { document.getElementById('s_password').src='<?php echo scriptPath; ?>/images/check.png'; document.getElementById('e_password').innerHTML = '<br /><small>' + $lang.get('user_reg_err_password_good') + '</small>'; } else { failed = true; if(frm.password.value.length < 6) { document.getElementById('e_password').innerHTML = '<br /><small>' + $lang.get('user_reg_msg_password_length') + '</small>'; } else if(frm.password.value != frm.password_confirm.value) { document.getElementById('e_password').innerHTML = '<br /><small>' + $lang.get('user_reg_msg_password_needmatch') + '</small>'; } else { document.getElementById('e_password').innerHTML = ''; } document.getElementById('s_password').src='<?php echo scriptPath; ?>/images/checkbad.png'; } } // E-mail address // workaround for idiot jEdit bug if ( validateEmail(frm.email.value) && ( field.name == 'email' || field.name == '_nil' ) ) { document.getElementById('s_email').src='<?php echo scriptPath; ?>/images/check.png'; } else { failed = true; document.getElementById('s_email').src='<?php echo scriptPath; ?>/images/checkbad.png'; } if(failed) { frm.submit.disabled = 'disabled'; } else { frm.submit.disabled = false; } } function checkUsername() { var frm = document.forms.regform; if(!namegood) { var regex = new RegExp('^([^<>&\?]+){2,}$', 'ig'); if ( frm.username.value.match(regex) ) { document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/checkunk.png'; document.getElementById('e_username').innerHTML = ' '; } else { document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/checkbad.png'; document.getElementById('e_username').innerHTML = '<br /><small>' + $lang.get('user_reg_err_username_invalid') + '</small>'; return false; } } document.getElementById('e_username').innerHTML = '<br /><small><b>' + $lang.get('user_reg_msg_username_checking') + '</b></small>'; ajaxGet('<?php echo scriptPath; ?>/ajax.php?title=null&_mode=checkusername&name='+escape(frm.username.value), function() { if ( ajax.readyState == 4 && ajax.status == 200 ) if(ajax.responseText == 'good') { document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/check.png'; document.getElementById('e_username').innerHTML = '<br /><small><b>' + $lang.get('user_reg_msg_username_available') + '</b></small>'; namegood = true; } else if(ajax.responseText == 'bad') { document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/checkbad.png'; document.getElementById('e_username').innerHTML = '<br /><small><b>' + $lang.get('user_reg_msg_username_unavailable') + '</b></small>'; namegood = false; } else { document.getElementById('e_username').innerHTML = ajax.responseText; } }); } function regenCaptcha() { var frm = document.forms.regform; document.getElementById('captchaimg').src = '<?php echo makeUrlNS("Special", "Captcha/$captchacode"); ?>/'+Math.floor(Math.random() * 100000); return false; } addOnloadHook(function() { <?php if ( getConfig('pw_strength_enable') == '1' ): ?> var frm = document.forms.regform; load_component('pwstrength'); password_score_field(frm.password); <?php endif; ?> load_component('crypto'); validateForm(); setTimeout('checkUsername();', 1000); }); // ]]> </script> </enano:no-opt> <?php } else { $year = intval( enano_date('Y') ); $year = $year - 13; $month = enano_date('F'); $day = enano_date('d'); $yo13_date = "$month $day, $year"; $link_coppa_yes = makeUrlNS('Special', 'Register', 'coppa=yes', true); $link_coppa_no = makeUrlNS('Special', 'Register', 'coppa=no', true); // COPPA enabled, ask age echo '<div class="tblholder">'; echo '<table border="0" cellspacing="1" cellpadding="4">'; echo '<tr> <td class="row1"> ' . $lang->get('user_reg_coppa_title') . ' </td> </tr> <tr> <td class="row3"> <a href="' . $link_coppa_no . '">' . $lang->get('user_reg_coppa_link_atleast13', array( 'yo13_date' => $yo13_date )) . '</a><br /> <a href="' . $link_coppa_yes . '">' . $lang->get('user_reg_coppa_link_not13', array( 'yo13_date' => $yo13_date )) . '</a> </td> </tr>'; echo '</table>'; echo '</div>'; } $template->footer(); } function page_Special_Contributions() { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; // This is a vast improvement over the old Special:Contributions in 1.0.x. $template->header(); $user = $paths->getParam(); if ( !$user && isset($_GET['user']) ) { $user = $_GET['user']; } else if ( !$user && !isset($_GET['user']) ) { echo '<p>' . $lang->get('userfuncs_contribs_err_no_user') . '</p>'; $template->footer(); return; } $user = $db->escape($user); $q = 'SELECT log_type, time_id, action, date_string, page_id, namespace, author, edit_summary, minor_edit, page_id, namespace, ( action = \'edit\' ) AS is_edit FROM '.table_prefix.'logs WHERE author=\''.$user.'\' AND log_type=\'page\' AND is_draft != 1 ORDER BY is_edit DESC, time_id DESC;'; $q = $db->sql_query($q); if ( !$q ) $db->_die('SpecialUserFuncs selecting contribution data'); echo '<h3>' . $lang->get('userfuncs_contribs_heading_edits') . '</h3>'; $cnt_edits = 0; $cnt_other = 0; $current = 'cnt_edits'; $cls = 'row2'; while ( $row = $db->fetchrow($q) ) { if ( $current == 'cnt_edits' && $row['is_edit'] != 1 ) { // No longer processing page edits - split the table if ( $cnt_edits == 0 ) { echo '<p>' . $lang->get('userfuncs_contribs_msg_no_edits') . '</p>'; } else { echo '</table></div>'; echo '<h3>' . $lang->get('userfuncs_contribs_heading_other') . '</h3>'; } $current = 'cnt_other'; $cls = 'row2'; } if ( $$current == 0 ) { echo '<div class="tblholder"> <table border="0" cellspacing="1" cellpadding="4">'; echo ' <tr> <th>' . $lang->get('history_col_datetime') . '</th>'; echo ' <th>' . $lang->get('history_col_page') . '</th>'; if ( $current == 'cnt_edits' ) { echo ' <th>' . $lang->get('history_col_summary') . '</th>'; } echo ' <th>' . $lang->get('history_col_minor') . '</th>'; if ( $current == 'cnt_other' ) { echo ' <th>' . $lang->get('history_col_action_taken') . '</th> <th>' . $lang->get('history_col_extra') . '</th> '; } echo ' <th>' . $lang->get('history_col_actions') . '</th> </tr>'; } $$current++; $cls = ( $cls == 'row1' ) ? 'row2' : 'row1'; echo '<tr>'; // date & time echo ' <td class="' . $cls . '">' . enano_date('d M Y h:i a', $row['time_id']) . '</td>'; // page & link to said page echo ' <td class="' . $cls . '"><a href="' . makeUrlNS($row['namespace'], $row['page_id']) . '">' . get_page_title_ns($row['page_id'], $row['namespace']) . '</a></td>'; switch ( $row['action'] ) { case 'edit': if ( $row['edit_summary'] == 'Automatic backup created when logs were purged' ) { $row['edit_summary'] = $lang->get('history_summary_clearlogs'); } else if ( empty($row['edit_summary']) ) { $row['edit_summary'] = '<span style="color: #808080">' . $lang->get('history_summary_none_given') . '</span>'; } echo ' <td class="' . $cls . '">' . $row['edit_summary'] . '</td>'; if ( $row['minor_edit'] == 1 ) { echo '<td class="' . $cls . '"><b>M</b></td>'; } else { echo '<td class="' . $cls . '"></td>'; } break; case 'prot': echo ' <td class="' . $cls . '"></td>'; echo ' <td class="' . $cls . '">' . $lang->get('history_log_protect') . '</td>'; echo ' <td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $row['edit_summary'] . '</td>'; break; case 'unprot': echo ' <td class="' . $cls . '"></td>'; echo ' <td class="' . $cls . '">' . $lang->get('history_log_unprotect') . '</td>'; echo ' <td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $row['edit_summary'] . '</td>'; break; case 'semiprot': echo ' <td class="' . $cls . '"></td>'; echo ' <td class="' . $cls . '">' . $lang->get('history_log_semiprotect') . '</td>'; echo ' <td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $row['edit_summary'] . '</td>'; break; case 'rename': echo ' <td class="' . $cls . '"></td>'; echo ' <td class="' . $cls . '">' . $lang->get('history_log_rename') . '</td>'; echo ' <td class="' . $cls . '">' . $lang->get('history_extra_oldtitle') . ' ' . htmlspecialchars($row['edit_summary']) . '</td>'; break; case 'create': echo ' <td class="' . $cls . '"></td>'; echo ' <td class="' . $cls . '">' . $lang->get('history_log_create') . '</td>'; echo ' <td class="' . $cls . '"></td>'; break; case 'delete': echo ' <td class="' . $cls . '"></td>'; echo ' <td class="' . $cls . '">' . $lang->get('history_log_delete') . '</td>'; echo ' <td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $row['edit_summary'] . '</td>'; break; case 'reupload': echo ' <td class="' . $cls . '"></td>'; echo ' <td class="' . $cls . '">' . $lang->get('history_log_uploadnew') . '</td>'; echo ' <td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $row['edit_summary'] . '</td>'; break; } // actions column echo ' <td class="' . $cls . '" style="text-align: center;">'; if ( $row['is_edit'] == 1 ) { echo ' <a href="' . makeUrlNS($row['namespace'], $row['page_id'], "oldid={$row['time_id']}", true) . '">' . $lang->get('history_action_view') . '</a> | '; echo ' <a href="' . makeUrlNS($row['namespace'], $row['page_id'], "do=rollback&id={$row['time_id']}", true) . '">' . $lang->get('history_action_restore') . '</a>'; } else { echo ' <a href="' . makeUrlNS($row['namespace'], $row['page_id'], "do=rollback&id={$row['time_id']}", true) . '">' . $lang->get('history_action_revert') . '</a>'; } echo ' </td>'; if ( $current == 'cnt_other' && $cnt_edits + $cnt_other >= $db->numrows($q) ) { echo '</table></div>'; } } if ( $current == 'cnt_edits' ) { // no "other" edits, close the table if ( $cnt_edits > 0 ) echo '</table></div>'; else echo '<p>' . $lang->get('userfuncs_contribs_msg_no_edits') . '</p>'; echo '<h3>' . $lang->get('userfuncs_contribs_heading_other') . '</h3>'; echo '<p>' . $lang->get('userfuncs_contribs_msg_no_other') . '</p>'; } $db->free_result(); $template->footer(); } function page_Special_ChangeStyle() { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; if ( !$session->user_logged_in ) { die_friendly('Access denied', '<p>You must be logged in to change your style. Spoofer.</p>'); } if(isset($_POST['theme']) && isset($_POST['style']) && isset($_POST['return_to'])) { if ( !preg_match('/^([a-z0-9_-]+)$/i', $_POST['theme']) ) die('Hacking attempt'); if ( !preg_match('/^([a-z0-9_-]+)$/i', $_POST['style']) ) die('Hacking attempt'); $d = ENANO_ROOT . '/themes/' . $_POST['theme']; $f = ENANO_ROOT . '/themes/' . $_POST['theme'] . '/css/' . $_POST['style'] . '.css'; if ( !file_exists($d) || !is_dir($d) ) { die('The directory "'.$d.'" does not exist.'); } if ( !file_exists($f) ) { die('The file "'.$f.'" does not exist.'); } $d = $db->escape($_POST['theme']); $f = $db->escape($_POST['style']); $q = 'UPDATE '.table_prefix.'users SET theme=\''.$d.'\',style=\''.$f.'\' WHERE username=\''.$session->username.'\''; if ( !$db->sql_query($q) ) { $db->_die('Your theme/style preferences were not updated.'); } else { redirect(makeUrl($_POST['return_to']), $lang->get('userfuncs_changetheme_success_title'), $lang->get('userfuncs_changetheme_success_body'), 3); } } else { $template->header(); $ret = ( isset($_POST['return_to']) ) ? $_POST['return_to'] : $paths->getParam(0); if ( !$ret ) { $ret = get_main_page(); } ?> <form action="<?php echo makeUrl($paths->page); ?>" method="post"> <?php if ( !isset($_POST['themeselected']) ) { ?> <h3><?php echo $lang->get('userfuncs_changetheme_heading_theme'); ?></h3> <p> <select name="theme"> <?php foreach ( $template->theme_list as $t ) { if ( $t['enabled'] ) { echo '<option value="'.$t['theme_id'].'"'; if ( $t['theme_id'] == $session->theme ) { echo ' selected="selected"'; } echo '>' . $t['theme_name'] . '</option>'; } } ?> </select> </p> <p><input type="hidden" name="return_to" value="<?php echo $ret; ?>" /> <input type="submit" name="themeselected" value="<?php echo $lang->get('userfuncs_changetheme_btn_continue'); ?>" /></p> <?php } else { $theme = $_POST['theme']; if ( !preg_match('/^([0-9A-z_-]+)$/i', $theme ) ) die('Hacking attempt'); ?> <h3><?php echo $lang->get('userfuncs_changetheme_heading_style'); ?></h3> <p> <select name="style"> <?php $dir = './themes/'.$theme.'/css/'; $list = Array(); // Open a known directory, and proceed to read its contents if (is_dir($dir)) { if ($dh = opendir($dir)) { while (($file = readdir($dh)) !== false) { if(preg_match('#^(.*?)\.css$#is', $file) && $file != '_printable.css') { $list[] = substr($file, 0, strlen($file)-4); } } closedir($dh); } } else die($dir.' is not a dir'); foreach ( $list as $l ) { echo '<option value="'.$l.'">'.capitalize_first_letter($l).'</option>'; } ?> </select> </p> <p><input type="hidden" name="return_to" value="<?php echo $ret; ?>" /> <input type="hidden" name="theme" value="<?php echo $theme; ?>" /> <input type="submit" name="allclear" value="<?php echo $lang->get('userfuncs_changetheme_btn_allclear'); ?>" /></p> <?php } ?> </form> <?php $template->footer(); } } function page_Special_ActivateAccount() { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; $user = $paths->getParam(0); if ( !$user ) { die_friendly($lang->get('userfuncs_activate_err_badlink_title'), '<p>' . $lang->get('userfuncs_activate_err_badlink_body') . '</p>'); } $key = $paths->getParam(1); if ( !$key ) { die_friendly($lang->get('userfuncs_activate_err_badlink_title'), '<p>' . $lang->get('userfuncs_activate_err_badlink_body') . '</p>'); } $s = $session->activate_account(str_replace('_', ' ', $user), $key); if ( $s > 0 ) { die_friendly($lang->get('userfuncs_activate_success_title'), '<p>' . $lang->get('userfuncs_activate_success_body') . '</p>'); } else { die_friendly($lang->get('userfuncs_activate_err_badlink_title'), '<p>' . $lang->get('userfuncs_activate_err_bad_key') . '</p>'); } } function page_Special_Captcha() { global $db, $session, $paths, $template, $plugins; // Common objects if ( $paths->getParam(0) == 'make' ) { $session->kill_captcha(); echo $session->make_captcha(); return; } $hash = $paths->getParam(0); if ( !$hash || !preg_match('#^([0-9a-f]*){32,40}$#i', $hash) ) { $paths->main_page(); } $session->make_captcha(7, $hash); $code = $session->generate_captcha_code(); $q = $db->sql_query('UPDATE ' . table_prefix . "captcha SET code = '$code' WHERE session_id = '$hash';"); if ( !$q ) $db->_die(); require ( ENANO_ROOT.'/includes/captcha.php' ); $captcha = captcha_object($hash, 'freecap'); // $captcha->debug = true; $captcha->make_image(); exit; } function page_Special_PasswordReset() { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; $template->header(); if($paths->getParam(0) == 'stage2') { $user_id = intval($paths->getParam(1)); $encpass = $paths->getParam(2); if ( $user_id < 2 ) { echo '<p>Hacking attempt</p>'; $template->footer(); return false; } if(!preg_match('#^([a-f0-9]+)$#i', $encpass)) { echo '<p>Hacking attempt</p>'; $template->footer(); return false; } $q = $db->sql_query('SELECT username,temp_password_time FROM '.table_prefix.'users WHERE user_id='.$user_id.' AND temp_password=\'' . $encpass . '\';'); if($db->numrows() < 1) { echo '<p>Invalid credentials</p>'; $template->footer(); return false; } $row = $db->fetchrow(); $db->free_result(); if ( ( intval($row['temp_password_time']) + ( 3600 * 24 ) ) < time() ) { echo '<p>' . $lang->get('userfuncs_passreset_err_pass_expired', array('reset_url' => makeUrlNS('Special', 'PasswordReset'))) . '</p>'; $template->footer(); return false; } if ( isset($_POST['do_stage2']) ) { $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); if($_POST['use_crypt'] == 'yes') { $crypt_key = $session->fetch_public_key($_POST['crypt_key']); if(!$crypt_key) { echo $lang->get('user_err_key_not_found'); $template->footer(); return false; } $crypt_key = hexdecode($crypt_key); $data = $aes->decrypt($_POST['crypt_data'], $crypt_key, ENC_HEX); if(strlen($data) < 6) { echo $lang->get('userfuncs_passreset_err_too_short'); $template->footer(); return false; } } else { $data = $_POST['pass']; $conf = $_POST['pass_confirm']; if($data != $conf) { echo $lang->get('userfuncs_passreset_err_no_match'); $template->footer(); return false; } if(strlen($data) < 6) { echo $lang->get('userfuncs_passreset_err_too_short'); $template->footer(); return false; } } if(empty($data)) { echo 'ERROR: Sanity check failed!'; $template->footer(); return false; } if ( getConfig('pw_strength_enable') == '1' ) { $min_score = intval(getConfig('pw_strength_minimum')); $inp_score = password_score($data); if ( $inp_score < $min_score ) { $url = makeUrl($paths->fullpage); echo "<p>" . $lang->get('userfuncs_passreset_err_failed_score', array('inp_score' => $inp_score, 'url' => $url)) . "</p>"; $template->footer(); return false; } } $encpass = $session->pk_encrypt($data, ENC_HEX); $q = $db->sql_query('UPDATE '.table_prefix.'users SET password=\'' . $encpass . '\',temp_password=\'\',temp_password_time=0 WHERE user_id='.$user_id.';'); if($q) { $session->login_without_crypto($row['username'], $data); echo '<p>' . $lang->get('userfuncs_passreset_stage2_success', array('url_mainpage' => makeUrl(get_main_page()))) . '</p>'; } else { echo $db->get_error(); } $template->footer(); return false; } // Password reset form $pubkey = $session->rijndael_genkey(); $evt_get_score = ( getConfig('pw_strength_enable') == '1' ) ? 'onkeyup="password_score_field(this);" ' : ''; $pw_meter = ( getConfig('pw_strength_enable') == '1' ) ? '<tr><td class="row1">' . $lang->get('userfuncs_passreset_stage2_lbl_strength') . '</td><td class="row1"><div id="pwmeter"></div><script type="text/javascript">password_score_field(document.forms.resetform.pass);</script></td></tr>' : ''; $pw_blurb = ( getConfig('pw_strength_enable') == '1' && intval(getConfig('pw_strength_minimum')) > -10 ) ? '<br /><small>' . $lang->get('userfuncs_passreset_stage2_blurb_strength') . '</small>' : ''; ?> <form action="<?php echo makeUrl($paths->fullpage); ?>" method="post" name="resetform" onsubmit="return runEncryption();"> <br /> <div class="tblholder"> <table border="0" style="width: 100%;" cellspacing="1" cellpadding="4"> <tr><th colspan="2"><?php echo $lang->get('userfuncs_passreset_stage2_th'); ?></th></tr> <tr><td class="row1"><?php echo $lang->get('userfuncs_passreset_stage2_lbl_password'); ?> <?php echo $pw_blurb; ?></td><td class="row1"><input name="pass" type="password" <?php echo $evt_get_score; ?>/></td></tr> <tr><td class="row2"><?php echo $lang->get('userfuncs_passreset_stage2_lbl_confirm'); ?> </td><td class="row2"><input name="pass_confirm" type="password" /></td></tr> <?php echo $pw_meter; ?> <tr> <td colspan="2" class="row3" style="text-align: center;"> <input type="hidden" name="use_crypt" value="no" /> <input type="hidden" name="crypt_key" value="<?php echo $pubkey; ?>" /> <input type="hidden" name="crypt_data" value="" /> <input type="submit" name="do_stage2" value="<?php echo $lang->get('userfuncs_passreset_stage2_btn_submit'); ?>" /> </td> </tr> </table> </div> </form> <script type="text/javascript"> if ( !KILL_SWITCH ) { disableJSONExts(); str = ''; for(i=0;i<keySizeInBits/4;i++) str+='0'; var key = hexToByteArray(str); var pt = hexToByteArray(str); var ct = rijndaelEncrypt(pt, key, "ECB"); var ct = byteArrayToHex(ct); switch(keySizeInBits) { case 128: v = '66e94bd4ef8a2c3b884cfa59ca342b2e'; break; case 192: v = 'aae06992acbf52a3e8f4a96ec9300bd7aae06992acbf52a3e8f4a96ec9300bd7'; break; case 256: v = 'dc95c078a2408989ad48a21492842087dc95c078a2408989ad48a21492842087'; break; } var testpassed = ( ct == v && md5_vm_test() ); var frm = document.forms.resetform; if(testpassed) { frm.use_crypt.value = 'yes'; var cryptkey = frm.crypt_key.value; frm.crypt_key.value = hex_md5(cryptkey); cryptkey = hexToByteArray(cryptkey); if(!cryptkey || ( ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ) && cryptkey.length != keySizeInBits / 8 ) { frm._login.disabled = true; len = ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ? '\nLen: '+cryptkey.length : ''; alert('The key is messed up\nType: '+typeof(cryptkey)+len); } } function runEncryption() { var frm = document.forms.resetform; pass1 = frm.pass.value; pass2 = frm.pass_confirm.value; if ( pass1 != pass2 ) { alert($lang.get('userfuncs_passreset_err_no_match')); return false; } if ( pass1.length < 6 ) { alert($lang.get('userfuncs_passreset_err_too_short')); return false; } if(testpassed) { pass = frm.pass.value; pass = stringToByteArray(pass); cryptstring = rijndaelEncrypt(pass, cryptkey, 'ECB'); if(!cryptstring) { return false; } cryptstring = byteArrayToHex(cryptstring); frm.crypt_data.value = cryptstring; frm.pass.value = ""; frm.pass_confirm.value = ""; } return true; } } </script> <?php $template->footer(); return true; } if ( $session->user_logged_in ) { $paths->main_page(); } if(isset($_POST['do_reset'])) { if($session->mail_password_reset($_POST['username'])) { echo '<p>' . $lang->get('userfuncs_passreset_stage1_success') . '</p>'; } else { echo '<p>' . $lang->get('userfuncs_passreset_stage1_error') . '</p>'; } $template->footer(); return true; } echo '<p>' . $lang->get('userfuncs_passreset_blurb_line1') . '</p> <p>' . $lang->get('userfuncs_passreset_blurb_line2') . '</p> <form action="'.makeUrl($paths->page).'" method="post" onsubmit="if(!submitAuthorized) return false;"> <p>' . $lang->get('userfuncs_passreset_lbl_username') . ' '.$template->username_field('username').'</p> <p><input type="submit" name="do_reset" value="' . $lang->get('userfuncs_passreset_btn_mailpasswd') . '" /></p> </form>'; $template->footer(); } function page_Special_Memberlist() { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; $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])'; } // 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', 'regist' => 'u.reg_time' ); $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 '<div class="tblholder"> <table border="0" cellspacing="1" cellpadding="4" style="text-align: center;"> <tr>'; echo '<td class="row1" style="width: 3.3714%;"><a href="' . makeUrlNS('Special', 'Memberlist', 'letter=&sort=' . $sortby . '&orderby=' . $target_order, true) . '">All</a></td>'; echo '<td class="row1" style="width: 3.3714%;"><a href="' . makeUrlNS('Special', 'Memberlist', 'letter=chr&sort=' . $sortby . '&orderby=' . $target_order, true) . '">#</a></td>'; foreach ( $startletters as $letter ) { echo '<td class="row1" style="width: 3.3714%;"><a href="' . makeUrlNS('Special', 'Memberlist', 'letter=' . $letter . '&sort=' . $sortby . '&orderby=' . $target_order, true) . '">' . strtoupper($letter) . '</a></td>'; } echo ' </tr> </table> </div>'; // User search if ( isset($_GET['finduser']) ) { $finduser = str_replace(array( '%', '_'), array('\\%', '\\_'), $_GET['finduser']); $finduser = str_replace(array('*', '?'), array('%', '_'), $finduser); $finduser = $db->escape($finduser); $username_where = ENANO_SQLFUNC_LOWERCASE . '(u.username) LIKE \'%' . strtolower($finduser) . '%\''; $finduser_url = 'finduser=' . rawurlencode($_GET['finduser']) . '&'; } else { if ( ENANO_DBLAYER == 'MYSQL' ) $username_where = 'lcase(u.username) REGEXP lcase("^' . $startletter_sql . '")'; else if ( ENANO_DBLAYER == 'PGSQL' ) $username_where = 'lower(u.username) ~ lower(\'^' . $startletter_sql . '\')'; $finduser_url = ''; } // Column markers $headings = '<tr> <th style="max-width: 50px;"> <a href="' . makeUrlNS('Special', 'Memberlist', $finduser_url . 'letter=' . $startletter . '&sort=uid&orderby=' . $sortorders['uid'], true) . '">#</a> </th> <th> <a href="' . makeUrlNS('Special', 'Memberlist', $finduser_url . 'letter=' . $startletter . '&sort=username&orderby=' . $sortorders['username'], true) . '">' . $lang->get('userfuncs_ml_column_username') . '</a> </th> <th> ' . $lang->get('userfuncs_ml_column_userlevel') . ' </th> <th> <a href="' . makeUrlNS('Special', 'Memberlist', $finduser_url . 'letter=' . $startletter . '&sort=email&orderby=' . $sortorders['email'], true) . '">' . $lang->get('userfuncs_ml_column_email') . '</a> </th> <th> <a href="' . makeUrlNS('Special', 'Memberlist', $finduser_url . 'letter=' . $startletter . '&sort=regist&orderby=' . $sortorders['regist'], true) . '">' . $lang->get('userfuncs_ml_column_regtime') . '</a> </th> </tr>'; // determine number of rows $q = $db->sql_query('SELECT u.user_id FROM '.table_prefix.'users AS u WHERE ' . $username_where . ' AND u.username != \'Anonymous\';'); if ( !$q ) $db->_die(); $num_rows = $db->numrows(); $db->free_result(); if ( !empty($finduser_url) ) { switch ( $num_rows ) { case 0: $str = $lang->get('userfuncs_ml_msg_matches_zero'); break; case 1: $str = $lang->get('userfuncs_ml_msg_matches_one'); break; default: $str = $lang->get('userfuncs_ml_msg_matches', array('matches' => $num_rows)); break; } echo "<h3>$str</h3>"; } // main selector $pgsql_additional_group_by = ( ENANO_DBLAYER == 'PGSQL' ) ? ', u.username, u.reg_time, u.email, u.user_level, u.user_has_avatar, u.avatar_type, x.email_public' : ''; $q = $db->sql_unbuffered_query('SELECT \'\' AS infobit, u.user_id, u.username, u.reg_time, u.email, u.user_level, u.user_has_avatar, u.avatar_type, x.email_public, COUNT(c.comment_id) AS num_comments FROM '.table_prefix.'users AS u LEFT JOIN '.table_prefix.'users_extra AS x ON ( u.user_id = x.user_id ) LEFT JOIN ' . table_prefix . 'comments AS c ON ( u.user_id = c.user_id ) WHERE ' . $username_where . ' AND u.username != \'Anonymous\' GROUP BY u.user_id' . $pgsql_additional_group_by . ' ORDER BY ' . $sort_sqllet . ' ' . $target_order . ';'); if ( !$q ) $db->_die(); // formatter parameters $formatter = new MemberlistFormatter(); $formatters = array( 'username' => array($formatter, 'username'), 'user_level' => array($formatter, 'user_level'), 'email' => array($formatter, 'email'), 'reg_time' => array($formatter, 'reg_time'), 'infobit' => array($formatter, 'infobit') ); $html = paginate( $q, // MySQL result resource '<tr> <td class="{_css_class}">{user_id}</td> <td class="{_css_class}" style="text-align: left;">{username}</td> <td class="{_css_class}">{user_level}</td> <td class="{_css_class}">{email}</small></td> <td class="{_css_class}">{reg_time}</td> </tr> <tr> <td colspan="5" class="row3" style="text-align: left;"> <div id="ml_moreinfo_{user_id}" style="display: none;"> {infobit} </div> </td> </tr> ', // TPL code for rows $num_rows, // Number of results makeUrlNS('Special', 'Memberlist', ( str_replace('%', '%%', $finduser_url) ) . 'letter=' . $startletter . '&offset=%s&sort=' . $sortby . '&orderby=' . $target_order ), // Result URL $offset, // Start at this number 25, // Results per page $formatters, // Formatting hooks '<div class="tblholder"> <table border="0" cellspacing="1" cellpadding="4" style="text-align: center;"> ' . $headings . ' ', // Header (printed before rows) ' ' . $headings . ' </table> </div> ' . '<div style="float: left;"> <form action="' . makeUrlNS('Special', 'Memberlist') . '" method="get" onsubmit="if ( !submitAuthorized ) return false;">' . ( urlSeparator == '&' ? '<input type="hidden" name="title" value="' . htmlspecialchars( $paths->page ) . '" />' : '' ) . ( $session->sid_super ? '<input type="hidden" name="auth" value="' . $session->sid_super . '" />' : '') . '<p>' . $lang->get('userfuncs_ml_lbl_finduser') . ' ' . $template->username_field('finduser') . ' <input type="submit" value="' . $lang->get('userfuncs_ml_btn_go') . '" /><br /> <small>' . $lang->get('userfuncs_ml_tip_wildcard') . '</small></p>' . '</form> </div>' // Footer (printed after rows) ); if ( $num_rows < 1 ) { echo ( isset($_GET['finduser']) ) ? '<p>' . $lang->get('userfuncs_ml_err_nousers_find') . '</p>' : '<p>' . $lang->get('userfuncs_ml_err_nousers') . '</p>'; } 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 global $lang; $userpage = $paths->nslist['User'] . sanitize_page_id($username); $class = ( isPage($userpage) ) ? '' : ' class="wikilink-nonexistent"'; $anchor = '<a href="' . makeUrlNS('User', sanitize_page_id($username)) . '"' . $class . ' onclick="load_component(\'jquery\'); load_component(\'jquery-ui\'); var el = document.getElementById(\'ml_moreinfo_' . $row['user_id'] . '\'); $(el).toggle(\'blind\'); return false;">' . htmlspecialchars($username) . '</a>'; if ( $session->user_level >= USER_LEVEL_ADMIN ) { $anchor .= ' <small>- <a href="' . makeUrlNS('Special', 'Administration', 'module=' . $paths->nslist['Admin'] . 'UserManager&src=get&username=' . urlencode($username), true) . '" onclick="ajaxAdminUser(\'' . addslashes(htmlspecialchars($username)) . '\'); return false;">' . $lang->get('userfuncs_ml_btn_adminuser') . '</a></small>'; } return $anchor; } function user_level($level, $row) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; switch ( $level ) { case USER_LEVEL_GUEST: $s_level = $lang->get('userfuncs_ml_level_guest'); break; case USER_LEVEL_MEMBER: case USER_LEVEL_CHPREF: $s_level = $lang->get('userfuncs_ml_level_member'); break; case USER_LEVEL_MOD: $s_level = $lang->get('userfuncs_ml_level_mod'); break; case USER_LEVEL_ADMIN: $s_level = $lang->get('userfuncs_ml_level_admin'); break; default: $s_level = $lang->get('userfuncs_ml_level_unknown', array( 'level' => $level )); } return $s_level; } function email($addy, $row) { global $lang; if ( $row['email_public'] == '1' ) { global $email; $addy = $email->encryptEmail($addy); return $addy; } else { return '<small><' . $lang->get('userfuncs_ml_email_nonpublic') . '></small>'; } } /** * Format a time as a reference to a day, with user-friendly "X days ago"/"Today"/"Yesterday" returned when relevant. * @param int UNIX timestamp * @return string */ function format_date($time) { global $lang; // Our formattting string to pass to enano_date() // This should not include minute/second info, only today's date in whatever format suits your fancy $formatstring = 'F j, Y'; // Today's date $today = enano_date($formatstring); // Yesterday's date $yesterday = enano_date($formatstring, (time() - (24*60*60))); // Date on the input $then = enano_date($formatstring, $time); // "X days ago" logic for ( $i = 2; $i <= 6; $i++ ) { // hours_in_day * minutes_in_hour * seconds_in_minute * num_days $offset = 24 * 60 * 60 * $i; $days_ago = enano_date($formatstring, (time() - $offset)); // so does the input timestamp match the date from $i days ago? if ( $then == $days_ago ) { // yes, return $i return $lang->get('userfuncs_ml_date_daysago', array('days_ago' => $i)); } } // either yesterday, today, or before 6 days ago switch($then) { case $today: return $lang->get('userfuncs_ml_date_today'); case $yesterday: return $lang->get('userfuncs_ml_date_yesterday'); default: return $then; } // .--. // |o_o | // |!_/ | // // \ \ // (| | ) // /'\_ _/`\ // \___)=(___/ return 'Linux rocks!'; } function reg_time($time, $row) { return $this->format_date($time); } function infobit($_, $row) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; $bit = ''; if ( $row['user_has_avatar'] == 1 ) { $bit .= '<div style="float: left; margin-right: 10px;"> <img alt=" " src="' . make_avatar_url(intval($row['user_id']), $row['avatar_type'], $row['email']) . '" /> </div>'; } $rank_data = $session->get_user_rank(intval($row['user_id'])); $userpage = $paths->nslist['User'] . sanitize_page_id($row['username']); $title = ( isPage($userpage) ) ? ' title="' . $lang->get('userfuncs_ml_tip_userpage') . '"' : ' title="' . $lang->get('userfuncs_ml_tip_nouserpage') . '"'; $bit .= '<a' . $title . ' href="' . makeUrlNS('User', $row['username'], false, true) . '" style="font-size: x-large; ' . $rank_data['rank_style'] . '">' . htmlspecialchars($row['username']) . '</a><br />'; if ( $rank_data['user_title'] ) $bit .= htmlspecialchars($rank_data['user_title']) . '<br />'; if ( $rank_data['rank_title'] ) $bit .= '<small>' . htmlspecialchars($lang->get($rank_data['rank_title'])) . '</small><br />'; $bit .= '<div style="text-align: right;"> <a href="' . makeUrlNS('Special', "PrivateMessages/Compose/To/{$row['username']}", false, true) . '" class="abutton abutton_blue"><img alt=" " src="' . cdnPath . '/images/icons/send_pm.png" /> ' . $lang->get('comment_btn_send_privmsg') . '</a> <a href="' . makeUrlNS('Special', "PrivateMessages/FriendList/Add/{$row['username']}", false, true) . '" class="abutton abutton_green"><img alt=" " src="' . cdnPath . '/images/icons/add_buddy.png" /> ' . $lang->get('comment_btn_add_buddy') . '</a> </div>'; return $bit; } } function page_Special_LangExportJSON() { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; $lang_id = ( $x = $paths->getParam(0) ) ? intval($x) : $lang->lang_id; if ( $lang->lang_id == $lang_id ) $lang_local =& $lang; else $lang_local = new Language($lang_id); $lang_strings = enano_json_encode($lang_local->strings); $etag = substr(sha1($lang_strings), 0, 20) . '-' . dechex($lang_local->lang_timestamp); if ( isset($_SERVER['HTTP_IF_NONE_MATCH']) ) { if ( "\"$etag\"" == $_SERVER['HTTP_IF_NONE_MATCH'] ) { header('HTTP/1.1 304 Not Modified'); exit(); } } $timestamp = enano_date('D, j M Y H:i:s T', $lang_local->lang_timestamp); // generate expires header $expires = date('r', mktime(-1, -1, -1, -1, -1, intval(date('y'))+1)); header("Last-Modified: $timestamp"); header("Date: $timestamp"); header("ETag: \"$etag\""); header('Content-type: text/javascript'); header("Expires: $expires"); $lang_local->fetch(); echo "if ( typeof(enano_lang) != 'object' ) var enano_lang = new Object(); enano_lang[{$lang->lang_id}] = " . $lang_strings . ";"; gzip_output(); exit(0); } /** * Fetches and displays an avatar from the filesystem. Avatar fetching is abstracted as of 1.1.4. */ function page_Special_Avatar() { global $db, $session, $paths, $template, $plugins; // Common objects global $aggressive_optimize_html; $aggressive_optimize_html = false; $img_types = array( IMAGE_TYPE_PNG => 'png', IMAGE_TYPE_GIF => 'gif', IMAGE_TYPE_JPG => 'jpg', IMAGE_TYPE_GRV => 'grv' ); $avi_id = $paths->getParam(0); if ( !$avi_id || !@preg_match('/^[a-f0-9]+$/', $avi_id) ) { echo 'Doesn\'t match the regexp'; return true; } $avi_id_dec = hexdecode($avi_id); $avi_id_dec = @unpack('Vdate/Vuid/vimg_type', $avi_id_dec); if ( !$avi_id_dec ) { echo 'Bad unpack'; return true; } // check parameters if ( !isset($img_types[$avi_id_dec['img_type']]) ) { echo 'Invalid image type'; return true; } // build file path $avi_type = $img_types[$avi_id_dec['img_type']]; // is this a gravatar? if ( $avi_type == 'grv' ) { // yes, we'll have to redirect // sanitize UID $uid = intval($avi_id_dec['uid']); // fetch email $q = $db->sql_query('SELECT email FROM ' . table_prefix . "users WHERE user_id = $uid;"); if ( !$q ) $db->_die(); if ( $db->numrows() < 1 ) return false; list($email) = $db->fetchrow_num(); $db->free_result(); $url = make_gravatar_url($url); // ship out the redirect header('HTTP/1.1 302 Permanent Redirect'); header("Location: $url"); } $avi_path = ENANO_ROOT . '/' . getConfig('avatar_directory') . '/' . $avi_id_dec['uid'] . '.' . $avi_type; if ( file_exists($avi_path) ) { $avi_mod_time = @filemtime($avi_path); $avi_mod_time = date('r', $avi_mod_time); $avi_size = @filesize($avi_path); header("Last-Modified: $avi_mod_time"); header("Content-Length: $avi_size"); header("Content-Type: image/$avi_type"); // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html header("Cache-Control: public"); // expire it 30 days from now $expiry_time = time() + ( 86400 * 30 ); header("Expires: " . date('r', $expiry_time)); $fh = @fopen($avi_path, 'r'); if ( !$fh ) { echo 'Could not open file'; return true; } while ( $fd = @fread($fh, 1024) ) { echo $fd; } fclose($fh); } return true; } ?>