plugins/SpecialAdmin.php~
changeset 0 902822492a68
equal deleted inserted replaced
-1:000000000000 0:902822492a68
       
     1 <?php
       
     2 /*
       
     3 Plugin Name: Runt - the Enano administration panel
       
     4 Plugin URI: http://enanocms.org/
       
     5 Description: Provides the page Special:Administration, which is the AJAX frontend to the various Admin:
       
     6 Author: Dan Fuhry
       
     7 Version: 1.0
       
     8 Author URI: http://enanocms.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\'=>\'Administration\',
       
    29       \'urlname\'=>\'Administration\',
       
    30       \'namespace\'=>\'Special\',
       
    31       \'special\'=>0,\'visible\'=>0,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       
    32       ));
       
    33     
       
    34     $paths->add_page(Array(
       
    35       \'name\'=>\'Manage the Sidebar\',
       
    36       \'urlname\'=>\'EditSidebar\',
       
    37       \'namespace\'=>\'Special\',
       
    38       \'special\'=>0,\'visible\'=>0,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       
    39       ));
       
    40   ');
       
    41 
       
    42 // function names are IMPORTANT!!! The name pattern is: page_<namespace ID>_<page URLname, without namespace>
       
    43 
       
    44 function page_Admin_Home() {
       
    45   global $db, $session, $paths, $template, $plugins; // Common objects
       
    46   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
    47   {
       
    48     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
    49     return;
       
    50   }
       
    51   
       
    52   
       
    53   // Basic information
       
    54   echo RenderMan::render(
       
    55 '== Welcome to Runt, the Enano administration panel. ==
       
    56 
       
    57 Thank you for choosing Enano as your CMS. This screen allows you to see some information about your website, plus some details about how your site is doing statistically.
       
    58 
       
    59 Using the links on the left you can control every aspect of your website\'s look and feel, plus you can manage users, work with pages, and install plugins to make your Enano installation even better.');
       
    60   
       
    61   // Check for the installer scripts
       
    62   if(file_exists(ENANO_ROOT.'/install.php') || file_exists(ENANO_ROOT.'/schema.sql'))
       
    63   {
       
    64     echo '<div class="error-box"><b>NOTE:</b> It appears that your install.php and/or schema.sql files still exist. It is HIGHLY RECOMMENDED that you delete or rename these files, to prevent getting your server hacked.</div>';
       
    65   }
       
    66   
       
    67   // Inactive users
       
    68   $q = $db->sql_query('SELECT * FROM '.table_prefix.'logs WHERE log_type=\'admin\' AND action=\'activ_req\';');
       
    69   if($q)
       
    70     if($db->numrows() > 0)
       
    71     {
       
    72       $n = $db->numrows();
       
    73       if($n == 1) $s = $n . ' user is';
       
    74       else $s = $n . ' users are';
       
    75       echo '<div class="warning-box">It appears that '.$s.' awaiting account activation. You can activate those accounts by going to the <a href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'UserManager\'); return false;">User Manager</a>.</div>';
       
    76     }
       
    77   $db->free_result();
       
    78   // Stats
       
    79   if(getConfig('log_hits') == '1')
       
    80   {
       
    81     $stats = stats_top_pages(10);
       
    82     $c = 0;
       
    83     $cls = 'row2';
       
    84     echo '<h3>Most requested pages</h3><div class="tblholder"><table style="width: 100%;" border="0" cellspacing="1" cellpadding="4"><tr><th>Page</th><th>Hits</th></tr>';
       
    85     foreach($stats as $page => $count)
       
    86     {
       
    87       if(isset($paths->pages[$page]))
       
    88       {
       
    89         echo '<tr>';
       
    90         $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
       
    91         echo '<td class="'.$cls.'"><a href="'.makeUrl($page).'">'.$paths->pages[$page]['name'].'</a></td><td style="text-align: center;" class="'.$cls.'">'.$count.'</td>';
       
    92         echo '</tr>';
       
    93       }
       
    94     }
       
    95     echo '</table></div>';
       
    96   }
       
    97   
       
    98   // Security log
       
    99   echo '<h3>Security log</h3>';
       
   100   echo '<div class="tblholder" style="/* max-height: 500px; clip: rect(0px,auto,auto,0px); overflow: auto; */"><table border="0" cellspacing="1" cellpadding="4" width="100%">';
       
   101   $cls = 'row2';                                                                                               
       
   102   echo '<tr><th style="width: 60%;">Type</th><th>Date</th><th>Username</th><th>IP Address</th></tr>';
       
   103   if(isset($_GET['fulllog']))
       
   104   {
       
   105     $l = 'SELECT action,date_string,author,edit_summary,time_id,page_text FROM '.table_prefix.'logs WHERE log_type=\'security\' ORDER BY time_id DESC, action ASC;';
       
   106   }
       
   107   else
       
   108   {
       
   109     $l = 'SELECT action,date_string,author,edit_summary,time_id,page_text FROM '.table_prefix.'logs WHERE log_type=\'security\' ORDER BY time_id DESC, action ASC LIMIT 5';
       
   110   }
       
   111   $q = $db->sql_query($l);
       
   112   while($r = $db->fetchrow())
       
   113   {
       
   114     if($cls == 'row2') $cls = 'row1';
       
   115     else $cls = 'row2';
       
   116     echo '<tr><td class="'.$cls.'">';
       
   117     switch($r['action']) {
       
   118       case "admin_auth_good": echo 'Successful elevated authentication'; if ( !empty($r['page_text']) ) { $level = $session->userlevel_to_string( intval($r['page_text']) ); echo "<br /><small>Authentication level: $level</small>"; } break;
       
   119       case "admin_auth_bad":  echo 'Failed administration logon'; break;
       
   120       case "activ_good": echo 'Successful account activation'; break;
       
   121       case "auth_good": echo 'Successful regular user logon'; break;
       
   122       case "activ_bad": echo 'Failed account activation'; break;
       
   123       case "auth_bad": echo 'Failed regular user logon'; break;
       
   124       case "sql_inject": echo 'SQL injection attempt<div style="max-width: 90%; clip: rect(0px,auto,auto,0px); overflow: auto; display: block; font-size: smaller;">Offending query: ' . htmlspecialchars($r['page_text']) . '</div>'; break;
       
   125       case "db_backup": echo 'Database backup created<br /><small>Tables: ' . $r['page_text'] . '</small>'; break;
       
   126       case "install_enano": echo "Installed Enano version {$r['page_text']}"; break;
       
   127     }
       
   128     echo '</td><td class="'.$cls.'">'.date('d M Y h:i a', $r['time_id']).'</td><td class="'.$cls.'">'.$r['author'].'</td><td class="'.$cls.'" style="cursor: pointer;" onclick="ajaxReverseDNS(this);" title="Click for reverse DNS info">'.$r['edit_summary'].'</td></tr>';
       
   129   }
       
   130   $db->free_result();
       
   131   echo '</table></div>';
       
   132   if(!isset($_GET['fulllog'])) echo '<p><a href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'Home&amp;fulllog\'); return false;">Full security log</a></p>';
       
   133   
       
   134 }
       
   135 
       
   136 function page_Admin_GeneralConfig() {
       
   137   global $db, $session, $paths, $template, $plugins; // Common objects
       
   138   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
   139   {
       
   140     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
   141     return;
       
   142   }
       
   143   
       
   144   if(isset($_POST['submit'])) {
       
   145     
       
   146     // Global site options
       
   147     setConfig('site_name', $_POST['site_name']);
       
   148     setConfig('site_desc', $_POST['site_desc']);
       
   149     setConfig('main_page', str_replace(' ', '_', $_POST['main_page']));
       
   150     setConfig('copyright_notice', $_POST['copyright']);
       
   151     setConfig('contact_email', $_POST['contact_email']);
       
   152     
       
   153     // Wiki mode
       
   154     if(isset($_POST['wikimode']))                setConfig('wiki_mode', '1');
       
   155     else                                         setConfig('wiki_mode', '0');
       
   156     if(isset($_POST['wiki_mode_require_login'])) setConfig('wiki_mode_require_login', '1');
       
   157     else                                         setConfig('wiki_mode_require_login', '0');
       
   158     if(isset($_POST['editmsg']))                 setConfig('wiki_edit_notice', '1');
       
   159     else                                         setConfig('wiki_edit_notice', '0');
       
   160     setConfig('wiki_edit_notice_text', $_POST['editmsg_text']);
       
   161     
       
   162     // Stats
       
   163     if(isset($_POST['log_hits']))                setConfig('log_hits', '1');
       
   164     else                                         setConfig('log_hits', '0');
       
   165     
       
   166     // Disablement
       
   167     if(isset($_POST['site_disabled'])) {         setConfig('site_disabled', '1'); setConfig('site_disabled_notice', $_POST['site_disabled_notice']); }
       
   168     else                                         setConfig('site_disabled', '0');
       
   169     
       
   170     // Account activation
       
   171     setConfig('account_activation', $_POST['account_activation']);
       
   172     
       
   173     // W3C compliance buttons
       
   174     if(isset($_POST['w3c-vh32']))     setConfig("w3c_vh32", "1");
       
   175     else                              setConfig("w3c_vh32", "0");
       
   176     if(isset($_POST['w3c-vh40']))     setConfig("w3c_vh40", "1");
       
   177     else                              setConfig("w3c_vh40", "0");
       
   178     if(isset($_POST['w3c-vh401']))    setConfig("w3c_vh401", "1");
       
   179     else                              setConfig("w3c_vh401", "0");
       
   180     if(isset($_POST['w3c-vxhtml10'])) setConfig("w3c_vxhtml10", "1");
       
   181     else                              setConfig("w3c_vxhtml10", "0");
       
   182     if(isset($_POST['w3c-vxhtml11'])) setConfig("w3c_vxhtml11", "1");
       
   183     else                              setConfig("w3c_vxhtml11", "0");
       
   184     if(isset($_POST['w3c-vcss']))     setConfig("w3c_vcss", "1");
       
   185     else                              setConfig("w3c_vcss", "0");
       
   186     
       
   187     // SourceForge.net logo
       
   188     if(isset($_POST['showsf'])) setConfig('sflogo_enabled', '1');
       
   189     else                        setConfig('sflogo_enabled', '0');
       
   190     setConfig('sflogo_groupid', $_POST['sfgroup']);
       
   191     setConfig('sflogo_type', $_POST['sflogo']);
       
   192     
       
   193     // Comment options
       
   194     if(isset($_POST['comment-approval'])) setConfig('approve_comments', '1');
       
   195     else                                  setConfig('approve_comments', '0');
       
   196     if(isset($_POST['enable-comments']))  setConfig('enable_comments', '1');
       
   197     else                                  setConfig('enable_comments', '0');
       
   198     setConfig('comments_need_login', $_POST['comments_need_login']);
       
   199     
       
   200     // Powered by link
       
   201     if ( isset($_POST['enano_powered_link']) ) setConfig('powered_btn', '1');
       
   202     else                                       setConfig('powered_btn', '0');    
       
   203     
       
   204     if(isset($_POST['dbdbutton']))        setConfig('dbd_button', '1');
       
   205     else                                  setConfig('dbd_button', '0');
       
   206     
       
   207     if($_POST['emailmethod'] == 'phpmail') setConfig('smtp_enabled', '0');
       
   208     else                                   setConfig('smtp_enabled', '1');
       
   209     
       
   210     setConfig('smtp_server', $_POST['smtp_host']);
       
   211     setConfig('smtp_user', $_POST['smtp_user']);
       
   212     if($_POST['smtp_pass'] != 'XXXXXXXXXXXX') setConfig('smtp_password', $_POST['smtp_pass']);
       
   213     
       
   214     echo '<div class="info-box">Your changes to the site configuration have been saved.</div><br />';
       
   215     
       
   216   }
       
   217   echo('<form name="main" action="'.htmlspecialchars(makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module'])).'" method="post" onsubmit="if(!submitAuthorized) return false;">');
       
   218   ?>
       
   219   <div class="tblholder">
       
   220     <table border="0" width="100%" cellspacing="1" cellpadding="4">
       
   221       
       
   222     <!-- Global options -->
       
   223     
       
   224       <tr><th colspan="2">Global site options</th></tr>
       
   225       <tr><th colspan="2" class="subhead">These options control the entire site.</th></tr>
       
   226       
       
   227       <tr><td class="row1" style="width: 50%;">Site name:</td>                      <td class="row1" style="width: 50%;"><input name="site_name" size="30" value="<?php echo getConfig('site_name'); ?>" /></td></tr>
       
   228       <tr><td class="row2">Site description:</td>               <td class="row2"><input name="site_desc" size="30" value="<?php echo getConfig('site_desc'); ?>" /></td></tr>
       
   229       <tr><td class="row1">Main page:</td>                      <td class="row1"><?php echo $template->pagename_field('main_page', str_replace('_', ' ', getConfig('main_page'))); ?></td></tr>
       
   230       <tr><td class="row2">Copyright notice shown on pages:</td><td class="row2"><input name="copyright" size="30" value="<?php echo getConfig('copyright_notice'); ?>" /></td></tr>
       
   231       <tr><td class="row1" colspan="2">Hint: If you're using Windows, you can make a "&copy;" symbol by holding ALT and pressing 0169 on the numeric keypad.</td></tr>
       
   232       <tr><td class="row2">Contact e-mail<br /><small>All e-mail sent from this site will appear to have come from the address shown here.</small></td><td class="row2"><input name="contact_email" type="text" size="40" value="<?php echo htmlspecialchars(getConfig('contact_email')); ?>" /></td></tr>
       
   233       
       
   234     <!-- Wiki mode -->
       
   235       
       
   236       <tr><th colspan="2">Wiki mode</th></tr>
       
   237       
       
   238       <tr>
       
   239         <td class="row3" rowspan="2">
       
   240           Enano can also act as a wiki, meaning anyone can edit and create pages. To enable Wiki Mode, check the box to the right.<br /><br />
       
   241           In Wiki Mode, certain HTML tags such as &lt;script&gt; and &lt;object&gt; are disabled, and all PHP code is disabled, except if the person editing the page is an administrator.<br /><br />
       
   242           Also, Enano keeps complete page history, which makes restoring vandalized pages easy. You can also protect pages so that they cannot be edited.
       
   243         </td>
       
   244         <td class="row1">
       
   245           <input type="checkbox" name="wikimode" id="wikimode" <?php if(getConfig('wiki_mode')=='1') echo('CHECKED '); ?> /><label for="wikimode">Enable Wiki Mode</label>
       
   246         </td>
       
   247       </tr>
       
   248       
       
   249       <tr><td class="row2"><label><input type="checkbox" name="wiki_mode_require_login"<?php if(getConfig('wiki_mode_require_login')=='1') echo('CHECKED '); ?>/> Only for logged in users</label></td></tr>
       
   250       
       
   251       <tr>
       
   252         <td class="row3" rowspan="2">
       
   253           <b>Edit page notice</b><br />
       
   254           When Wiki Mode is enabled, anyone can edit pages. Check the box below and enter a message to display it whenever the page editor is opened.
       
   255         </td>
       
   256         <td class="row1">
       
   257           <input onclick="if(this.checked) document.getElementById('editmsg_text').style.display='block'; else document.getElementById('editmsg_text').style.display='none';" type="checkbox" name="editmsg" id="editmsg" <?php if(getConfig('wiki_edit_notice')=='1') echo('CHECKED '); ?>/> <label for="editmsg">Show a message whenever pages are edited</label>
       
   258         </td>
       
   259       </tr>
       
   260       
       
   261       <tr>
       
   262         <td class="row2">
       
   263           <textarea <?php if(getConfig('wiki_edit_notice')!='1') echo('style="display:none" '); ?>rows="5" cols="30" name="editmsg_text" id="editmsg_text"><?php echo getConfig('wiki_edit_notice_text'); ?></textarea>
       
   264         </td>
       
   265       </tr>
       
   266       
       
   267     <!-- Site statistics -->
       
   268     
       
   269       <tr><th colspan="2">Statistics and hit counting</th></tr>
       
   270       
       
   271       <tr>
       
   272         <td class="row1">Enano has the ability to show statistics for every page on the site. This allows you to keep very close track of who is visiting your site, and from where.<br /><br />Unfortunately, some users don't like being logged. For this reason, you should state clearly what is logged (usually the username or IP address, current time, page name, and referer URL) in your privacy policy.</td>
       
   273         <td class="row1"><label><input type="checkbox" name="log_hits" <?php if(getConfig('log_hits') == '1') echo 'checked="checked" '; ?>/>  Log all page hits</label><br /><small>This excludes special and administration pages.</small></td>
       
   274       </tr>
       
   275       
       
   276     <!-- Comment options -->
       
   277       
       
   278       <tr><th colspan="2">Comment system</th></tr>
       
   279       <tr><td class="row1"><label for="enable-comments"><b>Enable the comment system</b></label>                      </td><td class="row1"><input name="enable-comments"  id="enable-comments"  type="checkbox" <?php if(getConfig('enable_comments')=='1')  echo('CHECKED '); ?>/></td></tr>
       
   280       <tr><td class="row2"><label for="comment-approval">Require approval before article comments can be shown</label></td><td class="row2"><input name="comment-approval" id="comment-approval" type="checkbox" <?php if(getConfig('approve_comments')=='1') echo('CHECKED '); ?>/></td></tr>
       
   281       <tr><td class="row1">Guest comment posting allowed                                                              </td><td class="row1"><label><input name="comments_need_login" type="radio" value="0" <?php if(getConfig('comments_need_login')=='0') echo 'CHECKED '; ?>/> Yes</label>
       
   282                                                                                                                                             <label><input name="comments_need_login" type="radio" value="1" <?php if(getConfig('comments_need_login')=='1') echo 'CHECKED '; ?>/> Require visual confirmation</label>
       
   283     <!-- Default permissions -->                                                                                                            <label><input name="comments_need_login" type="radio" value="2" <?php if(getConfig('comments_need_login')=='2') echo 'CHECKED '; ?>/> No (require login)</label></td></tr>
       
   284     
       
   285     <!--
       
   286     
       
   287     READ: Do not try to enable this, backend support for it has been disabled. To edit default
       
   288           permissions, select The Entire Website in any permissions editor window.
       
   289     
       
   290       <tr><th colspan="2">Default permissions for pages</th></tr>
       
   291       
       
   292       <tr>
       
   293         <td class="row1">You can edit the default set of permissions used when no other permissions are available. Permissions set here are used when no other permissions are available. As with other ACL rules, you can assign these defaults to every user or one specific user or group.</td>
       
   294         <td class="row1"><a href="#" onclick="ajaxOpenACLManager('__DefaultPermissions', 'Special'); return false;">Manage default permissions</a></td>
       
   295       </tr>
       
   296       
       
   297       -->
       
   298       
       
   299     <!-- enanocms.org link -->
       
   300     
       
   301     <tr>
       
   302       <th colspan="2">Promote Enano</th>
       
   303     </tr>
       
   304     <tr>
       
   305       <td class="row3">
       
   306         If you think Enano is nice, or if you want to show your support for the Enano team, you can do so by placing a link to the Enano
       
   307         homepage in your Links sidebar block. You absolutely don't have to do this, and you won't get degraded support if you don't. Because
       
   308         Enano is still relatively new in the CMS world, it needs all the attention it can get - and you can easily help to spread the word
       
   309         using this link.
       
   310       </td>
       
   311       <td class="row1">
       
   312         <label>
       
   313           <input name="enano_powered_link" type="checkbox" <?php if(getConfig('powered_btn') == '1') echo 'checked="checked"'; ?> />&nbsp;&nbsp;Place a link to www.enanocms.org on the sidebar
       
   314         </label>
       
   315       </td>
       
   316     </tr>
       
   317       
       
   318     <!-- Site disablement -->
       
   319     
       
   320       <tr><th colspan="2">Disable all site access</th></tr>
       
   321       
       
   322       <tr>
       
   323         <td class="row3" rowspan="2">Disabling the site allows you to work on the site without letting non-administrators see or use it.</td>
       
   324         <td class="row1"><label><input onclick="if(this.checked) document.getElementById('site_disabled_notice').style.display='block'; else document.getElementById('site_disabled_notice').style.display='none';" type="checkbox" name="site_disabled" <?php if(getConfig('site_disabled') == '1') echo 'checked="checked" '; ?>/>  Disable this site</label></td>
       
   325       </tr>
       
   326       <tr>
       
   327         <td class="row2">
       
   328           <div id="site_disabled_notice">
       
   329             Message to show to users:<br />
       
   330             <textarea name="site_disabled_notice" rows="7" cols="30"><?php echo getConfig('site_disabled_notice'); ?></textarea>
       
   331           </div>
       
   332         </td>
       
   333       </tr>
       
   334     
       
   335     <!-- Account activation -->
       
   336       
       
   337       <tr><th colspan="2">User account activation</th></tr>
       
   338       
       
   339       <tr>
       
   340         <td class="row3" colspan="2">
       
   341           If you would like to require users to confirm their e-mail addresses by way of account activation, you can enable this behavior here. If this option is set to "None", users will be able to register and use this site without confirming their e-mail addresses. If this option is set to "User", users will automatically be sent e-mails upon registration with a link to activate their accounts. And lastly, if this option is set to "Admin", users' accounts will not be active until an administrator activates the account.<br /><br />
       
   342           You may also disable registration completely if needed.<br /><br />
       
   343           <b>Note: because of abuse by project administrators, sending account activation e-mails will not work on SourceForge.net servers.</b>
       
   344         </td>
       
   345       </tr>
       
   346       
       
   347       <tr>
       
   348         <td class="row1">Account activation:</td><td class="row1">
       
   349           <?php
       
   350           echo '<label><input'; if(getConfig('account_activation') == 'disable') echo ' checked="checked"'; echo ' type="radio" name="account_activation" value="disable" /> Disable registration</label><br />';
       
   351           echo '<label><input'; if(getConfig('account_activation') != 'user' && getConfig('account_activation') != 'admin') echo ' checked="checked"'; echo ' type="radio" name="account_activation" value="none" /> None</label>';
       
   352           echo '<label><input'; if(getConfig('account_activation') == 'user') echo ' checked="checked"'; echo ' type="radio" name="account_activation" value="user" /> User</label>';
       
   353           echo '<label><input'; if(getConfig('account_activation') == 'admin') echo ' checked="checked"'; echo ' type="radio" name="account_activation" value="admin" /> Admin</label>';
       
   354           ?>
       
   355         </td>
       
   356       </tr>
       
   357       
       
   358     <!-- E-mail options -->
       
   359     
       
   360     <tr><th colspan="2">E-mail sent from the site</th></tr>
       
   361     <tr><td class="row1">E-mail sending method:<br /><small>Try using the built-in e-mail method first. If that doesn't work, you will need to enter valid SMTP information here.</small></td>
       
   362         <td class="row1"><label><input <?php if(getConfig('smtp_enabled') != '1') echo 'checked="checked"'; ?> type="radio" name="emailmethod" value="phpmail" />PHP's built-in mail() function</label><br />
       
   363                          <label><input <?php if(getConfig('smtp_enabled') == '1') echo 'checked="checked"'; ?> type="radio" name="emailmethod" value="smtp" />Use an external SMTP server</label></td>
       
   364         </tr>
       
   365     <tr><td class="row2">SMTP hostname:<br /><small>This option only applies to the external SMTP mode.</small></td>
       
   366         <td class="row2"><input value="<?php echo getConfig('smtp_server'); ?>" name="smtp_host" type="text" size="30" /></td>
       
   367         </tr>
       
   368     <tr><td class="row1">SMTP credentials:<br /><small>This option only applies to the external SMTP mode.</small></td>
       
   369         <td class="row1">Username: <input value="<?php echo getConfig('smtp_user'); ?>" name="smtp_user" type="text" size="30" /><br />
       
   370             Password: <input value="<?php if(getConfig('smtp_password') != false) echo 'XXXXXXXXXXXX'; ?>" name="smtp_pass" type="password" size="30" /></td>
       
   371         </tr>
       
   372       
       
   373     <!-- SourceForge.net logo -->
       
   374       
       
   375       <tr><th colspan="2">SourceForge.net logo</th></tr>
       
   376       
       
   377       <tr>
       
   378         <td colspan="2" class="row3">
       
   379           All projects hosted by SourceForge.net are required to display an official SourceForge.net logo on their pages.  If you want
       
   380           to display a SourceForge.net logo on the sidebar, check the box below, enter your group ID, and select an image type.
       
   381         </td>
       
   382       </tr>
       
   383       
       
   384       <?php
       
   385       if(getConfig("sflogo_enabled")=='1') $c='CHECKED ';
       
   386       else $c='';
       
   387       if(getConfig("sflogo_groupid")) $g=getConfig("sflogo_groupid");
       
   388       else $g='';
       
   389       if(getConfig("sflogo_type")) $t=getConfig("sflogo_type");
       
   390       else $t='1';
       
   391       ?>
       
   392       
       
   393       <tr>
       
   394         <td class="row1">Display the SourceForge.net logo on the right sidebar</td>
       
   395         <td class="row1"><input type=checkbox name="showsf" id="showsf" <?php echo $c; ?> /></td>
       
   396       </tr>
       
   397       
       
   398       <tr>
       
   399         <td class="row2">Group ID:</td>
       
   400         <td class="row2"><input value="<?php echo $g; ?>" type=text size=15 name=sfgroup /></td>
       
   401       </tr>
       
   402       
       
   403       <tr>
       
   404         <td class="row1">Logo style:</td>
       
   405         <td class="row1">
       
   406           <select name="sflogo">
       
   407             <option <?php if($t=='1') echo('SELECTED '); ?>value=1>88x31px, white</option>
       
   408             <option <?php if($t=='2') echo('SELECTED '); ?>value=2>125x37px, white</option>
       
   409             <option <?php if($t=='3') echo('SELECTED '); ?>value=3>125x37px, black</option>
       
   410             <option <?php if($t=='4') echo('SELECTED '); ?>value=4>125x37px, blue</option>
       
   411             <option <?php if($t=='5') echo('SELECTED '); ?>value=5>210x62px, white</option>
       
   412             <option <?php if($t=='6') echo('SELECTED '); ?>value=6>210x62px, black</option>
       
   413             <option <?php if($t=='7') echo('SELECTED '); ?>value=7>210x62px, blue</option>
       
   414           </select>
       
   415         </td>
       
   416       </tr>
       
   417       
       
   418     <!-- W3C validator buttons -->
       
   419       
       
   420       <tr><th colspan="2">W3C compliance logos</th></tr>
       
   421       <tr><th colspan="2" class="subhead">Enano generates (by default) Valid XHTML 1.1 code, plus valid CSS.  If you want to show this off, check the appropriate boxes below.</th></tr>
       
   422       
       
   423       <tr><td class="row1"><label for="w3c-vh32">HTML 3.2</label>     </td><td class="row1"><input type="checkbox" <?php if(getConfig('w3c_vh32')=='1')     echo('CHECKED '); ?> id="w3c-vh32"     name="w3c-vh32"     /></td></tr>
       
   424       <tr><td class="row2"><label for="w3c-vh40">HTML 4.0</label>     </td><td class="row2"><input type="checkbox" <?php if(getConfig('w3c_vh40')=='1')     echo('CHECKED '); ?> id="w3c-vh40"     name="w3c-vh40"     /></td></tr>
       
   425       <tr><td class="row1"><label for="w3c-vh401">HTML 4.01</label>   </td><td class="row1"><input type="checkbox" <?php if(getConfig('w3c_vh401')=='1')    echo('CHECKED '); ?> id="w3c-vh401"    name="w3c-vh401"    /></td></tr>
       
   426       <tr><td class="row2"><label for="w3c-vxhtml10">XHTML 1.0</label></td><td class="row2"><input type="checkbox" <?php if(getConfig('w3c_vxhtml10')=='1') echo('CHECKED '); ?> id="w3c-vxhtml10" name="w3c-vxhtml10" /></td></tr>
       
   427       <tr><td class="row1"><label for="w3c-vxhtml11">XHTML 1.1</label></td><td class="row1"><input type="checkbox" <?php if(getConfig('w3c_vxhtml11')=='1') echo('CHECKED '); ?> id="w3c-vxhtml11" name="w3c-vxhtml11" /></td></tr>
       
   428       <tr><td class="row2"><label for="w3c-vcss">CSS</label>          </td><td class="row2"><input type="checkbox" <?php if(getConfig('w3c_vcss')=='1')     echo('CHECKED '); ?> id="w3c-vcss"     name="w3c-vcss"     /></td></tr>
       
   429 
       
   430     <!-- DefectiveByDesign.org ad -->      
       
   431       
       
   432       <tr><th colspan="2">Defective By Design Anti-DRM button</th></tr>
       
   433       <tr><td colspan="2" class="row3"><b>The Enano project is strongly against Digital Restrictions Management.</b> DRM removes the freedoms that every consumer should have: to freely copy and use digital media items they legally purchased to their own devices. Showing your opposition to DRM is as easy as checking the box below to place a link to <a href="http://www.defectivebydesign.org">DefectiveByDesign.org</a> on your sidebar.</td></tr>
       
   434       <tr><td class="row1"><label for="dbdbutton">Help stop DRM by placing a link to DBD on the sidebar!</label></td><td class="row1"><input type="checkbox" name="dbdbutton" id="dbdbutton" <?php if(getConfig('dbd_button')=='1')  echo('checked="checked" '); ?>/></td></tr>
       
   435       
       
   436     <!-- Save button -->
       
   437       
       
   438       <tr><th style="text-align: right" class="subhead" colspan="2"><input type=submit name=submit value="Save changes" /></th></tr>
       
   439       
       
   440     </table>
       
   441   </div>
       
   442 </form>
       
   443   <?php
       
   444 }
       
   445 
       
   446 function page_Admin_UploadConfig()
       
   447 {
       
   448   global $db, $session, $paths, $template, $plugins; // Common objects
       
   449   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
   450   {
       
   451     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
   452     return;
       
   453   }
       
   454   
       
   455   if(isset($_POST['save']))
       
   456   {
       
   457     if(isset($_POST['enable_uploads'])) setConfig('enable_uploads', '1'); else setConfig('enable_uploads', '0');
       
   458     if(isset($_POST['enable_imagemagick'])) setConfig('enable_imagemagick', '1'); else setConfig('enable_imagemagick', '0');
       
   459     if(isset($_POST['cache_thumbs'])) setConfig('cache_thumbs', '1'); else setConfig('cache_thumbs', '0');
       
   460     if(isset($_POST['file_history'])) setConfig('file_history', '1'); else setConfig('file_history', '0');
       
   461     if(file_exists($_POST['imagemagick_path'])) setConfig('imagemagick_path', $_POST['imagemagick_path']);
       
   462     else echo '<span style="color: red"><b>Warning:</b> the file "'.$_POST['imagemagick_path'].'" was not found, and the ImageMagick file path was not updated.</span>';
       
   463     $max_upload = floor((float)$_POST['max_file_size'] * (int)$_POST['fs_units']);
       
   464     setConfig('max_file_size', $max_upload.'');
       
   465   }
       
   466   echo '<form name="main" action="'.htmlspecialchars(makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module'])).'" method="post">';
       
   467   ?>
       
   468   <h3>File upload configuration</h3>
       
   469   <p>Enano supports the ability to upload files to your website and store the files in the database. This enables you to embed images
       
   470      and such into pages without manually writing the HTML. However, the upload feature can sometimes pose a risk to your site, as viruses
       
   471      and executable files can sometimes be uploaded.</p>
       
   472   <p><label><input type="checkbox" name="enable_uploads" <?php if(getConfig('enable_uploads')=='1') echo 'checked="checked"'; ?> /> <b>Enable file uploads</b></label></p>
       
   473   <p>Maximum file size: <input name="max_file_size" onkeyup="if(!this.value.match(/^([0-9\.]+)$/ig)) this.value = this.value.substr(0,this.value.length-1);" value="<?php echo getConfig('max_file_size'); ?>" /> <select name="fs_units"><option value="1" selected="selected">bytes</option><option value="1024">KB</option><option value="1048576">MB</option></select></p>
       
   474   <p>You can allow Enano to generate thumbnails of images automatically. This feature requires ImageMagick to work properly. If your server
       
   475      does not have ImageMagick on it, Enano will simply make your users' browsers scale the images. In most cases this is fine, but if you
       
   476      are uploading large (>100KB) images and embedding them inside of pages, you should try to enable ImageMagick because transferring these
       
   477      large images many times can cost you quite a lot of bandwidth.</p>
       
   478   <p><label><input type="checkbox" name="enable_imagemagick" <?php if(getConfig('enable_imagemagick')=='1') echo 'checked="checked"'; ?> /> Use ImageMagick to scale images</label><br />
       
   479      Path to ImageMagick: <input type="text" name="imagemagick_path" value="<?php if(getConfig('imagemagick_path')) echo getConfig('imagemagick_path'); else echo '/usr/bin/convert'; ?>" /><br />
       
   480      On Linux and Unix servers, the most likely options here are /usr/bin/convert and /usr/local/bin/convert. If you server runs Windows, then
       
   481      ImageMagick is most likely to be C:\Windows\Convert.exe or C:\Windows\System32\Convert.exe.
       
   482      </p>
       
   483   <p>If you use ImageMagick to scale images, your server will be very busy constantly scaling images if your website is busy, and your site
       
   484      may experience slowdowns. You can dramatically speed up this scaling process if you use a directory to cache thumbnail images.</p>
       
   485   <p><b>Please note:</b> the cache/ directory on your server <u>must</u> be writable by the server. While this is not usually a problem on
       
   486      Windows servers, most Linux/Unix servers will require you to CHMOD the cache/ directory to 777. See your FTP client's user guide for
       
   487      more information on how to do this.<?php if(!is_writable(ENANO_ROOT.'/cache/')) echo ' <b>At present, it seems that the cache directory
       
   488      is not writable. The checkbox below has been disabled to maintain the stability of Enano.</b>'; ?></p>
       
   489   <p><label><input type="checkbox" name="cache_thumbs" <?php if(getConfig('cache_thumbs')=='1' && is_writable(ENANO_ROOT.'/cache/')) echo 'checked="checked"'; elseif(!is_writable(ENANO_ROOT.'/cache/')) echo 'readonly="readonly"'; ?> /> Cache thumbnailed images</label></p>
       
   490   <p>Lastly, you can choose whether file history will be saved. If this option is turned on, you will be able to roll back any malicious
       
   491      changes made to uploaded files, but this requires a significant amount of database storage. You should probably leave this option
       
   492      enabled unless you have less than 250MB of MySQL database space.</p>
       
   493   <p><label><input type="checkbox" name="file_history" <?php if(getConfig('file_history')=='1' && is_writable(ENANO_ROOT.'/cache/')) echo 'checked="checked"'; ?> /> Keep a history of uploaded files</label></p>
       
   494   <hr style="margin-left: 1em;" />
       
   495   <p><input type="submit" name="save" value="Save changes" style="font-weight: bold;" /></p>
       
   496   <?php
       
   497   echo '</form>';
       
   498 }
       
   499 
       
   500 function page_Admin_PluginManager() {
       
   501   global $db, $session, $paths, $template, $plugins; // Common objects
       
   502   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
   503   {
       
   504     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
   505     return;
       
   506   }
       
   507   
       
   508   
       
   509   if(isset($_GET['action'])) {
       
   510     switch($_GET['action']) {
       
   511       case "enable":
       
   512         setConfig('plugin_'.$_GET['plugin'], '1');
       
   513         break;
       
   514       case "disable":
       
   515         if($_GET['plugin']!='admin.php') setConfig('plugin_'.$_GET['plugin'], '0');
       
   516         else echo('<h3>Error disabling plugin</h3><p>The administration panel plugin cannot be disabled.</p>');
       
   517         break;
       
   518     }
       
   519   }
       
   520   $dir = './plugins/';
       
   521   $plugin_list = Array();
       
   522   $system = Array();
       
   523   if (is_dir($dir)) {
       
   524     if ($dh = opendir($dir)) {
       
   525       while (($file = readdir($dh)) !== false) {
       
   526         if(preg_match('#^(.*?)\.php$#is', $file) && $file != 'index.php')
       
   527         {
       
   528           if ( in_array($file, $plugins->system_plugins) )
       
   529           {
       
   530             $thelist =& $system;
       
   531             continue;
       
   532           }
       
   533           else
       
   534           {
       
   535             $thelist =& $plugin_list;
       
   536           }
       
   537           $f = file_get_contents($dir . $file);
       
   538           $f = explode("\n", $f);
       
   539           $f = array_slice($f, 2, 7);
       
   540           $f[0] = substr($f[0], 13, strlen($f[0]));
       
   541           $f[1] = substr($f[1], 12, strlen($f[1]));
       
   542           $f[2] = substr($f[2], 13, strlen($f[2]));
       
   543           $f[3] = substr($f[3], 8,  strlen($f[3]));
       
   544           $f[4] = substr($f[4], 9,  strlen($f[4]));
       
   545           $f[5] = substr($f[5], 12, strlen($f[5]));
       
   546           $thelist[$file] = Array();
       
   547           $thelist[$file]['name'] = $f[0];
       
   548           $thelist[$file]['uri']  = $f[1];
       
   549           $thelist[$file]['desc'] = $f[2];
       
   550           $thelist[$file]['auth'] = $f[3];
       
   551           $thelist[$file]['vers'] = $f[4];
       
   552           $thelist[$file]['aweb'] = $f[5];
       
   553         }
       
   554       }
       
   555       closedir($dh);
       
   556     }
       
   557   }
       
   558   echo('<div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4">
       
   559       <tr><th>Plugin filename</th><th>Plugin name</th><th>Description</th><th>Author</th><th>Version</th><th></th></tr>');
       
   560     $plugin_files = array_keys($plugin_list);
       
   561     $cls = 'row2';
       
   562     for ( $i = 0; $i < sizeof($plugin_files); $i++ )
       
   563     {
       
   564       $cls = ( $cls == 'row2' ) ? 'row3' : 'row2';
       
   565       echo '<tr>
       
   566               <td class="'.$cls.'">'.$plugin_files[$i].'</td>
       
   567               <td class="'.$cls.'"><a href="'.$plugin_list[$plugin_files[$i]]['uri'].'">'.$plugin_list[$plugin_files[$i]]['name'].'</a></td>
       
   568               <td class="'.$cls.'">'.$plugin_list[$plugin_files[$i]]['desc'].'</td>
       
   569               <td class="'.$cls.'"><a href="'.$plugin_list[$plugin_files[$i]]['aweb'].'">'.$plugin_list[$plugin_files[$i]]['auth'].'</a></td>
       
   570               <td class="'.$cls.'">'.$plugin_list[$plugin_files[$i]]['vers'].'</td>
       
   571               <td class="'.$cls.'">';
       
   572       if ( getConfig('plugin_'.$plugin_files[$i]) == '1' )
       
   573       {
       
   574         echo '<a href="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'&amp;action=disable&amp;plugin='.$plugin_files[$i].'">Disable</a>';
       
   575       }
       
   576       else
       
   577       {
       
   578         echo '<a href="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'&amp;action=enable&amp;plugin='.$plugin_files[$i].'">Enable</a>';
       
   579       }
       
   580       echo '</td></tr>';
       
   581     }
       
   582     echo '</table></div>';
       
   583 }
       
   584 
       
   585 function page_Admin_UploadAllowedMimeTypes()
       
   586 {
       
   587   global $db, $session, $paths, $template, $plugins; // Common objects
       
   588   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
   589   {
       
   590     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
   591     return;
       
   592   }
       
   593   
       
   594   global $mime_types, $mimetype_exps, $mimetype_extlist;
       
   595   if(isset($_POST['save']))
       
   596   {
       
   597     $bits = '';
       
   598     $keys = array_keys($mime_types);
       
   599     foreach($keys as $i => $k)
       
   600     {
       
   601       if(isset($_POST['ext_'.$k])) $bits .= '1';
       
   602       else $bits .= '0';
       
   603     }
       
   604     $bits = compress_bitfield($bits);
       
   605     setConfig('allowed_mime_types', $bits);
       
   606     echo '<div class="info-box">Your changes have been saved.</div>';
       
   607   }
       
   608   $allowed = fetch_allowed_extensions();
       
   609   ?>
       
   610   <h3>Allowed file types</h3>
       
   611    <p>Using the form below, you can decide which file types are allowed to be uploaded to this site.</p>
       
   612   <?php
       
   613   echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', (( isset($_GET['sqldbg'])) ? 'sqldbg&amp;' : '') .'module='.$paths->cpage['module']).'" method="post">';
       
   614     $c = -1;
       
   615     $t = -1;
       
   616     $cl = 'row1';
       
   617     echo "\n".'    <div class="tblholder">'."\n".'      <table cellspacing="1" cellpadding="2" style="margin: 0; padding: 0;" border="0">'."\n".'        <tr>'."\n        ";
       
   618     foreach($mime_types as $e => $m)
       
   619     {
       
   620       $c++;
       
   621       $t++;
       
   622       if($c == 3)
       
   623       {
       
   624         $c = 0;
       
   625         $cl = ( $cl == 'row1' ) ? 'row2' : 'row1';
       
   626         echo '</tr>'."\n".'        <tr>'."\n        ";
       
   627       }
       
   628       $seed = "extchkbx_{$e}_".md5(microtime() . mt_rand());
       
   629       $chk = (!empty($allowed[$e])) ? ' checked="checked"' : '';
       
   630       echo "  <td class='$cl'>\n            <label><input id='{$seed}' type='checkbox' name='ext_{$e}'{$chk} />.{$e}\n            ({$m})</label>\n          </td>\n        ";
       
   631     }
       
   632     while($c < 2)
       
   633     {
       
   634       $c++;
       
   635       echo "  <td class='{$cl}'></td>\n        ";
       
   636     }
       
   637     echo '<tr><th class="subhead" colspan="3"><input type="submit" name="save" value="Save changes" /></th></tr>';
       
   638     echo '</tr>'."\n".'      </table>'."\n".'    </div>';
       
   639     echo '</form>';
       
   640   ?>
       
   641   <?php
       
   642 }
       
   643 
       
   644 function page_Admin_Sidebar()
       
   645 {
       
   646   global $db, $session, $paths, $template, $plugins; // Common objects
       
   647   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
   648   {
       
   649     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
   650     return;
       
   651   }
       
   652   
       
   653   ?>
       
   654   <h2>Editing and managing the Enano sidebar</h2>
       
   655    <p>The Enano sidebar is a versatile tool when scripted correctly. You don't have to be a programmer to enjoy the features the Sidebar
       
   656       provides; however, editing the sidebar requires a small bit of programming knowledge and an understanding of Enano's system message
       
   657       markup language.
       
   658       </p>
       
   659    <p>The Enano system markup language is somewhat similar to HTML, in that it uses tags (&lt;example&gt;like this&lt;/example&gt;) for the
       
   660       main syntax. However, Enano uses curly brackets ({ and }) as opposed to less-than and greater-than signs (&lt; and &gt;).</p>
       
   661    <p>Programming the Enano sidebar requires the use of two tags: {slider} and {if}. The {slider} tag is used to create a new heading
       
   662       on the sidebar, and all text enclosed in that tag will be collapsed when the heading is clicked. To specify the text on the heading,
       
   663       use an equals sign (=) after the "slider" text. Then insert any links (they should be wiki-formatted) to internal Enano pages and
       
   664       external sites.</p>
       
   665    <p>So here is what the language for the default sidebar's "Navigation" heading looks like:</p>
       
   666    <pre>{slider=Navigation}
       
   667   [[Main Page|Home]]
       
   668   [[Enano:Sidebar|Edit the sidebar]]
       
   669 {/slider}</pre>
       
   670    <p>Pretty simple, huh? Good, now we're going to learn another common aspect of Enano programming: conditionals. The {if} tag allows you
       
   671       to decide whether a portion of the sidebar will be displayed based on a template variable. Currently the only available conditions are
       
   672       "user_logged_in" and "auth_admin", but more will be added soon. To use a conditional, enter {if conditional_name}, and then the
       
   673       wiki-formatted text that you want to be under that condition, and then close the tag with {/if}. In the same way, you can reverse the
       
   674       effect with {!if}. With {!if}, the closing tag is still {/if}, so keep that in mind. An {else} tag will be supported soon.</p>
       
   675    <p>Now it's time for some real fun: variables. All template variables can be accessed from the sidebar. A variable is simply the
       
   676       variable name, prefixed by a dollar sign ($). Some of the most common variables are $USERNAME, $SITE_NAME, $SITE_DESC, and $PAGE_NAME.
       
   677       The sidebar also has some special variables that it uses for some of its links. The logout link can be added with $LOGOUT_LINK, and
       
   678       the "change theme" button can be added with $STYLE_LINK.</p>
       
   679    <p>So here is the Enano markup for the portion of the sidebar that contains the user tools:</p>
       
   680    <pre>{slider=$USERNAME}
       
   681   [[User:$USERNAME|User page]]
       
   682   [[Special:Contributions?user=$USERNAME|My Contributions]]
       
   683   {if user_logged_in}
       
   684     [[Special:Preferences|Preferences]]
       
   685     $THEME_LINK
       
   686   {/if}
       
   687   {if auth_admin}
       
   688     [[Special:Administration|Administration]]
       
   689   {/if}
       
   690   {if user_logged_in}
       
   691     $LOGOUT_LINK
       
   692   {/if}
       
   693   {!if user_logged_in}
       
   694     Create an account
       
   695     Log in
       
   696   {/if}
       
   697 {/slider}</pre>
       
   698   <?php
       
   699 }
       
   700 
       
   701 function page_Admin_UserManager() {
       
   702   global $db, $session, $paths, $template, $plugins; // Common objects
       
   703   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
   704   {
       
   705     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
   706     return;
       
   707   }
       
   708   
       
   709   if(isset($_POST['go'])) {
       
   710     // We need the user ID before we can do anything
       
   711     $q = $db->sql_query('SELECT user_id,username,email,real_name,style,user_level FROM '.table_prefix.'users WHERE username=\'' . $db->escape($_POST['username']) . '\'');
       
   712     if(!$q) die('Error selecting user ID: '.mysql_error());
       
   713     if($db->numrows() < 1) { echo('User does not exist, please enter another username.'); return; }
       
   714     $r = $db->fetchrow();
       
   715     $db->free_result();
       
   716     if(isset($_POST['save']))
       
   717     {
       
   718       $_POST['level'] = intval($_POST['level']);
       
   719       
       
   720       $new_level = $_POST['level'];
       
   721       $old_level = intval($r['user_level']);
       
   722       
       
   723       $re = $session->update_user((int)$r['user_id'], $_POST['new_username'], false, $_POST['new_pass'], $_POST['email'], $_POST['real_name'], false, $_POST['level']);
       
   724       
       
   725       if($re == 'success')
       
   726       {
       
   727         
       
   728         if ( $new_level != $old_level )
       
   729         {
       
   730           $user_id = intval($r['user_id']);
       
   731           // We need to update group memberships
       
   732           if ( $old_level == USER_LEVEL_ADMIN ) 
       
   733           {
       
   734             $session->remove_user_from_group($user_id, GROUP_ID_ADMIN);
       
   735           }
       
   736           else if ( $old_level == USER_LEVEL_MOD ) 
       
   737           {
       
   738             $session->remove_user_from_group($user_id, GROUP_ID_MOD);
       
   739           }
       
   740           
       
   741           if ( $new_level == USER_LEVEL_ADMIN )
       
   742           {
       
   743             $session->add_user_to_group($user_id, GROUP_ID_ADMIN, false);
       
   744           }
       
   745           else if ( $new_level == USER_LEVEL_MOD )
       
   746           {
       
   747             $session->add_user_to_group($user_id, GROUP_ID_MOD, false);
       
   748           }
       
   749         }
       
   750         
       
   751         echo('<div class="info-box">Your changes have been saved.</div>');
       
   752       }
       
   753       else
       
   754       {
       
   755         echo('<div class="error-box">Error saving changes: '.implode('<br />', $re).'</div>');
       
   756       }
       
   757       $q = $db->sql_query('SELECT user_id,username,email,real_name,style,user_level FROM '.table_prefix.'users WHERE username=\''.$db->escape($_POST['username']).'\'');
       
   758       if ( !$q )
       
   759       {
       
   760         die('Error selecting user ID: '.mysql_error());
       
   761       }
       
   762       if($db->numrows($q) < 1)
       
   763       {
       
   764         die('User does not exist, please enter another username.');
       
   765       }
       
   766       $r = mysql_fetch_object($q);
       
   767       $db->free_result();
       
   768     }
       
   769     elseif(isset($_POST['deleteme']) && isset($_POST['delete_conf']))
       
   770     {
       
   771       $q = $db->sql_query('DELETE FROM users WHERE user_id='.$r['user_id'].';');
       
   772       if($q)
       
   773       {
       
   774         echo '<div class="error-box">The user account "'.$r['username'].'" was deleted.</div>';
       
   775       }
       
   776       else
       
   777       {
       
   778         echo '<div class="error-box">The user account "'.$r['username'].'" could not be deleted due to a database error.<br /><br />'.$db->get_error().'</div>';
       
   779       }
       
   780     }
       
   781     else
       
   782     {
       
   783       echo('
       
   784       <h3>Edit User Info</h3>
       
   785       <form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">
       
   786         <table border="0" style="margin-left: 0.2in;">   
       
   787           <tr><td>Username:</td><td><input type="text" name="new_username" value="'.$r['username'].'" /></td></tr>
       
   788           <tr><td>New Password:</td><td><input type="password" name="new_pass" /></td></tr>
       
   789           <tr><td>E-mail:</td><td><input type="text" name="email" value="'.$r['email'].'" /></td></tr>
       
   790           <tr><td>Real Name:</td><td><input type="text" name="real_name" value="'.$r['real_name'].'" /></td></tr>
       
   791           <tr><td>User level:</td><td><select name="level"><option '); if($r['user_level']==USER_LEVEL_CHPREF) echo('SELECTED'); echo(' value="'.USER_LEVEL_CHPREF.'">Regular User</option><option '); if($r['user_level']==USER_LEVEL_MOD) echo('SELECTED'); echo(' value="'.USER_LEVEL_MOD.'">Moderator</option><option '); if($r['user_level']==USER_LEVEL_ADMIN) echo('SELECTED'); echo(' value="'.USER_LEVEL_ADMIN.'">Administrator</option></select></td></tr>
       
   792           <tr><td>Delete user:</td><td><input type="hidden" name="go" /><input type="hidden" name="username" value="'.$r['username'].'" /><input onclick="return confirm(\'This is your last warning.\n\nAre you sure you want to delete this user account? Even if you delete this user account, the username will be shown in page edit history, comments, and other areas of the site.\n\nDeleting a user account CANNOT BE UNDONE and should only be done in extreme circumstances.\n\nIf the user has violated the site policy, deleting the account will not prevent him from using the site, for that you need to add a new ban rule.\n\nContinue deleting this user account?\')" type="submit" name="deleteme" value="Delete this user" style="color: red;" /> <label><input type="checkbox" name="delete_conf" /> I\'m absolutely sure</label>
       
   793           <tr><td align="center" colspan="2">
       
   794           <input type="submit" name="save" value="Save Changes" /></td></tr>
       
   795         </table>
       
   796       </form>
       
   797       ');
       
   798     }
       
   799   } elseif(isset($_POST['clearsessions'])) {
       
   800     // Get the current session information so the user doesn't get logged out
       
   801     $aes = new AESCrypt();
       
   802     $sk = md5($session->sid_super);
       
   803     $qb = $db->sql_query('SELECT session_key,salt,auth_level,source_ip,time FROM '.table_prefix.'session_keys WHERE session_key=\''.$sk.'\' AND user_id='.$session->user_id.' AND auth_level='.USER_LEVEL_ADMIN);
       
   804     if(!$qb) die('Error selecting session key info block B: '.$db->get_error());
       
   805     if($db->numrows($qb) < 1) die('Error: cannot read admin session info block B, aborting table clear process');
       
   806     $qa = $db->sql_query('SELECT session_key,salt,auth_level,source_ip,time FROM '.table_prefix.'session_keys WHERE session_key=\''.md5($session->sid).'\' AND user_id='.$session->user_id.' AND auth_level='.USER_LEVEL_MEMBER);
       
   807     if(!$qa) die('Error selecting session key info block A: '.$db->get_error());
       
   808     if($db->numrows($qa) < 1) die('Error: cannot read user session info block A, aborting table clear process');
       
   809     $ra = mysql_fetch_object($qa);
       
   810     $rb = mysql_fetch_object($qb);
       
   811     $db->free_result($qa);
       
   812     $db->free_result($qb);
       
   813     $db->sql_query('DELETE FROM '.table_prefix.'session_keys;');
       
   814     $db->sql_query('INSERT INTO '.table_prefix.'session_keys( session_key,salt,user_id,auth_level,source_ip,time ) VALUES( \''.$ra->session_key.'\', \''.$ra->salt.'\', \''.$session->user_id.'\', \''.$ra->auth_level.'\', \''.$ra->source_ip.'\', '.$ra->time.' ),( \''.$rb->session_key.'\', \''.$rb->salt.'\', \''.$session->user_id.'\', \''.$rb->auth_level.'\', \''.$rb->source_ip.'\', '.$rb->time.' )');
       
   815     echo('
       
   816       <div class="info-box">The session key table has been cleared. Your database should be a little bit smaller now.</div>
       
   817     ');
       
   818   }   
       
   819   echo('
       
   820   <h3>User Management</h3>
       
   821   <form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;">
       
   822     <p>Username: '.$template->username_field('username').' <input type="submit" name="go" value="Go" /></p>
       
   823     <h3>Clear session keys table</h3>
       
   824      <p>It\'s a good idea to clean out your session keys table every once in a while, since this helps to reduce database size. During this process you will be logged off and (hopefully) logged back on automatically. The side effects of this include all users except you being logged off.</p>
       
   825      <p><input type="submit" name="clearsessions" value="Clear session keys table" /></p>
       
   826   </form>
       
   827   ');
       
   828   if(isset($_GET['action']) && isset($_GET['user']))
       
   829   {
       
   830     switch($_GET['action'])
       
   831     {
       
   832       case "activate":
       
   833         $e = $db->sql_query('SELECT activation_key FROM '.table_prefix.'users WHERE username=\'' . $db->escape($_GET['user']) . '\'');
       
   834         if($e)
       
   835         {
       
   836           $row = $db->fetchrow();
       
   837           $db->free_result();
       
   838           if($session->activate_account($_GET['user'], $row['activation_key'])) { echo '<div class="info-box">The user account "'.$_GET['user'].'" has been activated.</div>'; $db->sql_query('DELETE FROM '.table_prefix.'logs WHERE time_id=' . $db->escape($_GET['logid'])); }
       
   839           else echo '<div class="warning-box">The user account "'.$_GET['user'].'" has NOT been activated, possibly because the account is already active.</div>';
       
   840         } else echo '<div class="error-box">Error activating account: '.mysql_error().'</div>';
       
   841         break;
       
   842       case "sendemail":
       
   843         if($session->send_activation_mail($_GET['user'])) { echo '<div class="info-box">The user "'.$_GET['user'].'" has been sent an e-mail with an activation link.</div>'; $db->sql_query('DELETE FROM '.table_prefix.'logs WHERE time_id=' . $db->escape($_GET['logid'])); }
       
   844         else echo '<div class="error-box">The user account "'.$_GET['user'].'" has not been activated, probably because of a bad SMTP configuration.</div>';
       
   845         break;
       
   846       case "deny":
       
   847         $e = $db->sql_query('DELETE FROM '.table_prefix.'logs WHERE log_type=\'admin\' AND action=\'activ_req\' AND edit_summary=\'' . $db->escape($_GET['user']) . '\';');
       
   848         if(!$e) echo '<div class="error-box">Error during row deletion: '.mysql_error().'</div>';
       
   849         else echo '<div class="info-box">All activation requests for the user "'.$_GET['user'].'" have been deleted.</div>';
       
   850         break;
       
   851     }
       
   852   }
       
   853   $q = $db->sql_query('SELECT log_type, action, time_id, date_string, author, edit_summary FROM '.table_prefix.'logs WHERE log_type=\'admin\' AND action=\'activ_req\' ORDER BY time_id DESC;');
       
   854   if($q)
       
   855   {
       
   856     if($db->numrows() > 0)
       
   857     {
       
   858       $n = $db->numrows();
       
   859       if($n == 1) $s = $n . ' user is';
       
   860       else $s = $n . ' users are';
       
   861       echo '<h3>'.$s . ' awaiting account activation</h3>';
       
   862       echo '<div class="tblholder">
       
   863             <table border="0" cellspacing="1" cellpadding="4" width="100%">
       
   864             <tr><th>Date of request</th><th>Requested by</th><th>Requested for</th><th colspan="3">Actions</th></tr>';
       
   865       $cls = 'row2';
       
   866       while($row = $db->fetchrow())
       
   867       {
       
   868         if($cls == 'row2') $cls = 'row1';
       
   869         else $cls = 'row2';
       
   870         echo '<tr><td class="'.$cls.'">'.date('F d, Y h:i a', $row['time_id']).'</td><td class="'.$cls.'">'.$row['author'].'</td><td class="'.$cls.'">'.$row['edit_summary'].'</td><td class="'.$cls.'" style="text-align: center;"><a href="'.makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'UserManager&amp;action=activate&amp;user='.$row['edit_summary'].'&amp;logid='.$row['time_id']).'">Activate now</a></td><td class="'.$cls.'" style="text-align: center;"><a href="'.makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'UserManager&amp;action=sendemail&amp;user='.$row['edit_summary'].'&amp;logid='.$row['time_id']).'">Send activation e-mail</a></td><td class="'.$cls.'" style="text-align: center;"><a href="'.makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'UserManager&amp;action=deny&amp;user='.$row['edit_summary'].'&amp;logid='.$row['time_id']).'">Deny request</a></td></tr>';
       
   871       }
       
   872       echo '</table>';
       
   873     }
       
   874     $db->free_result();
       
   875   }
       
   876 }
       
   877 
       
   878 function page_Admin_GroupManager()
       
   879 {
       
   880   global $db, $session, $paths, $template, $plugins; // Common objects
       
   881   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
   882   {
       
   883     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
   884     return;
       
   885   }
       
   886   
       
   887   if(isset($_POST['do_create_stage1']))
       
   888   {
       
   889     if(!preg_match('/^([A-z0-9 -]+)$/', $_POST['create_group_name']))
       
   890     {
       
   891       echo '<p>The group name you chose is invalid.</p>';
       
   892       return;
       
   893     }
       
   894     echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
       
   895     echo '<div class="tblholder">
       
   896           <table border="0" style="width:100%;" cellspacing="1" cellpadding="4">
       
   897           <tr><th colspan="2">Creating group: '.$_POST['create_group_name'].'</th></tr>
       
   898           <tr>
       
   899             <td class="row1">Group moderator</td><td class="row1">' . $template->username_field('group_mod') . '</td>
       
   900           </tr>
       
   901           <tr><td class="row2">Group status</td><td class="row2">
       
   902             <label><input type="radio" name="group_status" value="'.GROUP_CLOSED.'" checked="checked" /> Closed to new members</label><br />
       
   903             <label><input type="radio" name="group_status" value="'.GROUP_REQUEST.'" /> Members can ask to be added</label><br />
       
   904             <label><input type="radio" name="group_status" value="'.GROUP_OPEN.'" /> Members can join freely</label><br />
       
   905             <label><input type="radio" name="group_status" value="'.GROUP_HIDDEN.'" /> Group is hidden</label>
       
   906           </td></tr>
       
   907           <tr>
       
   908             <th class="subhead" colspan="2">
       
   909               <input type="hidden" name="create_group_name" value="'.$_POST['create_group_name'].'" />
       
   910               <input type="submit" name="do_create_stage2" value="Create group" />
       
   911             </th>
       
   912           </tr>
       
   913           </table>
       
   914           </div>';
       
   915     echo '</form>';
       
   916     return;
       
   917   }
       
   918   elseif(isset($_POST['do_create_stage2']))
       
   919   {
       
   920     if(!preg_match('/^([A-z0-9 -]+)$/', $_POST['create_group_name']))
       
   921     {
       
   922       echo '<p>The group name you chose is invalid.</p>';
       
   923       return;
       
   924     }
       
   925     if(!in_array(intval($_POST['group_status']), Array(GROUP_CLOSED, GROUP_OPEN, GROUP_HIDDEN, GROUP_REQUEST)))
       
   926     {
       
   927       echo '<p>Hacking attempt</p>';
       
   928       return;
       
   929     }
       
   930     $e = $db->sql_query('SELECT group_id FROM '.table_prefix.'groups WHERE group_name=\''.$db->escape($_POST['create_group_name']).'\';');
       
   931     if(!$e)
       
   932     {
       
   933       echo $db->get_error();
       
   934       return;
       
   935     }
       
   936     if($db->numrows() > 0)
       
   937     {
       
   938       echo '<p>The group name you entered already exists.</p>';
       
   939       return;
       
   940     }
       
   941     $db->free_result();
       
   942     $q = $db->sql_query('INSERT INTO '.table_prefix.'groups(group_name,group_type) VALUES( \''.$db->escape($_POST['create_group_name']).'\', ' . intval($_POST['group_status']) . ' )');
       
   943     if(!$q)
       
   944     {
       
   945       echo $db->get_error();
       
   946       return;
       
   947     }
       
   948     $e = $db->sql_query('SELECT user_id FROM '.table_prefix.'users WHERE username=\''.$db->escape($_POST['group_mod']).'\';');
       
   949     if(!$e)
       
   950     {
       
   951       echo $db->get_error();
       
   952       return;
       
   953     }
       
   954     if($db->numrows() < 1)
       
   955     {
       
   956       echo '<p>The username you entered could not be found.</p>';
       
   957       return;
       
   958     }
       
   959     $row = $db->fetchrow();
       
   960     $id = $row['user_id'];
       
   961     $db->free_result();
       
   962     $e = $db->sql_query('SELECT group_id FROM '.table_prefix.'groups WHERE group_name=\''.$db->escape($_POST['create_group_name']).'\';');
       
   963     if(!$e)
       
   964     {
       
   965       echo $db->get_error();
       
   966       return;
       
   967     }
       
   968     if($db->numrows() < 1)
       
   969     {
       
   970       echo '<p>The group ID could not be looked up.</p>';
       
   971       return;
       
   972     }
       
   973     $row = $db->fetchrow();
       
   974     $gid = $row['group_id'];
       
   975     $db->free_result();
       
   976     $e = $db->sql_query('INSERT INTO '.table_prefix.'group_members(group_id,user_id,is_mod) VALUES('.$gid.', '.$id.', 1);');
       
   977     if(!$e)
       
   978     {
       
   979       echo $db->get_error();
       
   980       return;
       
   981     }
       
   982     echo "<div class='info-box'>
       
   983             <b>Information</b><br />
       
   984             The group {$_POST['create_group_name']} has been created successfully.
       
   985           </div>";
       
   986   }
       
   987   if(isset($_POST['do_edit']) || isset($_POST['edit_do']))
       
   988   {
       
   989     // Fetch the group name
       
   990     $q = $db->sql_query('SELECT group_name,system_group FROM '.table_prefix.'groups WHERE group_id='.intval($_POST['group_edit_id']).';');
       
   991     if(!$q)
       
   992     {
       
   993       echo $db->get_error();
       
   994       return;
       
   995     }
       
   996     if($db->numrows() < 1)
       
   997     {
       
   998       echo '<p>Error: couldn\'t look up group name</p>';
       
   999     }
       
  1000     $row = $db->fetchrow();
       
  1001     $name = $row['group_name'];
       
  1002     $db->free_result();
       
  1003     if(isset($_POST['edit_do']))
       
  1004     {
       
  1005       if(isset($_POST['edit_do']['del_group']))
       
  1006       {
       
  1007         if ( $row['system_group'] == 1 )
       
  1008         {
       
  1009           echo '<div class="error-box">The group "' . $name . '" could not be deleted because it is a system group required for site functionality.</div>';
       
  1010         }
       
  1011         else
       
  1012         {
       
  1013           $q = $db->sql_query('DELETE FROM '.table_prefix.'group_members WHERE group_id='.intval($_POST['group_edit_id']).';');
       
  1014           if(!$q)
       
  1015           {
       
  1016             echo $db->get_error();
       
  1017             return;
       
  1018           }
       
  1019           $q = $db->sql_query('DELETE FROM '.table_prefix.'groups WHERE group_id='.intval($_POST['group_edit_id']).';');
       
  1020           if(!$q)
       
  1021           {
       
  1022             echo $db->get_error();
       
  1023             return;
       
  1024           }
       
  1025           echo '<div class="info-box">The group "'.$name.'" has been deleted. Return to the <a href="javascript:ajaxPage(\'Admin:GroupManager\');">group manager</a>.</div>';
       
  1026           return;
       
  1027         }
       
  1028       }
       
  1029       if(isset($_POST['edit_do']['save_name']))
       
  1030       {
       
  1031         if(!preg_match('/^([A-z0-9 -]+)$/', $_POST['group_name']))
       
  1032         {
       
  1033           echo '<p>The group name you chose is invalid.</p>';
       
  1034           return;
       
  1035         }
       
  1036         $q = $db->sql_query('UPDATE '.table_prefix.'groups SET group_name=\''.$db->escape($_POST['group_name']).'\'
       
  1037             WHERE group_id='.intval($_POST['group_edit_id']).';');
       
  1038         if(!$q)
       
  1039         {
       
  1040           echo $db->get_error();
       
  1041           return;
       
  1042         }
       
  1043         else
       
  1044         {
       
  1045           echo '<div class="info-box" style="margin: 0 0 10px 0;"">
       
  1046                   The group name has been updated.
       
  1047                 </div>';
       
  1048         }
       
  1049         $name = $_POST['group_name'];
       
  1050         
       
  1051       }
       
  1052       $q = $db->sql_query('SELECT member_id FROM '.table_prefix.'group_members
       
  1053                              WHERE group_id='.intval($_POST['group_edit_id']).';');
       
  1054       if(!$q)
       
  1055       {
       
  1056         echo $db->get_error();
       
  1057         return;
       
  1058       }
       
  1059       if($db->numrows() > 0)
       
  1060       {
       
  1061         while($row = $db->fetchrow($q))
       
  1062         {
       
  1063           if(isset($_POST['edit_do']['del_' . $row['member_id']]))
       
  1064           {
       
  1065             $e = $db->sql_query('DELETE FROM '.table_prefix.'group_members WHERE member_id='.$row['member_id']);
       
  1066             if(!$e)
       
  1067             {
       
  1068               echo $db->get_error();
       
  1069               return;
       
  1070             }
       
  1071           }
       
  1072         }
       
  1073       }
       
  1074       $db->free_result();
       
  1075       if(isset($_POST['edit_do']['add_member']))
       
  1076       {
       
  1077         $q = $db->sql_query('SELECT user_id FROM '.table_prefix.'users WHERE username=\''.$db->escape($_POST['edit_add_username']).'\';');
       
  1078         if(!$q)
       
  1079         {
       
  1080           echo $db->get_error();
       
  1081           return;
       
  1082         }
       
  1083         if($db->numrows() > 0)
       
  1084         {
       
  1085           $row = $db->fetchrow();
       
  1086           $user_id = $row['user_id'];
       
  1087           $is_mod = ( isset( $_POST['add_mod'] ) ) ? '1' : '0';
       
  1088           $q = $db->sql_query('INSERT INTO '.table_prefix.'group_members(group_id,user_id,is_mod) VALUES('.intval($_POST['group_edit_id']).','.$user_id.','.$is_mod.');');
       
  1089           if(!$q)
       
  1090           {
       
  1091             echo $db->get_error();
       
  1092             return;
       
  1093           }
       
  1094           else
       
  1095           {
       
  1096             echo '<div class="info-box" style="margin: 0 0 10px 0;"">
       
  1097                     The user "'.$_POST['edit_add_username'].'" has been added to this usergroup.
       
  1098                   </div>';
       
  1099           }
       
  1100         }
       
  1101         else
       
  1102           echo '<div class="warning-box"><b>The user "'.$_POST['edit_add_username'].'" could not be added.</b><br />This username does not exist.</div>';
       
  1103       }
       
  1104     }
       
  1105     $sg_disabled = ( $row['system_group'] == 1 ) ? ' value="Can\'t delete system group" disabled="disabled" style="color: #FF9773" ' : ' value="Delete this group" style="color: #FF3713" ';
       
  1106     echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
       
  1107     echo '<div class="tblholder">
       
  1108           <table border="0" style="width:100%;" cellspacing="1" cellpadding="4">
       
  1109           <tr><th>Edit group name</th></tr>
       
  1110           <tr>
       
  1111             <td class="row1">
       
  1112               Group name: <input type="text" name="group_name" value="'.$name.'" />
       
  1113             </td>
       
  1114           </tr>
       
  1115           <tr>
       
  1116             <th class="subhead">
       
  1117               <input type="submit" name="edit_do[save_name]" value="Save name" />
       
  1118               <input type="submit" name="edit_do[del_group]" '.$sg_disabled.' />
       
  1119             </th>
       
  1120           </tr>
       
  1121           </table>
       
  1122           </div>
       
  1123           <input type="hidden" name="group_edit_id" value="'.$_POST['group_edit_id'].'" />';
       
  1124     echo '</form>';
       
  1125     echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
       
  1126     echo '<div class="tblholder">
       
  1127           <table border="0" style="width:100%;" cellspacing="1" cellpadding="4">
       
  1128           <tr><th colspan="3">Edit group members</th></tr>';
       
  1129     $q = $db->sql_query('SELECT m.member_id,m.is_mod,u.username FROM '.table_prefix.'group_members AS m
       
  1130                            LEFT JOIN '.table_prefix.'users AS u
       
  1131                              ON u.user_id=m.user_id
       
  1132                              WHERE m.group_id='.intval($_POST['group_edit_id']).'
       
  1133                            ORDER BY m.is_mod DESC, u.username ASC;');
       
  1134     if(!$q)
       
  1135     {
       
  1136       echo $db->get_error();
       
  1137       return;
       
  1138     }
       
  1139     if($db->numrows() < 1)
       
  1140     {
       
  1141       echo '<tr><td colspan="3" class="row1">This group has no members.</td></tr>';
       
  1142     }
       
  1143     else
       
  1144     {
       
  1145       $cls = 'row2';
       
  1146       while($row = $db->fetchrow())
       
  1147       {
       
  1148         $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
       
  1149         $mod = ( $row['is_mod'] == 1 ) ? 'Mod' : '';
       
  1150         echo '<tr>
       
  1151                 <td class="'.$cls.'" style="width: 100%;">
       
  1152                   ' . $row['username'] . '
       
  1153                 </td>
       
  1154                 <td class="'.$cls.'">
       
  1155                   '.$mod.'
       
  1156                 </td>
       
  1157                 <td class="'.$cls.'">
       
  1158                   <input type="submit" name="edit_do[del_'.$row['member_id'].']" value="Remove member" />
       
  1159                 </td>
       
  1160               </tr>';
       
  1161       }
       
  1162     }
       
  1163     $db->free_result();
       
  1164     echo '</table>
       
  1165           </div>
       
  1166           <input type="hidden" name="group_edit_id" value="'.$_POST['group_edit_id'].'" />';
       
  1167     echo '</form>';
       
  1168     echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
       
  1169     echo '<div class="tblholder">
       
  1170           <table border="0" style="width:100%;" cellspacing="1" cellpadding="4">
       
  1171             <tr>
       
  1172               <th>Add a new member</th>
       
  1173             </tr>
       
  1174             <tr>
       
  1175               <td class="row1">
       
  1176                 Username: ' . $template->username_field('edit_add_username') . '
       
  1177               </td>
       
  1178             </tr>
       
  1179             <tr>
       
  1180               <td class="row2">
       
  1181                 <label><input type="checkbox" name="add_mod" /> Is a group moderator</label> (can add and delete other members)
       
  1182               </td>
       
  1183             </tr>
       
  1184             <tr>
       
  1185               <th class="subhead">
       
  1186                 <input type="submit" name="edit_do[add_member]" value="Add user to group" />
       
  1187               </th>
       
  1188             </tr>
       
  1189           </table>
       
  1190           </div>
       
  1191           <input type="hidden" name="group_edit_id" value="'.$_POST['group_edit_id'].'" />';
       
  1192     echo '</form>';
       
  1193     return;
       
  1194   }
       
  1195   echo '<h3>Manage Usergroups</h3>';
       
  1196   echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
       
  1197   $q = $db->sql_query('SELECT group_id,group_name FROM '.table_prefix.'groups ORDER BY group_name ASC;');
       
  1198   if(!$q)
       
  1199   {
       
  1200     echo $db->get_error();
       
  1201   }
       
  1202   else
       
  1203   {
       
  1204     echo '<div class="tblholder">
       
  1205           <table border="0" cellspacing="1" cellpadding="4" style="width: 100%;">
       
  1206           <tr>
       
  1207           <th>Edit an existing group</th>
       
  1208           </tr>';
       
  1209     echo '<tr><td class="row2"><select name="group_edit_id">';
       
  1210     while ( $row = $db->fetchrow() )
       
  1211     {
       
  1212       if ( $row['group_name'] != 'Everyone' )
       
  1213       {
       
  1214         echo '<option value="' . $row['group_id'] . '">' . htmlspecialchars( $row['group_name'] ) . '</option>';
       
  1215       }
       
  1216     }
       
  1217     $db->free_result();
       
  1218     echo '</select></td></tr>';
       
  1219     echo '<tr><td class="row1" style="text-align: center;"><input type="submit" name="do_edit" value="Edit group" /></td></tr>
       
  1220           </table>
       
  1221           </div>
       
  1222           </form><br />';
       
  1223   }
       
  1224   echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
       
  1225   echo '<div class="tblholder">
       
  1226         <table border="0" cellspacing="1" cellpadding="4" style="width: 100%;">
       
  1227         <tr>
       
  1228         <th colspan="2">Create a new group</th>
       
  1229         </tr>';
       
  1230   echo '<tr><td class="row2">Group name:</td><td class="row2"><input type="text" name="create_group_name" /></td></tr>';
       
  1231   echo '<tr><td colspan="2" class="row1" style="text-align: center;"><input type="submit" name="do_create_stage1" value="Continue >" /></td></tr>
       
  1232         </table>
       
  1233         </div>';
       
  1234   echo '</form>';
       
  1235 }
       
  1236 
       
  1237 function page_Admin_PageManager()
       
  1238 {
       
  1239   global $db, $session, $paths, $template, $plugins; // Common objects
       
  1240   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
  1241   {
       
  1242     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
  1243     return;
       
  1244   }
       
  1245   
       
  1246   
       
  1247   echo '<h2>Page management</h2>';
       
  1248   
       
  1249   if(isset($_POST['search']) || isset($_POST['select']) || ( isset($_GET['source']) && $_GET['source'] == 'ajax' )) {
       
  1250     // The object of the game: using only the text a user entered, guess the page ID and namespace. *sigh* I HATE writing search algorithms...
       
  1251     $source = ( isset($_GET['source']) ) ? $_GET['source'] : false;
       
  1252     if ( $source == 'ajax' )
       
  1253     {
       
  1254       $_POST['search'] = true;
       
  1255       $_POST['page_url'] = $_GET['page_id'];
       
  1256     }
       
  1257     if(isset($_POST['search'])) $pid = $_POST['page_url'];
       
  1258     elseif(isset($_POST['select'])) $pid = $_POST['page_force_url'];
       
  1259     else { echo 'Internal error selecting page search terms'; return false; }
       
  1260     // Look for a namespace prefix in the urlname, and assign a different namespace, if necessary
       
  1261     $k = array_keys($paths->nslist);
       
  1262     for($i=0;$i<sizeof($paths->nslist);$i++)
       
  1263     {
       
  1264       $ln = strlen($paths->nslist[$k[$i]]);
       
  1265       if(substr($pid, 0, $ln) == $paths->nslist[$k[$i]])
       
  1266       {
       
  1267         $ns = $k[$i];
       
  1268         $page_id = substr($pid, $ln, strlen($pid));
       
  1269       }
       
  1270     }
       
  1271     // The namespace is in $ns and the page name or ID (we don't know which yet) is in $page_id
       
  1272     // Now, iterate through $paths->pages searching for a page with this name or ID
       
  1273     for($i=0;$i<sizeof($paths->pages)/2;$i++)
       
  1274     {
       
  1275       if(!isset($final_pid))
       
  1276       {
       
  1277         if    ($paths->pages[$i]['urlname_nons'] == str_replace(' ', '_', $page_id)) $final_pid = str_replace(' ', '_', $page_id);
       
  1278         elseif($paths->pages[$i]['name'] == $page_id) $final_pid = $paths->pages[$i]['urlname_nons'];
       
  1279         elseif(strtolower($paths->pages[$i]['urlname_nons']) == strtolower(str_replace(' ', '_', $page_id))) $final_pid = $paths->pages[$i]['urlname_nons'];
       
  1280         elseif(strtolower($paths->pages[$i]['name']) == strtolower(str_replace('_', ' ', $page_id))) $final_pid = $paths->pages[$i]['urlname_nons'];
       
  1281         if(isset($final_pid)) { $_POST['name'] = $paths->pages[$i]['name']; $_POST['urlname'] = $paths->pages[$i]['urlname_nons']; }
       
  1282       }
       
  1283     }
       
  1284     if(!isset($final_pid)) { echo 'The page you searched for cannot be found. <a href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'PageManager\'); return false;">Back</a>'; return false; }
       
  1285     $_POST['namespace'] = $ns;
       
  1286     $_POST['old_namespace'] = $ns;
       
  1287     $_POST['page_id'] = $final_pid;
       
  1288     $_POST['old_page_id'] = $final_pid;
       
  1289     if(!isset($paths->pages[$paths->nslist[$_POST['namespace']].$_POST['urlname']])) { echo 'The page you searched for cannot be found. <a href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'PageManager\'); return false;">Back</a>'; return false; }
       
  1290   }
       
  1291   
       
  1292   if(isset($_POST['page_id']) && isset($_POST['namespace']) && !isset($_POST['cancel']))
       
  1293   {
       
  1294     $cpage = $paths->pages[$paths->nslist[$_POST['namespace']].$_POST['old_page_id']];
       
  1295     if(isset($_POST['submit']))
       
  1296     {
       
  1297       // Create a list of things to update
       
  1298       $page_info = Array(
       
  1299           'name'=>$_POST['name'],
       
  1300           'urlname'=>$_POST['page_id'],
       
  1301           'namespace'=>$_POST['namespace'],
       
  1302           'special'=>isset($_POST['special']) ? '1' : '0',
       
  1303           'visible'=>isset($_POST['visible']) ? '1' : '0',
       
  1304           'comments_on'=>isset($_POST['comments_on']) ? '1' : '0',
       
  1305           'protected'=>isset($_POST['protected']) ? '1' : '0'
       
  1306         );
       
  1307       // Build the query
       
  1308       $q = 'UPDATE '.table_prefix.'pages SET ';
       
  1309       $k = array_keys($page_info);
       
  1310       foreach($k as $c)
       
  1311       {
       
  1312         $q .= $c.'=\''.$db->escape($page_info[$c]).'\',';
       
  1313       }
       
  1314       $q = substr($q, 0, strlen($q)-1);
       
  1315       // Build the WHERE statements
       
  1316       $q .= ' WHERE ';
       
  1317       $k = array_keys($cpage);
       
  1318       foreach($k as $c)
       
  1319       {
       
  1320         if($c != 'urlname_nons' && $c != 'urlname' && $c != 'really_protected') $q .= $c.'=\''.$cpage[$c].'\' AND ';
       
  1321         elseif($c == 'urlname') $q .= $c.'=\''.$cpage['urlname_nons'].'\' AND ';
       
  1322       }
       
  1323       $q = substr($q, 0, strlen($q)-5) . ';';
       
  1324       // Send the completed query to MySQL
       
  1325       $e = $db->sql_query($q);
       
  1326       if(!$e) $db->_die('The page data could not be updated.');
       
  1327       // Update any additional tables
       
  1328       $q = Array(
       
  1329         'UPDATE '.table_prefix.'categories SET page_id=\''.$page_info['urlname'].'\',namespace=\''.$page_info['namespace'].'\' WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
       
  1330         'UPDATE '.table_prefix.'comments   SET page_id=\''.$page_info['urlname'].'\',namespace=\''.$page_info['namespace'].'\' WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
       
  1331         'UPDATE '.table_prefix.'logs       SET page_id=\''.$page_info['urlname'].'\',namespace=\''.$page_info['namespace'].'\' WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
       
  1332         'UPDATE '.table_prefix.'page_text  SET page_id=\''.$page_info['urlname'].'\',namespace=\''.$page_info['namespace'].'\' WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
       
  1333         );
       
  1334       foreach($q as $cq)
       
  1335       {
       
  1336         $e = $db->sql_query($cq);
       
  1337         if(!$e) $db->_die('Some of the additional tables containing page information could not be updated.');
       
  1338       }
       
  1339       // Update $cpage
       
  1340       $cpage = $page_info;
       
  1341       $cpage['urlname_nons'] = $cpage['urlname'];
       
  1342       $cpage['urlname'] = $paths->nslist[$cpage['namespace']].$cpage['urlname'];
       
  1343       $_POST['old_page_id'] = $page_info['urlname'];
       
  1344       $_POST['old_namespace'] = $page_info['namespace'];
       
  1345       echo '<div class="info-box">Your changes have been saved.</div>';
       
  1346     } elseif(isset($_POST['delete'])) {
       
  1347       $q = Array(
       
  1348         'DELETE FROM '.table_prefix.'categories WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
       
  1349         'DELETE FROM '.table_prefix.'comments   WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
       
  1350         'DELETE FROM '.table_prefix.'logs       WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
       
  1351         'DELETE FROM '.table_prefix.'page_text  WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
       
  1352         );
       
  1353       foreach($q as $cq)
       
  1354       {
       
  1355         $e = $db->sql_query($cq);
       
  1356         if(!$e) $db->_die('Some of the additional tables containing page information could not be updated.');
       
  1357       }
       
  1358       
       
  1359       if(!$db->sql_query(
       
  1360         'DELETE FROM '.table_prefix.'pages WHERE urlname="'.$db->escape($_POST['old_page_id']).'" AND namespace="'.$db->escape($_POST['old_namespace']).'";'
       
  1361       )) $db->_die('The page could not be deleted.');
       
  1362       echo '<div class="info-box">This page has been deleted.</p><p><a href="javascript:ajaxPage(\''.$paths->nslist['Admin'].'PageManager\');">Return to Page manager</a><br /><a href="javascript:ajaxPage(\''.$paths->nslist['Admin'].'Home\');">Admin home</a></div>';
       
  1363       return;
       
  1364     }
       
  1365     echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration'.htmlspecialchars(urlSeparator).(( isset($_GET['sqldbg']) ) ? 'sqldbg&amp;' : '') .'module='.$paths->cpage['module']).'" method="post">';
       
  1366     ?>
       
  1367     <h3>Modify page: <?php echo $_POST['name']; ?></h3>
       
  1368      <table border="0">
       
  1369        <tr><td>Namespace:</td><td><select name="namespace"><?php $nm = array_keys($paths->nslist); foreach($nm as $ns) { if($ns != 'Special' && $ns != 'Admin') { echo '<option '; if($_POST['namespace']==$ns) echo 'selected="selected" '; echo 'value="'.$ns.'">'; if($paths->nslist[$ns] == '') echo '[No prefix]'; else echo $paths->nslist[$ns]; echo '</option>'; } } ?></select></td></tr>
       
  1370        <tr><td>Page title:</td><td><input type="text" name="name" value="<?php echo $cpage['name']; ?>" /></td></tr>
       
  1371        <tr><td>Page URL string:<br /><small>No spaces, and don't enter the namespace prefix (e.g. User:).<br />Changing this value is usually not a good idea, especially for templates and project pages.</small></td><td><input type="text" name="page_id" value="<?php echo $cpage['urlname_nons']; ?>" /></td></tr>
       
  1372        <tr><td></td><td><input <?php if($cpage['comments_on']) echo 'checked="checked"'; ?> name="comments_on" type="checkbox" id="cmt" />  <label for="cmt">Enable comments for this page</label></td></tr>
       
  1373        <tr><td></td><td><input <?php if($cpage['special']) echo 'checked="checked"'; ?> name="special" type="checkbox" id="spc" />  <label for="spc">Bypass the template engine for this page</label><br /><small>This option enables you to use your own HTML headers and other code. It is recommended that only advanced users enable this feature. As with other Enano pages, you may use PHP code in your pages, meaning you can use Enano's API on the page.</small></td></tr>
       
  1374        <tr><td></td><td><input <?php if($cpage['visible']) echo 'checked="checked"'; ?> name="visible" type="checkbox" id="vis" />  <label for="vis">Allow this page to be shown in page lists</label><br /><small>Unchecking this checkbox prevents the page for being indexed for searching. The index is rebuilt each time a page is saved, and you can force an index rebuild by going to the page <?php echo $paths->nslist['Special']; ?>SearchRebuild.</small></td></tr>
       
  1375        <tr><td></td><td><input <?php if($cpage['protected']) echo 'checked="checked"'; ?> name="protected" type="checkbox" id="prt" />  <label for="prt">Prevent non-administrators from editing this page</label><br /><small>This option only has an effect when Wiki Mode is enabled.</small></td></tr>
       
  1376        <tr><td></td><td><input type="submit" name="delete" value="Delete page" style="color: red" onclick="return confirm('Do you REALLY want to delete this page?')" /></td></tr>
       
  1377        <tr><td colspan="2" style="text-align: center;"><hr /></td></tr>
       
  1378        <tr><td colspan="2" style="text-align: right;">
       
  1379        <input type="hidden" name="old_page_id" value="<?php echo $_POST['old_page_id']; ?>" />
       
  1380        <input type="hidden" name="old_namespace" value="<?php echo $_POST['old_namespace']; ?>" />
       
  1381        <input type="Submit" name="submit" value="Save changes" style="font-weight: bold;" />  <input type="submit" name="cancel" value="Cancel changes" /></td></tr>
       
  1382      </table>
       
  1383     <?php
       
  1384     echo '</form>';
       
  1385   } else {
       
  1386     echo '<h3>Please select a page</h3>';
       
  1387     echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
       
  1388     ?>
       
  1389       <p>Search for page title (remember prefixes like User: and File:) <?php echo $template->pagename_field('page_url'); ?>  <input type="submit" style="font-weight: bold;" name="search" value="Search" /></p>
       
  1390       <p>Select page title from a list: <select name="page_force_url">
       
  1391       <?php
       
  1392         for($i=0;$i<sizeof($paths->pages)/2;$i++)
       
  1393         {
       
  1394           if($paths->pages[$i]['namespace'] != 'Admin' && $paths->pages[$i]['namespace'] != 'Special') echo '<option value="'.$paths->nslist[$paths->pages[$i]['namespace']].$paths->pages[$i]['urlname_nons'].'">'.$paths->nslist[$paths->pages[$i]['namespace']].$paths->pages[$i]['name'].'</option>'."\n";
       
  1395         }
       
  1396       ?>
       
  1397       </select>  <input type="submit" name="select" value="Select" /></p>
       
  1398     <?php
       
  1399     echo '</form>';
       
  1400     
       
  1401   }
       
  1402 }
       
  1403 
       
  1404 function page_Admin_PageEditor()
       
  1405 {
       
  1406   global $db, $session, $paths, $template, $plugins; // Common objects
       
  1407   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
  1408   {
       
  1409     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
  1410     return;
       
  1411   }
       
  1412   
       
  1413   
       
  1414   echo '<h2>Edit page content</h2>';
       
  1415   
       
  1416   if(isset($_POST['search']) || isset($_POST['select'])) {
       
  1417     // The object of the game: using only the text a user entered, guess the page ID and namespace. *sigh* I HATE writing search algorithms...
       
  1418     if(isset($_POST['search'])) $pid = $_POST['page_url'];
       
  1419     elseif(isset($_POST['select'])) $pid = $_POST['page_force_url'];
       
  1420     else { echo 'Internal error selecting page search terms'; return false; }
       
  1421     // Look for a namespace prefix in the urlname, and assign a different namespace, if necessary
       
  1422     $k = array_keys($paths->nslist);
       
  1423     for($i=0;$i<sizeof($paths->nslist);$i++)
       
  1424     {
       
  1425       $ln = strlen($paths->nslist[$k[$i]]);
       
  1426       if(substr($pid, 0, $ln) == $paths->nslist[$k[$i]])
       
  1427       {
       
  1428         $ns = $k[$i];
       
  1429         $page_id = substr($pid, $ln, strlen($pid));
       
  1430       }
       
  1431     }
       
  1432     // The namespace is in $ns and the page name or ID (we don't know which yet) is in $page_id
       
  1433     // Now, iterate through $paths->pages searching for a page with this name or ID
       
  1434     for($i=0;$i<sizeof($paths->pages)/2;$i++)
       
  1435     {
       
  1436       if(!isset($final_pid))
       
  1437       {
       
  1438         if    ($paths->pages[$i]['urlname_nons'] == str_replace(' ', '_', $page_id)) $final_pid = str_replace(' ', '_', $page_id);
       
  1439         elseif($paths->pages[$i]['name'] == $page_id) $final_pid = $paths->pages[$i]['urlname_nons'];
       
  1440         elseif(strtolower($paths->pages[$i]['urlname_nons']) == strtolower(str_replace(' ', '_', $page_id))) $final_pid = $paths->pages[$i]['urlname_nons'];
       
  1441         elseif(strtolower($paths->pages[$i]['name']) == strtolower(str_replace('_', ' ', $page_id))) $final_pid = $paths->pages[$i]['urlname_nons'];
       
  1442         if(isset($final_pid)) { $_POST['name'] = $paths->pages[$i]['name']; $_POST['urlname'] = $paths->pages[$i]['urlname_nons']; }
       
  1443       }
       
  1444     }
       
  1445     if(!isset($final_pid)) { echo 'The page you searched for cannot be found. <a href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'PageManager\'); return false;">Back</a>'; return false; }
       
  1446     $_POST['namespace'] = $ns;
       
  1447     $_POST['page_id'] = $final_pid;
       
  1448     if(!isset($paths->pages[$paths->nslist[$_POST['namespace']].$_POST['urlname']])) { echo 'The page you searched for cannot be found. <a href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'PageManager\'); return false;">Back</a>'; return false; }
       
  1449   }
       
  1450   
       
  1451   if(isset($_POST['page_id']) && !isset($_POST['cancel']))
       
  1452   {
       
  1453     echo '<form name="main" action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">';
       
  1454     if(!isset($_POST['content']) || isset($_POST['revert'])) $content = RenderMan::getPage($_POST['page_id'], $_POST['namespace'], 0, false, false, false, false);
       
  1455     else $content = $_POST['content'];
       
  1456     if(isset($_POST['save']))
       
  1457     {
       
  1458       $data = $content;
       
  1459       $id = md5( microtime() . mt_rand() );
       
  1460       
       
  1461       $minor = isset($_POST['minor']) ? 'true' : 'false';
       
  1462       $q='INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,page_id,namespace,page_text,char_tag,author,edit_summary,minor_edit) VALUES(\'page\', \'edit\', '.time().', \''.date('d M Y h:i a').'\', \'' . $db->escape($_POST['page_id']) . '\', \'' . $db->escape($_POST['namespace']) . '\', \''.$data.'\', \''.$id.'\', \''.$session->username.'\', \''.$db->escape(htmlspecialchars($_POST['summary'])).'\', '.$minor.');';
       
  1463       if(!$db->sql_query($q)) $db->_die('The history (log) entry could not be inserted into the logs table.');
       
  1464       
       
  1465       $query = 'UPDATE '.table_prefix.'page_text SET page_text=\''.$db->escape($data).'\',char_tag=\''.$id.'\' WHERE page_id=\'' . $db->escape($_POST['page_id']) . '\' AND namespace=\'' . $db->escape($_POST['namespace']) . '\';';
       
  1466       $e = $db->sql_query($query);
       
  1467       if(!$e) echo '<div class="warning-box">The page data could not be saved. MySQL said: '.mysql_error().'<br /><br />Query:<br /><pre>'.$query.'</pre></div>';
       
  1468       else echo '<div class="info-box">Your page has been saved. <a href="'.makeUrlNS($_POST['namespace'], $_POST['page_id']).'">View page...</a></div>';
       
  1469     } elseif(isset($_POST['preview'])) {
       
  1470       echo '<h3>Preview</h3><p><b>Reminder:</b> This is only a preview; your changes to this page have not yet been saved.</p><div style="margin: 1em; padding: 10px; border: 1px dashed #606060; background-color: #F8F8F8; max-height: 200px; overflow: auto;">'.RenderMan::render($content).'</div>';
       
  1471     }
       
  1472     ?>
       
  1473     <p>
       
  1474     <textarea name="content" rows="20" cols="60" style="width: 100%;"><?php echo htmlspecialchars($content); ?></textarea><br />
       
  1475     Edit summary: <input name="summary" value="<?php if(isset($_POST['summary'])) echo $_POST['summary']; ?>" size="40" /><br />
       
  1476     <label><input type="checkbox" name="minor" <?php if(isset($_POST['minor'])) echo 'checked="checked" '; ?>/>  This is a minor edit</label>
       
  1477     </p>
       
  1478     <p>
       
  1479     <input type="hidden" name="page_id" value="<?php echo $_POST['page_id']; ?>" />
       
  1480     <input type="hidden" name="namespace" value="<?php echo $_POST['namespace']; ?>" />
       
  1481     <input type="submit" name="save" value="Save changes" style="font-weight: bold;" />&nbsp;&nbsp;<input type="submit" name="preview" value="Show preview" />&nbsp;&nbsp;<input type="submit" name="revert" value="Revert changes" onclick="return confirm('Do you really want to revert your changes?');" />&nbsp;&nbsp;<input type="submit" name="cancel" value="Cancel" onclick="return confirm('Do you really want to cancel your changes?');" />
       
  1482     </p>
       
  1483     <?php
       
  1484     echo '</form>';
       
  1485   } else {
       
  1486     echo '<h3>Please select a page</h3>';
       
  1487     echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
       
  1488     ?>
       
  1489       <p>Search for page title (remember prefixes like User: and File:) <?php echo $template->pagename_field('page_url'); ?>  <input type="submit" style="font-weight: bold;" name="search" value="Search" /></p>
       
  1490       <p>Select page title from a list: <select name="page_force_url">
       
  1491       <?php
       
  1492         for($i=0;$i<sizeof($paths->pages)/2;$i++)
       
  1493         {
       
  1494           if($paths->pages[$i]['namespace'] != 'Admin' && $paths->pages[$i]['namespace'] != 'Special') echo '<option value="'.$paths->nslist[$paths->pages[$i]['namespace']].$paths->pages[$i]['urlname_nons'].'">'.$paths->nslist[$paths->pages[$i]['namespace']].$paths->pages[$i]['name'].'</option>'."\n";
       
  1495         }
       
  1496       ?>
       
  1497       </select>  <input type="submit" name="select" value="Select" /></p>
       
  1498     <?php
       
  1499     echo '</form>';
       
  1500   }
       
  1501 }
       
  1502 
       
  1503 function page_Admin_ThemeManager() 
       
  1504 {
       
  1505   
       
  1506   global $db, $session, $paths, $template, $plugins; // Common objects
       
  1507   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
  1508   {
       
  1509     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
  1510     return;
       
  1511   }
       
  1512   
       
  1513   
       
  1514   // Get the list of styles in the themes/ dir
       
  1515   $h = opendir('./themes');
       
  1516   $l = Array();
       
  1517   if(!$h) die('Error opening directory "./themes" for reading.');
       
  1518   while(false !== ($n = readdir($h))) {
       
  1519     if($n != '.' && $n != '..' && is_dir('./themes/'.$n))
       
  1520       $l[] = $n;
       
  1521   }
       
  1522   closedir($h);
       
  1523   echo('
       
  1524   <h3>Theme Management</h3>
       
  1525    <p>Install, uninstall, and manage Enano themes.</p>
       
  1526   ');
       
  1527   if(isset($_POST['disenable'])) {
       
  1528     $q = 'SELECT enabled FROM '.table_prefix.'themes WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
       
  1529     $s = $db->sql_query($q);
       
  1530     if(!$s) die('Error selecting enabled/disabled state value: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1531     $r = $db->fetchrow_num($s);
       
  1532     $db->free_result();
       
  1533     if($r[0] == 1) $e = 0;
       
  1534     else $e = 1;
       
  1535     $s=true;
       
  1536     if($e==0)
       
  1537     {
       
  1538       $c = $db->sql_query('SELECT * FROM '.table_prefix.'themes WHERE enabled=1');
       
  1539       if(!$c) $db->_die('The backup check for having at least on theme enabled failed.');
       
  1540       if($db->numrows() <= 1) { echo '<div class="warning-box">You cannot disable the last remaining theme.</div>'; $s=false; }
       
  1541     }
       
  1542     $db->free_result();
       
  1543     if($s) {
       
  1544     $q = 'UPDATE '.table_prefix.'themes SET enabled='.$e.' WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
       
  1545     $a = $db->sql_query($q);
       
  1546     if(!$a) die('Error updating enabled/disabled state value: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1547     else echo('<div class="info-box">The theme "'.$_POST['theme_id'].'" has been  '. ( ( $e == '1' ) ? 'enabled' : 'disabled' ).'.</div>');
       
  1548     }
       
  1549   }
       
  1550   elseif(isset($_POST['edit'])) {
       
  1551     
       
  1552     $dir = './themes/'.$_POST['theme_id'].'/css/';
       
  1553     $list = Array();
       
  1554     // Open a known directory, and proceed to read its contents
       
  1555     if (is_dir($dir)) {
       
  1556       if ($dh = opendir($dir)) {
       
  1557         while (($file = readdir($dh)) !== false) {
       
  1558           if(preg_match('#^(.*?)\.css$#is', $file) && $file != '_printable.css') {
       
  1559             $list[$file] = capitalize_first_letter(substr($file, 0, strlen($file)-4));
       
  1560           }
       
  1561         }
       
  1562         closedir($dh);
       
  1563       }
       
  1564     }
       
  1565     $lk = array_keys($list);
       
  1566     
       
  1567     $q = 'SELECT theme_name,default_style FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\'';
       
  1568     $s = $db->sql_query($q);
       
  1569     if(!$s) die('Error selecting name value: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1570     $r = $db->fetchrow_num($s);
       
  1571     $db->free_result();
       
  1572     echo('<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">');
       
  1573     echo('<div class="question-box">
       
  1574           Theme name displayed to users: <input type="text" name="name" value="'.$r[0].'" /><br /><br />
       
  1575           Default stylesheet: <select name="defaultcss">');
       
  1576     foreach ($lk as $l)
       
  1577     {
       
  1578       if($r[1] == $l) $v = ' selected="selected"';
       
  1579       else $v = '';
       
  1580       echo "<option value='{$l}'$v>{$list[$l]}</option>";
       
  1581     }
       
  1582     echo('</select><br /><br />
       
  1583           <input type="submit" name="editsave" value="OK" /><input type="hidden" name="theme_id" value="'.$_POST['theme_id'].'" />
       
  1584           </div>');
       
  1585     echo('</form>');
       
  1586   }
       
  1587   elseif(isset($_POST['editsave'])) {
       
  1588     $q = 'UPDATE '.table_prefix.'themes SET theme_name=\'' . $db->escape($_POST['name']) . '\',default_style=\''.$db->escape($_POST['defaultcss']).'\' WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
       
  1589     $s = $db->sql_query($q);
       
  1590     if(!$s) die('Error updating name value: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1591     else echo('<div class="info-box">Theme data updated.</div>');
       
  1592   }
       
  1593   elseif(isset($_POST['up'])) {
       
  1594     // If there is only one theme or if the selected theme is already at the top, do nothing
       
  1595     $q = 'SELECT theme_order FROM '.table_prefix.'themes ORDER BY theme_order;';
       
  1596     $s = $db->sql_query($q);
       
  1597     if(!$s) die('Error selecting order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1598     $q = 'SELECT theme_order FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\'';
       
  1599     $sn = $db->sql_query($q);
       
  1600     if(!$sn) die('Error selecting order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1601     $r = $db->fetchrow_num($sn);
       
  1602     if( /* check for only one theme... */ $db->numrows($s) < 2 || $r[0] == 1 /* ...and check if this theme is already at the top */ ) { echo('<div class="warning-box">This theme is already at the top of the list, or there is only one theme installed.</div>'); } else {
       
  1603       // Get the order IDs of the selected theme and the theme before it
       
  1604       $q = 'SELECT theme_order FROM '.table_prefix.'themes WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
       
  1605       $s = $db->sql_query($q);
       
  1606       if(!$s) die('Error selecting order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1607       $r = $db->fetchrow_num($s);
       
  1608       $r = $r[0];
       
  1609       $rb = $r - 1;
       
  1610       // Thank God for jEdit's rectangular selection and the ablity to edit multiple lines at the same time ;)
       
  1611       $q = 'UPDATE '.table_prefix.'themes SET theme_order=0 WHERE theme_order='.$rb.'';      /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1612       $q = 'UPDATE '.table_prefix.'themes SET theme_order='.$rb.' WHERE theme_order='.$r.''; /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1613       $q = 'UPDATE '.table_prefix.'themes SET theme_order='.$r.' WHERE theme_order=0';       /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1614       echo('<div class="info-box">Theme moved up.</div>');
       
  1615     }
       
  1616     $db->free_result($s);
       
  1617     $db->free_result($sn);
       
  1618   }
       
  1619   elseif(isset($_POST['down'])) {
       
  1620     // If there is only one theme or if the selected theme is already at the top, do nothing
       
  1621     $q = 'SELECT theme_order FROM '.table_prefix.'themes ORDER BY theme_order;';
       
  1622     $s = $db->sql_query($q);
       
  1623     if(!$s) die('Error selecting order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1624     $r = $db->fetchrow_num($s);
       
  1625     if( /* check for only one theme... */ $db->numrows($s) < 2 || $r[0] == $db->numrows($s) /* ...and check if this theme is already at the bottom */ ) { echo('<div class="warning-box">This theme is already at the bottom of the list, or there is only one theme installed.</div>'); } else {
       
  1626       // Get the order IDs of the selected theme and the theme before it
       
  1627       $q = 'SELECT theme_order FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\'';
       
  1628       $s = $db->sql_query($q);
       
  1629       if(!$s) die('Error selecting order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1630       $r = $db->fetchrow_num($s);
       
  1631       $r = $r[0];
       
  1632       $rb = $r + 1;
       
  1633       // Thank God for jEdit's rectangular selection and the ablity to edit multiple lines at the same time ;)
       
  1634       $q = 'UPDATE '.table_prefix.'themes SET theme_order=0 WHERE theme_order='.$rb.'';      /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1635       $q = 'UPDATE '.table_prefix.'themes SET theme_order='.$rb.' WHERE theme_order='.$r.''; /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1636       $q = 'UPDATE '.table_prefix.'themes SET theme_order='.$r.' WHERE theme_order=0';       /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1637       echo('<div class="info-box">Theme moved down.</div>');
       
  1638     }
       
  1639   }
       
  1640   else if(isset($_POST['uninstall'])) 
       
  1641   {
       
  1642     $q = 'SELECT * FROM '.table_prefix.'themes;';
       
  1643     $s = $db->sql_query($q);
       
  1644     if ( !$s )
       
  1645     {
       
  1646       die('Error getting theme count: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1647     }
       
  1648     $n = $db->numrows($s);
       
  1649     $db->free_result();
       
  1650     
       
  1651     if ( $_POST['theme_id'] == 'oxygen' )
       
  1652     {
       
  1653       echo '<div class="error-box">The Oxygen theme is used by Enano for installation, upgrades, and error messages, and cannot be uninstalled.</div>';
       
  1654     }
       
  1655     else
       
  1656     {
       
  1657       if($n < 2)
       
  1658       {
       
  1659         echo '<div class="error-box">The theme could not be uninstalled because it is the only theme left.</div>';
       
  1660       }
       
  1661       else
       
  1662       {
       
  1663         $q = 'DELETE FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\' LIMIT 1;';
       
  1664         $s = $db->sql_query($q);
       
  1665         if ( !$s )
       
  1666         {
       
  1667           die('Error deleting theme data: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1668         }
       
  1669         else
       
  1670         {
       
  1671           echo('<div class="info-box">Theme uninstalled.</div>');
       
  1672         }
       
  1673       }
       
  1674     }
       
  1675   }
       
  1676   elseif(isset($_POST['install'])) {
       
  1677     $q = 'SELECT * FROM '.table_prefix.'themes;';
       
  1678     $s = $db->sql_query($q);
       
  1679     if(!$s) die('Error getting theme count: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1680     $n = $db->numrows($s);
       
  1681     $n++;
       
  1682     $theme_id = $_POST['theme_id'];
       
  1683     $theme = Array();
       
  1684     include('./themes/'.$theme_id.'/theme.cfg');
       
  1685     $q = 'INSERT INTO '.table_prefix.'themes(theme_id,theme_name,theme_order,enabled) VALUES(\''.$theme['theme_id'].'\', \''.$theme['theme_name'].'\', '.$n.', 1)';
       
  1686     $s = $db->sql_query($q);
       
  1687     if(!$s) die('Error inserting theme data: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
       
  1688     else echo('<div class="info-box">Theme "'.$theme['theme_name'].'" installed.</div>');
       
  1689   }
       
  1690   echo('
       
  1691   <h3>Currently installed themes</h3>
       
  1692     <form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">
       
  1693     <p>
       
  1694       <select name="theme_id">
       
  1695         ');
       
  1696         $q = 'SELECT theme_id,theme_name,enabled FROM '.table_prefix.'themes ORDER BY theme_order';
       
  1697         $s = $db->sql_query($q);
       
  1698         if(!$s) die('Error selecting theme data: '.mysql_error().'<br /><u>Attempted SQL:</u><br />'.$q);
       
  1699         while ( $r = $db->fetchrow_num($s) ) {
       
  1700           if($r[2] < 1) $r[1] .= ' (disabled)';
       
  1701           echo('<option value="'.$r[0].'">'.$r[1].'</option>');
       
  1702         }
       
  1703         $db->free_result();
       
  1704         echo('
       
  1705         </select> <input type="submit" name="disenable" value="Enable/Disable" /> <input type="submit" name="edit" value="Change settings" /> <input type="submit" name="up" value="Move up" /> <input type="submit" name="down" value="Move down" /> <input type="submit" name="uninstall" value="Uninstall" style="color: #DD3300; font-weight: bold;" />
       
  1706       </p>
       
  1707     </form>
       
  1708     <h3>Install a new theme</h3>
       
  1709   ');
       
  1710     $theme = Array();
       
  1711     $obb = '';
       
  1712     for($i=0;$i<sizeof($l);$i++) {
       
  1713       if(is_file('./themes/'.$l[$i].'/theme.cfg') && file_exists('./themes/'.$l[$i].'/theme.cfg')) {
       
  1714         include('./themes/'.$l[$i].'/theme.cfg');
       
  1715         $q = 'SELECT * FROM '.table_prefix.'themes WHERE theme_id=\''.$theme['theme_id'].'\'';
       
  1716         $s = $db->sql_query($q);
       
  1717         if(!$s) die('Error selecting list of currently installed themes: '.mysql_error().'<br /><u>Attempted SQL:</u><br />'.$q);
       
  1718         if($db->numrows($s) < 1) {
       
  1719           $obb .= '<option value="'.$theme['theme_id'].'">'.$theme['theme_name'].'</option>';
       
  1720         }
       
  1721         $db->free_result();
       
  1722       }
       
  1723     }
       
  1724     if($obb != '') {
       
  1725       echo('<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post"><p>');
       
  1726       echo('<select name="theme_id">');
       
  1727       echo($obb);
       
  1728       echo('</select>');
       
  1729       echo('
       
  1730       <input type="submit" name="install" value="Install this theme" />
       
  1731       </p></form>');
       
  1732     } else echo('<p>All themes are currently installed.</p>');
       
  1733 }
       
  1734 
       
  1735 function page_Admin_BanControl()
       
  1736 {
       
  1737   global $db, $session, $paths, $template, $plugins; // Common objects
       
  1738   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
  1739   {
       
  1740     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
  1741     return;
       
  1742   }
       
  1743   
       
  1744   if(isset($_GET['action']) && $_GET['action'] == 'delete' && isset($_GET['id']) && $_GET['id'] != '')
       
  1745   {
       
  1746     $e = $db->sql_query('DELETE FROM '.table_prefix.'banlist WHERE ban_id=' . $db->escape($_GET['id']) . '');
       
  1747     if(!$e) $db->_die('The ban list entry was not deleted.');
       
  1748   }
       
  1749   if(isset($_POST['create']))
       
  1750   {
       
  1751     $q = 'INSERT INTO '.table_prefix.'banlist(ban_type,ban_value,reason,is_regex) VALUES( ' . $db->escape($_POST['type']) . ', \'' . $db->escape($_POST['value']) . '\', \''.$db->escape($_POST['reason']).'\'';
       
  1752       if(isset($_POST['regex'])) $q .= ', 1';
       
  1753       else $q .= ', 0';
       
  1754     $q .= ');';
       
  1755     $e = $db->sql_query($q);
       
  1756     if(!$e) $db->_die('The banlist could not be updated.');
       
  1757   }
       
  1758   $q = $db->sql_query('SELECT ban_id,ban_type,ban_value,is_regex FROM '.table_prefix.'banlist ORDER BY ban_type;');
       
  1759   if(!$q) $db->_die('The banlist data could not be selected.');
       
  1760   echo '<table border="0" cellspacing="1" cellpadding="4">';
       
  1761   echo '<tr><th>Type</th><th>Value</th><th>Regular Expression</th><th></th></tr>';
       
  1762   if($db->numrows() < 1) echo '<td colspan="4">No ban rules yet.</td>';
       
  1763   while($r = $db->fetchrow())
       
  1764   {
       
  1765     if($r['ban_type']==BAN_IP) $t = 'IP address';
       
  1766     elseif($r['ban_type']==BAN_USER) $t = 'Username';
       
  1767     elseif($r['ban_type']==BAN_EMAIL) $t = 'E-mail address';
       
  1768     if($r['is_regex']) $g = 'Yes'; else $g = 'No';
       
  1769     echo '<tr><td>'.$t.'</td><td>'.$r['ban_value'].'</td><td>'.$g.'</td><td><a href="'.makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'BanControl&amp;action=delete&amp;id='.$r['ban_id']).'">Delete</a></td></tr>';
       
  1770   }
       
  1771   $db->free_result();
       
  1772   echo '</table>';
       
  1773   echo '<h3>Create new ban rule</h3>';
       
  1774   echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">';
       
  1775   ?>
       
  1776   Type: <select name="type"><option value="<?php echo BAN_IP; ?>">IP address</option><option value="<?php echo BAN_USER; ?>">Username</option><option value="<?php echo BAN_EMAIL; ?>">E-mail address</option></select><br />
       
  1777   Rule: <input type="text" name="value" size="30" /><br />
       
  1778   Reason to show to the banned user: <textarea name="reason" rows="7" cols="20"></textarea><br />
       
  1779   <input type="checkbox" name="regex" id="regex" />  <label for="regex">This rule is a regular expression</label> (advanced users only)<br />
       
  1780   <input type="submit" style="font-weight: bold;" name="create" value="Create new ban rule" />
       
  1781   <?php
       
  1782   echo '</form>';
       
  1783 }
       
  1784 
       
  1785 function page_Admin_MassEmail()
       
  1786 {
       
  1787   global $db, $session, $paths, $template, $plugins; // Common objects
       
  1788   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
  1789   {
       
  1790     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
  1791     return;
       
  1792   }
       
  1793   
       
  1794   global $enano_config;
       
  1795   if ( isset($_POST['do_send']) )
       
  1796   {
       
  1797     $use_smtp = getConfig('smtp_enabled') == '1';
       
  1798     
       
  1799     //
       
  1800     // Let's do some checking to make sure that mass mail functions
       
  1801     // are working in win32 versions of php. (copied from phpBB)
       
  1802     //
       
  1803     if ( preg_match('/[c-z]:\\\.*/i', getenv('PATH')) && !$use_smtp)
       
  1804     {
       
  1805       $ini_val = ( @phpversion() >= '4.0.0' ) ? 'ini_get' : 'get_cfg_var';
       
  1806 
       
  1807       // We are running on windows, force delivery to use our smtp functions
       
  1808       // since php's are broken by default
       
  1809       $use_smtp = true;
       
  1810       $enano_config['smtp_server'] = @$ini_val('SMTP');
       
  1811     }
       
  1812     
       
  1813     $mail = new emailer( !empty($use_smtp) );
       
  1814     
       
  1815     // Validate subject/message body
       
  1816     $subject = stripslashes(trim($_POST['subject']));
       
  1817     $message = stripslashes(trim($_POST['message']));
       
  1818     
       
  1819     if ( empty($subject) )
       
  1820       $errors[] = 'Please enter a subject.';
       
  1821     if ( empty($message) )
       
  1822       $errors[] = 'Please enter a message.';
       
  1823     
       
  1824     // Get list of members
       
  1825     if ( !empty($_POST['userlist']) )
       
  1826     {
       
  1827       $userlist = str_replace(', ', ',', $_POST['userlist']);
       
  1828       $userlist = explode(',', $userlist);
       
  1829       foreach ( $userlist as $k => $u )
       
  1830       {
       
  1831         if ( $u == $session->username )
       
  1832         {
       
  1833           // Message is automatically sent to the sender
       
  1834           unset($userlist[$k]);
       
  1835         }
       
  1836         else
       
  1837         {
       
  1838           $userlist[$k] = $db->escape($u);
       
  1839         }
       
  1840       }
       
  1841       $userlist = 'WHERE username=\'' . implode('\' OR username=\'', $userlist) . '\'';
       
  1842       
       
  1843       $q = $db->sql_query('SELECT email FROM '.table_prefix.'users ' . $userlist . ';');
       
  1844       if ( !$q )
       
  1845         $db->_die();
       
  1846       
       
  1847       if ( $row = $db->fetchrow() )
       
  1848       {
       
  1849         do {
       
  1850           $mail->cc($row['email']);
       
  1851         } while ( $row = $db->fetchrow() );
       
  1852       }
       
  1853       
       
  1854       $db->free_result();
       
  1855       
       
  1856     }
       
  1857     else
       
  1858     {
       
  1859       // Sending to a usergroup
       
  1860       
       
  1861       $group_id = intval($_POST['group_id']);
       
  1862       if ( $group_id < 1 )
       
  1863       {
       
  1864         $errors[] = 'Invalid group ID';
       
  1865       }
       
  1866       else
       
  1867       {
       
  1868         $q = $db->sql_query('SELECT u.email FROM '.table_prefix.'group_members AS g
       
  1869                                LEFT JOIN '.table_prefix.'users AS u
       
  1870                                  ON (u.user_id=g.user_id)
       
  1871                                WHERE g.group_id=' . $group_id . ';');
       
  1872         if ( !$q )
       
  1873           $db->_die();
       
  1874         
       
  1875         if ( $row = $db->fetchrow() )
       
  1876         {
       
  1877           do {
       
  1878             $mail->cc($row['email']);
       
  1879           } while ( $row = $db->fetchrow() );
       
  1880         }
       
  1881         
       
  1882         $db->free_result();
       
  1883       }
       
  1884     }
       
  1885     
       
  1886     if ( sizeof($errors) < 1 )
       
  1887     {
       
  1888     
       
  1889       $mail->from(getConfig('contact_email'));
       
  1890       $mail->replyto(getConfig('contact_email'));
       
  1891       $mail->set_subject($subject);
       
  1892       $mail->email_address(getConfig('contact_email'));
       
  1893       
       
  1894       // Copied/modified from phpBB
       
  1895       $email_headers = 'X-AntiAbuse: Website server name - ' . $_SERVER['SERVER_NAME'] . "\n";
       
  1896       $email_headers .= 'X-AntiAbuse: User_id - ' . $session->user_id . "\n";
       
  1897       $email_headers .= 'X-AntiAbuse: Username - ' . $session->username . "\n";
       
  1898       $email_headers .= 'X-AntiAbuse: User IP - ' . $_SERVER['REMOTE_ADDR'] . "\n";
       
  1899       
       
  1900       $mail->extra_headers($email_headers);
       
  1901       
       
  1902       $tpl = 'The following message was mass-mailed by {SENDER}, one of the administrators from {SITE_NAME}. If this message contains spam or any comments which you find abusive or offensive, please contact the administration team at:
       
  1903   
       
  1904 {CONTACT_EMAIL}
       
  1905 
       
  1906 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
  1907 {MESSAGE}
       
  1908 ';
       
  1909   
       
  1910       $mail->use_template($tpl);
       
  1911       
       
  1912       $mail->assign_vars(array(
       
  1913           'SENDER' => $session->username,
       
  1914           'SITE_NAME' => getConfig('site_name'),
       
  1915           'CONTACT_EMAIL' => getConfig('contact_email'),
       
  1916           'MESSAGE' => $message
       
  1917         ));
       
  1918       
       
  1919       //echo '<pre>'.print_r($mail,true).'</pre>';
       
  1920       
       
  1921       // All done
       
  1922       $mail->send();
       
  1923       $mail->reset();
       
  1924       
       
  1925       echo '<div class="info-box">Your message has been sent.</div>';
       
  1926       
       
  1927     }
       
  1928     else
       
  1929     {
       
  1930       echo '<div class="warning-box">Could not send message for the following reason(s):<ul><li>' . implode('</li><li>', $errors) . '</li></ul></div>';
       
  1931     }
       
  1932     
       
  1933   }
       
  1934   echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">';
       
  1935   ?>
       
  1936   <div class="tblholder">
       
  1937     <table border="0" cellspacing="1" cellpadding="4">
       
  1938       <tr>
       
  1939         <th colspan="2">Send mass e-mail</th>
       
  1940       </tr>
       
  1941       <tr>
       
  1942         <td class="row2" rowspan="2" style="width: 30%; min-width: 200px;">
       
  1943           Send message to:<br />
       
  1944           <small>
       
  1945             By default, this message will be sent to the group selected here. You may instead send the message to a specific
       
  1946             list of users by entering them in the second row, with usernames separated by a single comma (no space).
       
  1947           </small>
       
  1948         </td>
       
  1949         <td class="row1">
       
  1950           <select name="group_id">
       
  1951             <?php
       
  1952             $q = $db->sql_query('SELECT group_name,group_id FROM '.table_prefix.'groups ORDER BY group_name ASC;');
       
  1953             if ( !$q )
       
  1954               $db->_die();
       
  1955             while ( $row = $db->fetchrow() )
       
  1956             {
       
  1957               echo '<option value="' . $row['group_id'] . '">' . $row['group_name'] . '</option>';
       
  1958             }
       
  1959             ?>
       
  1960           </select>
       
  1961         </td>
       
  1962       </tr>
       
  1963       <tr>
       
  1964         <td class="row1">
       
  1965           Usernames: <input type="text" name="userlist" size="50" />
       
  1966         </td>
       
  1967       </tr>
       
  1968       <tr>
       
  1969         <td class="row2" style="width: 30%; min-width: 200px;">
       
  1970           Subject:
       
  1971         </td>
       
  1972         <td class="row1">
       
  1973           <input name="subject" type="text" size="50" />
       
  1974         </td>
       
  1975       </tr>
       
  1976       <tr>
       
  1977         <td class="row2"  style="width: 30%; min-width: 200px;">
       
  1978           Message:
       
  1979         </td>
       
  1980         <td class="row1">
       
  1981           <textarea name="message" rows="30" cols="60" style="width: 100%;"></textarea>
       
  1982         </td>
       
  1983       </tr>
       
  1984       <tr>
       
  1985         <th class="subhead" colspan="2" style="text-align: left;" valign="middle">
       
  1986           <div style="float: right;"><input type="submit" name="do_send" value="Send message" /></div>
       
  1987           <small style="font-weight: normal;">Please be warned: it may take a LONG time to send this message. <b>Please do not stop the script until the process is finished.</b></small>
       
  1988         </th>
       
  1989       </tr>
       
  1990       
       
  1991     </table>
       
  1992   </div>
       
  1993   <?php
       
  1994   echo '</form>';
       
  1995 }
       
  1996 
       
  1997 function page_Admin_DBBackup()
       
  1998 {
       
  1999   global $db, $session, $paths, $template, $plugins; // Common objects
       
  2000   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
  2001   {
       
  2002     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
  2003     return;
       
  2004   }
       
  2005   
       
  2006   global $system_table_list;
       
  2007   if(isset($_GET['submitting']) && $_GET['submitting'] == 'yes')
       
  2008   {
       
  2009     
       
  2010     if(defined('SQL_BACKUP_CRYPT'))
       
  2011       // Try to increase our time limit
       
  2012       @set_time_limit(300); // five minutes
       
  2013     // Do the actual export
       
  2014     $aesext = ( defined('SQL_BACKUP_CRYPT') ) ? '.tea' : '';
       
  2015     $filename = 'enano_backup_' . date('dmy') . '.sql' . $aesext;
       
  2016     ob_start();
       
  2017     header('Content-disposition: attachment, filename="'.$filename.'";');
       
  2018     header('Content-type: application/transact-sql');
       
  2019     // Spew some headers
       
  2020     $headdate = date('F d, Y \a\t h:i a');
       
  2021     echo <<<HEADER
       
  2022 -- Enano CMS SQL backup
       
  2023 -- Generated on {$headdate} by {$session->username}
       
  2024 
       
  2025 HEADER;
       
  2026     // build the table list
       
  2027     $base = ( isset($_POST['do_system_tables']) ) ? $system_table_list : Array();
       
  2028     $add  = ( isset($_POST['additional_tables'])) ? $_POST['additional_tables'] : Array();
       
  2029     $tables = array_merge($base, $add);
       
  2030     
       
  2031     // Log it!
       
  2032     $e = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'db_backup\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($session->username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', \'' . $db->escape(implode(', ', $tables)) . '\')');
       
  2033     if ( !$e )
       
  2034       $db->_die();
       
  2035     
       
  2036     foreach($tables as $i => $t)
       
  2037     {
       
  2038       if(!preg_match('#^([a-z0-9_]+)$#i', $t))
       
  2039         die('Hacking attempt');
       
  2040       // if($t == table_prefix.'files' && isset($_POST['do_data']))
       
  2041       //   unset($tables[$i]);
       
  2042     }
       
  2043     foreach($tables as $t)
       
  2044     {
       
  2045       // Sorry folks - this script CAN'T backup enano_files, enano_search_index, and enano_search_cache due to the sheer size of the tables.
       
  2046       // If encryption is enabled the log data will be excluded too.
       
  2047       echo export_table(
       
  2048         $t,
       
  2049         isset($_POST['do_struct']),
       
  2050         ( isset($_POST['do_data']) /* && $t != table_prefix.'files' && $t != table_prefix.'search_index' && $t != table_prefix.'search_cache' && ( !defined('SQL_BACKUP_CRYPT') || ( defined('SQL_BACKUP_CRYPT') && $t != table_prefix.'logs' ) ) */ ),
       
  2051         false
       
  2052         ) . "\n";
       
  2053     }
       
  2054     $data = ob_get_contents();
       
  2055     ob_end_clean();
       
  2056     if(defined('SQL_BACKUP_CRYPT'))
       
  2057     {
       
  2058       // Free some memory, we don't need this stuff any more
       
  2059       $db->close();
       
  2060       unset($paths, $db, $template, $plugins);
       
  2061       $tea = new TEACrypt();
       
  2062       $data = $tea->encrypt($data, $session->private_key);
       
  2063     }
       
  2064     header('Content-length: '.strlen($data));
       
  2065     echo $data;
       
  2066     exit;
       
  2067   }
       
  2068   else
       
  2069   {
       
  2070     // Show the UI
       
  2071     echo '<form action="'.makeUrlNS('Admin', 'DBBackup', 'submitting=yes', true).'" method="post" enctype="multipart/form-data">';
       
  2072     ?>
       
  2073     <p>This page allows you to back up your Enano database should something go miserably wrong.</p>
       
  2074     <p><label><input type="checkbox" name="do_system_tables" checked="checked" />  Export tables that are part of the Enano core</label><p>
       
  2075     <p>Additional tables to export:</p>
       
  2076     <p><select name="additional_tables[]" multiple="multiple">
       
  2077        <?php
       
  2078          $q = $db->sql_query('SHOW TABLES;') or $db->_die('Somehow we were denied the request to get the list of tables.');
       
  2079          while($row = $db->fetchrow_num())
       
  2080          {
       
  2081            if(!in_array($row[0], $system_table_list)) echo '<option value="'.$row[0].'">'.$row[0].'</option>';
       
  2082          }
       
  2083        ?>
       
  2084        </select>
       
  2085        </p>
       
  2086     <p><label><input type="checkbox" name="do_struct" checked="checked" /> Include table structure</label><br />
       
  2087        <label><input type="checkbox" name="do_data"   checked="checked" /> Include table data</label>
       
  2088        </p>
       
  2089     <p><input type="submit" value="Create backup" /></p>
       
  2090     <?php
       
  2091     echo '</form>';
       
  2092   }
       
  2093 }
       
  2094 
       
  2095 function page_Admin_AdminLogout()
       
  2096 {
       
  2097   global $db, $session, $paths, $template, $plugins; // Common objects
       
  2098   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
  2099   {
       
  2100     echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
       
  2101     return;
       
  2102   }
       
  2103   
       
  2104   $session->logout(USER_LEVEL_ADMIN);
       
  2105   echo '<h3>You have now been logged out of the administration panel.</h3><p>You will continue to be logged into the website, but you will need to re-authenticate before you can access the administration panel again.</p><p>Return to the <a href="'.makeUrl(getConfig('main_page')).'">Main Page</a>.</p>';
       
  2106 }
       
  2107 
       
  2108 function page_Special_Administration()
       
  2109 {
       
  2110   global $db, $session, $paths, $template, $plugins; // Common objects
       
  2111   
       
  2112   if($session->auth_level < USER_LEVEL_ADMIN) {
       
  2113     redirect(makeUrlNS('Special', 'Login/'.$paths->page, 'level='.USER_LEVEL_ADMIN), 'Not authorized', 'You need an authorization level of '.USER_LEVEL_ADMIN.' to use this page, your auth level is: ' . $session->auth_level, 0);
       
  2114     exit;
       
  2115   }
       
  2116   else
       
  2117   {
       
  2118     $template->load_theme('admin', 'default');
       
  2119     $template->init_vars();
       
  2120     if( !isset( $_GET['noheaders'] ) ) 
       
  2121     {
       
  2122       $template->header();
       
  2123     }
       
  2124     echo 'Administer your Enano website.';
       
  2125     ?>
       
  2126     <script type="text/javascript">
       
  2127     function ajaxPage(t)
       
  2128     {
       
  2129       if ( t == namespace_list.Admin + 'AdminLogout' )
       
  2130       {
       
  2131         var mb = new messagebox(MB_YESNO|MB_ICONQUESTION, 'Are you sure you want to de-authenticate?', 'If you de-authenticate, you will no longer be able to use the administration panel until you re-authenticate again. You may do so at any time using the Administration button on the sidebar.');
       
  2132         mb.onclick['Yes'] = function() {
       
  2133           var tigraentry = document.getElementById('i_div0_0').parentNode;
       
  2134           var tigraobj = $(tigraentry);
       
  2135           var div = document.createElement('div');
       
  2136           div.style.backgroundColor = '#FFFFFF';
       
  2137           domObjChangeOpac(70, div);
       
  2138           div.style.position = 'absolute';
       
  2139           var top = tigraobj.Top();
       
  2140           var left = tigraobj.Left();
       
  2141           var width = tigraobj.Width();
       
  2142           var height = tigraobj.Height();
       
  2143           div.style.top = top + 'px';
       
  2144           div.style.left = left + 'px';
       
  2145           div.style.width = width + 'px';
       
  2146           div.style.height = height + 'px';
       
  2147           var body = document.getElementsByTagName('body')[0];
       
  2148           enlighten(true);
       
  2149           body.appendChild(div);
       
  2150           ajaxPageBin(namespace_list.Admin + 'AdminLogout');
       
  2151         }
       
  2152         return;
       
  2153       }
       
  2154       ajaxPageBin(t);
       
  2155     }
       
  2156     function ajaxPageBin(t)
       
  2157     {
       
  2158       document.getElementById('ajaxPageContainer').innerHTML = '<div class="wait-box">Loading page...</div>';
       
  2159       ajaxGet('<?php echo scriptPath; ?>/ajax.php?title='+t+'&_mode=getpage&noheaders&auth=<?php echo $session->sid_super; ?>', function() {
       
  2160           if(ajax.readyState == 4) {
       
  2161             document.getElementById('ajaxPageContainer').innerHTML = ajax.responseText;
       
  2162             fadeInfoBoxes();
       
  2163           }
       
  2164         });
       
  2165     }
       
  2166     function _enanoAdminOnload() { ajaxPage('<?php echo $paths->nslist['Admin']; ?>Home'); }
       
  2167     var TREE_TPL = {
       
  2168       'target'  : '_self',  // name of the frame links will be opened in
       
  2169                   // other possible values are: _blank, _parent, _search, _self and _top
       
  2170     
       
  2171       'icon_e'  : '<?php echo scriptPath; ?>/images/icons/empty.gif',      // empty image
       
  2172       'icon_l'  : '<?php echo scriptPath; ?>/images/icons/line.gif',       // vertical line
       
  2173       'icon_32' : '<?php echo scriptPath; ?>/images/icons/base.gif',       // root leaf icon normal
       
  2174       'icon_36' : '<?php echo scriptPath; ?>/images/icons/base.gif',       // root leaf icon selected
       
  2175       'icon_48' : '<?php echo scriptPath; ?>/images/icons/base.gif',       // root icon normal
       
  2176       'icon_52' : '<?php echo scriptPath; ?>/images/icons/base.gif',       // root icon selected
       
  2177       'icon_56' : '<?php echo scriptPath; ?>/images/icons/base.gif',       // root icon opened
       
  2178       'icon_60' : '<?php echo scriptPath; ?>/images/icons/base.gif',       // root icon selected
       
  2179       'icon_16' : '<?php echo scriptPath; ?>/images/icons/folder.gif',     // node icon normal
       
  2180       'icon_20' : '<?php echo scriptPath; ?>/images/icons/folderopen.gif', // node icon selected
       
  2181       'icon_24' : '<?php echo scriptPath; ?>/images/icons/folder.gif',     // node icon opened
       
  2182       'icon_28' : '<?php echo scriptPath; ?>/images/icons/folderopen.gif', // node icon selected opened
       
  2183       'icon_0'  : '<?php echo scriptPath; ?>/images/icons/page.gif',       // leaf icon normal
       
  2184       'icon_4'  : '<?php echo scriptPath; ?>/images/icons/page.gif',       // leaf icon selected
       
  2185       'icon_8'  : '<?php echo scriptPath; ?>/images/icons/page.gif',       // leaf icon opened
       
  2186       'icon_12' : '<?php echo scriptPath; ?>/images/icons/page.gif',       // leaf icon selected
       
  2187       'icon_2'  : '<?php echo scriptPath; ?>/images/icons/joinbottom.gif', // junction for leaf
       
  2188       'icon_3'  : '<?php echo scriptPath; ?>/images/icons/join.gif',       // junction for last leaf
       
  2189       'icon_18' : '<?php echo scriptPath; ?>/images/icons/plusbottom.gif', // junction for closed node
       
  2190       'icon_19' : '<?php echo scriptPath; ?>/images/icons/plus.gif',       // junction for last closed node
       
  2191       'icon_26' : '<?php echo scriptPath; ?>/images/icons/minusbottom.gif',// junction for opened node
       
  2192       'icon_27' : '<?php echo scriptPath; ?>/images/icons/minus.gif'       // junction for last opended node
       
  2193     };
       
  2194     <?php
       
  2195     echo $paths->parseAdminTree(); // Make a Javascript array that defines the tree
       
  2196     if(!isset($_GET['module'])) { echo 'addOnloadHook(_enanoAdminOnload);'; } ?>
       
  2197     </script>
       
  2198     <table border="0" width="100%">
       
  2199       <tr>
       
  2200         <td class="holder" valign="top">
       
  2201           <div class="pad" style="padding-right: 20px;">
       
  2202             <script type="text/javascript">
       
  2203             new tree(TREE_ITEMS, TREE_TPL);
       
  2204             </script>
       
  2205           </div>
       
  2206         </td>
       
  2207         <td width="100%" valign="top">
       
  2208           <div class="pad" id="ajaxPageContainer">
       
  2209           <?php
       
  2210           if(isset($_GET['module'])) 
       
  2211           {
       
  2212             // Look for a namespace prefix in the urlname, and assign a different namespace, if necessary
       
  2213             $k = array_keys($paths->nslist);
       
  2214             for ( $i = 0; $i < sizeof($paths->nslist); $i++ )
       
  2215             {
       
  2216               $ln = strlen( $paths->nslist[ $k[ $i ] ] );
       
  2217               if ( substr($_GET['module'], 0, $ln) == $paths->nslist[$k[$i]] )
       
  2218               {
       
  2219                 $ns = $k[$i];
       
  2220                 $nm = substr($_GET['module'], $ln, strlen($_GET['module']));
       
  2221               }
       
  2222             }
       
  2223             $fname = 'page_'.$ns.'_'.$nm;
       
  2224             $s = strpos($fname, '?noheaders');
       
  2225             if($s) $fname = substr($fname, 0, $s);
       
  2226             $paths->cpage['module'] = $_GET['module'];
       
  2227             if ( function_exists($fname) && $_GET['module'] != $paths->nslist['Special'] . 'Administration' )
       
  2228             {
       
  2229               eval($fname.'();');
       
  2230             }
       
  2231           } 
       
  2232           else 
       
  2233           {
       
  2234             echo '<div class="wait-box">Please wait while the administration panel loads. You need to be using a recent browser with AJAX support in order to use Runt.</div>';
       
  2235           }
       
  2236           ?>
       
  2237           </div>
       
  2238         </td>
       
  2239       </tr>
       
  2240     </table>
       
  2241   
       
  2242     <?php
       
  2243   }
       
  2244   if(!isset($_GET['noheaders']))
       
  2245   {
       
  2246     $template->footer();
       
  2247   }
       
  2248 }
       
  2249 
       
  2250 function page_Special_EditSidebar()
       
  2251 {
       
  2252   global $db, $session, $paths, $template, $plugins; // Common objects
       
  2253   
       
  2254   if($session->auth_level < USER_LEVEL_ADMIN) 
       
  2255   {
       
  2256     redirect(makeUrlNS('Special', 'Login/'.$paths->page, 'level='.USER_LEVEL_ADMIN), '', '', false);
       
  2257     exit;
       
  2258   }
       
  2259   else 
       
  2260   {
       
  2261     
       
  2262     $template->add_header('<script type="text/javascript" src="'.scriptPath.'/includes/clientside/dbx.js"></script>');
       
  2263     $template->add_header('<script type="text/javascript" src="'.scriptPath.'/includes/clientside/dbx-key.js"></script>');
       
  2264     $template->add_header('<script type="text/javascript" src="'.scriptPath.'/includes/clientside/sbedit.js"></script>');
       
  2265     $template->add_header('<link rel="stylesheet" type="text/css" href="'.scriptPath.'/includes/clientside/dbx.css" />');
       
  2266     
       
  2267     // Knock the sidebars dead to keep javascript in plugins from interfering
       
  2268     $template->tpl_strings['SIDEBAR_LEFT']  = '';
       
  2269     $template->tpl_strings['SIDEBAR_RIGHT'] = '';
       
  2270     
       
  2271     $template->load_theme('oxygen', 'bleu');
       
  2272     $template->init_vars();
       
  2273     
       
  2274     $template->header();
       
  2275     
       
  2276     if(isset($_POST['save']))
       
  2277     {
       
  2278       // Write the new block order to the database
       
  2279       // The only way to do this is with tons of queries (one per block + one select query at the start to count everything) but afaik its safe...
       
  2280       // Anyone know a better way to do this?
       
  2281       $q = $db->sql_query('SELECT item_order,item_id,sidebar_id FROM '.table_prefix.'sidebar ORDER BY sidebar_id ASC, item_order ASC;');
       
  2282       if ( !$q )
       
  2283       {
       
  2284         $db->_die('The sidebar order data could not be selected.');
       
  2285       }
       
  2286       $orders = Array();
       
  2287       while($row = $db->fetchrow())
       
  2288       {
       
  2289         $orders[] = Array(
       
  2290             count($orders),
       
  2291             $row['item_id'],
       
  2292             $row['sidebar_id'],
       
  2293           );
       
  2294       }
       
  2295       $db->free_result();
       
  2296       
       
  2297       // We now have an array with each sidebar ID in its respective order. Explode the order string in $_POST['order_(left|right)'] and use it to build a set of queries.
       
  2298       $ol = explode(',', $_POST['order_left']);
       
  2299       $odr = explode(',', $_POST['order_right']);
       
  2300       $om = array_merge($ol, $odr);
       
  2301       unset($ol, $odr);
       
  2302       $queries = Array();
       
  2303       foreach($orders as $k => $v)
       
  2304       {
       
  2305         $queries[] = 'UPDATE '.table_prefix.'sidebar SET item_order='.$om[$k].' WHERE item_id='.$v[1].';';
       
  2306       }
       
  2307       foreach($queries as $sql)
       
  2308       {
       
  2309         $q = $db->sql_query($sql);
       
  2310         if(!$q)
       
  2311         {
       
  2312           $t = $db->get_error();
       
  2313           echo $t;
       
  2314           $template->footer();
       
  2315           exit;
       
  2316         }
       
  2317       }
       
  2318       echo '<div class="info-box" style="margin: 10px 0;">The sidebar order information was updated successfully.</div>';
       
  2319     }
       
  2320     elseif(isset($_POST['create']))
       
  2321     {
       
  2322       switch((int)$_POST['type'])
       
  2323       {
       
  2324         case BLOCK_WIKIFORMAT:
       
  2325           $content = $_POST['wikiformat_content'];
       
  2326           break;
       
  2327         case BLOCK_TEMPLATEFORMAT:
       
  2328           $content = $_POST['templateformat_content'];
       
  2329           break;
       
  2330         case BLOCK_HTML:
       
  2331           $content = $_POST['html_content'];
       
  2332           break;
       
  2333         case BLOCK_PHP:
       
  2334           $content = $_POST['php_content'];
       
  2335           break;
       
  2336         case BLOCK_PLUGIN:
       
  2337           $content = $_POST['plugin_id'];
       
  2338           break;
       
  2339       }
       
  2340       // Get the value of item_order
       
  2341       
       
  2342       $q = $db->sql_query('SELECT * FROM '.table_prefix.'sidebar WHERE sidebar_id='.$db->escape($_POST['sidebar_id']).';');
       
  2343       if(!$q) $db->_die('The order number could not be selected');
       
  2344       $io = $db->numrows();
       
  2345       
       
  2346       $db->free_result();
       
  2347       
       
  2348       $q = 'INSERT INTO '.table_prefix.'sidebar(block_name, block_type, sidebar_id, block_content, item_order) VALUES ( \''.$db->escape($_POST['title']).'\', \''.$db->escape($_POST['type']).'\', \''.$db->escape($_POST['sidebar_id']).'\', \''.$db->escape($content).'\', '.$io.' );';
       
  2349       $result = $db->sql_query($q);
       
  2350       if(!$result)
       
  2351       {
       
  2352         echo $db->get_error();
       
  2353         $template->footer();
       
  2354         exit;
       
  2355       }
       
  2356       
       
  2357       echo '<div class="info-box" style="margin: 10px 0;">The item was added.</div>';
       
  2358       
       
  2359     }
       
  2360     
       
  2361     if(isset($_GET['action']) && isset($_GET['id']))
       
  2362     {
       
  2363       if(preg_match('#^([0-9]*)$#', $_GET['id']))
       
  2364       {
       
  2365       } else {
       
  2366         echo '<div class="warning-box">Error with action: $_GET["id"] was not an integer, aborting to prevent SQL injection</div>';
       
  2367       }
       
  2368       switch($_GET['action'])
       
  2369       {
       
  2370         case 'new':
       
  2371           ?>
       
  2372           <script type="text/javascript">
       
  2373           function setType(input)
       
  2374           {
       
  2375             val = input.value;
       
  2376             if(!val)
       
  2377             {
       
  2378               return false;
       
  2379             }
       
  2380             var divs = getElementsByClassName(document, 'div', 'sbadd_block');
       
  2381             for(var i in divs)
       
  2382             {
       
  2383               if(divs[i].id == 'blocktype_'+val) divs[i].style.display = 'block';
       
  2384               else divs[i].style.display = 'none';
       
  2385             }
       
  2386           }
       
  2387           </script>
       
  2388           
       
  2389           <form action="<?php echo makeUrl($paths->page); ?>" method="post">
       
  2390           
       
  2391             <p>
       
  2392               What type of block should this be?
       
  2393             </p>
       
  2394             <p>
       
  2395               <select name="type" onchange="setType(this)"> <?php /* (NOT WORKING, at least in firefox 2) onload="var thingy = this; setTimeout('setType(thingy)', 500);" */ ?>
       
  2396                 <option value="<?php echo BLOCK_WIKIFORMAT; ?>">Wiki-formatted block</option>
       
  2397                 <option value="<?php echo BLOCK_TEMPLATEFORMAT; ?>">Template-formatted block (old pre-beta 3 behavior)</option>
       
  2398                 <option value="<?php echo BLOCK_HTML; ?>">Raw HTML block</option>
       
  2399                 <option value="<?php echo BLOCK_PHP; ?>">PHP code block (danger, Will Robinson!)</option>
       
  2400                 <option value="<?php echo BLOCK_PLUGIN; ?>">Use code from a plugin</option>
       
  2401               </select>
       
  2402             </p>
       
  2403             
       
  2404             <p>
       
  2405             
       
  2406               Block title: <input name="title" type="text" size="40" /><br />
       
  2407               Which sidebar: <select name="sidebar_id"><option value="<?php echo SIDEBAR_LEFT; ?>">Left</option><option value="<?php echo SIDEBAR_RIGHT; ?>">Right</option></select>
       
  2408             
       
  2409             </p>
       
  2410             
       
  2411             <div class="sbadd_block" id="blocktype_<?php echo BLOCK_WIKIFORMAT; ?>">
       
  2412               <p>
       
  2413                 Wikitext:
       
  2414               </p>
       
  2415               <p>
       
  2416                 <textarea style="width: 98%;" name="wikiformat_content" rows="15" cols="50"></textarea>
       
  2417               </p>
       
  2418             </div>
       
  2419             
       
  2420             <div class="sbadd_block" id="blocktype_<?php echo BLOCK_TEMPLATEFORMAT; ?>">
       
  2421               <p>
       
  2422                 Template code:
       
  2423               </p>
       
  2424               <p>
       
  2425                 <textarea style="width: 98%;" name="templateformat_content" rows="15" cols="50"></textarea>
       
  2426               </p>
       
  2427             </div>
       
  2428             
       
  2429             <div class="sbadd_block" id="blocktype_<?php echo BLOCK_HTML; ?>">
       
  2430               <p>
       
  2431                 HTML to place inside the sidebar:
       
  2432               </p>
       
  2433               <p>
       
  2434                 <textarea style="width: 98%;" name="html_content" rows="15" cols="50"></textarea>
       
  2435               </p>
       
  2436             </div>
       
  2437             
       
  2438             <div class="sbadd_block" id="blocktype_<?php echo BLOCK_PHP; ?>">
       
  2439               <p>
       
  2440                 <b>WARNING:</b> If you don't know what you're doing, or if you are not fluent in PHP, stop now and choose a different block type. You will brick your Enano installation if you are not careful here.
       
  2441                 ALWAYS remember to write secure code! The Enano team is not responsible if someone drops all your tables because of an SQL injection vulnerability in your sidebar code. You are probably better off using the template-formatted block type.
       
  2442               </p>
       
  2443               <p>
       
  2444                 <span style="color: red;">
       
  2445                   It is especially important to note that this code is NOT checked for errors! If there is a syntax error in your code here, it will prevent any pages from loading AT ALL. So you need to use an external PHP editor (like <a href="http://www.jedit.org">jEdit</a>) to check your syntax before you hit save.
       
  2446                 </span> You have been warned.
       
  2447               </p>
       
  2448               <p>
       
  2449                 Also, you should avoid using output buffering functions (ob_[start|end|get_contents|clean]) here, because Enano uses those to track output from this script.
       
  2450               </p>
       
  2451               <p>
       
  2452                 The standard &lt;?php and ?&gt; tags work here. Don't use an initial "&lt;?php" or it will cause a parse error.
       
  2453               </p>
       
  2454               <p>
       
  2455                 PHP code:
       
  2456               </p>
       
  2457               <p>
       
  2458                 <textarea style="width: 98%;" name="php_content" rows="15" cols="50"></textarea>
       
  2459               </p>
       
  2460             </div>
       
  2461             
       
  2462             <div class="sbadd_block" id="blocktype_<?php echo BLOCK_PLUGIN; ?>">
       
  2463               <p>
       
  2464                 Plugin:
       
  2465               </p>
       
  2466               <p>
       
  2467                 <select name="plugin_id">
       
  2468                 <?php
       
  2469                   foreach($template->plugin_blocks as $k => $c)
       
  2470                   {
       
  2471                     echo '<option value="'.$k.'">'.$k.'</option>';
       
  2472                   }
       
  2473                 ?>
       
  2474                 </select>
       
  2475               </p>
       
  2476             </div>
       
  2477             
       
  2478             <p>
       
  2479             
       
  2480               <input type="submit" name="create" value="Create new block" style="font-weight: bold;" />&nbsp;
       
  2481               <input type="submit" name="cancel" value="Cancel" />
       
  2482             
       
  2483             </p>
       
  2484             
       
  2485           </form>
       
  2486           
       
  2487           <script type="text/javascript">
       
  2488             var divs = getElementsByClassName(document, 'div', 'sbadd_block');
       
  2489             for(var i in divs)
       
  2490             {
       
  2491               if(divs[i].id != 'blocktype_<?php echo BLOCK_WIKIFORMAT; ?>') setTimeout("document.getElementById('"+divs[i].id+"').style.display = 'none';", 500);
       
  2492             }
       
  2493           </script>
       
  2494           
       
  2495           <?php
       
  2496           $template->footer();
       
  2497           return;
       
  2498           break;
       
  2499         case 'move':
       
  2500           if( !isset($_GET['side']) || ( isset($_GET['side']) && !preg_match('#^([0-9]+)$#', $_GET['side']) ) )
       
  2501           {
       
  2502             echo '<div class="warning-box" style="margin: 10px 0;">$_GET[\'side\'] contained an SQL injection attempt</div>';
       
  2503             break;
       
  2504           }
       
  2505           $query = $db->sql_query('UPDATE '.table_prefix.'sidebar SET sidebar_id=' . $db->escape($_GET['side']) . ' WHERE item_id=' . $db->escape($_GET['id']) . ';');
       
  2506           if(!$query)
       
  2507           {
       
  2508             echo $db->get_error();
       
  2509             $template->footer();
       
  2510             exit;
       
  2511           }
       
  2512           echo '<div class="info-box" style="margin: 10px 0;">Item moved.</div>';
       
  2513           break;
       
  2514         case 'delete':
       
  2515           $query = $db->sql_query('DELETE FROM '.table_prefix.'sidebar WHERE item_id=' . $db->escape($_GET['id']) . ';'); // Already checked for injection attempts ;-)
       
  2516           if(!$query)
       
  2517           {
       
  2518             echo $db->get_error();
       
  2519             $template->footer();
       
  2520             exit;
       
  2521           }
       
  2522           if(isset($_GET['ajax']))
       
  2523           {
       
  2524             ob_end_clean();
       
  2525             die('GOOD');
       
  2526           }
       
  2527           echo '<div class="error-box" style="margin: 10px 0;">Item deleted.</div>';
       
  2528           break;
       
  2529         case 'disenable';
       
  2530           $q = $db->sql_query('SELECT item_enabled FROM '.table_prefix.'sidebar WHERE item_id=' . $db->escape($_GET['id']) . ';');
       
  2531           if(!$q)
       
  2532           {
       
  2533             echo $db->get_error();
       
  2534             $template->footer();
       
  2535             exit;
       
  2536           }
       
  2537           $r = $db->fetchrow();
       
  2538           $db->free_result();
       
  2539           $e = ( $r['item_enabled'] == 1 ) ? '0' : '1';
       
  2540           $q = $db->sql_query('UPDATE '.table_prefix.'sidebar SET item_enabled='.$e.' WHERE item_id=' . $db->escape($_GET['id']) . ';');
       
  2541           if(!$q)
       
  2542           {
       
  2543             echo $db->get_error();
       
  2544             $template->footer();
       
  2545             exit;
       
  2546           }
       
  2547           if(isset($_GET['ajax']))
       
  2548           {
       
  2549             ob_end_clean();
       
  2550             die('GOOD');
       
  2551           }
       
  2552           break;
       
  2553         case 'getsource':
       
  2554           $q = $db->sql_query('SELECT block_content,block_type FROM '.table_prefix.'sidebar WHERE item_id=' . $db->escape($_GET['id']) . ';');
       
  2555           if(!$q)
       
  2556           {
       
  2557             echo $db->get_error();
       
  2558             $template->footer();
       
  2559             exit;
       
  2560           }
       
  2561           ob_end_clean();
       
  2562           $r = $db->fetchrow();
       
  2563           $db->free_result();
       
  2564           if($r['block_type'] == BLOCK_PLUGIN) die('HOUSTON_WE_HAVE_A_PLUGIN');
       
  2565           die($r['block_content']);
       
  2566           break;
       
  2567         case 'save':
       
  2568           $q = $db->sql_query('UPDATE '.table_prefix.'sidebar SET block_content=\''.$db->escape(rawurldecode($_POST['content'])).'\' WHERE item_id=' . $db->escape($_GET['id']) . ';');
       
  2569           if(!$q)
       
  2570           {
       
  2571             echo 'var status=unescape(\''.hexencode($db->get_error()).'\');';
       
  2572             exit;
       
  2573           }
       
  2574           $q = $db->sql_query('SELECT block_type,block_content FROM '.table_prefix.'sidebar WHERE item_id=' . $db->escape($_GET['id']) . ';');
       
  2575           if(!$q)
       
  2576           {
       
  2577             echo 'var status=unescape(\''.hexencode($db->get_error()).'\');';
       
  2578             exit;
       
  2579           }
       
  2580           $row = $db->fetchrow();
       
  2581           $db->free_result();
       
  2582           switch($row['block_type'])
       
  2583           {
       
  2584             case BLOCK_WIKIFORMAT:
       
  2585             default:
       
  2586               $c = RenderMan::render($row['block_content']);
       
  2587               break;
       
  2588             case BLOCK_TEMPLATEFORMAT:
       
  2589               $c = $template->tplWikiFormat($row['block_content'], false, 'sidebar-editor.tpl');
       
  2590               $c = preg_replace('#<a (.*?)>(.*?)</a>#is', '<a href="#" onclick="return false;">\\2</a>', $c);
       
  2591               break;
       
  2592             case BLOCK_HTML:
       
  2593               $c = $row['block_content'];
       
  2594               $c = preg_replace('#<a (.*?)>(.*?)</a>#is', '<a href="#" onclick="return false;">\\2</a>', $c);
       
  2595               break;
       
  2596             case BLOCK_PHP:
       
  2597               ob_start();
       
  2598               eval($row['block_content']);
       
  2599               $c = ob_get_contents();
       
  2600               ob_end_clean();
       
  2601               $c = preg_replace('#<a (.*?)>(.*?)</a>#is', '<a href="#" onclick="return false;">\\2</a>', $c);
       
  2602               break;
       
  2603             case BLOCK_PLUGIN:
       
  2604               $c = ($template->fetch_block($row['block_content'])) ? $template->fetch_block($row['block_content']) : 'Can\'t find plugin block';
       
  2605               break;
       
  2606           }
       
  2607           die('var status = \'GOOD\'; var content = unescape(\''.hexencode($c).'\');');
       
  2608           break;
       
  2609       }
       
  2610     }
       
  2611     
       
  2612     $q = $db->sql_query('SELECT item_id,sidebar_id,item_enabled,block_name,block_type,block_content FROM '.table_prefix.'sidebar ORDER BY sidebar_id ASC, item_order ASC;');
       
  2613     if(!$q) $db->_die('The sidebar text data could not be selected.');
       
  2614     
       
  2615     $vars = $template->extract_vars('sidebar-editor.tpl');
       
  2616     
       
  2617     $parser = $template->makeParserText($vars['sidebar_button']);
       
  2618     $parser->assign_vars(Array(
       
  2619         'HREF'=>'#',
       
  2620         'FLAGS'=>'onclick="return false;"',
       
  2621         'TEXT'=>'Change theme'
       
  2622       ));
       
  2623     $template->tpl_strings['THEME_LINK'] = $parser->run();
       
  2624     $parser->assign_vars(Array(
       
  2625         'TEXT'=>'Log out',
       
  2626       ));
       
  2627     $template->tpl_strings['LOGOUT_LINK'] = $parser->run();
       
  2628     
       
  2629     $n1 = Array();
       
  2630     $n2 = Array();
       
  2631     $n  =& $n1;
       
  2632     
       
  2633     echo '<table border="0"><tr><td valign="top"><div class="dbx-group" id="sbedit_left">';
       
  2634     //if(isset($vars['sidebar_top'])) echo $template->parse($vars['sidebar_top']);
       
  2635     
       
  2636     // Time for the loop
       
  2637     // what this loop does is fetch the row data, then send it out to the appropriate parser for formatting,
       
  2638     // then puts the result into $c, which is then sent to the template compiler for insertion into the TPL code.
       
  2639     while($row = $db->fetchrow())
       
  2640     {
       
  2641       if(isset($current_side))
       
  2642       {
       
  2643         if($current_side != $row['sidebar_id'])
       
  2644         {
       
  2645           // Time to switch!
       
  2646           //if(isset($vars['sidebar_top'])) echo $template->parse($vars['sidebar_bottom']);
       
  2647           echo '</div></td><td valign="top"><div class="dbx-group" id="sbedit_right">';
       
  2648           //echo '</td><td valign="top">';
       
  2649           //if(isset($vars['sidebar_top'])) echo $template->parse($vars['sidebar_top']);
       
  2650           $n =& $n2;
       
  2651         }
       
  2652       }
       
  2653       $n[] = count($n);
       
  2654       $current_side = $row['sidebar_id'];
       
  2655       switch($row['block_type'])
       
  2656       {
       
  2657         case BLOCK_WIKIFORMAT:
       
  2658         default:
       
  2659           $parser = $template->makeParserText($vars['sidebar_section']);
       
  2660           $c = RenderMan::render($row['block_content']);
       
  2661           break;
       
  2662         case BLOCK_TEMPLATEFORMAT:
       
  2663           $parser = $template->makeParserText($vars['sidebar_section']);
       
  2664           $c = $template->tplWikiFormat($row['block_content'], false, 'sidebar-editor.tpl');
       
  2665           $c = preg_replace('#<a (.*?)>(.*?)</a>#is', '<a href="#" onclick="return false;">\\2</a>', $c);
       
  2666           break;
       
  2667         case BLOCK_HTML:
       
  2668           $parser = $template->makeParserText($vars['sidebar_section_raw']);
       
  2669           $c = $row['block_content'];
       
  2670           $c = preg_replace('#<a (.*?)>(.*?)</a>#is', '<a href="#" onclick="return false;">\\2</a>', $c);
       
  2671           break;
       
  2672         case BLOCK_PHP:
       
  2673           $parser = $template->makeParserText($vars['sidebar_section_raw']);
       
  2674           ob_start();
       
  2675           eval($row['block_content']);
       
  2676           $c = ob_get_contents();
       
  2677           ob_end_clean();
       
  2678           $c = preg_replace('#<a (.*?)>(.*?)</a>#is', '<a href="#" onclick="return false;">\\2</a>', $c);
       
  2679           break;
       
  2680         case BLOCK_PLUGIN:
       
  2681           $parser = $template->makeParserText($vars['sidebar_section_raw']);
       
  2682           $c = ($template->fetch_block($row['block_content'])) ? $template->fetch_block($row['block_content']) : 'Can\'t find plugin block';
       
  2683           break;
       
  2684       }
       
  2685       $t = $template->tplWikiFormat($row['block_name']);
       
  2686       if($row['item_enabled'] == 0) $t .= ' <span id="disabled_'.$row['item_id'].'" style="color: red;">(disabled)</span>';
       
  2687       else           $t .= ' <span id="disabled_'.$row['item_id'].'" style="color: red; display: none;">(disabled)</span>';
       
  2688       $side = ( $row['sidebar_id'] == SIDEBAR_LEFT ) ? SIDEBAR_RIGHT : SIDEBAR_LEFT;
       
  2689       $tb = '<a title="Enable or disable this block"    href="'.makeUrl($paths->page, 'action=disenable&id='.$row['item_id'].''       , true).'" onclick="ajaxDisenableBlock(\''.$row['item_id'].'\'); return false;"   ><img alt="Enable/disable this block" style="border-width: 0;" src="'.scriptPath.'/images/disenable.png" /></a>
       
  2690              <a title="Edit the contents of this block" href="'.makeUrl($paths->page, 'action=edit&id='.$row['item_id'].''            , true).'" onclick="ajaxEditBlock(\''.$row['item_id'].'\', this); return false;"><img alt="Edit this block" style="border-width: 0;" src="'.scriptPath.'/images/edit.png" /></a>
       
  2691              <a title="Permanently delete this block"   href="'.makeUrl($paths->page, 'action=delete&id='.$row['item_id'].''          , true).'" onclick="if(confirm(\'Do you really want to delete this block?\')) { ajaxDeleteBlock(\''.$row['item_id'].'\', this); } return false;"><img alt="Delete this block" style="border-width: 0;" src="'.scriptPath.'/images/delete.png" /></a>
       
  2692              <a title="Move this block to the other sidebar" href="'.makeUrl($paths->page, 'action=move&id='.$row['item_id'].'&side='.$side, true).'"><img alt="Move this block" style="border-width: 0;" src="'.scriptPath.'/images/move.png" /></a>';
       
  2693       $as = '';
       
  2694       $ae = '&nbsp;&nbsp;'.$tb;
       
  2695       $parser->assign_vars(Array('CONTENT'=>$c,'TITLE'=>$t,'ADMIN_START'=>$as,'ADMIN_END'=>$ae));
       
  2696       echo $parser->run();
       
  2697       unset($parser);
       
  2698       
       
  2699     }
       
  2700     $db->free_result();
       
  2701     //if(isset($vars['sidebar_top'])) echo $template->parse($vars['sidebar_bottom']);
       
  2702     echo '</div></td></tr></table>';
       
  2703     echo '<form action="'.makeUrl($paths->page).'" method="post">';
       
  2704     $order = implode(',', $n1);
       
  2705     echo "<input type='hidden' id='divOrder_Left' name='order_left' value='{$order}' />";
       
  2706     $order = implode(',', $n2);
       
  2707     echo "<input type='hidden' id='divOrder_Right' name='order_right' value='{$order}' />";
       
  2708     echo '
       
  2709           <div style="margin: 0 auto 0 auto; text-align: center;">
       
  2710             <input type="submit" name="save" style="font-weight: bold;" value="Save changes" />
       
  2711             <input type="submit" name="revert" style="font-weight: normal;" value="Revert" onclick="return confirm(\'Do you really want to revert your changes?\nNote: this does not revert edits or deletions, those are saved as soon as you confirm the action.\')" />
       
  2712             <br />
       
  2713             <a href="'.makeUrl($paths->page, 'action=new&id=0', true).'">Create new block</a>  |  <a href="'.makeUrl(getConfig('main_page'), false, true).'">Main Page</a>
       
  2714           </div>
       
  2715         </form>
       
  2716          ';
       
  2717   }
       
  2718   
       
  2719   $template->footer();
       
  2720 }
       
  2721 
       
  2722 ?>