plugins/admin/ThemeManager.php
changeset 465 fe8b8c9b54e8
parent 433 c892b2013d3e
child 471 7906fb190fc1
equal deleted inserted replaced
464:8063eace5b67 465:fe8b8c9b54e8
    10  *
    10  *
    11  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
    11  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
    12  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
    12  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
    13  */
    13  */
    14 
    14 
    15 function page_Admin_ThemeManager()
    15 function page_Admin_ThemeManager($force_no_json = false)
    16 {
    16 {
    17   global $db, $session, $paths, $template, $plugins; // Common objects
    17   global $db, $session, $paths, $template, $plugins; // Common objects
    18   global $lang;
    18   global $lang;
    19   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
    19   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
    20   {
    20   {
    81   }
    81   }
    82   
    82   
    83   $installable = array_flip($installable);
    83   $installable = array_flip($installable);
    84   
    84   
    85   // AJAX code
    85   // AJAX code
    86   if ( $paths->getParam(0) === 'action.json' )
    86   if ( $paths->getParam(0) === 'action.json' && !$force_no_json )
    87   {
    87   {
    88     return ajaxServlet_Admin_ThemeManager($themes);
    88     return ajaxServlet_Admin_ThemeManager($themes);
    89   }
    89   }
    90   
    90   
    91   // List installed themes
    91   // List installed themes
   207       $row['is_default'] = ( getConfig('theme_default') === $theme_id );
   207       $row['is_default'] = ( getConfig('theme_default') === $theme_id );
   208       $row['group_list'] = ( empty($row['group_list']) ) ? array() : enano_json_decode($row['group_list']);
   208       $row['group_list'] = ( empty($row['group_list']) ) ? array() : enano_json_decode($row['group_list']);
   209       
   209       
   210       // Build a list of group names
   210       // Build a list of group names
   211       $row['group_names'] = array();
   211       $row['group_names'] = array();
   212       foreach ( $row['group_list'] as $group_id )
   212       $q = $db->sql_query('SELECT group_id, group_name FROM ' . table_prefix . 'groups;');
   213       {
   213       if ( !$q )
   214         $row['group_names'][$group_id] = '';
   214         $db->die_json();
   215       }
   215       while ( $gr = $db->fetchrow() )
   216       if ( count($row['group_names']) > 0 )
   216       {
   217       {
   217         $row['group_names'][ intval($gr['group_id']) ] = $gr['group_name'];
   218         $idlist = 'group_id = ' . implode(' OR group_id = ', array_keys($row['group_names']));
   218       }
   219         $q = $db->sql_query('SELECT group_id, group_name FROM ' . table_prefix . "groups WHERE $idlist;");
   219       $db->free_result();
       
   220       
       
   221       // Build a list of usernames
       
   222       $row['usernames'] = array();
       
   223       foreach ( $row['group_list'] as $el )
       
   224       {
       
   225         if ( !preg_match('/^u:([0-9]+)$/', $el, $match) )
       
   226           continue;
       
   227         $uid =& $match[1];
       
   228         $q = $db->sql_query('SELECT username FROM ' . table_prefix . "users WHERE user_id = $uid;");
   220         if ( !$q )
   229         if ( !$q )
   221           $db->die_json();
   230           $db->die_json();
   222         while ( $gr = $db->fetchrow_num() )
   231         if ( $db->numrows() < 1 )
   223         {
   232         {
   224           list($group_id, $group_name) = $gr;
   233           $db->free_result();
   225           $row['group_names'][$group_id] = $group_name;
   234           continue;
   226         }
   235         }
       
   236         list($username) = $db->fetchrow_num();
       
   237         $row['usernames'][$uid] = $username;
       
   238         $db->free_result();
   227       }
   239       }
   228       
   240       
   229       echo enano_json_encode($row);
   241       echo enano_json_encode($row);
   230       break;
   242       break;
       
   243     case 'uid_lookup':
       
   244       $username = @$request['username'];
       
   245       if ( empty($username) )
       
   246       {
       
   247         die(enano_json_encode(array(
       
   248             'mode' => 'error',
       
   249             'error' => $lang->get('acptm_err_invalid_username')
       
   250           )));
       
   251       }
       
   252       $username = $db->escape(strtolower($username));
       
   253       $q = $db->sql_query('SELECT user_id, username FROM ' . table_prefix . "users WHERE " . ENANO_SQLFUNC_LOWERCASE . "(username) = '$username';");
       
   254       if ( !$q )
       
   255         $db->die_json();
       
   256       
       
   257       if ( $db->numrows() < 1 )
       
   258       {
       
   259         die(enano_json_encode(array(
       
   260             'mode' => 'error',
       
   261             'error' => $lang->get('acptm_err_username_not_found')
       
   262           )));
       
   263       }
       
   264       
       
   265       list($uid, $username_real) = $db->fetchrow_num();
       
   266       $db->free_result();
       
   267       
       
   268       echo enano_json_encode(array(
       
   269           'uid' => $uid,
       
   270           'username' => $username_real
       
   271         ));
       
   272       break;
       
   273     case 'save_theme':
       
   274       if ( !isset($request['theme_data']) )
       
   275       {
       
   276         die(enano_json_encode(array(
       
   277             'mode' => 'error',
       
   278             'error' => 'No theme data in request'
       
   279           )));
       
   280       }
       
   281       $theme_data =& $request['theme_data'];
       
   282       // Perform integrity check on theme data
       
   283       $chk_theme_exists = isset($themes[@$theme_data['theme_id']]);
       
   284       $theme_data['theme_name'] = trim(@$theme_data['theme_name']);
       
   285       $chk_name_good = !empty($theme_data['theme_name']);
       
   286       $chk_policy_good = in_array(@$theme_data['group_policy'], array('allow_all', 'whitelist', 'blacklist'));
       
   287       $chk_grouplist_good = true;
       
   288       foreach ( $theme_data['group_list'] as $acl_entry )
       
   289       {
       
   290         if ( !preg_match('/^(u|g):[0-9]+$/', $acl_entry) )
       
   291         {
       
   292           $chk_grouplist_good = false;
       
   293           break;
       
   294         }
       
   295       }
       
   296       $chk_style_good = @in_array(@$theme_data['default_style'], @$themes[@$theme_data['theme_id']]['css']);
       
   297       if ( !$chk_theme_exists || !$chk_name_good || !$chk_policy_good || !$chk_grouplist_good || !$chk_style_good )
       
   298       {
       
   299         die(enano_json_encode(array(
       
   300             'mode' => 'error',
       
   301             'error' => $lang->get('acptm_err_save_validation_failed')
       
   302           )));
       
   303       }
       
   304       
       
   305       $enable = ( $theme_data['enabled'] ) ? '1' : '0';
       
   306       $theme_default = getConfig('theme_default');
       
   307       $warn_default = ( $theme_default === $theme_data['theme_id'] || $theme_data['make_default'] ) ?
       
   308                         ' ' . $lang->get('acptm_warn_access_with_default') . ' ' :
       
   309                         ' ';
       
   310       if ( $enable == 0 && ( $theme_default === $theme_data['theme_id'] || $theme_data['make_default'] ) )
       
   311       {
       
   312         $enable = '1';
       
   313         $warn_default .= $lang->get('acptm_warn_cant_disable_default');
       
   314       }
       
   315       
       
   316       // We're good. Update the theme...
       
   317       $q = $db->sql_query('UPDATE ' . table_prefix . 'themes SET
       
   318                                theme_name = \'' . $db->escape($theme_data['theme_name']) . '\',
       
   319                                default_style = \'' . $db->escape($theme_data['default_style']) . '\',
       
   320                                group_list = \'' . $db->escape(enano_json_encode($theme_data['group_list'])) . '\',
       
   321                                group_policy = \'' . $db->escape($theme_data['group_policy']) . '\',
       
   322                                enabled = ' . $enable . '
       
   323                              WHERE theme_id = \'' . $db->escape($theme_data['theme_id']) . '\';');
       
   324       if ( !$q )
       
   325         $db->die_json();
       
   326       
       
   327       if ( $theme_data['make_default'] )
       
   328       {
       
   329         setConfig('theme_default', $theme_data['theme_id']);
       
   330       }
       
   331       
       
   332       echo '<div class="info-box"><b>' . $lang->get('acptm_msg_save_success') . '</b>' . $warn_default . '</div>';
       
   333       
       
   334       page_Admin_ThemeManager(true);
       
   335       break;
       
   336     case 'install':
       
   337       $theme_id =& $request['theme_id'];
       
   338       if ( !isset($themes[$theme_id]) )
       
   339       {
       
   340         die(enano_json_encode(array(
       
   341             'mode' => 'error',
       
   342             'error' => 'Theme was deleted from themes/ directory or couldn\'t read theme metadata from filesystem'
       
   343           )));
       
   344       }
       
   345       if ( !isset($themes[$theme_id]['css'][0]) )
       
   346       {
       
   347         die(enano_json_encode(array(
       
   348             'mode' => 'error',
       
   349             'error' => 'Theme doesn\'t have any files in css/, thus it can\'t be installed. (translators: l10n?)'
       
   350           )));
       
   351       }
       
   352       // build dataset
       
   353       $theme_name = $db->escape($themes[$theme_id]['theme_name']);
       
   354       $default_style = $db->escape($themes[$theme_id]['css'][0]);
       
   355       $theme_id = $db->escape($theme_id);
       
   356       
       
   357       // insert it
       
   358       $q = $db->sql_query('INSERT INTO ' . table_prefix . "themes(theme_id, theme_name, default_style, enabled, group_list, group_policy)\n"
       
   359                         . "  VALUES( '$theme_id', '$theme_name', '$default_style', 1, '[]', 'allow_all' );");
       
   360       if ( !$q )
       
   361         $db->die_json();
       
   362       
       
   363       // The response isn't processed unless it's in JSON.
       
   364       echo 'Roger that, over and out.';
       
   365       
       
   366       break;
       
   367     case 'uninstall':
       
   368       $theme_id =& $request['theme_id'];
       
   369       $theme_default = getConfig('theme_default');
       
   370       
       
   371       // Validation
       
   372       if ( !isset($themes[$theme_id]) )
       
   373       {
       
   374         die(enano_json_encode(array(
       
   375             'mode' => 'error',
       
   376             'error' => 'Theme was deleted from themes/ directory or couldn\'t read theme metadata from filesystem'
       
   377           )));
       
   378       }
       
   379       
       
   380       if ( $theme_id == $theme_default )
       
   381       {
       
   382         die(enano_json_encode(array(
       
   383             'mode' => 'error',
       
   384             'error' => $lang->get('acptm_err_uninstalling_default')
       
   385           )));
       
   386       }
       
   387       
       
   388       if ( $theme_id == 'oxygen' )
       
   389       {
       
   390         die(enano_json_encode(array(
       
   391             'mode' => 'error',
       
   392             'error' => $lang->get('acptm_err_uninstalling_oxygen')
       
   393           )));
       
   394       }
       
   395       
       
   396       $theme_id = $db->escape($theme_id);
       
   397       
       
   398       $q = $db->sql_query('DELETE FROM ' . table_prefix . "themes WHERE theme_id = '$theme_id';");
       
   399       if ( !$q )
       
   400         $db->die_json();
       
   401       
       
   402       // Change all the users that were on that theme to the default
       
   403       $default_style = $themes[$theme_default]['default_style'];
       
   404       $default_style = preg_replace('/\.css$/', '', $default_style);
       
   405       
       
   406       $theme_default = $db->escape($theme_default);
       
   407       $default_style = $db->escape($default_style);
       
   408       
       
   409       $q = $db->sql_query('UPDATE ' . table_prefix . "users SET theme = '$theme_default', style = '$default_style' WHERE theme = '$theme_id';");
       
   410       if ( !$q )
       
   411         $db->die_json();
       
   412       
       
   413       echo '<div class="info-box">' . $lang->get('acptm_msg_uninstall_success') . '</div>';
       
   414       
       
   415       page_Admin_ThemeManager(true);
       
   416       break;
   231   }
   417   }
   232 }
   418 }
   233 
   419 
   234 function page_Admin_ThemeManagerOld() 
       
   235 {
       
   236   global $db, $session, $paths, $template, $plugins; // Common objects
       
   237   global $lang;
       
   238   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
       
   239   {
       
   240     $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
       
   241     echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
       
   242     echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
       
   243     return;
       
   244   }
       
   245   
       
   246   
       
   247   // Get the list of styles in the themes/ dir
       
   248   $h = opendir('./themes');
       
   249   $l = Array();
       
   250   if(!$h) die('Error opening directory "./themes" for reading.');
       
   251   while(false !== ($n = readdir($h))) {
       
   252     if($n != '.' && $n != '..' && is_dir('./themes/'.$n))
       
   253       $l[] = $n;
       
   254   }
       
   255   closedir($h);
       
   256   echo('
       
   257   <h3>Theme Management</h3>
       
   258    <p>Install, uninstall, and manage Enano themes.</p>
       
   259   ');
       
   260   if(isset($_POST['disenable'])) {
       
   261     $q = 'SELECT enabled FROM '.table_prefix.'themes WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
       
   262     $s = $db->sql_query($q);
       
   263     if(!$s) die('Error selecting enabled/disabled state value: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   264     $r = $db->fetchrow_num($s);
       
   265     $db->free_result();
       
   266     if($r[0] == 1) $e = 0;
       
   267     else $e = 1;
       
   268     $s=true;
       
   269     if($e==0)
       
   270     {
       
   271       $c = $db->sql_query('SELECT * FROM '.table_prefix.'themes WHERE enabled=1');
       
   272       if(!$c) $db->_die('The backup check for having at least on theme enabled failed.');
       
   273       if($db->numrows() <= 1) { echo '<div class="warning-box">You cannot disable the last remaining theme.</div>'; $s=false; }
       
   274     }
       
   275     $db->free_result();
       
   276     if($s) {
       
   277     $q = 'UPDATE '.table_prefix.'themes SET enabled='.$e.' WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
       
   278     $a = $db->sql_query($q);
       
   279     if(!$a) die('Error updating enabled/disabled state value: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   280     else echo('<div class="info-box">The theme "'.$_POST['theme_id'].'" has been  '. ( ( $e == '1' ) ? 'enabled' : 'disabled' ).'.</div>');
       
   281     }
       
   282   }
       
   283   elseif(isset($_POST['edit'])) {
       
   284     
       
   285     $dir = './themes/'.$_POST['theme_id'].'/css/';
       
   286     $list = Array();
       
   287     // Open a known directory, and proceed to read its contents
       
   288     if (is_dir($dir)) {
       
   289       if ($dh = opendir($dir)) {
       
   290         while (($file = readdir($dh)) !== false) {
       
   291           if(preg_match('#^(.*?)\.css$#is', $file) && $file != '_printable.css') {
       
   292             $list[$file] = capitalize_first_letter(substr($file, 0, strlen($file)-4));
       
   293           }
       
   294         }
       
   295         closedir($dh);
       
   296       }
       
   297     }
       
   298     $lk = array_keys($list);
       
   299     
       
   300     $q = 'SELECT theme_name,default_style FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\'';
       
   301     $s = $db->sql_query($q);
       
   302     if(!$s) die('Error selecting name value: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   303     $r = $db->fetchrow_num($s);
       
   304     $db->free_result();
       
   305     acp_start_form();
       
   306     echo('<div class="question-box">
       
   307           Theme name displayed to users: <input type="text" name="name" value="'.$r[0].'" /><br /><br />
       
   308           Default stylesheet: <select name="defaultcss">');
       
   309     foreach ($lk as $l)
       
   310     {
       
   311       if($r[1] == $l) $v = ' selected="selected"';
       
   312       else $v = '';
       
   313       echo "<option value='{$l}'$v>{$list[$l]}</option>";
       
   314     }
       
   315     echo('</select><br /><br />
       
   316           <input type="submit" name="editsave" value="OK" /><input type="hidden" name="theme_id" value="'.$_POST['theme_id'].'" />
       
   317           </div>');
       
   318     echo('</form>');
       
   319   }
       
   320   elseif(isset($_POST['editsave'])) {
       
   321     $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']) . '\'';
       
   322     $s = $db->sql_query($q);
       
   323     if(!$s) die('Error updating name value: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   324     else echo('<div class="info-box">Theme data updated.</div>');
       
   325   }
       
   326   elseif(isset($_POST['up'])) {
       
   327     // If there is only one theme or if the selected theme is already at the top, do nothing
       
   328     $q = 'SELECT theme_order FROM '.table_prefix.'themes ORDER BY theme_order;';
       
   329     $s = $db->sql_query($q);
       
   330     if(!$s) die('Error selecting order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   331     $q = 'SELECT theme_order FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\'';
       
   332     $sn = $db->sql_query($q);
       
   333     if(!$sn) die('Error selecting order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   334     $r = $db->fetchrow_num($sn);
       
   335     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 {
       
   336       // Get the order IDs of the selected theme and the theme before it
       
   337       $q = 'SELECT theme_order FROM '.table_prefix.'themes WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
       
   338       $s = $db->sql_query($q);
       
   339       if(!$s) die('Error selecting order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   340       $r = $db->fetchrow_num($s);
       
   341       $r = $r[0];
       
   342       $rb = $r - 1;
       
   343       // Thank God for jEdit's rectangular selection and the ablity to edit multiple lines at the same time ;)
       
   344       $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: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   345       $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: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   346       $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: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   347       echo('<div class="info-box">Theme moved up.</div>');
       
   348     }
       
   349     $db->free_result($s);
       
   350     $db->free_result($sn);
       
   351   }
       
   352   elseif(isset($_POST['down'])) {
       
   353     // If there is only one theme or if the selected theme is already at the top, do nothing
       
   354     $q = 'SELECT theme_order FROM '.table_prefix.'themes ORDER BY theme_order;';
       
   355     $s = $db->sql_query($q);
       
   356     if(!$s) die('Error selecting order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   357     $r = $db->fetchrow_num($s);
       
   358     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 {
       
   359       // Get the order IDs of the selected theme and the theme before it
       
   360       $q = 'SELECT theme_order FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\'';
       
   361       $s = $db->sql_query($q);
       
   362       if(!$s) die('Error selecting order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   363       $r = $db->fetchrow_num($s);
       
   364       $r = $r[0];
       
   365       $rb = $r + 1;
       
   366       // Thank God for jEdit's rectangular selection and the ablity to edit multiple lines at the same time ;)
       
   367       $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: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   368       $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: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   369       $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: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   370       echo('<div class="info-box">Theme moved down.</div>');
       
   371     }
       
   372   }
       
   373   else if(isset($_POST['uninstall'])) 
       
   374   {
       
   375     $q = 'SELECT * FROM '.table_prefix.'themes;';
       
   376     $s = $db->sql_query($q);
       
   377     if ( !$s )
       
   378     {
       
   379       die('Error getting theme count: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   380     }
       
   381     $n = $db->numrows($s);
       
   382     $db->free_result();
       
   383     
       
   384     if ( $_POST['theme_id'] == 'oxygen' )
       
   385     {
       
   386       echo '<div class="error-box">The Oxygen theme is used by Enano for installation, upgrades, and error messages, and cannot be uninstalled.</div>';
       
   387     }
       
   388     else
       
   389     {
       
   390       if($n < 2)
       
   391       {
       
   392         echo '<div class="error-box">The theme could not be uninstalled because it is the only theme left.</div>';
       
   393       }
       
   394       else
       
   395       {
       
   396         $q = 'DELETE FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\' LIMIT 1;';
       
   397         $s = $db->sql_query($q);
       
   398         if ( !$s )
       
   399         {
       
   400           die('Error deleting theme data: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   401         }
       
   402         else
       
   403         {
       
   404           echo('<div class="info-box">Theme uninstalled.</div>');
       
   405         }
       
   406       }
       
   407     }
       
   408   }
       
   409   elseif(isset($_POST['install'])) {
       
   410     $q = 'SELECT theme_id FROM '.table_prefix.'themes;';
       
   411     $s = $db->sql_query($q);
       
   412     if(!$s) die('Error getting theme count: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   413     $n = $db->numrows($s);
       
   414     $n++;
       
   415     $theme_id = $_POST['theme_id'];
       
   416     $theme = Array();
       
   417     include('./themes/'.$theme_id.'/theme.cfg');
       
   418     if ( !isset($theme['theme_id']) )
       
   419     {
       
   420       echo '<div class="error-box">Could not load theme.cfg (theme metadata file)</div>';
       
   421     }
       
   422     else
       
   423     {
       
   424       $default_style = false;
       
   425       if ( $dh = opendir('./themes/' . $theme_id . '/css') )
       
   426       {
       
   427         while ( $file = readdir($dh) )
       
   428         {
       
   429           if ( $file != '_printable.css' && preg_match('/\.css$/i', $file) )
       
   430           {
       
   431             $default_style = $file;
       
   432             break;
       
   433           }
       
   434         }
       
   435         closedir($dh);
       
   436       }
       
   437       else
       
   438       {
       
   439         die('The /css subdirectory could not be located in the theme\'s directory');
       
   440       }
       
   441       
       
   442       if ( $default_style )
       
   443       {
       
   444         $q = 'INSERT INTO '.table_prefix.'themes(theme_id,theme_name,theme_order,enabled,default_style) VALUES(\''.$db->escape($theme['theme_id']).'\', \''.$db->escape($theme['theme_name']).'\', '.$n.', 1, \'' . $db->escape($default_style) . '\')';
       
   445         $s = $db->sql_query($q);
       
   446         if(!$s) die('Error inserting theme data: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
       
   447         else echo('<div class="info-box">Theme "'.$theme['theme_name'].'" installed.</div>');
       
   448       }
       
   449       else
       
   450       {
       
   451         echo '<div class="error-box">Could not determine the default style for the theme.</div>';
       
   452       }
       
   453     }
       
   454   }
       
   455   echo('
       
   456   <h3>Currently installed themes</h3>
       
   457     <form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">
       
   458     <p>
       
   459       <select name="theme_id">
       
   460         ');
       
   461         $q = 'SELECT theme_id,theme_name,enabled FROM '.table_prefix.'themes ORDER BY theme_order';
       
   462         $s = $db->sql_query($q);
       
   463         if(!$s) die('Error selecting theme data: '.$db->get_error().'<br /><u>Attempted SQL:</u><br />'.$q);
       
   464         while ( $r = $db->fetchrow_num($s) ) {
       
   465           if($r[2] < 1) $r[1] .= ' (disabled)';
       
   466           echo('<option value="'.$r[0].'">'.$r[1].'</option>');
       
   467         }
       
   468         $db->free_result();
       
   469         echo('
       
   470         </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;" />
       
   471       </p>
       
   472     </form>
       
   473     <h3>Install a new theme</h3>
       
   474   ');
       
   475     $theme = Array();
       
   476     $obb = '';
       
   477     for($i=0;$i<sizeof($l);$i++) {
       
   478       if(is_file('./themes/'.$l[$i].'/theme.cfg') && file_exists('./themes/'.$l[$i].'/theme.cfg')) {
       
   479         include('./themes/'.$l[$i].'/theme.cfg');
       
   480         $q = 'SELECT * FROM '.table_prefix.'themes WHERE theme_id=\''.$theme['theme_id'].'\'';
       
   481         $s = $db->sql_query($q);
       
   482         if(!$s) die('Error selecting list of currently installed themes: '.$db->get_error().'<br /><u>Attempted SQL:</u><br />'.$q);
       
   483         if($db->numrows($s) < 1) {
       
   484           $obb .= '<option value="'.$theme['theme_id'].'">'.$theme['theme_name'].'</option>';
       
   485         }
       
   486         $db->free_result();
       
   487       }
       
   488     }
       
   489     if($obb != '') {
       
   490       echo('<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post"><p>');
       
   491       echo('<select name="theme_id">');
       
   492       echo($obb);
       
   493       echo('</select>');
       
   494       echo('
       
   495       <input type="submit" name="install" value="Install this theme" />
       
   496       </p></form>');
       
   497     } else echo('<p>All themes are currently installed.</p>');
       
   498 }