plugins/SpecialUserFuncs.php~
changeset 0 902822492a68
equal deleted inserted replaced
-1:000000000000 0:902822492a68
       
     1 <?php
       
     2 /*
       
     3 Plugin Name: Special user/login-related pages
       
     4 Plugin URI: http://enano.homelinux.org/
       
     5 Description: Provides the pages Special:Login, Special:Logout, Special:Register, and Special:Preferences.
       
     6 Author: Dan Fuhry
       
     7 Version: 1.0
       
     8 Author URI: http://enano.homelinux.org/
       
     9 */
       
    10 
       
    11 /*
       
    12  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
       
    13  * Version 1.0 release candidate 2
       
    14  * Copyright (C) 2006-2007 Dan Fuhry
       
    15  *
       
    16  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
       
    17  * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
       
    18  *
       
    19  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
       
    20  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
       
    21  */
       
    22  
       
    23 global $db, $session, $paths, $template, $plugins; // Common objects
       
    24 
       
    25 $plugins->attachHook('base_classes_initted', '
       
    26   global $paths;
       
    27     $paths->add_page(Array(
       
    28       \'name\'=>\'Log in\',
       
    29       \'urlname\'=>\'Login\',
       
    30       \'namespace\'=>\'Special\',
       
    31       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       
    32       ));
       
    33     $paths->add_page(Array(
       
    34       \'name\'=>\'Log out\',
       
    35       \'urlname\'=>\'Logout\',
       
    36       \'namespace\'=>\'Special\',
       
    37       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       
    38       ));
       
    39     $paths->add_page(Array(
       
    40       \'name\'=>\'Register\',
       
    41       \'urlname\'=>\'Register\',
       
    42       \'namespace\'=>\'Special\',
       
    43       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       
    44       ));
       
    45     $paths->add_page(Array(
       
    46       \'name\'=>\'Edit Profile\',
       
    47       \'urlname\'=>\'Preferences\',
       
    48       \'namespace\'=>\'Special\',
       
    49       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       
    50       ));
       
    51     
       
    52     $paths->add_page(Array(
       
    53       \'name\'=>\'Contributions\',
       
    54       \'urlname\'=>\'Contributions\',
       
    55       \'namespace\'=>\'Special\',
       
    56       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       
    57       ));
       
    58     
       
    59     $paths->add_page(Array(
       
    60       \'name\'=>\'Change style\',
       
    61       \'urlname\'=>\'ChangeStyle\',
       
    62       \'namespace\'=>\'Special\',
       
    63       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       
    64       ));
       
    65     
       
    66     $paths->add_page(Array(
       
    67       \'name\'=>\'Activate user account\',
       
    68       \'urlname\'=>\'ActivateAccount\',
       
    69       \'namespace\'=>\'Special\',
       
    70       \'special\'=>0,\'visible\'=>0,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       
    71       ));
       
    72     
       
    73     $paths->add_page(Array(
       
    74       \'name\'=>\'Captcha\',
       
    75       \'urlname\'=>\'Captcha\',
       
    76       \'namespace\'=>\'Special\',
       
    77       \'special\'=>0,\'visible\'=>0,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       
    78       ));
       
    79     
       
    80     $paths->add_page(Array(
       
    81       \'name\'=>\'Forgot password\',
       
    82       \'urlname\'=>\'PasswordReset\',
       
    83       \'namespace\'=>\'Special\',
       
    84       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       
    85       ));
       
    86     ');
       
    87 
       
    88 // function names are IMPORTANT!!! The name pattern is: page_<namespace ID>_<page URLname, without namespace>
       
    89 
       
    90 $__login_status = '';
       
    91 
       
    92 function page_Special_Login()
       
    93 {
       
    94   global $db, $session, $paths, $template, $plugins; // Common objects
       
    95   global $__login_status;
       
    96   
       
    97   $pubkey = $session->rijndael_genkey();
       
    98   $challenge = $session->dss_rand();
       
    99   
       
   100   if ( isset($_GET['act']) && $_GET['act'] == 'getkey' )
       
   101   {
       
   102     $response = Array(
       
   103       'key' => $pubkey,
       
   104       'challenge' => $challenge
       
   105       );
       
   106     $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
       
   107     $response = $json->encode($response);
       
   108     echo $response;
       
   109     return null;
       
   110   }
       
   111   
       
   112   $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;
       
   113   if ( isset($_POST['login']) )
       
   114   {
       
   115     if ( in_array($_POST['auth_level'], array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') ) )
       
   116     {
       
   117       $level = intval($_POST['auth_level']);
       
   118     }
       
   119   }
       
   120   
       
   121   if ( $level > USER_LEVEL_MEMBER && !$session->user_logged_in )
       
   122   {
       
   123     $level = USER_LEVEL_MEMBER;
       
   124   }
       
   125   $template->header();
       
   126   echo '<form action="'.makeUrl($paths->nslist['Special'].'Login').'" method="post" name="loginform" onsubmit="runEncryption();">';
       
   127   $header = ( $level > USER_LEVEL_MEMBER ) ? 'Please re-enter your login details' : 'Please enter your username and password to log in.';
       
   128   if ( isset($_POST['login']) )
       
   129   {
       
   130     echo '<p>'.$__login_status.'</p>';
       
   131   }
       
   132   if ( $p = $paths->getAllParams() )
       
   133   {
       
   134     echo '<input type="hidden" name="return_to" value="'.$p.'" />';
       
   135   }
       
   136   else if ( isset($_POST['login']) && isset($_POST['return_to']) )
       
   137   {
       
   138     echo '<input type="hidden" name="return_to" value="'.htmlspecialchars($_POST['return_to']).'" />';
       
   139   }
       
   140   ?>
       
   141     <div class="tblholder">
       
   142       <table border="0" style="width: 100%;" cellspacing="1" cellpadding="4">
       
   143         <tr>
       
   144           <th colspan="3"><?php echo $header; ?></th>
       
   145         </tr>
       
   146         <tr>
       
   147           <td colspan="3" class="row1">
       
   148             <?php
       
   149             if ( $level <= USER_LEVEL_MEMBER )
       
   150             {
       
   151               echo '<p>Logging in enables you to use your preferences and access member information. If you don\'t have a username and password here, you can <a href="'.makeUrl($paths->nslist['Special'].'Register').'">create an account</a>.</p>';
       
   152             }
       
   153             else
       
   154             {
       
   155               echo '<p>You are requesting that a sensitive operation be performed. To continue, please re-enter your password to confirm your identity.</p>';
       
   156             }
       
   157             ?>
       
   158           </td>
       
   159         </tr>
       
   160         <tr>
       
   161           <td class="row2">
       
   162             Username:
       
   163           </td>
       
   164           <td class="row1">
       
   165             <input name="username" size="25" type="text" <?php
       
   166               if ( $level <= USER_LEVEL_MEMBER )
       
   167               {
       
   168                 echo 'tabindex="1" ';
       
   169               }
       
   170               if ( $session->user_logged_in )
       
   171               {
       
   172                 echo 'value="' . $session->username . '"';
       
   173               }
       
   174               ?> />
       
   175           </td>
       
   176           <?php if ( $level <= USER_LEVEL_MEMBER ) { ?>
       
   177           <td rowspan="2" class="row3">
       
   178             <small>Forgot your password? <a href="<?php echo makeUrlNS('Special', 'PasswordReset'); ?>">No problem.</a><br />
       
   179             Maybe you need to <a href="<?php echo makeUrlNS('Special', 'Register'); ?>">create an account</a>.</small>
       
   180           </td>
       
   181           <?php } ?>
       
   182         </tr>
       
   183         <tr>
       
   184           <td class="row2">Password:<br /></td><td class="row1"><input name="pass" size="25" type="password" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '2' : '1'; ?>" /></td>
       
   185          </tr>
       
   186          <?php if ( $level <= USER_LEVEL_MEMBER ) { ?>
       
   187          <tr>
       
   188            <td class="row3" colspan="3">
       
   189              <p><b>Important note regarding cryptography:</b> Some countries do not allow the import or use of cryptographic technology. If you live in one of the countries listed below, you should <a href="<?php if($p=$paths->getParam(0))$u='/'.$p;else $u='';echo makeUrl($paths->page.$u, 'level='.$level.'&use_crypt=0', true); ?>">log in without using encryption</a>.</p>
       
   190              <p>This restriction applies to the following countries: Belarus, China, India, Israel, Kazakhstan, Mongolia, Pakistan, Russia, Saudi Arabia, Singapore, Tunisia, Venezuela, and Vietnam.</p>
       
   191            </td>
       
   192          </tr>
       
   193          <?php } ?>
       
   194          <tr>
       
   195            <th colspan="3" style="text-align: center" class="subhead"><input type="submit" name="login" value="Log in" tabindex="3" /></th>
       
   196          </tr>
       
   197       </table>
       
   198     </div>
       
   199       <input type="hidden" name="challenge_data" value="<?php echo $challenge; ?>" />
       
   200       <input type="hidden" name="use_crypt" value="no" />
       
   201       <input type="hidden" name="crypt_key" value="<?php echo $pubkey; ?>" />
       
   202       <input type="hidden" name="crypt_data" value="" />
       
   203       <input type="hidden" name="auth_level" value="<?php echo (string)$level; ?>" />
       
   204     </form>
       
   205     <?php
       
   206       echo $session->aes_javascript('loginform', 'pass', 'use_crypt', 'crypt_key', 'crypt_data', 'challenge_data');
       
   207     ?>
       
   208   <?php
       
   209   $template->footer();
       
   210 }
       
   211 
       
   212 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
       
   213 {
       
   214   global $db, $session, $paths, $template, $plugins; // Common objects
       
   215   global $__login_status;
       
   216   if ( isset($_GET['act']) && $_GET['act'] == 'ajaxlogin' )
       
   217   {
       
   218     $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
       
   219     $data = $json->decode($_POST['params']);
       
   220     $level = ( isset($data['level']) ) ? intval($data['level']) : USER_LEVEL_MEMBER;
       
   221     $result = $session->login_with_crypto($data['username'], $data['crypt_data'], $data['crypt_key'], $data['challenge'], $level);
       
   222     $session->start();
       
   223     //echo "$result\n$session->sid_super";
       
   224     //exit;
       
   225     if ( $result == 'success' )
       
   226     {
       
   227       $response = Array(
       
   228           'result' => 'success',
       
   229           'key' => $session->sid_super // ( ( $session->sid_super ) ? $session->sid_super : $session->sid )
       
   230         );
       
   231     }
       
   232     else
       
   233     {
       
   234       $response = Array(
       
   235           'result' => 'error',
       
   236           'error' => $result
       
   237         );
       
   238     }
       
   239     $response = $json->encode($response);
       
   240     echo $response;
       
   241     $db->close();
       
   242     exit;
       
   243   }
       
   244   if(isset($_POST['login'])) {
       
   245     if($_POST['use_crypt'] == 'yes')
       
   246     {
       
   247       $result = $session->login_with_crypto($_POST['username'], $_POST['crypt_data'], $_POST['crypt_key'], $_POST['challenge_data'], intval($_POST['auth_level']));
       
   248     }
       
   249     else
       
   250     {
       
   251       $result = $session->login_without_crypto($_POST['username'], $_POST['pass'], false, intval($_POST['auth_level']));
       
   252     }
       
   253     $session->start();
       
   254     $paths->init();
       
   255     if($result == 'success')
       
   256     {
       
   257       $template->load_theme($session->theme, $session->style);
       
   258       if(isset($_POST['return_to']))
       
   259       {
       
   260         $name = ( isset($paths->pages[$_POST['return_to']]['name']) ) ? $paths->pages[$_POST['return_to']]['name'] : $_POST['return_to'];
       
   261         redirect( makeUrl($_POST['return_to']), 'Login successful', 'You have successfully logged into the '.getConfig('site_name').' site as "'.$session->username.'". Redirecting to ' . $name . '...' );
       
   262       }
       
   263       else
       
   264       {
       
   265         $paths->main_page();
       
   266       }
       
   267     }
       
   268     else
       
   269     {
       
   270       $GLOBALS['__login_status'] = $result;
       
   271     }
       
   272   }
       
   273 }
       
   274 
       
   275 function page_Special_Logout() {
       
   276   global $db, $session, $paths, $template, $plugins; // Common objects
       
   277   $l = $session->logout();
       
   278   if($l == 'success') $paths->main_page();
       
   279   $template->header();
       
   280   echo '<h3>An error occurred during the logout process.</h3><p>'.$l.'</p>';
       
   281   $template->footer();
       
   282 }
       
   283 
       
   284 function page_Special_Register() {
       
   285   global $db, $session, $paths, $template, $plugins; // Common objects
       
   286   if(getConfig('account_activation') == 'disable' && ( ( $session->user_level >= USER_LEVEL_ADMIN && !isset($_GET['IWannaPlayToo']) ) || $session->user_level < USER_LEVEL_ADMIN || !$session->user_logged_in ))
       
   287   {
       
   288     $s = ($session->user_level >= USER_LEVEL_ADMIN) ? '<p>Oops...it seems that you <em>are</em> the administrator...hehe...you can also <a href="'.makeUrl($paths->page, 'IWannaPlayToo', true).'">force account registration to work</a>.</p>' : '';
       
   289     die_friendly('Registration disabled', '<p>The administrator has disabled new user registration on this site.</p>' . $s);
       
   290   }
       
   291   if(isset($_POST['submit'])) {
       
   292     $captcharesult = $session->get_captcha($_POST['captchahash']);
       
   293     if($captcharesult != $_POST['captchacode'])
       
   294       $s = 'The confirmation code you entered was incorrect.';
       
   295     else
       
   296       // CAPTCHA code was correct, create the account
       
   297       $s = $session->create_user($_POST['username'], $_POST['password'], $_POST['email'], $_POST['real_name']);
       
   298     if($s == 'success')
       
   299     {
       
   300       switch(getConfig('account_activation'))
       
   301       {
       
   302         case "none":
       
   303         default:
       
   304           $str = 'You may now <a href="'.makeUrlNS('Special', 'Login').'">log in</a> with the username and password that you created.';
       
   305           break;
       
   306         case "user":
       
   307           $str = 'Because this site requires account activation, you have been sent an e-mail with further instructions. Please follow the instructions in that e-mail to continue your registration.';
       
   308           break;
       
   309         case "admin":
       
   310           $str = 'Because this site requires administrative account activation, you cannot use your account at the moment. A notice has been sent to the site administration team that will alert them that your account has been created.';
       
   311           break;
       
   312       }
       
   313       die_friendly('Registration successful', '<p>Thank you for registering, your user account has been created. '.$str.'</p>');
       
   314     }
       
   315   }
       
   316   $template->header();
       
   317   echo 'A user account enables you to have greater control over your browsing experience.';
       
   318   $session->kill_captcha();
       
   319   $captchacode = $session->make_captcha();
       
   320   ?>
       
   321     <h3>Create a user account</h3>
       
   322     <form name="regform" action="<?php echo makeUrl($paths->page); ?>" method="post">
       
   323       <div class="tblholder">
       
   324         <table border="0" width="100%" cellspacing="1" cellpadding="4">
       
   325           <tr><th class="subhead" colspan="3">Please tell us a little bit about yourself.</th></tr>
       
   326           <?php if(isset($_POST['submit'])) echo '<tr><td colspan="3" class="row2" style="color: red;">'.$s.'</td></tr>'; ?>
       
   327           <tr><td class="row1" style="width: 50%;">Preferred username:<span id="e_username"></span></td><td class="row1" style="width: 50%;"><input type="text" name="username" size="30" onkeyup="namegood = false; validateForm();" onblur="checkUsername();" /></td><td class="row1" style="max-width: 24px;"><img alt="Good/bad icon" src="<?php echo scriptPath; ?>/images/bad.gif" id="s_username" /></td></tr>
       
   328           <tr><td class="row3" style="width: 50%;" rowspan="2">Password:<span id="e_password"></span></td><td class="row3" style="width: 50%;"><input type="password" name="password" size="30" onkeyup="validateForm();" /></td><td rowspan="2" class="row3" style="max-width: 24px;"><img alt="Good/bad icon" src="<?php echo scriptPath; ?>/images/bad.gif" id="s_password" /></td></tr>
       
   329           <tr><td class="row3" style="width: 50%;"><input type="password" name="password_confirm" size="30" onkeyup="validateForm();" /> <small>Enter your password again to confirm.</small></td></tr>
       
   330           <tr><td class="row1" style="width: 50%;">E-mail address:<?php if(getConfig('account_activation')=='user') echo '<br /><small>An e-mail with an account activation key will be sent to this address, so please ensure that it is correct.</small></td>'; ?><td class="row1" style="width: 50%;"><input type="text" name="email" size="30" onkeyup="validateForm();" /></td><td class="row1" style="max-width: 24px;"><img alt="Good/bad icon" src="<?php echo scriptPath; ?>/images/bad.gif" id="s_email" /></td></tr>
       
   331           <tr><td class="row3" style="width: 50%;">Real name:<br /><small>Giving your real name is totally optional. If you choose to provide your real name, it will be used to provide attribution for any edits or contributions you may make to this site.</small><td class="row3" style="width: 50%;"><input type="text" name="real_name" size="30" /></td><td class="row3" style="max-width: 24px;"></td></tr>
       
   332           <tr><td class="row1" style="width: 50%;" rowspan="2">Visual confirmation<br /><small>Please enter the code shown in the image to the right into the text box. This process helps to ensure that this registration is not being performed by an automated bot. If the image to the right is illegible, you can <a href="#" onclick="regenCaptcha(); return false;">generate a new image</a>.<br /><br />If you are visually impaired or otherwise cannot read the text shown to the right, please contact the site management and they will create an account for you.</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>
       
   333           <tr><td class="row1" colspan="2">Code: <input name="captchacode" type="text" size="10" /><input type="hidden" name="captchahash" value="<?php echo $captchacode; ?>" /></td></tr>
       
   334           <tr><td class="row2" colspan="3" style="text-align: center;"><input type="submit" name="submit" value="Create my account" /></td></tr>
       
   335         </table>
       
   336       </div>
       
   337     </form>
       
   338     <script type="text/javascript">
       
   339       // <![CDATA[
       
   340       var namegood = false;
       
   341       function validateForm()
       
   342       {
       
   343         var frm = document.forms.regform;
       
   344         failed = false;
       
   345         
       
   346         // Username
       
   347         if(!namegood)
       
   348         {
       
   349           if(frm.username.value.match(/^([A-z0-9 \!@\-\(\)]+){2,}$/ig))
       
   350           {
       
   351             document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/unknown.gif';
       
   352             document.getElementById('e_username').innerHTML = ''; // '<br /><small><b>Checking availability...</b></small>';
       
   353           } else {
       
   354             failed = true;
       
   355             document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/bad.gif';
       
   356             document.getElementById('e_username').innerHTML = '<br /><small>Your username must be at least two characters in length and may contain only alphanumeric characters (A-Z and 0-9), spaces, and the following characters: :, !, @, #, *.</small>';
       
   357           }
       
   358         }
       
   359         document.getElementById('b_username').innerHTML = '';
       
   360         if(hex_md5(frm.real_name.value) == 'fa8e397ae0f6cd5b0f90a3f48178cd7e')
       
   361         {
       
   362           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" />';
       
   363         }
       
   364         
       
   365         // Password
       
   366         if(frm.password.value.match(/^(.+){6,}$/ig) && frm.password_confirm.value.match(/^(.+){6,}$/ig) && frm.password.value == frm.password_confirm.value)
       
   367         {
       
   368           document.getElementById('s_password').src='<?php echo scriptPath; ?>/images/good.gif';
       
   369           document.getElementById('e_password').innerHTML = '<br /><small>The password you entered is valid.</small>';
       
   370         } else {
       
   371           failed = true;
       
   372           if(frm.password.value.length < 6)
       
   373             document.getElementById('e_password').innerHTML = '<br /><small>Your password must be at least six characters in length.</small>';
       
   374           else if(frm.password.value != frm.password_confirm.value)
       
   375             document.getElementById('e_password').innerHTML = '<br /><small>The passwords you entered do not match.</small>';
       
   376           else
       
   377             document.getElementById('e_password').innerHTML = '';
       
   378           document.getElementById('s_password').src='<?php echo scriptPath; ?>/images/bad.gif';
       
   379         }
       
   380         
       
   381         // E-mail address
       
   382         if(frm.email.value.match(/^(?:[\w\d]+\.?)+@(?:(?:[\w\d]\-?)+\.)+\w{2,4}$/))
       
   383         {
       
   384           document.getElementById('s_email').src='<?php echo scriptPath; ?>/images/good.gif';
       
   385         } else {
       
   386           failed = true;
       
   387           document.getElementById('s_email').src='<?php echo scriptPath; ?>/images/bad.gif';
       
   388         }
       
   389         if(failed)
       
   390         {
       
   391           frm.submit.disabled = 'disabled';
       
   392         } else {
       
   393           frm.submit.disabled = false;
       
   394         }
       
   395       }
       
   396       function checkUsername()
       
   397       {
       
   398         var frm = document.forms.regform;
       
   399         
       
   400         if(!namegood)
       
   401         {
       
   402           if(frm.username.value.match(/^([A-z0-9 \.:\!@\#\*]+){2,}$/ig))
       
   403           {
       
   404             document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/unknown.gif';
       
   405             document.getElementById('e_username').innerHTML = '';
       
   406           } else {
       
   407             document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/bad.gif';
       
   408             document.getElementById('e_username').innerHTML = '<br /><small>Your username must be at least two characters in length and may contain only alphanumeric characters (A-Z and 0-9), spaces, and the following characters: :, !, @, #, *.</small>';
       
   409             return false;
       
   410           }
       
   411         }
       
   412         
       
   413         document.getElementById('e_username').innerHTML = '<br /><small><b>Checking availability...</b></small>';
       
   414         ajaxGet('<?php echo scriptPath; ?>/ajax.php?title=null&_mode=checkusername&name='+escape(frm.username.value), function() {
       
   415           if(ajax.readyState == 4)
       
   416             if(ajax.responseText == 'good')
       
   417             {
       
   418               document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/good.gif';
       
   419               document.getElementById('e_username').innerHTML = '<br /><small><b>This username is available.</b></small>';
       
   420               namegood = true;
       
   421             } else if(ajax.responseText == 'bad') {
       
   422               document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/bad.gif';
       
   423               document.getElementById('e_username').innerHTML = '<br /><small><b>Error: that username is already taken.</b></small>';
       
   424               namegood = false;
       
   425             } else {
       
   426               document.getElementById('e_username').innerHTML = ajax.responseText;
       
   427             }
       
   428         });
       
   429       }
       
   430       function regenCaptcha()
       
   431       {
       
   432         var frm = document.forms.regform;
       
   433         document.getElementById('captchaimg').src = '<?php echo makeUrlNS("Special", "Captcha/"); ?>'+frm.captchahash.value+'/'+Math.floor(Math.random() * 100000);
       
   434         return false;
       
   435       }
       
   436       validateForm();
       
   437       setTimeout('checkUsername();', 1000);
       
   438       // ]]>
       
   439     </script>
       
   440   <?php
       
   441   $template->footer();
       
   442 }
       
   443 
       
   444 /*
       
   445 If you want the old preferences page back, be my guest.
       
   446 function page_Special_Preferences() {
       
   447   global $db, $session, $paths, $template, $plugins; // Common objects
       
   448   $template->header();
       
   449   if(isset($_POST['submit'])) {
       
   450     $data = $session->update_user($session->user_id, $_POST['username'], $_POST['current_pass'], $_POST['new_pass'], $_POST['email'], $_POST['real_name'], $_POST['sig']);
       
   451     if($data == 'success') echo '<h3>Information</h3><p>Your profile has been updated. <a href="'.scriptPath.'/">Return to the index page</a>.</p>';
       
   452     else echo $data;
       
   453   } else {
       
   454     echo '
       
   455     <h3>Edit your profile</h3>
       
   456     <form action="'.makeUrl($paths->nslist['Special'].'Preferences').'" method="post">
       
   457       <table border="0" style="margin-left: 0.2in;">   
       
   458         <tr><td>Username:</td><td><input type="text" name="username" value="'.$session->username.'" /></td></tr>
       
   459         <tr><td>Current Password:</td><td><input type="password" name="current_pass" /></td></tr>
       
   460         <tr><td colspan="2"><small>You only need to enter your current password if you are changing your e-mail address or changing your password.</small></td></tr>
       
   461         <tr><td>New Password:</td><td><input type="password" name="new_pass" /></td></tr>
       
   462         <tr><td>E-mail:</td><td><input type="text" name="email" value="'.$session->email.'" /></td></tr>
       
   463         <tr><td>Real Name:</td><td><input type="text" name="real_name" value="'.$session->real_name.'" /></td></tr>
       
   464         <tr><td>Signature:<br /><small>Your signature appears<br />below your comment posts.</small></td><td><textarea rows="10" cols="40" name="sig">'.$session->signature.'</textarea></td></tr>
       
   465         <tr><td colspan="2">
       
   466         <input type="submit" name="submit" value="Save Changes" /></td></tr>
       
   467       </table>
       
   468     </form>
       
   469     ';
       
   470   }
       
   471   $template->footer();
       
   472 }
       
   473 */
       
   474 
       
   475 function page_Special_Contributions() {
       
   476   global $db, $session, $paths, $template, $plugins; // Common objects
       
   477   $template->header();
       
   478   $user = $paths->getParam();
       
   479   if(!$user && isset($_GET['user']))
       
   480   {
       
   481     $user = $_GET['user'];
       
   482   }
       
   483   elseif(!$user && !isset($_GET['user']))
       
   484   {
       
   485     echo 'No user selected!';
       
   486     $template->footer();
       
   487     $db->close();
       
   488     exit;
       
   489   }
       
   490   
       
   491   $user = $db->escape($user);
       
   492   
       
   493   $q = 'SELECT time_id,date_string,page_id,namespace,author,edit_summary,minor_edit,page_id,namespace FROM '.table_prefix.'logs WHERE author=\''.$user.'\' AND action=\'edit\' ORDER BY time_id DESC;';
       
   494   if(!$db->sql_query($q)) $db->_die('The history data for the page "'.$paths->cpage['name'].'" could not be selected.');
       
   495   echo 'History of edits and actions<h3>Edits:</h3>';
       
   496   if($db->numrows() < 1) echo 'No history entries in this category.';
       
   497   while($r = $db->fetchrow()) {    
       
   498     echo '<a href="#" onclick="ajaxHistView(\''.$r['time_id'].'\', \''.$paths->nslist[$r['namespace']].$r['page_id'].'\'); return false;"><i>'.$r['date_string'].'</i></a> (<a href="#" onclick="ajaxRollback(\''.$r['time_id'].'\'); return false;">revert</a>) <a href="'.makeUrl($paths->nslist[$r['namespace']].$r['page_id']).'">'.$paths->nslist[$r['namespace']].$r['page_id'].'</a>: '.$r['edit_summary'];
       
   499     if($r['minor_edit']) echo '<b> - minor edit</b>';
       
   500     echo '<br />';
       
   501   }
       
   502   $db->free_result();
       
   503   echo '<h3>Other changes:</h3>';
       
   504   $q = 'SELECT log_type,time_id,action,date_string,page_id,namespace,author,edit_summary,minor_edit,page_id,namespace FROM '.table_prefix.'logs WHERE author=\''.$user.'\' AND action!=\'edit\' ORDER BY time_id DESC;';
       
   505   if(!$db->sql_query($q)) $db->_die('The history data for the page "'.$paths->cpage['name'].'" could not be selected.');
       
   506   if($db->numrows() < 1) echo 'No history entries in this category.';
       
   507   while($r = $db->fetchrow()) {
       
   508     if($r['log_type']=='page') {
       
   509     echo '(<a href="#" onclick="ajaxRollback(\''.$r['time_id'].'\'); return false;">rollback</a>) <i>'.$r['date_string'].'</i> <a href="'.makeUrl($paths->nslist[$r['namespace']].$r['page_id']).'">'.$paths->nslist[$r['namespace']].$r['page_id'].'</a>: ';
       
   510     if($r['action']=='prot') echo 'Protected page; reason: '.$r['edit_summary'];
       
   511     elseif($r['action']=='unprot') echo 'Unprotected page; reason: '.$r['edit_summary'];
       
   512     elseif($r['action']=='rename') echo 'Renamed page; old title was: '.$r['edit_summary'];
       
   513     elseif($r['action']=='create') echo 'Created page';
       
   514     elseif($r['action']=='delete') echo 'Deleted page';
       
   515     if($r['minor_edit']) echo '<b> - minor edit</b>';
       
   516     echo '<br />';
       
   517     } elseif($r['log_type']=='security') {
       
   518       // Not implemented, and when it is, it won't be public
       
   519     }
       
   520   }
       
   521   $db->free_result();
       
   522   $template->footer();
       
   523 }
       
   524 
       
   525 function page_Special_ChangeStyle()
       
   526 {
       
   527   global $db, $session, $paths, $template, $plugins; // Common objects
       
   528   if(!$session->user_logged_in) die_friendly('Access denied', '<p>You must be logged in to change your style. Spoofer.</p>');
       
   529   if(isset($_POST['theme']) && isset($_POST['style']) && isset($_POST['return_to']))
       
   530   {
       
   531     $d = ENANO_ROOT . '/themes/' . $_POST['theme'];
       
   532     $f = ENANO_ROOT . '/themes/' . $_POST['theme'] . '/css/' . $_POST['style'] . '.css';
       
   533     if(!file_exists($d) || !is_dir($d)) die('The directory "'.$d.'" does not exist.');
       
   534     if(!file_exists($f)) die('The file "'.$f.'" does not exist.');
       
   535     $d = $db->escape($_POST['theme']);
       
   536     $f = $db->escape($_POST['style']);
       
   537     $q = 'UPDATE '.table_prefix.'users SET theme=\''.$d.'\',style=\''.$f.'\' WHERE username=\''.$session->username.'\'';
       
   538     if(!$db->sql_query($q))
       
   539     {
       
   540       $db->_die('Your theme/style preferences were not updated.');
       
   541     }
       
   542     else
       
   543     {
       
   544       redirect(makeUrl($_POST['return_to']), '', '', 0);
       
   545     }
       
   546   }
       
   547   else
       
   548   {
       
   549     $template->header();
       
   550       $ret = ( isset($_POST['return_to']) ) ? $_POST['return_to'] : $paths->getParam(0);
       
   551       if(!$ret) $ret = getConfig('main_page');
       
   552       ?>
       
   553         <form action="<?php echo makeUrl($paths->page); ?>" method="post">
       
   554           <?php if(!isset($_POST['themeselected'])) { ?>
       
   555             <h3>Please select a new theme:</h3>
       
   556             <p>
       
   557               <select name="theme">
       
   558                <?php
       
   559                 foreach($template->theme_list as $t) {
       
   560                   if($t['enabled'])
       
   561                   {
       
   562                     echo '<option value="'.$t['theme_id'].'"';
       
   563                     if($t['theme_id'] == $session->theme) echo ' selected="selected"';
       
   564                     echo '>'.$t['theme_name'].'</option>';
       
   565                   }
       
   566                 }
       
   567                ?>
       
   568               </select>
       
   569             </p>
       
   570             <p><input type="hidden" name="return_to" value="<?php echo $ret; ?>" />
       
   571                <input type="submit" name="themeselected" value="Continue" /></p>
       
   572           <?php } else { 
       
   573             $theme = $_POST['theme'];
       
   574             if ( !preg_match('/^([0-9A-z_-]+)$/i', $theme ) )
       
   575               die('Hacking attempt');
       
   576             ?>
       
   577             <h3>Please select a stylesheet:</h3>
       
   578             <p>
       
   579               <select name="style">
       
   580                 <?php
       
   581                   $dir = './themes/'.$theme.'/css/';
       
   582                   $list = Array();
       
   583                   // Open a known directory, and proceed to read its contents
       
   584                   if (is_dir($dir)) {
       
   585                     if ($dh = opendir($dir)) {
       
   586                       while (($file = readdir($dh)) !== false) {
       
   587                         if(preg_match('#^(.*?)\.css$#is', $file) && $file != '_printable.css') {
       
   588                           $list[] = substr($file, 0, strlen($file)-4);
       
   589                         }
       
   590                       }
       
   591                       closedir($dh);
       
   592                     }
       
   593                   } else die($dir.' is not a dir');
       
   594                   foreach ( $list as $l )
       
   595                   {
       
   596                     echo '<option value="'.$l.'">'.capitalize_first_letter($l).'</option>';
       
   597                   }
       
   598                 ?>
       
   599               </select>
       
   600             </p>
       
   601             <p><input type="hidden" name="return_to" value="<?php echo $ret; ?>" />
       
   602                <input type="hidden" name="theme" value="<?php echo $theme; ?>" />
       
   603                <input type="submit" name="allclear" value="Change style" /></p>
       
   604           <?php } ?>
       
   605         </form>
       
   606       <?php
       
   607     $template->footer();
       
   608   }
       
   609 }
       
   610 
       
   611 function page_Special_ActivateAccount()
       
   612 {
       
   613   global $db, $session, $paths, $template, $plugins; // Common objects
       
   614   $user = $paths->getParam(0);
       
   615   if(!$user) die_friendly('Account activation error', '<p>The URL was incorrect.</p>');
       
   616   $key = $paths->getParam(1);
       
   617   if(!$key) die_friendly('Account activation error', '<p>The URL was incorrect.</p>');
       
   618   $s = $session->activate_account(str_replace('_', ' ', $user), $key);
       
   619   if($s > 0) die_friendly('Activation successful', '<p>Your account is now active. Thank you for registering.</p>');
       
   620   else die_friendly('Activation failed', '<p>The activation key was probably incorrect.</p>');
       
   621 }
       
   622 
       
   623 function page_Special_Captcha()
       
   624 {
       
   625   global $db, $session, $paths, $template, $plugins; // Common objects
       
   626   if($paths->getParam(0) == 'make')
       
   627   {
       
   628     $session->kill_captcha();
       
   629     echo $session->make_captcha();
       
   630     return;
       
   631   }
       
   632   $hash = $paths->getParam(0);
       
   633   if(!$hash || !preg_match('#^([0-9a-f]*){32,32}$#i', $hash)) $paths->main_page();
       
   634   $code = $session->get_captcha($hash);
       
   635   if(!$code) die('Invalid hash or IP address incorrect.');
       
   636   require(ENANO_ROOT.'/includes/captcha.php');
       
   637   $captcha = new captcha($code);
       
   638   //header('Content-disposition: attachment; filename=autocaptcha.png');
       
   639   $captcha->make_image();
       
   640   exit;
       
   641 }
       
   642 
       
   643 function page_Special_PasswordReset()
       
   644 {
       
   645   global $db, $session, $paths, $template, $plugins; // Common objects
       
   646   $template->header();
       
   647   if($paths->getParam(0) == 'stage2')
       
   648   {
       
   649     $user_id = intval($paths->getParam(1));
       
   650     $encpass = $paths->getParam(2);
       
   651     if ( $user_id < 2 )
       
   652     {
       
   653       echo '<p>Hacking attempt</p>';
       
   654       $template->footer();
       
   655       return false;
       
   656     }
       
   657     if(!preg_match('#^([a-f0-9]+)$#i', $encpass))
       
   658     {
       
   659       echo '<p>Hacking attempt</p>';
       
   660       $template->footer();
       
   661       return false;
       
   662     }
       
   663     
       
   664     $q = $db->sql_query('SELECT username,temp_password_time FROM '.table_prefix.'users WHERE user_id='.$user_id.' AND temp_password=\'' . $encpass . '\';');
       
   665     if($db->numrows() < 1)
       
   666     {
       
   667       echo '<p>Invalid credentials</p>';
       
   668       $template->footer();
       
   669       return false;
       
   670     }
       
   671     $row = $db->fetchrow();
       
   672     $db->free_result();
       
   673     
       
   674     if ( ( intval($row['temp_password_time']) + 3600 * 24 ) < time() )
       
   675     {
       
   676       echo '<p>Password has expired</p>';
       
   677       $template->footer();
       
   678       return false;
       
   679     }
       
   680     
       
   681     if ( isset($_POST['do_stage2']) )
       
   682     {
       
   683       $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE);
       
   684       if($_POST['use_crypt'] == 'yes')
       
   685       {
       
   686         $crypt_key = $session->fetch_public_key($_POST['crypt_key']);
       
   687         if(!$crypt_key)
       
   688         {
       
   689           echo 'ERROR: Couldn\'t look up public key for decryption.';
       
   690           $template->footer();
       
   691           return false;
       
   692         }
       
   693         $crypt_key = hexdecode($crypt_key);
       
   694         $data = $aes->decrypt($_POST['crypt_data'], $crypt_key, ENC_HEX);
       
   695         if(strlen($data) < 6)
       
   696         {
       
   697           echo 'ERROR: Your password must be six characters or greater in length.';
       
   698           $template->footer();
       
   699           return false;
       
   700         }
       
   701       }
       
   702       else
       
   703       {
       
   704         $data = $_POST['pass'];
       
   705         $conf = $_POST['pass_confirm'];
       
   706         if($data != $conf)
       
   707         {
       
   708           echo 'ERROR: The passwords you entered do not match.';
       
   709           $template->footer();
       
   710           return false;
       
   711         }
       
   712         if(strlen($data) < 6)
       
   713         {
       
   714           echo 'ERROR: Your password must be six characters or greater in length.';
       
   715           $template->footer();
       
   716           return false;
       
   717         }
       
   718       }
       
   719       if(empty($data))
       
   720       {
       
   721         echo 'ERROR: Sanity check failed!';
       
   722         $template->footer();
       
   723         return false;
       
   724       }
       
   725       $encpass = $aes->encrypt($data, $session->private_key, ENC_HEX);
       
   726       $q = $db->sql_query('UPDATE '.table_prefix.'users SET password=\'' . $encpass . '\',temp_password=\'\',temp_password_time=0 WHERE user_id='.$user_id.';');
       
   727       
       
   728       if($q)
       
   729       {
       
   730         $session->login_without_crypto($row['username'], $data);
       
   731         echo '<p>Your password has been reset. Return to the <a href="' . makeUrl(getConfig('main_page')) . '">main page</a>.</p>';
       
   732       }
       
   733       else
       
   734       {
       
   735         echo $db->get_error();
       
   736       }
       
   737       
       
   738       $template->footer();
       
   739       return false;
       
   740     }
       
   741     
       
   742     // Password reset form
       
   743     $pubkey = $session->rijndael_genkey();
       
   744     
       
   745     ?>
       
   746     <form action="<?php echo makeUrl($paths->fullpage); ?>" method="post" name="resetform" onsubmit="return runEncryption();">
       
   747       <br />
       
   748       <div class="tblholder">
       
   749         <table border="0" style="width: 100%;" cellspacing="1" cellpadding="4">
       
   750           <tr><th colspan="2">Reset password</th></tr>
       
   751           <tr><td class="row1">Password:</td><td class="row1"><input name="pass" type="password" /></td></tr>
       
   752           <tr><td class="row2">Confirm: </td><td class="row2"><input name="pass_confirm" type="password" /></td></tr>
       
   753           <tr>
       
   754             <td colspan="2" class="row1" style="text-align: center;">
       
   755               <input type="hidden" name="use_crypt" value="no" />
       
   756               <input type="hidden" name="crypt_key" value="<?php echo $pubkey; ?>" />
       
   757               <input type="hidden" name="crypt_data" value="" />
       
   758               <input type="submit" name="do_stage2" value="Reset password" />
       
   759             </td>
       
   760           </tr>
       
   761         </table>
       
   762       </div>
       
   763     </form>
       
   764     <script type="text/javascript">
       
   765     disableJSONExts();
       
   766       str = '';
       
   767       for(i=0;i<keySizeInBits/4;i++) str+='0';
       
   768       var key = hexToByteArray(str);
       
   769       var pt = hexToByteArray(str);
       
   770       var ct = rijndaelEncrypt(pt, key, "ECB");
       
   771       var ct = byteArrayToHex(ct);
       
   772       switch(keySizeInBits)
       
   773       {
       
   774         case 128:
       
   775           v = '66e94bd4ef8a2c3b884cfa59ca342b2e';
       
   776           break;
       
   777         case 192:
       
   778           v = 'aae06992acbf52a3e8f4a96ec9300bd7aae06992acbf52a3e8f4a96ec9300bd7';
       
   779           break;
       
   780         case 256:
       
   781           v = 'dc95c078a2408989ad48a21492842087dc95c078a2408989ad48a21492842087';
       
   782           break;
       
   783       }
       
   784       var testpassed = ( ct == v && md5_vm_test() );
       
   785       var frm = document.forms.resetform;
       
   786       if(testpassed)
       
   787       {
       
   788         frm.use_crypt.value = 'yes';
       
   789         var cryptkey = frm.crypt_key.value;
       
   790         frm.crypt_key.value = hex_md5(cryptkey);
       
   791         cryptkey = hexToByteArray(cryptkey);
       
   792         if(!cryptkey || ( ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ) && cryptkey.length != keySizeInBits / 8 )
       
   793         {
       
   794           frm._login.disabled = true;
       
   795           len = ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ? '\nLen: '+cryptkey.length : '';
       
   796           alert('The key is messed up\nType: '+typeof(cryptkey)+len);
       
   797         }
       
   798       }
       
   799       function runEncryption()
       
   800       {
       
   801         pass1 = frm.pass.value;
       
   802         pass2 = frm.pass_confirm.value;
       
   803         if ( pass1 != pass2 )
       
   804         {
       
   805           alert('The passwords you entered do not match.');
       
   806           return false;
       
   807         }
       
   808         if ( pass1.length < 6 )
       
   809         {
       
   810           alert('The new password must be 6 characters or greater in length.');
       
   811           return false;
       
   812         }
       
   813         if(testpassed)
       
   814         {
       
   815           pass = frm.pass.value;
       
   816           pass = stringToByteArray(pass);
       
   817           cryptstring = rijndaelEncrypt(pass, cryptkey, 'ECB');
       
   818           if(!cryptstring)
       
   819           {
       
   820             return false;
       
   821           }
       
   822           cryptstring = byteArrayToHex(cryptstring);
       
   823           frm.crypt_data.value = cryptstring;
       
   824           frm.pass.value = "";
       
   825           frm.pass_confirm.value = "";
       
   826         }
       
   827         return true;
       
   828       }
       
   829     </script>
       
   830     <?php
       
   831     $template->footer();
       
   832     return true;
       
   833   }
       
   834   if(isset($_POST['do_reset']))
       
   835   {
       
   836     if($session->mail_password_reset($_POST['username']))
       
   837     {
       
   838       echo '<p>An e-mail has been sent to the e-mail address on file for your username with a new password in it. Please check your e-mail for further instructions.</p>';
       
   839     }
       
   840     else
       
   841     {
       
   842       echo '<p>Error occured, your new password was not sent.</p>';
       
   843     }
       
   844     $template->footer();
       
   845     return true;
       
   846   }
       
   847   echo '<p>Don\'t worry, it happens to the best of us.</p>
       
   848         <p>To reset your password, just enter your username below, and a new password will be e-mailed to you.</p>
       
   849         <form action="'.makeUrl($paths->page).'" method="post" onsubmit="if(!submitAuthorized) return false;">
       
   850           <p>Username:  '.$template->username_field('username').'</p>
       
   851           <p><input type="submit" name="do_reset" value="Mail new password" /></p>
       
   852         </form>';
       
   853   $template->footer();
       
   854 }
       
   855 
       
   856 ?>