[ Index ]

PHP Cross Reference of phpBB 3.0 Beta 3

title

Body

[close]

/includes/acp/ -> acp_styles.php (source)

   1  <?php
   2  /** 
   3  *
   4  * @package acp
   5  * @version $Id: acp_styles.php,v 1.58 2006/11/03 21:04:09 acydburn Exp $
   6  * @copyright (c) 2005 phpBB Group 
   7  * @license http://opensource.org/licenses/gpl-license.php GNU Public License 
   8  *
   9  */
  10  
  11  /**
  12  * @package acp
  13  */
  14  class acp_styles
  15  {
  16      var $u_action;
  17  
  18      var $style_cfg;
  19      var $template_cfg;
  20      var $theme_cfg;
  21      var $imageset_cfg;
  22      var $imageset_keys;
  23  
  24  	function main($id, $mode)
  25      {
  26          global $db, $user, $auth, $template, $cache;
  27          global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
  28  
  29          // Hardcoded template bitfield to add for new templates
  30          $bitfield = new bitfield();
  31          $bitfield->set(0);
  32          $bitfield->set(3);
  33          $bitfield->set(8);
  34          $bitfield->set(9);
  35          $bitfield->set(11);
  36          $bitfield->set(12);
  37          define('TEMPLATE_BITFIELD', $bitfield->get_base64());
  38  
  39          $user->add_lang('acp/styles');
  40  
  41          $this->tpl_name = 'acp_styles';
  42          $this->page_title = 'ACP_CAT_STYLES';
  43  
  44          $action = request_var('action', '');
  45          $action = (isset($_POST['add'])) ? 'add' : $action;
  46          $style_id = request_var('id', 0);
  47  
  48          // Fill the configuration variables
  49          $this->style_cfg = $this->template_cfg = $this->theme_cfg = $this->imageset_cfg = '
  50  #
  51  # phpBB {MODE} configuration file
  52  #
  53  # @package phpBB3
  54  # @copyright (c) 2005 phpBB Group 
  55  # @license http://opensource.org/licenses/gpl-license.php GNU Public License 
  56  #
  57  #
  58  # At the left is the name, please do not change this
  59  # At the right the value is entered
  60  # For on/off options the valid values are on, off, 1, 0, true and false
  61  #
  62  # Values get trimmed, if you want to add a space in front or at the end of
  63  # the value, then enclose the value with single or double quotes. 
  64  # Single and double quotes do not need to be escaped.
  65  #
  66  # 
  67  
  68  # General Information about this {MODE}
  69  name = {NAME}
  70  copyright = {COPYRIGHT}
  71  version = {VERSION}
  72  ';
  73  
  74          $this->theme_cfg .= '
  75  # Some configuration options
  76  
  77  #
  78  # You have to turn this option on if you want to use the 
  79  # path template variables ({T_IMAGESET_PATH} for example) within
  80  # your css file.
  81  # This is mostly the case if you want to use language specific
  82  # images within your css file.
  83  #
  84  parse_css_file = {PARSE_CSS_FILE}
  85  
  86  #
  87  # This option defines the pagination seperator in templates.
  88  #
  89  pagination_sep = \'{PAGINATION_SEP}\'
  90  ';
  91  
  92          $this->imageset_keys = array(
  93              'logos' => array(
  94                  'site_logo',
  95              ),
  96              'buttons'    => array(
  97                  'icon_contact_aim', 'icon_contact_email', 'icon_contact_icq', 'icon_contact_jabber', 'icon_contact_msnm', 'icon_contact_pm', 'icon_contact_yahoo', 'icon_contact_www', 'icon_post_delete', 'icon_post_edit', 'icon_post_info', 'icon_post_quote', 'icon_post_report', 'icon_user_online', 'icon_user_offline', 'icon_user_profile', 'icon_user_search', 'icon_user_warn', 'button_pm_forward', 'button_pm_new', 'button_pm_reply', 'button_topic_locked', 'button_topic_new', 'button_topic_reply',
  98              ),
  99              'icons'        => array(
 100                  'icon_post_target', 'icon_post_target_unread', 'icon_topic_attach', 'icon_topic_latest', 'icon_topic_newest', 'icon_topic_reported', 'icon_topic_unapproved', 'icon_friend', 'icon_foe',
 101              ),
 102              'forums'    => array(
 103                  'forum_link', 'forum_read', 'forum_read_locked', 'forum_read_subforum', 'forum_unread', 'forum_unread_locked', 'forum_unread_subforum',
 104              ),
 105              'folders'    => array(
 106                  'topic_moved', 'topic_read', 'topic_read_mine', 'topic_read_hot', 'topic_read_hot_mine', 'topic_read_locked', 'topic_read_locked_mine', 'topic_unread', 'topic_unread_mine', 'topic_unread_hot', 'topic_unread_hot_mine', 'topic_unread_locked', 'topic_unread_locked_mine', 'sticky_read', 'sticky_read_mine', 'sticky_read_locked', 'sticky_read_locked_mine', 'sticky_unread', 'sticky_unread_mine', 'sticky_unread_locked', 'sticky_unread_locked_mine', 'announce_read', 'announce_read_mine', 'announce_read_locked', 'announce_read_locked_mine', 'announce_unread', 'announce_unread_mine', 'announce_unread_locked', 'announce_unread_locked_mine', 'global_read', 'global_read_mine', 'global_read_locked', 'global_read_locked_mine', 'global_unread', 'global_unread_mine', 'global_unread_locked', 'global_unread_locked_mine', 'pm_read', 'pm_unread',
 107              ),
 108              'polls'        => array(
 109                  'poll_left', 'poll_center', 'poll_right',
 110              ),
 111              'ui'        => array(
 112                  'upload_bar',
 113              ),
 114              'user'        => array(
 115                  'user_icon1', 'user_icon2', 'user_icon3', 'user_icon4', 'user_icon5', 'user_icon6', 'user_icon7', 'user_icon8', 'user_icon9', 'user_icon10',
 116              ),
 117          );
 118  
 119          // Execute overall actions
 120          switch ($action)
 121          {
 122              case 'delete':
 123                  if ($style_id)
 124                  {
 125                      $this->remove($mode, $style_id);
 126                      return;
 127                  }
 128              break;
 129  
 130              case 'export':
 131                  if ($style_id)
 132                  {
 133                      $this->export($mode, $style_id);
 134                      return;
 135                  }
 136              break;
 137  
 138              case 'install':
 139                  $this->install($mode);
 140                  return;
 141              break;
 142  
 143              case 'add':
 144                  $this->add($mode);
 145                  return;
 146              break;
 147  
 148              case 'details':
 149                  if ($style_id)
 150                  {
 151                      $this->details($mode, $style_id);
 152                      return;
 153                  }
 154              break;
 155  
 156              case 'edit':
 157                  if ($style_id)
 158                  {
 159                      switch ($mode)
 160                      {
 161                          case 'imageset':
 162                              return $this->edit_imageset($style_id);
 163                          case 'template':
 164                              return $this->edit_template($style_id);
 165                          case 'theme':
 166                              return $this->edit_theme($style_id);
 167                      }
 168                  }
 169              break;
 170  
 171              case 'cache':
 172                  if ($style_id)
 173                  {
 174                      switch ($mode)
 175                      {
 176                          case 'template':
 177                              return $this->template_cache($style_id);
 178                      }
 179                  }
 180              break;
 181          }
 182  
 183          switch ($mode)
 184          {
 185              case 'style':
 186  
 187                  switch ($action)
 188                  {
 189                      case 'activate':
 190                      case 'deactivate':
 191  
 192                          if ($style_id == $config['default_style'])
 193                          {
 194                              trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING);
 195                          }
 196  
 197                          $sql = 'UPDATE ' . STYLES_TABLE . '
 198                              SET style_active = ' . (($action == 'activate') ? 1 : 0) . '
 199                              WHERE style_id = ' . $style_id;
 200                          $db->sql_query($sql);
 201  
 202                          // Set style to default for any member using deactivated style
 203                          if ($action == 'deactivate')
 204                          {
 205                              $sql = 'UPDATE ' . USERS_TABLE . '
 206                                  SET user_style = ' . $config['default_style'] . "
 207                                  WHERE user_style = $style_id";
 208                              $db->sql_query($sql);
 209  
 210                              $sql = 'UPDATE ' . FORUMS_TABLE . '
 211                                  SET forum_style = 0
 212                                  WHERE forum_style = ' . $style_id;
 213                              $db->sql_query($sql);
 214                          }
 215                      break;
 216                  }
 217  
 218                  $this->frontend('style', array('details'), array('export', 'delete'));
 219              break;
 220  
 221              case 'template':
 222  
 223                  switch ($action)
 224                  {
 225                      // Refresh template data stored in db and clear cache
 226                      case 'refresh':
 227  
 228                          $sql = 'SELECT *
 229                              FROM ' . STYLES_TEMPLATE_TABLE . "
 230                              WHERE template_id = $style_id";
 231                          $result = $db->sql_query($sql);
 232                          $template_row = $db->sql_fetchrow($result);
 233                          $db->sql_freeresult($result);
 234  
 235                          if (!$template_row)
 236                          {
 237                              trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
 238                          }
 239  
 240                          if (confirm_box(true))
 241                          {
 242                              $template_refreshed = '';
 243  
 244                              // Only refresh database if the template is stored in the database
 245                              if ($template_row['template_storedb'] && file_exists("{$phpbb_root_path}styles/{$template_row['template_path']}/template/"))
 246                              {
 247                                  $filelist = array('' => array());
 248  
 249                                  $sql = 'SELECT template_filename, template_mtime
 250                                      FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
 251                                      WHERE template_id = $style_id";
 252                                  $result = $db->sql_query($sql);
 253  
 254                                  while ($row = $db->sql_fetchrow($result))
 255                                  {
 256                                      if (@filemtime("{$phpbb_root_path}styles/{$template_row['template_path']}/template/" . $row['template_filename']) > $row['template_mtime'])
 257                                      {
 258                                          // get folder info from the filename
 259                                          if (($slash_pos = strrpos($row['template_filename'], '/')) === false)
 260                                          {
 261                                              $filelist[''][] = $row['template_filename'];
 262                                          }
 263                                          else
 264                                          {
 265                                              $filelist[substr($row['template_filename'], 0, $slash_pos + 1)] = substr($row['template_filename'], $slash_pos + 1, strlen($row['template_filename']) - $slashpos - 1);
 266                                          }
 267                                      }
 268                                  }
 269                                  $db->sql_freeresult($result);
 270  
 271                                  $this->store_templates('update', $style_id, $template_row['template_path'], $filelist);
 272                                  unset($filelist);
 273  
 274                                  $template_refreshed = $user->lang['TEMPLATE_REFRESHED'] . '<br />';
 275                                  add_log('admin', 'LOG_TEMPLATE_REFRESHED', $template_row['template_name']);
 276                              }
 277  
 278                              $this->clear_template_cache($template_row);
 279  
 280                              trigger_error($template_refreshed . $user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action));
 281                          }
 282                          else
 283                          {
 284                              confirm_box(false, ($template_row['template_storedb']) ? $user->lang['CONFIRM_TEMPLATE_REFRESH'] : $user->lang['CONFIRM_TEMPLATE_CLEAR_CACHE'], build_hidden_fields(array(
 285                                  'i'            => $id,
 286                                  'mode'        => $mode,
 287                                  'action'    => $action,
 288                                  'id'        => $style_id
 289                              )));
 290                          }
 291  
 292                      break;
 293                  }
 294  
 295                  $this->frontend('template', array('edit', 'cache', 'details'), array('refresh', 'export', 'delete'));
 296              break;
 297  
 298              case 'theme':
 299  
 300                  switch ($action)
 301                  {
 302                      // Refresh theme data stored in the database
 303                      case 'refresh':
 304  
 305                          $sql = 'SELECT *
 306                              FROM ' . STYLES_THEME_TABLE . "
 307                              WHERE theme_id = $style_id";
 308                          $result = $db->sql_query($sql);
 309                          $theme_row = $db->sql_fetchrow($result);
 310                          $db->sql_freeresult($result);
 311  
 312                          if (!$theme_row)
 313                          {
 314                              trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
 315                          }
 316  
 317                          if (!$theme_row['theme_storedb'])
 318                          {
 319                              trigger_error($user->lang['THEME_ERR_REFRESH_FS'] . adm_back_link($this->u_action), E_USER_WARNING);
 320                          }
 321  
 322                          if (confirm_box(true))
 323                          {
 324                              if ($theme_row['theme_storedb'] && file_exists("{$phpbb_root_path}styles/{$theme_row['theme_path']}/theme/stylesheet.css"))
 325                              {
 326                                  // Save CSS contents
 327                                  $sql_ary = array(
 328                                      'theme_mtime'    => @filemtime("{$phpbb_root_path}styles/{$theme_row['theme_path']}/theme/stylesheet.css"),
 329                                      'theme_data'    => $this->db_theme_data($theme_row)
 330                                  );
 331  
 332                                  $sql = 'UPDATE ' . STYLES_THEME_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
 333                                      WHERE theme_id = $style_id";
 334                                  $db->sql_query($sql);
 335  
 336                                  $cache->destroy('sql', STYLES_THEME_TABLE);
 337  
 338                                  add_log('admin', 'LOG_THEME_REFRESHED', $theme_row['theme_name']);
 339                                  trigger_error($user->lang['THEME_REFRESHED'] . adm_back_link($this->u_action));
 340                              }
 341                          }
 342                          else
 343                          {
 344                              confirm_box(false, $user->lang['CONFIRM_THEME_REFRESH'], build_hidden_fields(array(
 345                                  'i'            => $id,
 346                                  'mode'        => $mode,
 347                                  'action'    => $action,
 348                                  'id'        => $style_id
 349                              )));
 350                          }
 351                      break;
 352                  }
 353  
 354                  $this->frontend('theme', array('edit', 'details'), array('refresh', 'export', 'delete'));
 355              break;
 356  
 357              case 'imageset':
 358  
 359                  switch ($action)
 360                  {
 361                      case 'refresh':
 362  
 363                          $sql = 'SELECT *
 364                              FROM ' . STYLES_IMAGESET_TABLE . "
 365                              WHERE imageset_id = $style_id";
 366                          $result = $db->sql_query($sql);
 367                          $imageset_row = $db->sql_fetchrow($result);
 368                          $db->sql_freeresult($result);
 369  
 370                          if (!$imageset_row)
 371                          {
 372                              trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING);
 373                          }
 374  
 375                          if (confirm_box(true))
 376                          {
 377                              $sql_ary = array();
 378  
 379                              $cfg_data = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/imageset.cfg");
 380                      
 381                              $imageset_definitions = array();
 382                              foreach ($this->imageset_keys as $topic => $key_array)
 383                              {
 384                                  $imageset_definitions = array_merge($imageset_definitions, $key_array);
 385                              }
 386                  
 387                              foreach ($cfg_data as $key => $value)
 388                              {
 389                                  if (strpos($key, 'img_') === 0)
 390                                  {
 391                                      $key = substr($key, 4);
 392                                      if (in_array($key, $imageset_definitions))
 393                                      {
 394                                          $sql_ary[$key] = str_replace('{PATH}', "styles/{$imageset_row['imageset_path']}/imageset/", trim($value));
 395                                      }
 396                                  }
 397                              }
 398                              unset($cfg_data);
 399  
 400                              if (sizeof($sql_ary))
 401                              {
 402                                  $sql = 'UPDATE ' . STYLES_IMAGESET_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
 403                                      WHERE imageset_id = $style_id";
 404                                  $db->sql_query($sql);
 405                              }
 406  
 407                              $cache->destroy('sql', STYLES_IMAGESET_TABLE);
 408  
 409                              add_log('admin', 'LOG_IMAGESET_REFRESHED', $imageset_row['imageset_name']);
 410                              trigger_error($user->lang['IMAGESET_REFRESHED'] . adm_back_link($this->u_action));
 411                          }
 412                          else
 413                          {
 414                              confirm_box(false, $user->lang['CONFIRM_IMAGESET_REFRESH'], build_hidden_fields(array(
 415                                  'i'            => $id,
 416                                  'mode'        => $mode,
 417                                  'action'    => $action,
 418                                  'id'        => $style_id
 419                              )));
 420                          }
 421                      break;
 422                  }
 423  
 424                  $this->frontend('imageset', array('edit', 'details'), array('refresh', 'export', 'delete'));
 425              break;
 426          }
 427      }
 428  
 429      /**
 430      * Build Frontend with supplied options
 431      */
 432  	function frontend($mode, $options, $actions)
 433      {
 434          global $user, $template, $db, $config, $phpbb_root_path, $phpEx;
 435  
 436          $sql_from = '';
 437          $style_count = array();
 438  
 439          switch ($mode)
 440          {
 441              case 'style':
 442                  $sql_from = STYLES_TABLE;
 443  
 444                  $sql = 'SELECT user_style, COUNT(user_style) AS style_count
 445                      FROM ' . USERS_TABLE . '
 446                      GROUP BY user_style';
 447                  $result = $db->sql_query($sql);
 448  
 449                  while ($row = $db->sql_fetchrow($result))
 450                  {
 451                      $style_count[$row['user_style']] = $row['style_count'];
 452                  }
 453                  $db->sql_freeresult($result);
 454  
 455              break;
 456  
 457              case 'template':
 458                  $sql_from = STYLES_TEMPLATE_TABLE;
 459              break;
 460  
 461              case 'theme':
 462                  $sql_from = STYLES_THEME_TABLE;
 463              break;
 464  
 465              case 'imageset':
 466                  $sql_from = STYLES_IMAGESET_TABLE;
 467              break;
 468          }
 469  
 470          $l_prefix = strtoupper($mode);
 471  
 472          $this->page_title = 'ACP_' . $l_prefix . 'S';
 473  
 474          $template->assign_vars(array(
 475              'S_FRONTEND'        => true,
 476              'S_STYLE'            => ($mode == 'style') ? true : false,
 477  
 478              'L_TITLE'            => $user->lang[$this->page_title],
 479              'L_EXPLAIN'            => $user->lang[$this->page_title . '_EXPLAIN'],
 480              'L_NAME'            => $user->lang[$l_prefix . '_NAME'],
 481              'L_INSTALLED'        => $user->lang['INSTALLED_' . $l_prefix],
 482              'L_UNINSTALLED'        => $user->lang['UNINSTALLED_' . $l_prefix],
 483              'L_NO_UNINSTALLED'    => $user->lang['NO_UNINSTALLED_' . $l_prefix],
 484              'L_CREATE'            => $user->lang['CREATE_' . $l_prefix],
 485  
 486              'U_ACTION'            => $this->u_action,
 487              )
 488          );
 489  
 490          $sql = "SELECT *
 491              FROM $sql_from";
 492          $result = $db->sql_query($sql);
 493  
 494          $installed = array();
 495  
 496          $basis_options = '<option class="sep" value="">' . $user->lang['OPTIONAL_BASIS'] . '</option>';
 497          while ($row = $db->sql_fetchrow($result))
 498          {
 499              $installed[] = $row[$mode . '_name'];
 500              $basis_options .= '<option value="' . $row[$mode . '_id'] . '">' . $row[$mode . '_name'] . '</option>';
 501  
 502              $stylevis = ($mode == 'style' && !$row['style_active']) ? 'activate' : 'deactivate';
 503  
 504              $s_options = array();
 505              foreach ($options as $option)
 506              {
 507                  $s_options[] = '<a href="' . $this->u_action . "&amp;action=$option&amp;id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>';
 508              }
 509  
 510              $s_actions = array();
 511              foreach ($actions as $option)
 512              {
 513                  $s_actions[] = '<a href="' . $this->u_action . "&amp;action=$option&amp;id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>';
 514              }
 515  
 516              $template->assign_block_vars('installed', array(
 517                  'S_DEFAULT_STYLE'        => ($mode == 'style' && $row['style_id'] == $config['default_style']) ? true : false,
 518                  'U_EDIT'                => $this->u_action . '&amp;action=' . (($mode == 'style') ? 'details' : 'edit') . '&amp;id=' . $row[$mode . '_id'],
 519                  'U_STYLE_ACT_DEACT'        => $this->u_action . '&amp;action=' . $stylevis . '&amp;id=' . $row[$mode . '_id'],
 520                  'L_STYLE_ACT_DEACT'        => $user->lang['STYLE_' . strtoupper($stylevis)],
 521                  'S_OPTIONS'                => implode(' | ', $s_options),
 522                  'S_ACTIONS'                => implode(' | ', $s_actions),
 523                  'U_PREVIEW'                => ($mode == 'style') ? append_sid("{$phpbb_root_path}index.$phpEx", "$mode=" . $row[$mode . '_id']) : '',
 524  
 525                  'NAME'                    => $row[$mode . '_name'],
 526                  'STYLE_COUNT'            => ($mode == 'style' && isset($style_count[$row['style_id']])) ? $style_count[$row['style_id']] : 0,
 527                  )
 528              );
 529          }
 530          $db->sql_freeresult($result);
 531  
 532          // Grab uninstalled items
 533          $new_ary = $cfg = array();
 534  
 535          $dp = opendir("{$phpbb_root_path}styles");
 536          while (($file = readdir($dp)) !== false)
 537          {
 538              $subpath = ($mode != 'style') ? "$mode/" : '';
 539              if ($file[0] != '.' && file_exists("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
 540              {
 541                  if ($cfg = file("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
 542                  {
 543                      $items = parse_cfg_file('', $cfg);
 544                      $name = (isset($items['name'])) ? trim($items['name']) : false;
 545  
 546                      if ($name && !in_array($name, $installed))
 547                      {
 548                          $new_ary[] = array(
 549                              'path'        => $file,
 550                              'name'        => $name,
 551                              'copyright'    => $items['copyright'],
 552                          );
 553                      }
 554                  }
 555              }
 556          }
 557          unset($installed);
 558          @closedir($dp);
 559  
 560          if (sizeof($new_ary))
 561          {
 562              foreach ($new_ary as $cfg)
 563              {
 564                  $template->assign_block_vars('uninstalled', array(
 565                      'NAME'            => $cfg['name'],
 566                      'COPYRIGHT'        => $cfg['copyright'],
 567                      'U_INSTALL'        => $this->u_action . '&amp;action=install&amp;path=' . urlencode($cfg['path']))
 568                  );
 569              }
 570          }
 571          unset($new_ary);
 572  
 573          $template->assign_vars(array(
 574              'S_BASIS_OPTIONS'        => $basis_options)
 575          );
 576  
 577      }
 578  
 579      /**
 580      * Provides a template editor which allows saving changes to template files on the filesystem or in the database.
 581      *
 582      * @param int $template_id specifies which template set is being edited
 583      */
 584  	function edit_template($template_id)
 585      {
 586          global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode;
 587  
 588          $this->page_title = 'EDIT_TEMPLATE';
 589  
 590          $filelist = $filelist_cats = array();
 591  
 592          // we want newlines no carriage returns!
 593          $_POST['template_data'] = (isset($_POST['template_data']) && !empty($_POST['template_data'])) ? str_replace(array("\r\n", "\r"), array("\n", "\n"), $_POST['template_data']) : '';
 594  
 595          $template_data    = (STRIP) ? stripslashes($_POST['template_data']) : $_POST['template_data'];
 596          $template_file    = request_var('template_file', '');
 597          $text_rows        = max(5, min(999, request_var('text_rows', 20)));
 598          $save_changes    = (isset($_POST['save'])) ? true : false;
 599  
 600          // make sure template_file path doesn't go upwards
 601          $template_file = str_replace('..', '.', $template_file);
 602          
 603          // Retrieve some information about the template
 604          $sql = 'SELECT template_storedb, template_path, template_name
 605              FROM ' . STYLES_TEMPLATE_TABLE . "
 606              WHERE template_id = $template_id";
 607          $result = $db->sql_query($sql);
 608          $template_info = $db->sql_fetchrow($result);
 609          $db->sql_freeresult($result);
 610  
 611          if (!$template_info)
 612          {
 613              trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
 614          }
 615  
 616          // save changes to the template if the user submitted any
 617          if ($save_changes && $template_file)
 618          {
 619              // Get the filesystem location of the current file
 620              $file = "{$phpbb_root_path}styles/{$template_info['template_path']}/template/$template_file";
 621              $additional = '';
 622  
 623              // If the template is stored on the filesystem try to write the file else store it in the database
 624              if (!$safe_mode && !$template_info['template_storedb'] && file_exists($file) && is_writeable($file))
 625              {
 626                  if (!($fp = fopen($file, 'wb')))
 627                  {
 628                      trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
 629                  }
 630                  fwrite($fp, $template_data);
 631                  fclose($fp);
 632              }
 633              else
 634              {
 635                  $db->sql_transaction('begin');
 636  
 637                  // If it's not stored in the db yet, then update the template setting and store all template files in the db
 638                  if (!$template_info['template_storedb'])
 639                  {
 640                      $sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . '
 641                          SET template_storedb = 1
 642                          WHERE template_id = ' . $template_id;
 643                      $db->sql_query($sql);
 644  
 645                      $filelist = filelist("{$phpbb_root_path}styles/{$template_info['template_path']}/template", '', 'html');
 646                      $this->store_templates('insert', $template_id, $template_info['template_path'], $filelist);
 647  
 648                      add_log('admin', 'LOG_TEMPLATE_EDIT_DETAILS', $template_info['template_name']);
 649                      $additional .= '<br />' . $user->lang['EDIT_TEMPLATE_STORED_DB'];
 650                  }
 651  
 652                  // Update the template_data table entry for this template file
 653                  $sql = 'UPDATE ' . STYLES_TEMPLATE_DATA_TABLE . "
 654                      SET template_data = '" . $db->sql_escape($template_data) . "', template_mtime = " . time() . "
 655                      WHERE template_id = $template_id
 656                          AND template_filename = '" . $db->sql_escape($template_file) . "'";
 657                  $db->sql_query($sql);
 658  
 659                  $db->sql_transaction('commit');
 660              }
 661  
 662              // destroy the cached version of the template (filename without extension)
 663              $this->clear_template_cache($template_info, array(substr($template_file, 0, -5)));
 664  
 665              add_log('admin', 'LOG_TEMPLATE_EDIT', $template_info['template_name'], $template_file);
 666              trigger_error($user->lang['TEMPLATE_FILE_UPDATED'] . $additional . adm_back_link($this->u_action . "&amp;action=edit&amp;id=$template_id&amp;text_rows=$text_rows&amp;template_file=$template_file"));
 667          }
 668  
 669          // Generate a category array containing template filenames
 670          if (!$template_info['template_storedb'])
 671          {
 672              $template_path = "{$phpbb_root_path}styles/{$template_info['template_path']}/template";
 673  
 674              $filelist = filelist($template_path, '', 'html');
 675              $filelist[''] = array_diff($filelist[''], array('bbcode.html'));
 676  
 677              if ($template_file)
 678              {
 679                  if (!file_exists($template_path . "/$template_file") || !($template_data = file_get_contents($template_path . "/$template_file")))
 680                  {
 681                      trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
 682                  }
 683              }
 684          }
 685          else
 686          {
 687              $sql = 'SELECT *
 688                  FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
 689                  WHERE template_id = $template_id";
 690              $result = $db->sql_query($sql);
 691  
 692              $filelist = array('' => array());
 693              while ($row = $db->sql_fetchrow($result))
 694              {
 695                  $file_info = pathinfo($row['template_filename']);
 696  
 697                  if (($file_info['basename'] != 'bbcode') && ($file_info['extension'] == 'html'))
 698                  {
 699                      if (($file_info['dirname'] == '.') || empty($file_info['dirname']))
 700                      {
 701                          $filelist[''][] = $row['template_filename'];
 702                      }
 703                      else
 704                      {
 705                          $filelist[$file_info['dirname'] . '/'][] = "{$file_info['basename']}.{$file_info['extension']}";
 706                      }
 707                  }
 708  
 709                  if ($row['template_filename'] == $template_file)
 710                  {
 711                      $template_data = $row['template_data'];
 712                  }
 713              }
 714              $db->sql_freeresult($result);
 715              unset($file_info);
 716          }
 717  
 718          // Now create the categories
 719          $filelist_cats[''] = array();
 720          foreach ($filelist as $pathfile => $file_ary)
 721          {
 722              // Use the directory name as category name
 723              if (!empty($pathfile))
 724              {
 725                  $filelist_cats[$pathfile] = array();
 726                  foreach ($file_ary as $file)
 727                  {
 728                      $filelist_cats[$pathfile][$pathfile . $file] = $file;
 729                  }
 730              }
 731              // or if it's in the main category use the word before the first underscore to group files
 732              else
 733              {
 734                  $cats = array();
 735                  foreach ($file_ary as $file)
 736                  {
 737                      $cats[] = substr($file, 0, strpos($file, '_'));
 738                      $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file;
 739                  }
 740  
 741                  $cats = array_values(array_unique($cats));
 742  
 743                  // we don't need any single element categories so put them into the misc '' category
 744                  for ($i = 0, $n = sizeof($cats); $i < $n; $i++)
 745                  {
 746                      if (sizeof($filelist_cats[$cats[$i]]) == 1)
 747                      {
 748                          $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]);
 749                          unset($filelist_cats[$cats[$i]]);
 750                      }
 751                  }
 752                  unset($cats);
 753              }
 754          }
 755          unset($filelist);
 756  
 757          // Generate list of categorised template files
 758          $tpl_options = '';
 759          ksort($filelist_cats);
 760          foreach ($filelist_cats as $category => $tpl_ary)
 761          {
 762              ksort($tpl_ary);
 763  
 764              if (!empty($category))
 765              {
 766                  $tpl_options .= '<option class="sep" value="">' . $category . '</option>';
 767              }
 768  
 769              foreach ($tpl_ary as $filename => $file)
 770              {
 771                  $selected = ($template_file == $filename) ? ' selected="selected"' : '';
 772                  $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>';
 773              }
 774          }
 775  
 776          $template->assign_vars(array(
 777              'S_EDIT_TEMPLATE'    => true,
 778              'S_HIDDEN_FIELDS'    => build_hidden_fields(array('template_file' => $template_file)),
 779              'S_TEMPLATES'        => $tpl_options,
 780  
 781              'U_ACTION'            => $this->u_action . "&amp;action=edit&amp;id=$template_id&amp;text_rows=$text_rows",
 782              'U_BACK'            => $this->u_action,
 783  
 784              'SELECTED_TEMPLATE'    => $template_info['template_name'],
 785              'TEMPLATE_FILE'        => $template_file,
 786              'TEMPLATE_DATA'        => htmlspecialchars($template_data),
 787              'TEXT_ROWS'            => $text_rows)
 788          );
 789      }
 790  
 791      /**
 792      * Allows the admin to view cached versions of template files and clear single template cache files
 793      *
 794      * @param int $template_id specifies which template's cache is shown
 795      */
 796  	function template_cache($template_id)
 797      {
 798          global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template;
 799  
 800          $source        = str_replace('/', '.', request_var('source', ''));
 801          $file_ary    = array_diff(request_var('delete', array('')), array(''));
 802          $submit        = isset($_POST['submit']) ? true : false;
 803  
 804          $sql = 'SELECT *
 805              FROM ' . STYLES_TEMPLATE_TABLE . "
 806              WHERE template_id = $template_id";
 807          $result = $db->sql_query($sql);
 808          $template_row = $db->sql_fetchrow($result);
 809          $db->sql_freeresult($result);
 810  
 811          if (!$template_row)
 812          {
 813              trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
 814          }
 815  
 816          // User wants to delete one or more files ...
 817          if ($submit && $file_ary)
 818          {
 819              $this->clear_template_cache($template_row, $file_ary);
 820              trigger_error($user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action . "&amp;action=cache&amp;id=$template_id"));
 821          }
 822  
 823          $cache_prefix = 'tpl_' . $template_row['template_path'];
 824  
 825          // Someone wants to see the cached source ... so we'll highlight it,
 826          // add line numbers and indent it appropriately. This could be nasty
 827          // on larger source files ...
 828          if ($source && file_exists("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx"))
 829          {
 830              adm_page_header($user->lang['TEMPLATE_CACHE']);
 831  
 832              $template->set_filenames(array(
 833                  'body'    => 'viewsource.html')
 834              );
 835  
 836              $template->assign_vars(array(
 837                  'FILENAME'    => str_replace('.', '/', $source) . '.html')
 838              );
 839  
 840              $code = str_replace(array("\r\n", "\r"), array("\n", "\n"), file_get_contents("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx"));
 841  
 842              $conf = array('highlight.bg', 'highlight.comment', 'highlight.default', 'highlight.html', 'highlight.keyword', 'highlight.string');
 843              foreach ($conf as $ini_var)
 844              {
 845                  @ini_set($ini_var, str_replace('highlight.', 'syntax', $ini_var));
 846              }
 847  
 848              $marker = 'MARKER' . time();
 849              $code = highlight_string(str_replace("\n", $marker, $code), true);
 850              $code = str_replace($marker, "\n", $code);
 851  
 852              $str_from = array('<span style="color: ', '<font color="syntax', '</font>', '<code>', '</code>','[', ']', '.', ':');
 853              $str_to = array('<span class="', '<span class="syntax', '</span>', '', '', '&#91;', '&#93;', '&#46;', '&#58;');
 854  
 855              $code = str_replace($str_from, $str_to, $code);
 856              $code = preg_replace('#^(<span class="[a-z_]+">)\n?(.*?)\n?(</span>)$#is', '$1$2$3', $code);
 857  
 858              $code = explode("\n", $code);
 859  
 860              foreach ($code as $key => $line)
 861              {
 862                  $template->assign_block_vars('source', array(
 863                      'LINENUM'    => $key + 1,
 864                      'LINE'        => preg_replace('#([^ ;])&nbsp;([^ &])#', '$1 $2', $line))
 865                  );
 866                  unset($code[$key]);
 867              }
 868  
 869              adm_page_footer();
 870          }
 871  
 872          $filemtime = array();
 873          if ($template_row['template_storedb'])
 874          {
 875              $sql = 'SELECT template_filename, template_mtime
 876                  FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
 877                  WHERE template_id = $template_id";
 878              $result = $db->sql_query($sql);
 879  
 880              $filemtime = array();
 881              while ($row = $db->sql_fetchrow($result))
 882              {
 883                  $filemtime[$row['template_filename']] = $row['template_mtime'];
 884              }
 885              $db->sql_freeresult($result);
 886          }
 887  
 888          // Get a list of cached template files and then retrieve additional information about them
 889          $file_ary = $this->template_cache_filelist($template_row['template_path']);
 890  
 891          foreach ($file_ary as $file)
 892          {
 893              $filename = "{$cache_prefix}_$file.html.$phpEx";
 894  
 895              $template->assign_block_vars('file', array(
 896                  'U_VIEWSOURCE'    => $this->u_action . "&amp;action=cache&amp;id=$template_id&amp;source=$file",
 897                  'UA_VIEWSOURCE'    => str_replace('&amp;', '&', $this->u_action) . "&action=cache&id=$template_id&source=$file",
 898  
 899                  'CACHED'        => $user->format_date(filemtime("{$phpbb_root_path}cache/$filename")),
 900                  'FILENAME'        => $file,
 901                  'FILESIZE'        => sprintf('%.1f KB', filesize("{$phpbb_root_path}cache/$filename") / 1024),
 902                  'MODIFIED'        => $user->format_date((!$template_row['template_storedb']) ? filemtime("{$phpbb_root_path}styles/{$template_row['template_path']}/template/$file.html") : $filemtime[$file . '.html']))
 903              );
 904          }
 905          unset($filemtime);
 906  
 907          $template->assign_vars(array(
 908              'S_CACHE'            => true,
 909              'S_TEMPLATE'        => true,
 910  
 911              'U_ACTION'            => $this->u_action . "&amp;action=cache&amp;id=$template_id",
 912              'U_BACK'            => $this->u_action)
 913          );
 914      }
 915  
 916      /**
 917      * Provides a css editor and a basic easier to use stylesheet editing tool for less experienced (or lazy) users
 918      *
 919      * @param int $theme_id specifies which theme is being edited
 920      */
 921  	function edit_theme($theme_id)
 922      {
 923          global $phpbb_root_path, $phpbb_admin_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode;
 924  
 925          $this->page_title = 'EDIT_THEME';
 926  
 927          // we want newlines no carriage returns!
 928          $_POST['css_data'] = (isset($_POST['css_data']) && !empty($_POST['css_data'])) ? str_replace(array("\r\n", "\r"), array("\n", "\n"), $_POST['css_data']) : '';
 929  
 930          // get user input
 931          $text_rows        = max(5, min(999, request_var('text_rows', 20)));
 932          $hide_css        = request_var('hidecss', false);
 933          $show_css        = !$hide_css && request_var('showcss', false);
 934          $edit_class        = request_var('css_class', '');
 935          $custom_class    = request_var('custom_class', '');
 936          $css_data        = (STRIP) ? stripslashes($_POST['css_data']) : $_POST['css_data'];
 937          $submit            = isset($_POST['submit']) ? true : false;
 938          $add_custom        = isset($_POST['add_custom']) ? true : false;
 939          $matches        = array();
 940  
 941          // Retrieve some information about the theme
 942          $sql = 'SELECT theme_storedb, theme_path, theme_name, theme_data
 943              FROM ' . STYLES_THEME_TABLE . "
 944              WHERE theme_id = $theme_id";
 945          $result = $db->sql_query($sql);
 946  
 947          if (!($theme_info = $db->sql_fetchrow($result)))
 948          {
 949              trigger_error($user->lang['NO_THEME'] . adm_bacl_link($this->u_action), E_USER_WARNING);
 950          }
 951          $db->sql_freeresult($result);
 952  
 953          $stylesheet_path = $phpbb_root_path . 'styles/' . $theme_info['theme_path'] . '/theme/stylesheet.css';
 954          // Get the CSS data from either database or filesystem
 955          if (!$theme_info['theme_storedb'])
 956          {
 957              if (!file_exists($stylesheet_path) || !($stylesheet = file_get_contents($stylesheet_path)))
 958              {
 959                  trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
 960              }
 961          }
 962          else
 963          {
 964              $stylesheet = &$theme_info['theme_data'];
 965          }
 966  
 967          // Pull out a list of classes
 968          $classes = array();
 969          if (preg_match_all('/^([a-z0-9\.,:#> \t]+?)[ \t\n]*?\{.*?\}/msi', $stylesheet, $matches))
 970          {
 971              $classes = $matches[1];
 972          }
 973  
 974          // Generate html for the list of classes
 975          $s_hidden_fields = array();
 976          $s_classes = '';
 977          sort($classes);
 978          foreach ($classes as $class)
 979          {
 980              $selected = ($class == $edit_class) ? ' selected="selected"' : '';
 981              $s_classes .= '<option value="' . $class . '"' . $selected . '>' . $class . '</option>';
 982          }
 983  
 984          $template->assign_vars(array(
 985              'S_EDIT_THEME'        => true,
 986              'S_SHOWCSS'            => $show_css,
 987              'S_CLASSES'            => $s_classes,
 988              'S_CLASS'            => $edit_class,
 989  
 990              'U_ACTION'            => $this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;showcss=$show_css&amp;text_rows=$text_rows",
 991              'U_BACK'            => $this->u_action,
 992  
 993              'SELECTED_THEME'    => $theme_info['theme_name'],
 994              'TEXT_ROWS'            => $text_rows)
 995          );
 996  
 997          // only continue if we are really editing anything
 998          if (!$edit_class && !$add_custom)
 999          {
1000              return;
1001          }
1002  
1003          // These are the elements for the simple view
1004          $match_elements = array(
1005              'colors'    => array('background-color', 'color',),
1006              'sizes'        => array('font-size', 'line-height',),
1007              'images'    => array('background-image',),
1008              'repeat'    => array('background-repeat',),
1009              'other'        => array('font-weight', 'font-family', 'font-style', 'text-decoration',),
1010          );
1011  
1012          // Used in an sprintf statement to generate appropriate output for rawcss mode
1013          $map_elements = array(
1014              'colors'    => '%s',
1015              'sizes'        => '%1.10f',
1016              'images'    => 'url(\'./%s\')',
1017              'repeat'    => '%s',
1018              'other'        => '%s',
1019          );
1020  
1021          $units = array('px', '%', 'em', 'pt');
1022          $repeat_types = array(
1023              ''            => $user->lang['UNSET'],
1024              'none'        => $user->lang['REPEAT_NO'],
1025              'repeat-x'    => $user->lang['REPEAT_X'],
1026              'repeat-y'    => $user->lang['REPEAT_Y'],
1027              'both'        => $user->lang['REPEAT_ALL'],
1028          );
1029  
1030          // Fill css_data with the class contents from the stylesheet
1031          // in case we just selected a class and it's not filled yet
1032          if (!$css_data && !$submit && !isset($_POST['hidecss']) && !isset($_POST['showcss']) && !$add_custom)
1033          {
1034              preg_match('#^[ \t]*?' . preg_quote($edit_class, '#') . '[ \t\n]*?\{(.*?)\}#ms', $stylesheet, $matches);
1035  
1036              if (!isset($matches[1]))
1037              {
1038                  trigger_error($user->lang['NO_CLASS'] . adm_back_link($this->u_action), E_USER_WARNING);
1039              }
1040  
1041              $css_data = implode(";\n", array_diff(array_map('trim', explode("\n", preg_replace("#;[\n]*#s", "\n", $matches[1]))), array('')));
1042              if ($css_data)
1043              {
1044                  $css_data .= ';';
1045              }
1046          }
1047  
1048          // If we don't show raw css and the user did not submit any modification
1049          // then generate a list of css elements and output them via the template
1050          if (!$show_css && !$submit && !$add_custom)
1051          {
1052              $css_elements = array_diff(array_map('trim', explode("\n", preg_replace("#;[\n]*#s", "\n", $css_data))), array(''));
1053  
1054              // Grab list of potential images for the "images" type
1055              $img_filelist = filelist($phpbb_root_path . 'styles/' . $theme_info['theme_name'] . '/theme');
1056  
1057              foreach ($match_elements as $type => $match_ary)
1058              {
1059                  foreach ($match_ary as $match)
1060                  {
1061                      $var = str_replace('-', '_', $match);
1062                      $value = '';
1063                      $unit = '';
1064  
1065                      if (sizeof($css_elements))
1066                      {
1067                          // first read in the setting
1068                          foreach ($css_elements as $key => $element)
1069                          {
1070                              if (preg_match('#^' . preg_quote($match, '#') . ':[ \t\n]*?(.*?)$#', $element, $matches))
1071                              {
1072                                  switch ($type)
1073                                  {
1074                                      case 'sizes':
1075                                          $value = trim($matches[1]);
1076  
1077                                          if (preg_match('#(.*?)(px|%|em|pt)#', $matches[1], $matches))
1078                                          {
1079                                              $unit = trim($matches[2]);
1080                                              $value = trim($matches[1]);
1081                                          }
1082                                      break;
1083  
1084                                      case 'images':
1085                                          if (preg_match('#url\(\'(.*?)\'\)#', $matches[1], $matches))
1086                                          {
1087                                              $value = trim($matches[1]);
1088                                          }
1089                                      break;
1090  
1091                                      case 'colors':
1092                                          $value = trim($matches[1]);
1093                                          if ($value[0] == '#')
1094                                          {
1095                                              $value = substr($value, 1);
1096                                          }
1097                                      break;
1098  
1099                                      default:
1100                                          $value = trim($matches[1]);
1101                                  }
1102  
1103                                  // Remove this element from array
1104                                  unset($css_elements[$key]);
1105                                  break;
1106                              }
1107                          }
1108                      }
1109  
1110                      // then display it in the template
1111                      switch ($type)
1112                      {
1113                          case 'sizes':
1114                              // generate a list of units
1115                              $s_units = '';
1116                              foreach ($units as $unit_option)
1117                              {
1118                                  $selected = ($unit_option == $unit) ? ' selected="selected"' : '';
1119                                  $s_units .= "<option value=\"$unit_option\"$selected>$unit_option</option>";
1120                              }
1121                              $s_units = '<option value=""' . (($unit == '') ? ' selected="selected"' : '') . '>' . $user->lang['NO_UNIT'] . '</option>' . $s_units;
1122  
1123                              $template->assign_vars(array(
1124                                  strtoupper($var) => $value,
1125                                  'S_' . strtoupper($var) . '_UNITS' => $s_units)
1126                              );
1127                          break;
1128  
1129                          case 'images':
1130                              // generate a list of images for this setting
1131                              $s_imglist = '';
1132                              foreach ($img_filelist as $path => $img_ary)
1133                              {
1134                                  foreach ($img_ary as $img)
1135                                  {
1136                                      $img = htmlspecialchars(((substr($path, 0, 1) == '/') ? substr($path, 1) : $path) . $img);
1137  
1138                                      $selected = (preg_match('#' . preg_quote($img) . '$#', $value)) ? ' selected="selected"' : '';
1139                                      $s_imglist .= "<option value=\"$img\"$selected>$img</option>";
1140                                  }
1141                              }
1142                              $s_imglist = '<option value=""' . (($value == '') ? ' selected="selected"' : '') . '>' . $user->lang['NO_IMAGE'] . '</option>' . $s_imglist;
1143  
1144                              $template->assign_vars(array(
1145                                  'S_' . strtoupper($var) => $s_imglist)
1146                              );
1147                              unset($s_imglist);
1148                          break;
1149  
1150                          case 'repeat':
1151                              // generate a list of repeat options
1152                              $s_repeat_types = '';
1153                              foreach ($repeat_types as $repeat_type => $repeat_lang)
1154                              {
1155                                  $selected = ($value == $repeat_type) ? ' selected="selected"' : '';
1156                                  $s_repeat_types .= "<option value=\"$repeat_type\"$selected>$repeat_lang</option>";
1157                              }
1158  
1159                              $template->assign_vars(array(
1160                                  'S_' . strtoupper($var) => $s_repeat_types)
1161                              );
1162  
1163                          default:
1164                              $template->assign_vars(array(
1165                                  strtoupper($var) => $value)
1166                              );
1167                      }
1168                  }
1169              }
1170  
1171              // Any remaining elements must be custom data so we save that in a hidden field
1172              if (sizeof($css_elements))
1173              {
1174                  $s_hidden_fields['cssother'] = implode(' ;; ', $css_elements);
1175              }
1176  
1177              unset($img_filelist, $css_elements);
1178          }
1179          // else if we are showing raw css or the user submitted data from the simple view
1180          // then we need to turn the given information into raw css
1181          elseif (!$css_data && !$add_custom)
1182          {
1183              foreach ($match_elements as $type => $match_ary)
1184              {
1185                  foreach ($match_ary as $match)
1186                  {
1187                      $var = str_replace('-', '_', $match);
1188                      $value = '';
1189                      $unit = '';
1190  
1191                      // retrieve and validate data for this setting
1192                      switch ($type)
1193                      {
1194                          case 'sizes':
1195                              $value = request_var($var, 0.0);
1196                              $unit = request_var($var . '_unit', '');
1197  
1198                              if ((request_var($var, '') === '') || !in_array($unit, $units))
1199                              {
1200                                  $value = '';
1201                              }
1202                          break;
1203  
1204                          case 'images':
1205                              $value = str_replace('..', '.', request_var($var, ''));
1206                              if (!file_exists("{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme/" . $value))
1207                              {
1208                                  $value = '';
1209                              }
1210                          break;
1211  
1212                          case 'colors':
1213                              $value = request_var($var, '');
1214                              if (preg_match('#^(?:[A-F0-9]{6}|[A-F0-9]{3})$#', $value))
1215                              {
1216                                  $value = '#' . $value;
1217                              }
1218                          break;
1219  
1220                          case 'repeat':
1221                              $value = request_var($var, '');
1222                              if (!isset($repeat_types[$value]))
1223                              {
1224                                  $value = '';
1225                              }
1226                          break;
1227  
1228                          default:
1229                              $value = request_var($var, '');
1230                      }
1231  
1232                      // use the element mapping to create raw css code
1233                      if ($value !== '')
1234                      {
1235                          $css_data .= $match . ': ' . ($type == 'sizes' ? rtrim(sprintf($map_elements[$type], $value), '0') : sprintf($map_elements[$type], $value)) . $unit . ";\n";
1236                      }
1237                  }
1238              }
1239  
1240              // append additional data sent to us
1241              if ($other = request_var('cssother', ''))
1242              {
1243                  $css_data .= str_replace(' ;; ', ";\n", $other) . ';';
1244                  $css_data = preg_replace("#\*/;\n#", "*/\n", $css_data);
1245              }
1246          }
1247          // make sure we have $show_css set, so we can link to the show_css page if we need to
1248          elseif (!$hide_css)
1249          {
1250              $show_css = true;
1251          }
1252  
1253          if ($submit || $add_custom)
1254          {
1255              if ($submit)
1256              {
1257                  // if the user submitted a modification replace the old class definition in the stylesheet
1258                  // with the new one
1259                  if (preg_match('#^' . preg_quote($edit_class, '#') . '[ \t\n]*?\{(.*?)\}#ms', $stylesheet))
1260                  {
1261                      $stylesheet = preg_replace('#^(' . preg_quote($edit_class, '#') . '[ \t\n]*?\{).*?(\})#ms', "$1\n\t" . str_replace("\n", "\n\t", $css_data) . "\n$2", $stylesheet);
1262                  }
1263                  $message = $user->lang['THEME_UPDATED'];
1264              }
1265              else
1266              {
1267                  // check whether the custom class name is valid
1268                  if (!preg_match('/^[a-z0-9#:.\- ]+$/i', $add_custom))
1269                  {
1270                      trigger_error($user->lang['THEME_ERR_CLASS_CHARS'] . adm_back_link($this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;text_rows=$text_rows"), E_USER_WARNING);
1271                  }
1272                  else
1273                  {
1274                      // append an empty class definition to the stylesheet
1275                      $stylesheet .= "\n$custom_class\n{\n}";
1276                      $message = $user->lang['THEME_CLASS_ADDED'];
1277                  }
1278              }
1279  
1280              // where should we store the CSS?
1281              if (!$safe_mode && !$theme_info['theme_storedb'] && file_exists($stylesheet_path) && is_writeable($stylesheet_path))
1282              {
1283                  // write stylesheet to file
1284                  if (!($fp = fopen($stylesheet_path, 'wb')))
1285                  {
1286                      trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
1287                  }
1288                  fwrite($fp, $stylesheet);
1289                  fclose($fp);
1290              }
1291              else
1292              {
1293                  // Write stylesheet to db
1294                  $sql_ary = array(
1295                      'theme_mtime'        => time(),
1296                      'theme_storedb'        => 1,
1297                      'theme_data'        => $this->db_theme_data($theme_info, $stylesheet),
1298                  );
1299                  $sql = 'UPDATE ' . STYLES_THEME_TABLE . '
1300                      SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
1301                      WHERE theme_id = ' . $theme_id;
1302                  $db->sql_query($sql);
1303  
1304                  $cache->destroy('sql', STYLES_THEME_TABLE);
1305  
1306                  // notify the user if the template was not stored in the db before his modification
1307                  if (!$theme_info['theme_storedb'])
1308                  {
1309                      add_log('admin', 'LOG_THEME_EDIT_DETAILS', $theme_info['theme_name']);
1310                      $message .= '<br />' . $user->lang['EDIT_THEME_STORED_DB'];
1311                  }
1312              }
1313  
1314              $cache->destroy('sql', STYLES_THEME_TABLE);
1315              add_log('admin', ($add_custom) ? 'LOG_THEME_EDIT_ADD' : 'LOG_THEME_EDIT', $theme_info['theme_name'], ($add_custom) ? $custom_class : $edit_class);
1316  
1317              trigger_error($message . adm_back_link($this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;css_class=$edit_class&amp;showcss=$show_css&amp;text_rows=$text_rows"));
1318          }
1319          unset($matches);
1320  
1321          $s_hidden_fields['css_class'] = $edit_class;
1322  
1323          $template->assign_vars(array(
1324              'S_HIDDEN_FIELDS'    => build_hidden_fields($s_hidden_fields),
1325  
1326              'U_SWATCH'            => append_sid("{$phpbb_admin_path}swatch.$phpEx", 'form=acp_theme') . '&amp;name=',
1327              'UA_SWATCH'            => append_sid("{$phpbb_admin_path}swatch.$phpEx", 'form=acp_theme', false) . '&name=',
1328  
1329              'CSS_DATA'            => htmlspecialchars($css_data))
1330          );
1331      }
1332  
1333  
1334      /**
1335      * Edit imagesets
1336      *
1337      * @param int $imageset_id specifies which imageset is being edited
1338      */
1339  	function edit_imageset($imageset_id)
1340      {
1341          global $db, $user, $phpbb_root_path, $cache, $template;
1342  
1343          $this->page_title = 'EDIT_IMAGESET';
1344          $update        = (isset($_POST['update'])) ? true : false;
1345          $imgname    = request_var('imgname', '');
1346          $imgpath    = request_var('imgpath', '');
1347          $imgsize    = request_var('imgsize', false);
1348          $imgwidth    = request_var('imgwidth', 0);
1349  
1350          $imgname    = preg_replace('#[^a-z0-9\-+_]#i', '', $imgname);
1351          $imgpath    = str_replace('..', '.', $imgpath);
1352  
1353          if ($imageset_id)
1354          {
1355              $sql_select = ($imgname) ? ", $imgname" : '';
1356  
1357              $sql = "SELECT imageset_path, imageset_name, imageset_copyright$sql_select
1358                  FROM " . STYLES_IMAGESET_TABLE . "
1359                  WHERE imageset_id = $imageset_id";
1360              $result = $db->sql_query($sql);
1361              $imageset_row = $db->sql_fetchrow($result);
1362              $db->sql_freeresult($result);
1363  
1364              if (!$imageset_row)
1365              {
1366                  trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING);
1367              }
1368              extract($imageset_row);
1369  
1370              // Check to see whether the selected image exists in the table
1371              $valid_name = ($update) ? false : true;
1372  
1373              foreach ($this->imageset_keys as $category => $img_ary)
1374              {
1375                  if (in_array($imgname, $img_ary))
1376                  {
1377                      $valid_name = true;
1378                      break;
1379                  }
1380              }
1381  
1382              if ($update && $imgpath)
1383              {
1384                  if ($valid_name)
1385                  {
1386                      // If imgwidth and imgheight are non-zero grab the actual size
1387                      // from the image itself ... we ignore width settings for the poll center
1388                      // image
1389                      $imgwidth = $imgheight = '';
1390                      if ($imgsize)
1391                      {
1392                          list($imgwidth, $imgheight) = getimagesize("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath");
1393                          $imgheight = '*' . $imgheight;
1394                          $imgwidth = ($imgname != 'poll_center') ? '*' . $imgwidth : '';
1395                      }
1396  
1397                      $imgpath = preg_replace('/^([^\/]+\/)/', '{LANG}/', $imgpath) . $imgheight . $imgwidth;
1398  
1399                      $sql = 'UPDATE ' . STYLES_IMAGESET_TABLE . "
1400                          SET $imgname = '" . $db->sql_escape($imgpath) . "'
1401                          WHERE imageset_id = $imageset_id";
1402                      $db->sql_query($sql);
1403  
1404                      $cache->destroy('sql', STYLES_IMAGESET_TABLE);
1405  
1406                      add_log('admin', 'LOG_IMAGESET_EDIT', $imageset_name);
1407  
1408                      $template->assign_var('SUCCESS', true);
1409                      $$imgname = $imgpath;
1410                  }
1411              }
1412          }
1413  
1414          // Generate list of image options
1415          $img_options = '';
1416          foreach ($this->imageset_keys as $category => $img_ary)
1417          {
1418              $template->assign_block_vars('category', array(
1419                  'NAME'            => $user->lang['IMG_CAT_' . strtoupper($category)]
1420              ));
1421  
1422              foreach ($img_ary as $img)
1423              {
1424                  $template->assign_block_vars('category.images', array(
1425                      'SELECTED'            => ($img == $imgname),
1426                      'VALUE'                => $img,
1427                      'TEXT'                => (($category == 'custom') ? $img : $user->lang['IMG_' . strtoupper($img)])
1428                  ));
1429              }
1430          }
1431  
1432          // TODO
1433          // Check whether localised buttons exist in admins language first
1434          // Clean up this code
1435          $imglang = '';
1436          $imagesetlist = array('nolang' => array(), 'lang' => array());
1437  
1438          $dir = "{$phpbb_root_path}styles/$imageset_path/imageset";
1439          $dp = opendir($dir);
1440          while (($file = readdir($dp)) !== false)
1441          {
1442              if (!is_file($dir . '/' . $file) && !is_link($dir . '/' . $file) && $file[0] != '.' && strtoupper($file) != 'CVS' && !sizeof($imagesetlist['lang']))
1443              {
1444                  $dp2 = opendir("$dir/$file");
1445                  while (($file2 = readdir($dp2)) !== false)
1446                  {
1447                      $imglang = $file;
1448                      if (preg_match('#\.(?:gif|jpg|png)$#', $file2))
1449                      {
1450                          $imagesetlist['lang'][] = "$file/$file2";
1451                      }
1452                  }
1453                  closedir($dp2);
1454              }
1455              else if (preg_match('#\.(?:gif|jpg|png)$#', $file))
1456              {
1457                  $imagesetlist['nolang'][] = $file;
1458              }
1459          }
1460          closedir($dp);
1461  
1462          // Make sure the list of possible images is sorted alphabetically
1463          sort($imagesetlist['nolang']);
1464          sort($imagesetlist['lang']);
1465  
1466          $imagesetlist_options = '';
1467          foreach ($imagesetlist as $type => $img_ary)
1468          {
1469              $template->assign_block_vars('imagesetlist', array(
1470                  'TYPE'    => ($type == 'lang')
1471              ));
1472              foreach ($img_ary as $img)
1473              {
1474                  $imgtext = preg_replace('/^([^\/]+\/)/', '', $img);
1475                  $selected = (!empty($imgname) && strpos($$imgname, $imgtext) !== false);
1476                  if ($selected)
1477                  {
1478                      $template->assign_var('IMAGE_SELECT', true);
1479                  }
1480                  $template->assign_block_vars('imagesetlist.images', array(
1481                      'SELECTED'            => $selected,
1482                      'TEXT'                => $imgtext,
1483                      'VALUE'                => htmlspecialchars($img)
1484                  ));
1485              }
1486          }
1487  
1488          $imgsize_bool = (!empty($imgname) && ($imgsize || preg_match('#\*\d+#', $$imgname))) ? true : false;
1489  
1490          $img_info = (!empty($imgname)) ? explode('*', $$imgname) : array();
1491  
1492          $template->assign_vars(array(
1493              'S_EDIT_IMAGESET'    => true,
1494              'L_TITLE'            => $user->lang[$this->page_title],
1495              'L_EXPLAIN'            => $user->lang[$this->page_title . '_EXPLAIN'],
1496              'IMAGE_OPTIONS'        => $img_options,
1497              'IMAGELIST_OPTIONS'    => $imagesetlist_options,
1498              'IMAGE_SIZE'        => $imgsize_bool,
1499              'IMAGE_REQUEST'        => (!empty($img_info[0])) ? '../styles/' . $imageset_path . '/imageset/' . str_replace('{LANG}', $imglang, $img_info[0]) : '',
1500              'U_ACTION'            => $this->u_action . "&amp;action=edit&amp;id=$imageset_id",
1501              'U_BACK'            => $this->u_action,
1502              'NAME'                => $imageset_name,
1503              'ERROR'                => !$valid_name
1504          ));
1505      }
1506  
1507      /**
1508      * Remove style/template/theme/imageset
1509      */
1510  	function remove($mode, $style_id)
1511      {
1512          global $db, $template, $user, $phpbb_root_path, $cache, $config;
1513  
1514          $new_id = request_var('new_id', 0);
1515          $update = (isset($_POST['update'])) ? true : false;
1516  
1517          switch ($mode)
1518          {
1519              case 'style':
1520                  $sql_from = STYLES_TABLE;
1521                  $sql_select = 'style_name';
1522              break;
1523  
1524              case 'template':
1525                  $sql_from = STYLES_TEMPLATE_TABLE;
1526                  $sql_select = 'template_name, template_path, template_storedb';
1527              break;
1528  
1529              case 'theme':
1530                  $sql_from = STYLES_THEME_TABLE;
1531                  $sql_select = 'theme_name, theme_path, theme_storedb';
1532              break;
1533  
1534              case 'imageset':
1535                  $sql_from = STYLES_IMAGESET_TABLE;
1536                  $sql_select = 'imageset_name, imageset_path';
1537              break;
1538          }
1539  
1540          $l_prefix = strtoupper($mode);
1541  
1542          $sql = "SELECT $sql_select
1543              FROM $sql_from
1544              WHERE {$mode}_id = $style_id";
1545          $result = $db->sql_query($sql);
1546          $style_row = $db->sql_fetchrow($result);
1547          $db->sql_freeresult($result);
1548  
1549          if (!$style_row)
1550          {
1551              trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
1552          }
1553  
1554          $sql = "SELECT {$mode}_id, {$mode}_name
1555              FROM $sql_from
1556              WHERE {$mode}_id <> $style_id
1557              ORDER BY {$mode}_name ASC";
1558          $result = $db->sql_query($sql);
1559  
1560          $s_options = '';
1561  
1562          if ($row = $db->sql_fetchrow($result))
1563          {
1564              do
1565              {
1566                  $s_options .= '<option value="' . $row[$mode . '_id'] . '">' . $row[$mode . '_name'] . '</option>';
1567              }
1568              while ($row = $db->sql_fetchrow($result));
1569          }
1570          else
1571          {
1572              trigger_error($user->lang['ONLY_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
1573          }
1574          $db->sql_freeresult($result);
1575  
1576          if ($update)
1577          {
1578              $sql = "DELETE FROM $sql_from
1579                  WHERE {$mode}_id = $style_id";
1580              $db->sql_query($sql);
1581  
1582              if ($mode == 'style')
1583              {
1584                  $sql = 'UPDATE ' . USERS_TABLE . "
1585                      SET user_style = $new_id
1586                      WHERE user_style = $style_id";
1587                  $db->sql_query($sql);
1588  
1589                  $sql = 'UPDATE ' . FORUMS_TABLE . "
1590                      SET forum_style = $new_id
1591                      WHERE forum_style = $style_id";
1592                  $db->sql_query($sql);
1593  
1594                  if ($style_id == $config['default_style'])
1595                  {
1596                      set_config('default_style', $new_id);
1597                  }
1598              }
1599              else
1600              {
1601                  $sql = 'UPDATE ' . STYLES_TABLE . "
1602                      SET {$mode}_id = $new_id
1603                      WHERE {$mode}_id = $style_id";
1604                  $db->sql_query($sql);
1605              }
1606  
1607              $cache->destroy('sql', STYLES_TABLE);
1608  
1609              add_log('admin', 'LOG_' . $l_prefix . '_DELETE', $style_row[$mode . '_name']);
1610              $message = ($mode != 'style') ? $l_prefix . '_DELETED_FS' : $l_prefix . '_DELETED';
1611              trigger_error($user->lang[$message] . adm_back_link($this->u_action));
1612          }
1613  
1614          $this->page_title = 'DELETE_' . $l_prefix;
1615  
1616          $template->assign_vars(array(
1617              'S_DELETE'            => true,
1618              'S_REPLACE_OPTIONS'    => $s_options,
1619  
1620              'L_TITLE'            => $user->lang[$this->page_title],
1621              'L_EXPLAIN'            => $user->lang[$this->page_title . '_EXPLAIN'],
1622              'L_NAME'            => $user->lang[$l_prefix . '_NAME'],
1623              'L_REPLACE'            => $user->lang['REPLACE_' . $l_prefix],
1624              'L_REPLACE_EXPLAIN'    => $user->lang['REPLACE_' . $l_prefix . '_EXPLAIN'],
1625  
1626              'U_ACTION'        => $this->u_action . "&amp;action=delete&amp;id=$style_id",
1627              'U_BACK'        => $this->u_action,
1628  
1629              'NAME'            => $style_row[$mode . '_name'],
1630              )
1631          );
1632      }
1633  
1634      /**
1635      * Export style or style elements
1636      */
1637  	function export($mode, $style_id)
1638      {
1639          global $db, $template, $user, $phpbb_root_path, $cache, $phpEx, $config;
1640  
1641          $update = (isset($_POST['update'])) ? true : false;
1642  
1643          $inc_template = request_var('inc_template', 0);
1644          $inc_theme = request_var('inc_theme', 0);
1645          $inc_imageset = request_var('inc_imageset', 0);
1646          $store = request_var('store', 0);
1647          $format = request_var('format', '');
1648  
1649          $error = array();
1650          $methods = array('tar');
1651  
1652          $available_methods = array('tar.gz' => 'zlib', 'tar.bz2' => 'bz2', 'zip' => 'zlib');
1653          foreach ($available_methods as $type => $module)
1654          {
1655              if (!@extension_loaded($module))
1656              {
1657                  continue;
1658              }
1659  
1660              $methods[] = $type;
1661          }
1662  
1663          if (!in_array($format, $methods))
1664          {
1665              $format = 'tar';
1666          }
1667  
1668          switch ($mode)
1669          {
1670              case 'style':
1671                  if ($update && ($inc_template + $inc_theme + $inc_imageset) < 1)
1672                  {
1673                      $error[] = $user->lang['STYLE_ERR_MORE_ELEMENTS'];
1674                  }
1675  
1676                  $name = 'style_name';
1677  
1678                  $sql_select = 's.style_id, s.style_name, s.style_copyright';
1679                  $sql_select .= ($inc_template) ? ', t.*' : ', t.template_name';
1680                  $sql_select .= ($inc_theme) ? ', c.*' : ', c.theme_name';
1681                  $sql_select .= ($inc_imageset) ? ', i.*' : ', i.imageset_name';
1682                  $sql_from = STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . ' i';
1683                  $sql_where = "s.style_id = $style_id AND t.template_id = s.template_id AND c.theme_id = s.theme_id AND i.imageset_id = s.imageset_id";
1684  
1685                  $l_prefix = 'STYLE';
1686              break;
1687  
1688              case 'template':
1689                  $name = 'template_name';
1690  
1691                  $sql_select = '*';
1692                  $sql_from = STYLES_TEMPLATE_TABLE;
1693                  $sql_where = "template_id = $style_id";
1694  
1695                  $l_prefix = 'TEMPLATE';
1696              break;
1697  
1698              case 'theme':
1699                  $name = 'theme_name';
1700  
1701                  $sql_select = '*';
1702                  $sql_from = STYLES_THEME_TABLE;
1703                  $sql_where = "theme_id = $style_id";
1704  
1705                  $l_prefix = 'THEME';
1706              break;
1707  
1708              case 'imageset':
1709                  $name = 'imageset_name';
1710  
1711                  $sql_select = '*';
1712                  $sql_from = STYLES_IMAGESET_TABLE;
1713                  $sql_where = "imageset_id = $style_id";
1714  
1715                  $l_prefix = 'IMAGESET';
1716              break;
1717          }
1718  
1719          if ($update && !sizeof($error))
1720          {
1721              $sql = "SELECT $sql_select
1722                  FROM $sql_from
1723                  WHERE $sql_where";
1724              $result = $db->sql_query($sql);
1725              $style_row = $db->sql_fetchrow($result);
1726              $db->sql_freeresult($result);
1727  
1728              if (!$style_row)
1729              {
1730                  trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
1731              }
1732  
1733              $var_ary = array('style_id', 'style_name', 'style_copyright', 'template_id', 'template_name', 'template_path', 'template_copyright', 'template_storedb', 'bbcode_bitfield', 'theme_id', 'theme_name', 'theme_path', 'theme_copyright', 'theme_storedb', 'theme_mtime', 'theme_data', 'imageset_id', 'imageset_name', 'imageset_path', 'imageset_copyright');
1734  
1735              foreach ($var_ary as $var)
1736              {
1737                  if (!isset($style_row[$var]))
1738                  {
1739                      $style_row[$var] = '';
1740                  }
1741              }
1742  
1743              $files = $data = array();
1744  
1745              if ($mode == 'style')
1746              {
1747                  $style_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['style_name'], $style_row['style_copyright'], $config['version']), $this->style_cfg);
1748  
1749                  $style_cfg .= (!$inc_template) ? "\ntemplate = {$style_row['template_name']}" : '';
1750                  $style_cfg .= (!$inc_theme) ? "\ntheme = {$style_row['theme_name']}" : '';
1751                  $style_cfg .= (!$inc_imageset) ? "\nimageset = {$style_row['imageset_name']}" : '';
1752  
1753                  $data[] = array(
1754                      'src'        => $style_cfg,
1755                      'prefix'    => 'style.cfg'
1756                  );
1757  
1758                  unset($style_cfg);
1759              }
1760  
1761              // Export template core code
1762              if ($mode == 'template' || $inc_template)
1763              {
1764                  $template_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['template_name'], $style_row['template_copyright'], $config['version']), $this->template_cfg);
1765                  $template_cfg .= "\nbbcode_bitfield = {$style_row['bbcode_bitfield']}";
1766  
1767                  $data[] = array(
1768                      'src'        => $template_cfg,
1769                      'prefix'    => 'template/template.cfg'
1770                  );
1771  
1772                  // This is potentially nasty memory-wise ...
1773                  if (!$style_row['template_storedb'])
1774                  {
1775                      $files[] = array(
1776                          'src'        => "styles/{$style_row['template_path']}/template/",
1777                          'prefix-'    => "styles/{$style_row['template_path']}/",
1778                          'prefix+'    => false,
1779                          'exclude'    => 'template.cfg'
1780                      );
1781                  }
1782                  else
1783                  {
1784                      $sql = 'SELECT template_filename, template_data
1785                          FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
1786                          WHERE template_id = {$style_row['template_id']}";
1787                      $result = $db->sql_query($sql);
1788  
1789                      while ($row = $db->sql_fetchrow($result))
1790                      {
1791                          $data[] = array(
1792                              'src' => $row['template_data'],
1793                              'prefix' => 'template/' . $row['template_filename']
1794                          );
1795                      }
1796                      $db->sql_freeresult($result);
1797                  }
1798                  unset($template_cfg);
1799              }
1800  
1801              // Export theme core code
1802              if ($mode == 'theme' || $inc_theme)
1803              {
1804                  $theme_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['theme_name'], $style_row['theme_copyright'], $config['version']), $this->theme_cfg);
1805  
1806                  // Read old cfg file
1807                  $items = $cache->obtain_cfg_items($style_row);
1808                  $items = $items['theme'];
1809  
1810                  if (!isset($items['parse_css_file']))
1811                  {
1812                      $items['parse_css_file'] = 'off';
1813                  }
1814  
1815                  if (!isset($items['pagination_sep']))
1816                  {
1817                      $items['pagination_sep'] = ', ';
1818                  }
1819  
1820                  $theme_cfg = str_replace(array('{PARSE_CSS_FILE}', '{PAGINATION_SEP}'), array($items['parse_css_file'], $items['pagination_sep']), $theme_cfg);
1821  
1822                  $files[] = array(
1823                      'src'        => "styles/{$style_row['theme_path']}/theme/",
1824                      'prefix-'    => "styles/{$style_row['theme_path']}/",
1825                      'prefix+'    => false,
1826                      'exclude'    => ($style_row['theme_storedb']) ? 'stylesheet.css,theme.cfg' : 'theme.cfg'
1827                  );
1828  
1829                  $data[] = array(
1830                      'src'        => $theme_cfg,
1831                      'prefix'    => 'theme/theme.cfg'
1832                  );
1833  
1834                  if ($style_row['theme_storedb'])
1835                  {
1836                      $data[] = array(
1837                          'src'        => $style_row['theme_data'],
1838                          'prefix'    => 'theme/stylesheet.css'
1839                      );
1840                  }
1841  
1842                  unset($items, $theme_cfg);
1843              }
1844  
1845              // Export imageset core code
1846              if ($mode == 'imageset' || $inc_imageset)
1847              {
1848                  $imageset_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['imageset_name'], $style_row['imageset_copyright'], $config['version']), $this->imageset_cfg);
1849  
1850                  foreach ($this->imageset_keys as $topic => $key_array)
1851                  {
1852                      foreach ($key_array as $key)
1853                      {
1854                          $imageset_cfg .= "\nimg_" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $style_row[$key]);
1855                      }
1856                  }
1857  
1858                  $files[] = array(
1859                      'src'        => "styles/{$style_row['imageset_path']}/imageset/",
1860                      'prefix-'    => "styles/{$style_row['imageset_path']}/",
1861                      'prefix+'    => false,
1862                      'exclude'    => 'imageset.cfg'
1863                  );
1864  
1865                  $data[] = array(
1866                      'src'        => trim($imageset_cfg),
1867                      'prefix'    => 'imageset/imageset.cfg'
1868                  );
1869  
1870                  unset($imageset_cfg);
1871              }
1872  
1873              switch ($format)
1874              {
1875                  case 'tar':
1876                      $ext = '.tar';
1877                      $mimetype = 'x-tar';
1878                      $compress = 'compress_tar';
1879                  break;
1880  
1881                  case 'zip':
1882                      $ext = '.zip';
1883                      $mimetype = 'zip';
1884                  break;
1885  
1886                  case 'tar.gz':
1887                      $ext = '.tar.gz';
1888                      $mimetype = 'x-gzip';
1889                  break;
1890  
1891                  case 'tar.bz2':
1892                      $ext = '.tar.bz2';
1893                      $mimetype = 'x-bzip2';
1894                  break;
1895  
1896                  default:
1897                      $error[] = $user->lang[$l_prefix . '_ERR_ARCHIVE'];
1898              }
1899  
1900              if (!sizeof($error))
1901              {
1902                  include($phpbb_root_path . 'includes/functions_compress.' . $phpEx);
1903  
1904                  if ($mode == 'style')
1905                  {
1906                      $path = preg_replace('#[^\w-]+#', '_', $style_row['style_name']);
1907                  }
1908                  else
1909                  {
1910                      $path = $style_row[$mode . '_path'];
1911                  }
1912  
1913                  if ($format == 'zip')
1914                  {
1915                      $compress = new compress_zip('w', $phpbb_root_path . "store/$path$ext");
1916                  }
1917                  else
1918                  {
1919                      $compress = new compress_tar('w', $phpbb_root_path . "store/$path$ext", $ext);
1920                  }
1921  
1922                  if (sizeof($files))
1923                  {
1924                      foreach ($files as $file_ary)
1925                      {
1926                          $compress->add_file($file_ary['src'], $file_ary['prefix-'], $file_ary['prefix+'], $file_ary['exclude']);
1927                      }
1928                  }
1929  
1930                  if (sizeof($data))
1931                  {
1932                      foreach ($data as $data_ary)
1933                      {
1934                          $compress->add_data($data_ary['src'], $data_ary['prefix']);
1935                      }
1936                  }
1937  
1938                  $compress->close();
1939  
1940                  add_log('admin', 'LOG_' . $l_prefix . '_EXPORT', $style_row[$mode . '_name']);
1941  
1942                  if (!$store)
1943                  {
1944                      $compress->download($path);
1945                      @unlink("{$phpbb_root_path}store/$path$ext");
1946                      exit;
1947                  }
1948  
1949                  trigger_error(sprintf($user->lang[$l_prefix . '_EXPORTED'], "store/$path$ext") . adm_back_link($this->u_action));
1950              }
1951          }
1952  
1953          $sql = "SELECT {$mode}_id, {$mode}_name
1954              FROM " . (($mode == 'style') ? STYLES_TABLE : $sql_from) . "
1955              WHERE {$mode}_id = $style_id";
1956          $result = $db->sql_query($sql);
1957          $style_row = $db->sql_fetchrow($result);
1958          $db->sql_freeresult($result);
1959  
1960          if (!$style_row)
1961          {
1962              trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
1963          }
1964  
1965          $this->page_title = $l_prefix . '_EXPORT';
1966  
1967          $format_buttons = '';
1968          foreach ($methods as $method)
1969          {
1970              $format_buttons .= '<input type="radio"' . ((!$format_buttons) ? ' id="format"' : '') . ' class="radio" value="' . $method . '" name="format"' . (($method == $format) ? ' checked="checked"' : '') . ' />&nbsp;' . $method . '&nbsp;';
1971          }
1972  
1973          $template->assign_vars(array(
1974              'S_EXPORT'        => true,
1975              'S_ERROR_MSG'    => (sizeof($error)) ? true : false,
1976              'S_STYLE'        => ($mode == 'style') ? true : false,
1977  
1978              'L_TITLE'        => $user->lang[$this->page_title],
1979              'L_EXPLAIN'        => $user->lang[$this->page_title . '_EXPLAIN'],
1980              'L_NAME'        => $user->lang[$l_prefix . '_NAME'],
1981  
1982              'U_ACTION'        => $this->u_action . '&amp;action=export&amp;id=' . $style_id,
1983              'U_BACK'        => $this->u_action,
1984  
1985              'ERROR_MSG'            => (sizeof($error)) ? implode('<br />', $error) : '',
1986              'NAME'                => $style_row[$mode . '_name'],
1987              'FORMAT_BUTTONS'    => $format_buttons)
1988          );
1989      }
1990  
1991      /**
1992      * Display details
1993      */
1994  	function details($mode, $style_id)
1995      {
1996          global $template, $db, $config, $user, $safe_mode, $cache, $phpbb_root_path;
1997  
1998          $update = (isset($_POST['update'])) ? true : false;
1999          $l_type = strtoupper($mode);
2000  
2001          $error = array();
2002          $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE);
2003  
2004          switch ($mode)
2005          {
2006              case 'style':
2007                  $sql_from = STYLES_TABLE;
2008              break;
2009  
2010              case 'template':
2011                  $sql_from = STYLES_TEMPLATE_TABLE;
2012              break;
2013  
2014              case 'theme':
2015                  $sql_from = STYLES_THEME_TABLE;
2016              break;
2017  
2018              case 'imageset':
2019                  $sql_from = STYLES_IMAGESET_TABLE;
2020              break;
2021          }
2022  
2023          $sql = "SELECT *
2024              FROM $sql_from
2025              WHERE {$mode}_id = $style_id";
2026          $result = $db->sql_query($sql);
2027          $style_row = $db->sql_fetchrow($result);
2028          $db->sql_freeresult($result);
2029  
2030          if (!$style_row)
2031          {
2032              trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING);
2033          }
2034  
2035          $style_row['style_default'] = ($mode == 'style' && $config['default_style'] == $style_id) ? 1 : 0;
2036  
2037          if ($update)
2038          {
2039              $name = request_var('name', '');
2040              $copyright = request_var('copyright', '', true);
2041  
2042              $template_id = request_var('template_id', 0);
2043              $theme_id = request_var('theme_id', 0);
2044              $imageset_id = request_var('imageset_id', 0);
2045  
2046              $style_active = request_var('style_active', 0);
2047              $style_default = request_var('style_default', 0);
2048              $store_db = request_var('store_db', 0);
2049  
2050              if ($mode == 'style' && (!$template_id || !$theme_id || !$imageset_id))
2051              {
2052                  $error[] = $user->lang['STYLE_ERR_NO_IDS'];
2053              }
2054  
2055              if ($mode == 'style' && $style_row['style_active'] && !$style_active && $config['default_style'] == $style_id)
2056              {
2057                  $error[] = $user->lang['DEACTIVATE_DEFAULT'];
2058              }
2059  
2060              if (!$name)
2061              {
2062                  $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME'];
2063              }
2064  
2065              if (!sizeof($error))
2066              {
2067                  // Check length settings
2068                  if (utf8_strlen($name) > 30)
2069                  {
2070                      $error[] = $user->lang[$l_type . '_ERR_NAME_LONG'];
2071                  }
2072  
2073                  if (utf8_strlen($copyright) > 60)
2074                  {
2075                      $error[] = $user->lang[$l_type . '_ERR_COPY_LONG'];
2076                  }
2077              }
2078          }
2079  
2080          if ($update && sizeof($error))
2081          {
2082              $style_row = array_merge($style_row, array(
2083                  'template_id'            => $template_id,
2084                  'theme_id'                => $theme_id,
2085                  'imageset_id'            => $imageset_id,
2086                  'style_active'            => $style_active,
2087                  $mode . '_storedb'        => $store_db,
2088                  $mode . '_name'            => $name,
2089                  $mode . '_copyright'    => $copyright)
2090              );
2091          }
2092  
2093          // User has submitted form and no errors have occured
2094          if ($update && !sizeof($error))
2095          {
2096              $sql_ary = array(
2097                  $mode . '_name'            => $name,
2098                  $mode . '_copyright'    => $copyright
2099              );
2100  
2101              switch ($mode)
2102              {
2103                  case 'style':
2104  
2105                      $sql_ary += array(
2106                          'template_id'        => $template_id,
2107                          'theme_id'            => $theme_id,
2108                          'imageset_id'        => $imageset_id,
2109                          'style_active'        => $style_active,
2110                      );
2111                  break;
2112  
2113                  case 'imageset':
2114                  break;
2115  
2116                  case 'theme':
2117  
2118                      if ($style_row['theme_storedb'] != $store_db)
2119                      {
2120                          $theme_data = '';
2121  
2122                          if (!$style_row['theme_storedb'])
2123                          {
2124                              $theme_data = $this->db_theme_data($style_row);
2125                          }
2126                          else if (!$store_db && !$safe_mode && is_writeable("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css"))
2127                          {
2128                              $store_db = 1;
2129                              $theme_data = $style_row['theme_data'];
2130  
2131                              if ($fp = @fopen("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css", 'wb'))
2132                              {
2133                                  $store_db = (@fwrite($fp, str_replace("styles/{$style_row['theme_path']}/theme/", './', $theme_data))) ? 0 : 1;
2134                              }
2135                              fclose($fp);
2136                          }
2137  
2138                          $sql_ary += array(
2139                              'theme_mtime'    => ($store_db) ? filemtime("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css") : 0,
2140                              'theme_storedb'    => $store_db,
2141                              'theme_data'    => ($store_db) ? $theme_data : '',
2142                          );
2143                      }
2144                  break;
2145  
2146                  case 'template':
2147  
2148                      if ($style_row['template_storedb'] != $store_db)
2149                      {
2150                          if (!$store_db && !$safe_mode && is_writeable("{$phpbb_root_path}styles/{$style_row['template_path']}/template"))
2151                          {
2152                              $sql = 'SELECT *
2153                                  FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
2154                                  WHERE template_id = $style_id";
2155                              $result = $db->sql_query($sql);
2156  
2157                              while ($row = $db->sql_fetchrow($result))
2158                              {
2159                                  if (!($fp = @fopen("{$phpbb_root_path}styles/{$style_row['template_path']}/template/" . $row['template_filename'], 'wb')))
2160                                  {
2161                                      $store_db = 1;
2162                                      break;
2163                                  }
2164  
2165                                  fwrite($fp, $row['template_data']);
2166                                  fclose($fp);
2167                              }
2168                              $db->sql_freeresult($result);
2169  
2170                              if (!$store_db)
2171                              {
2172                                  $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
2173                                      WHERE template_id = $style_id";
2174                                  $db->sql_query($sql);
2175                              }
2176                          }
2177                          else if ($store_db)
2178                          {
2179                              $filelist = filelist("{$phpbb_root_path}styles/{$style_row['template_path']}/template", '', 'html');
2180                              $this->store_templates('insert', $style_id, $style_row['template_path'], $filelist);
2181                          }
2182  
2183                          $sql_ary += array(
2184                              'template_storedb'    => $store_db,
2185                          );
2186                      }
2187                  break;
2188              }
2189  
2190              if (sizeof($sql_ary))
2191              {
2192                  $sql = "UPDATE $sql_from
2193                      SET " . $db->sql_build_array('UPDATE', $sql_ary) . "
2194                      WHERE {$mode}_id = $style_id";
2195                  $db->sql_query($sql);
2196  
2197                  // Making this the default style?
2198                  if ($mode == 'style' && $style_default)
2199                  {
2200                      set_config('default_style', $style_id);
2201                  }
2202              }
2203  
2204              $cache->destroy('sql', STYLES_TABLE);
2205  
2206              add_log('admin', 'LOG_' . $l_type . '_EDIT_DETAILS', $name);
2207              trigger_error($user->lang[$l_type . '_DETAILS_UPDATED'] . adm_back_link($this->u_action));
2208          }
2209  
2210          if ($mode == 'style')
2211          {
2212              foreach ($element_ary as $element => $table)
2213              {
2214                  $sql = "SELECT {$element}_id, {$element}_name
2215                      FROM $table
2216                      ORDER BY {$element}_id ASC";
2217                  $result = $db->sql_query($sql);
2218  
2219                  ${$element . '_options'} = '';
2220                  while ($row = $db->sql_fetchrow($result))
2221                  {
2222                      $selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : '';
2223                      ${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>';
2224                  }
2225                  $db->sql_freeresult($result);
2226              }
2227          }
2228  
2229          $this->page_title = 'EDIT_DETAILS_' . $l_type;
2230  
2231          $template->assign_vars(array(
2232              'S_DETAILS'                => true,
2233              'S_ERROR_MSG'            => (sizeof($error)) ? true : false,
2234              'S_STYLE'                => ($mode == 'style') ? true : false,
2235              'S_TEMPLATE'            => ($mode == 'template') ? true : false,
2236              'S_THEME'                => ($mode == 'theme') ? true : false,
2237              'S_IMAGESET'            => ($mode == 'imageset') ? true : false,
2238              'S_STORE_DB'            => (isset($style_row[$mode . '_storedb'])) ? $style_row[$mode . '_storedb'] : 0,
2239              'S_STYLE_ACTIVE'        => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0,
2240              'S_STYLE_DEFAULT'        => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0,
2241  
2242              'S_TEMPLATE_OPTIONS'    => ($mode == 'style') ? $template_options : '',
2243              'S_THEME_OPTIONS'        => ($mode == 'style') ? $theme_options : '',
2244              'S_IMAGESET_OPTIONS'    => ($mode == 'style') ? $imageset_options : '',
2245  
2246              'U_ACTION'        => $this->u_action . '&amp;action=details&amp;id=' . $style_id,
2247              'U_BACK'        => $this->u_action,
2248  
2249              'L_TITLE'                => $user->lang[$this->page_title],
2250              'L_EXPLAIN'                => $user->lang[$this->page_title . '_EXPLAIN'],
2251              'L_NAME'                => $user->lang[$l_type . '_NAME'],
2252              'L_LOCATION'            => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '',
2253              'L_LOCATION_EXPLAIN'    => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '',
2254  
2255              'ERROR_MSG'        => (sizeof($error)) ? implode('<br />', $error) : '',
2256              'NAME'            => $style_row[$mode . '_name'],
2257              'COPYRIGHT'        => $style_row[$mode . '_copyright'],
2258              )
2259          );
2260      }
2261  
2262      /**
2263      * Load css file contents
2264      */
2265  	function load_css_file($path, $filename)
2266      {
2267          global $phpbb_root_path;
2268  
2269          $file = "{$phpbb_root_path}styles/$path/theme/$filename";
2270  
2271          if (file_exists($file) && ($content = file_get_contents($file)))
2272          {
2273              $content = trim($content);
2274          }
2275          else
2276          {
2277              $content = '';
2278          }
2279  
2280          return $content;
2281      }
2282  
2283      /**
2284      * Returns a string containing the value that should be used for the theme_data column in the theme database table.
2285      * Includes contents of files loaded via @import
2286      *
2287      * @param array $theme_row is an associative array containing the theme's current database entry
2288      * @param mixed $stylesheet can either be the new content for the stylesheet or false to load from the standard file
2289      * @param string $root_path should only be used in case you want to use a different root path than "{$phpbb_root_path}styles/{$theme_row['theme_path']}"
2290      *
2291      * @return string Stylesheet data for theme_data column in the theme table
2292      */
2293  	function db_theme_data($theme_row, $stylesheet = false, $root_path = '')
2294      {
2295          global $phpbb_root_path;
2296  
2297          if (!$root_path)
2298          {
2299              $root_path = $phpbb_root_path . 'styles/' . $theme_row['theme_path'];
2300          }
2301  
2302          if (!$stylesheet)
2303          {
2304              $stylesheet = '';
2305              if (file_exists($root_path . '/theme/stylesheet.css'))
2306              {
2307                  $stylesheet = file_get_contents($root_path . '/theme/stylesheet.css');
2308              }
2309          }
2310  
2311          // Match CSS imports
2312          $matches = array();
2313          preg_match_all('/@import url\(["\'](.*)["\']\);/i', $stylesheet, $matches);
2314  
2315          if (sizeof($matches))
2316          {
2317              foreach ($matches[0] as $idx => $match)
2318              {
2319                  $stylesheet = str_replace($match, acp_styles::load_css_file($theme_row['theme_path'], $matches[1][$idx]), $stylesheet);
2320              }
2321          }
2322  
2323          // adjust paths
2324          return str_replace('./', 'styles/' . $theme_row['theme_path'] . '/theme/', $stylesheet);
2325      }
2326  
2327      /**
2328      * Store template files into db
2329      */
2330  	function store_templates($mode, $style_id, $template_path, $filelist)
2331      {
2332          global $phpbb_root_path, $phpEx, $db;
2333  
2334          $template_path = $template_path . '/template/';
2335          $includes = array();
2336          foreach ($filelist as $pathfile => $file_ary)
2337          {
2338              foreach ($file_ary as $file)
2339              {
2340                  if (!($fp = fopen("{$phpbb_root_path}styles/$template_path$pathfile$file", 'r')))
2341                  {
2342                      trigger_error("Could not open {$phpbb_root_path}styles/$template_path$pathfile$file", E_USER_ERROR);
2343                  }
2344                  $template_data = fread($fp, filesize("{$phpbb_root_path}styles/$template_path$pathfile$file"));
2345                  fclose($fp);
2346  
2347                  if (preg_match_all('#<!-- INCLUDE (.*?\.html) -->#is', $template_data, $matches))
2348                  {
2349                      foreach ($matches[1] as $match)
2350                      {
2351                          $includes[trim($match)][] = $file;
2352                      }
2353                  }
2354              }
2355          }
2356  
2357          foreach ($filelist as $pathfile => $file_ary)
2358          {
2359              foreach ($file_ary as $file)
2360              {
2361                  // Skip index.
2362                  if (strpos($file, 'index.') === 0)
2363                  {
2364                      continue;
2365                  }
2366  
2367                  // We could do this using extended inserts ... but that could be one
2368                  // heck of a lot of data ...
2369                  $sql_ary = array(
2370                      'template_id'            => $style_id,
2371                      'template_filename'        => "$pathfile$file",
2372                      'template_included'        => (isset($includes[$file])) ? implode(':', $includes[$file]) . ':' : '',
2373                      'template_mtime'        => filemtime("{$phpbb_root_path}styles/$template_path$pathfile$file"),
2374                      'template_data'            => file_get_contents("{$phpbb_root_path}styles/$template_path$pathfile$file"),
2375                  );
2376  
2377                  if ($mode == 'insert')
2378                  {
2379                      $sql = 'INSERT INTO ' . STYLES_TEMPLATE_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
2380                  }
2381                  else
2382                  {
2383                      $sql = 'UPDATE ' . STYLES_TEMPLATE_DATA_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
2384                          WHERE template_id = $style_id
2385                              AND template_filename = '" . $db->sql_escape("$pathfile$file") . "'";
2386                  }
2387                  $db->sql_query($sql);
2388              }
2389          }
2390      }
2391  
2392      /**
2393      * Returns an array containing all template filenames for one template that are currently cached.
2394      *
2395      * @param string $template_path contains the name of the template's folder in /styles/
2396      *
2397      * @return array of filenames that exist in /styles/$template_path/template/ (without extension!)
2398      */
2399  	function template_cache_filelist($template_path)
2400      {
2401          global $phpbb_root_path, $phpEx, $user;
2402  
2403          $cache_prefix = 'tpl_' . $template_path;
2404  
2405          if (!($dp = @opendir("{$phpbb_root_path}cache")))
2406          {
2407              trigger_error($user->lang['TEMPLATE_ERR_CACHE_READ'] . adm_back_link($this->u_action), E_USER_WARNING);
2408          }
2409  
2410          $file_ary = array();
2411          while ($file = readdir($dp))
2412          {
2413              if (is_file($phpbb_root_path . 'cache/' . $file) && (strpos($file, $cache_prefix) === 0))
2414              {
2415                  $file_ary[] = str_replace('.', '/', preg_replace('#^' . preg_quote($cache_prefix, '#') . '_(.*?)\.html\.' . $phpEx . '$#i', '\1', $file));
2416              }
2417          }
2418          closedir($dp);
2419  
2420          return $file_ary;
2421      }
2422  
2423      /**
2424      * Destroys cached versions of template files
2425      *
2426      * @param array $template_row contains the template's row in the STYLES_TEMPLATE_TABLE database table
2427      * @param mixed $file_ary is optional and may contain an array of template file names which should be refreshed in the cache.
2428      *    The file names should be the original template file names and not the cache file names.
2429      */
2430  	function clear_template_cache($template_row, $file_ary = false)
2431      {
2432          global $phpbb_root_path, $phpEx, $user;
2433  
2434          $cache_prefix = 'tpl_' . $template_row['template_path'];
2435  
2436          if (!$file_ary || !is_array($file_ary))
2437          {
2438              $file_ary = $this->template_cache_filelist($template_row['template_path']);
2439              $log_file_list = $user->lang['ALL_FILES'];
2440          }
2441          else
2442          {
2443              $log_file_list = implode(', ', $file_ary);
2444          }
2445  
2446          foreach ($file_ary as $file)
2447          {
2448              $file = str_replace('/', '.', $file);
2449  
2450              $file = "{$phpbb_root_path}cache/{$cache_prefix}_$file.html.$phpEx";
2451              if (file_exists($file) && is_file($file))
2452              {
2453                  @unlink($file);
2454              }
2455          }
2456          unset($file_ary);
2457  
2458          add_log('admin', 'LOG_TEMPLATE_CACHE_CLEARED', $template_row['template_name'], $log_file_list);
2459      }
2460  
2461      /**
2462      * Install Style/Template/Theme/Imageset
2463      */
2464  	function install($mode)
2465      {
2466          global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template;
2467  
2468          $l_type = strtoupper($mode);
2469  
2470          $error = $installcfg = $style_row = array();
2471          $root_path = $cfg_file = '';
2472          $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE);
2473  
2474          $install_path = request_var('path', '');
2475          $update = (isset($_POST['update'])) ? true : false;
2476  
2477          // Installing, obtain cfg file contents
2478          if ($install_path)
2479          {
2480              $root_path = $phpbb_root_path . 'styles/' . $install_path . '/';
2481              $cfg_file = ($mode == 'style') ? "$root_path$mode.cfg" : "$root_path$mode/$mode.cfg";
2482  
2483              if (!file_exists($cfg_file))
2484              {
2485                  $error[] = $user->lang[$l_type . '_ERR_NOT_' . $l_type];
2486              }
2487              else
2488              {
2489                  $installcfg = parse_cfg_file($cfg_file);
2490              }
2491          }
2492  
2493          // Installing
2494          if (sizeof($installcfg))
2495          {
2496              $name        = $installcfg['name'];
2497              $copyright    = $installcfg['copyright'];
2498              $version    = $installcfg['version'];
2499  
2500              $style_row = array(
2501                  $mode . '_id'            => 0,
2502                  $mode . '_name'            => '',
2503                  $mode . '_copyright'    => ''
2504              );
2505  
2506              switch ($mode)
2507              {
2508                  case 'style':
2509  
2510                      $style_row = array(
2511                          'style_id'            => 0,
2512                          'style_name'        => $installcfg['name'],
2513                          'style_copyright'    => $installcfg['copyright']
2514                      );
2515  
2516                      $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : '';
2517                      $reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : '';
2518                      $reqd_imageset = (isset($installcfg['required_imageset'])) ? $installcfg['required_imageset'] : '';
2519  
2520                      // Check to see if each element is already installed, if it is grab the id
2521                      foreach ($element_ary as $element => $table)
2522                      {
2523                          $style_row = array_merge($style_row, array(
2524                              $element . '_id'            => 0,
2525                              $element . '_name'            => '',
2526                              $element . '_copyright'        => '')
2527                          );
2528  
2529                           $this->test_installed($element, $error, $root_path, ${'reqd_' . $element}, $style_row[$element . '_id'], $style_row[$element . '_name'], $style_row[$element . '_copyright']);
2530                      }
2531  
2532                  break;
2533  
2534                  case 'template':
2535                      $this->test_installed('template', $error, $root_path, false, $style_row['template_id'], $style_row['template_name'], $style_row['template_copyright']);
2536                  break;
2537  
2538                  case 'theme':
2539                      $this->test_installed('theme', $error, $root_path, false, $style_row['theme_id'], $style_row['theme_name'], $style_row['theme_copyright']);
2540                  break;
2541  
2542                  case 'imageset':
2543                      $this->test_installed('imageset', $error, $root_path, false, $style_row['imageset_id'], $style_row['imageset_name'], $style_row['imageset_copyright']);
2544                  break;
2545              }
2546          }
2547          else
2548          {
2549              trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING);
2550          }
2551  
2552          $style_row['store_db'] = request_var('store_db', 0);
2553          $style_row['style_active'] = request_var('style_active', 1);
2554          $style_row['style_default'] = request_var('style_default', 0);
2555  
2556          // User has submitted form and no errors have occured
2557          if ($update && !sizeof($error))
2558          {
2559              if ($mode == 'style')
2560              {
2561                  $this->install_style($error, 'install', $root_path, $style_row['style_id'], $style_row['style_name'], $install_path, $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row);
2562              }
2563              else
2564              {
2565                  $style_row['store_db'] = $this->install_element($mode, $error, 'install', $root_path, $style_row[$mode . '_id'], $style_row[$mode . '_name'], $install_path, $style_row[$mode . '_copyright'], $style_row['store_db']);
2566              }
2567  
2568              if (!sizeof($error))
2569              {
2570                  $cache->destroy('sql', STYLES_TABLE);
2571  
2572                  $message = ($style_row['store_db']) ? '_ADDED_DB' : '_ADDED';
2573                  trigger_error($user->lang[$l_type . $message] . adm_back_link($this->u_action));
2574              }
2575          }
2576  
2577          $this->page_title = 'INSTALL_' . $l_type;
2578  
2579          $template->assign_vars(array(
2580              'S_DETAILS'            => true,
2581              'S_INSTALL'            => true,
2582              'S_ERROR_MSG'        => (sizeof($error)) ? true : false,
2583              'S_STYLE'            => ($mode == 'style') ? true : false,
2584              'S_TEMPLATE'        => ($mode == 'template') ? true : false,
2585              'S_THEME'            => ($mode == 'theme') ? true : false,
2586  
2587              'S_STORE_DB'            => (isset($style_row[$mode . '_storedb'])) ? $style_row[$mode . '_storedb'] : 0,
2588              'S_STYLE_ACTIVE'        => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0,
2589              'S_STYLE_DEFAULT'        => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0,
2590  
2591              'U_ACTION'            => $this->u_action . "&amp;action=install&amp;path=" . urlencode($install_path),
2592              'U_BACK'            => $this->u_action,
2593  
2594              'L_TITLE'                => $user->lang[$this->page_title],
2595              'L_EXPLAIN'                => $user->lang[$this->page_title . '_EXPLAIN'],
2596              'L_NAME'                => $user->lang[$l_type . '_NAME'],
2597              'L_LOCATION'            => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '',
2598              'L_LOCATION_EXPLAIN'    => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '',
2599  
2600              'ERROR_MSG'            => (sizeof($error)) ? implode('<br />', $error) : '',
2601              'NAME'                => $style_row[$mode . '_name'],
2602              'COPYRIGHT'            => $style_row[$mode . '_copyright'],
2603              'TEMPLATE_NAME'        => ($mode == 'style') ? $style_row['template_name'] : '',
2604              'THEME_NAME'        => ($mode == 'style') ? $style_row['theme_name'] : '',
2605              'IMAGESET_NAME'        => ($mode == 'style') ? $style_row['imageset_name'] : '')
2606          );
2607      }
2608  
2609      /**
2610      * Add new style
2611      */
2612  	function add($mode)
2613      {
2614          global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template;
2615  
2616          $l_type = strtoupper($mode);
2617          $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE);
2618          $error = array();
2619  
2620          $style_row = array(
2621              $mode . '_name'            => request_var('name', ''),
2622              $mode . '_copyright'    => request_var('copyright', '', true),
2623              'template_id'            => 0,
2624              'theme_id'                => 0,
2625              'imageset_id'            => 0,
2626              'store_db'                => request_var('store_db', 0),
2627              'style_active'            => request_var('style_active', 1),
2628              'style_default'            => request_var('style_default', 0),
2629          );
2630  
2631          $basis = request_var('basis', 0);
2632          $update = (isset($_POST['update'])) ? true : false;
2633  
2634          if ($basis)
2635          {
2636              switch ($mode)
2637              {
2638                  case 'style':
2639                      $sql_select = 'template_id, theme_id, imageset_id';
2640                      $sql_from = STYLES_TABLE;
2641                  break;
2642  
2643                  case 'template':
2644                      $sql_select = 'template_id';
2645                      $sql_from = STYLES_TEMPLATE_TABLE;
2646                  break;
2647  
2648                  case 'theme':
2649                      $sql_select = 'theme_id';
2650                      $sql_from = STYLES_THEME_TABLE;
2651                  break;
2652  
2653                  case 'imageset':
2654                      $sql_select = 'imageset_id';
2655                      $sql_from = STYLES_IMAGESET_TABLE;
2656                  break;
2657              }
2658  
2659              $sql = "SELECT $sql_select
2660                  FROM $sql_from
2661                  WHERE {$mode}_id = $basis";
2662              $result = $db->sql_query($sql);
2663              $row = $db->sql_fetchrow($result);
2664              $db->sql_freeresult($result);
2665  
2666              if (!$row)
2667              {
2668                  $error[] = $user->lang['NO_' . $l_type];
2669              }
2670  
2671              if (!sizeof($error))
2672              {
2673                  $style_row['template_id']    = (isset($row['template_id'])) ? $row['template_id'] : $style_row['template_id'];
2674                  $style_row['theme_id']        = (isset($row['theme_id'])) ? $row['theme_id'] : $style_row['theme_id'];
2675                  $style_row['imageset_id']    = (isset($row['imageset_id'])) ? $row['imageset_id'] : $style_row['imageset_id'];
2676              }
2677          }
2678  
2679          if ($update)
2680          {
2681              $style_row['template_id'] = request_var('template_id', $style_row['template_id']);
2682              $style_row['theme_id'] = request_var('theme_id', $style_row['theme_id']);
2683              $style_row['imageset_id'] = request_var('imageset_id', $style_row['imageset_id']);
2684  
2685              if ($mode == 'style' && (!$style_row['template_id'] || !$style_row['theme_id'] || !$style_row['imageset_id']))
2686              {
2687                  $error[] = $user->lang['STYLE_ERR_NO_IDS'];
2688              }
2689          }
2690  
2691          // User has submitted form and no errors have occured
2692          if ($update && !sizeof($error))
2693          {
2694              if ($mode == 'style')
2695              {
2696                  $style_row['style_id'] = 0;
2697  
2698                  $this->install_style($error, 'add', '', $style_row['style_id'], $style_row['style_name'], '', $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row);
2699              }
2700  
2701              if (!sizeof($error))
2702              {
2703                  $cache->destroy('sql', STYLES_TABLE);
2704  
2705                  $message = ($style_row['store_db']) ? '_ADDED_DB' : '_ADDED';
2706                  trigger_error($user->lang[$l_type . $message] . adm_back_link($this->u_action));
2707              }
2708          }
2709  
2710          if ($mode == 'style')
2711          {
2712              foreach ($element_ary as $element => $table)
2713              {
2714                  $sql = "SELECT {$element}_id, {$element}_name
2715                      FROM $table
2716                      ORDER BY {$element}_id ASC";
2717                  $result = $db->sql_query($sql);
2718  
2719                  ${$element . '_options'} = '';
2720                  while ($row = $db->sql_fetchrow($result))
2721                  {
2722                      $selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : '';
2723                      ${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>';
2724                  }
2725                  $db->sql_freeresult($result);
2726              }
2727          }
2728  
2729          $this->page_title = 'ADD_' . $l_type;
2730  
2731          $template->assign_vars(array(
2732              'S_DETAILS'            => true,
2733              'S_ADD'                => true,
2734              'S_ERROR_MSG'        => (sizeof($error)) ? true : false,
2735              'S_STYLE'            => ($mode == 'style') ? true : false,
2736              'S_TEMPLATE'        => ($mode == 'template') ? true : false,
2737              'S_THEME'            => ($mode == 'theme') ? true : false,
2738              'S_BASIS'            => ($basis) ? true : false,
2739  
2740              'S_STORE_DB'            => (isset($style_row['storedb'])) ? $style_row['storedb'] : 0,
2741              'S_STYLE_ACTIVE'        => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0,
2742              'S_STYLE_DEFAULT'        => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0,
2743              'S_TEMPLATE_OPTIONS'    => ($mode == 'style') ? $template_options : '',
2744              'S_THEME_OPTIONS'        => ($mode == 'style') ? $theme_options : '',
2745              'S_IMAGESET_OPTIONS'    => ($mode == 'style') ? $imageset_options : '',
2746  
2747              'U_ACTION'            => $this->u_action . '&amp;action=add&amp;basis=' . $basis,
2748              'U_BACK'            => $this->u_action,
2749  
2750              'L_TITLE'                => $user->lang[$this->page_title],
2751              'L_EXPLAIN'                => $user->lang[$this->page_title . '_EXPLAIN'],
2752              'L_NAME'                => $user->lang[$l_type . '_NAME'],
2753              'L_LOCATION'            => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '',
2754              'L_LOCATION_EXPLAIN'    => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '',
2755  
2756              'ERROR_MSG'            => (sizeof($error)) ? implode('<br />', $error) : '',
2757              'NAME'                => $style_row[$mode . '_name'],
2758              'COPYRIGHT'            => $style_row[$mode . '_copyright'])
2759          );
2760  
2761      }
2762  
2763      /**
2764      * Is this element installed? If not, grab its cfg details
2765      */
2766  	function test_installed($element, &$error, $root_path, $reqd_name, &$id, &$name, &$copyright)
2767      {
2768          global $db, $user;
2769  
2770          switch ($element)
2771          {
2772              case 'template':
2773                  $sql_from = STYLES_TEMPLATE_TABLE;
2774              break;
2775  
2776              case 'theme':
2777                  $sql_from = STYLES_THEME_TABLE;
2778              break;
2779  
2780              case 'imageset':
2781                  $sql_from = STYLES_IMAGESET_TABLE;
2782              break;
2783          }
2784  
2785          $l_element = strtoupper($element);
2786  
2787          $chk_name = ($reqd_name !== false) ? $reqd_name : $name;
2788  
2789          $sql = "SELECT {$element}_id, {$element}_name
2790              FROM $sql_from
2791              WHERE {$element}_name = '" . $db->sql_escape($chk_name) . "'";
2792          $result = $db->sql_query($sql);
2793  
2794          if ($row = $db->sql_fetchrow($result))
2795          {
2796              $name = $row[$element . '_name'];
2797              $id = $row[$element . '_id'];
2798          }
2799          else
2800          {
2801              if (!($cfg = @file("$root_path$element/$element.cfg")))
2802              {
2803                  $error[] = sprintf($user->lang['REQUIRES_' . $l_element], $reqd_name);
2804                  return false;
2805              }
2806  
2807              $cfg = parse_cfg_file("$root_path$element/$element.cfg", $cfg);
2808  
2809              $name = $cfg['name'];
2810              $copyright = $cfg['copyright'];
2811              $id = 0;
2812  
2813              unset($cfg);
2814          }
2815          $db->sql_freeresult($result);
2816      }
2817  
2818      /**
2819      * Install/Add style
2820      */
2821  	function install_style(&$error, $action, $root_path, &$id, $name, $path, $copyright, $active, $default, &$style_row)
2822      {
2823          global $config, $db, $user;
2824  
2825          $element_ary = array('template', 'theme', 'imageset');
2826  
2827          if (!$name)
2828          {
2829              $error[] = $user->lang['STYLE_ERR_STYLE_NAME'];
2830          }
2831  
2832          // Check length settings
2833          if (utf8_strlen($name) > 30)
2834          {
2835              $error[] = $user->lang['STYLE_ERR_NAME_LONG'];
2836          }
2837  
2838          if (utf8_strlen($copyright) > 60)
2839          {
2840              $error[] = $user->lang['STYLE_ERR_COPY_LONG'];
2841          }
2842  
2843          // Check if the name already exist
2844          $sql = 'SELECT style_id
2845              FROM ' . STYLES_TABLE . "
2846              WHERE style_name = '" . $db->sql_escape($name) . "'";
2847          $result = $db->sql_query($sql);
2848          $row = $db->sql_fetchrow($result);
2849          $db->sql_freeresult($result);
2850  
2851          if ($row)
2852          {
2853              $error[] = $user->lang['STYLE_ERR_NAME_EXIST'];
2854          }
2855  
2856          if (sizeof($error))
2857          {
2858              return false;
2859          }
2860  
2861          foreach ($element_ary as $element)
2862          {
2863              // Zero id value ... need to install element ... run usual checks
2864              // and do the install if necessary
2865              if (!$style_row[$element . '_id'])
2866              {
2867                  $this->install_element($element, $error, $action, $root_path, $style_row[$element . '_id'], $style_row[$element . '_name'], $path, $style_row[$element . '_copyright']);
2868              }
2869          }
2870  
2871          if (!$style_row['template_id'] || !$style_row['theme_id'] || !$style_row['imageset_id'])
2872          {
2873              $error[] = $user->lang['STYLE_ERR_NO_IDS'];
2874          }
2875  
2876          if (sizeof($error))
2877          {
2878              return false;
2879          }
2880  
2881          $db->sql_transaction('begin');
2882  
2883          $sql_ary = array(
2884              'style_name'        => $name,
2885              'style_copyright'    => $copyright,
2886              'style_active'        => $active,
2887              'template_id'        => $style_row['template_id'],
2888              'theme_id'            => $style_row['theme_id'],
2889              'imageset_id'        => $style_row['imageset_id'],
2890          );
2891  
2892          $sql = 'INSERT INTO ' . STYLES_TABLE . '
2893              ' .  $db->sql_build_array('INSERT', $sql_ary);
2894          $db->sql_query($sql);
2895  
2896          $id = $db->sql_nextid();
2897  
2898          if ($default)
2899          {
2900              $sql = 'UPDATE ' . USERS_TABLE . "
2901                  SET user_style = $id
2902                  WHERE user_style = " . $config['default_style'];
2903              $db->sql_query($sql);
2904  
2905              set_config('default_style', $id);
2906          }
2907  
2908          $db->sql_transaction('commit');
2909  
2910          add_log('admin', 'LOG_STYLE_ADD', $name);
2911      }
2912  
2913      /**
2914      * Install/add an element, doing various checks as we go
2915      */
2916  	function install_element($mode, &$error, $action, $root_path, &$id, $name, $path, $copyright, $store_db = 0)
2917      {
2918          global $phpbb_root_path, $db, $user;
2919  
2920          switch ($mode)
2921          {
2922              case 'template':
2923                  $sql_from = STYLES_TEMPLATE_TABLE;
2924              break;
2925  
2926              case 'theme':
2927                  $sql_from = STYLES_THEME_TABLE;
2928              break;
2929  
2930              case 'imageset':
2931                  $sql_from = STYLES_IMAGESET_TABLE;
2932              break;
2933          }
2934  
2935          $l_type = strtoupper($mode);
2936  
2937          if (!$name)
2938          {
2939              $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME'];
2940          }
2941  
2942          // Check length settings
2943          if (utf8_strlen($name) > 30)
2944          {
2945              $error[] = $user->lang[$l_type . '_ERR_NAME_LONG'];
2946          }
2947  
2948          if (utf8_strlen($copyright) > 60)
2949          {
2950              $error[] = $user->lang[$l_type . '_ERR_COPY_LONG'];
2951          }
2952  
2953          // Check if the name already exist
2954          $sql = "SELECT {$mode}_id
2955              FROM $sql_from
2956              WHERE {$mode}_name = '" . $db->sql_escape($name) . "'";
2957          $result = $db->sql_query($sql);
2958          $row = $db->sql_fetchrow($result);
2959          $db->sql_freeresult($result);
2960  
2961          if ($row)
2962          {
2963              // If it exist, we just use the stlye on installation
2964              if ($action == 'install')
2965              {
2966                  $id = $row[$mode . '_id'];
2967                  return false;
2968              }
2969  
2970              $error[] = $user->lang[$l_type . '_ERR_NAME_EXIST'];
2971          }
2972  
2973          if (sizeof($error))
2974          {
2975              return false;
2976          }
2977  
2978          $sql_ary = array(
2979              $mode . '_name'            => $name,
2980              $mode . '_copyright'    => $copyright,
2981              $mode . '_path'            => $path,
2982          );
2983  
2984          switch ($mode)
2985          {
2986              case 'template':
2987                  // We set a pre-defined bitfield here which we may use further in 3.2
2988                  $sql_ary += array(
2989                      'bbcode_bitfield'    => TEMPLATE_BITFIELD,
2990                      'template_storedb'    => $store_db
2991                  );
2992              break;
2993  
2994              case 'theme':
2995                  // We are only interested in the theme configuration for now
2996                  $theme_cfg = parse_cfg_file("{$phpbb_root_path}styles/$path/theme/theme.cfg");
2997  
2998                  if (isset($theme_cfg['parse_css_file']) && $theme_cfg['parse_css_file'])
2999                  {
3000                      $store_db = 1;
3001                  }
3002  
3003                  $sql_ary += array(
3004                      'theme_storedb'    => $store_db,
3005                      'theme_data'    => ($store_db) ? $this->db_theme_data($sql_ary, false, $root_path) : '',
3006                      'theme_mtime'    => filemtime("{$phpbb_root_path}styles/$path/theme/stylesheet.css")
3007                  );
3008              break;
3009  
3010              case 'imageset':
3011                  $cfg_data = parse_cfg_file("$root_path$mode/imageset.cfg");
3012      
3013                  $imageset_definitions = array();
3014                  foreach ($this->imageset_keys as $topic => $key_array)
3015                  {
3016                      $imageset_definitions = array_merge($imageset_definitions, $key_array);
3017                  }
3018      
3019                  foreach ($cfg_data as $key => $value)
3020                  {
3021                      if (strpos($key, 'img_') === 0)
3022                      {
3023                          $key = substr($key, 4);
3024                          if (in_array($key, $imageset_definitions))
3025                          {
3026                              $sql_ary[$key] = str_replace('{PATH}', "styles/$path/imageset/", trim($value));
3027                          }
3028                      }
3029                  }
3030                  unset($cfg_data);
3031              break;
3032          }
3033  
3034          $db->sql_transaction('begin');
3035  
3036          $sql = "INSERT INTO $sql_from
3037              " . $db->sql_build_array('INSERT', $sql_ary);
3038          $db->sql_query($sql);
3039  
3040          $id = $db->sql_nextid();
3041  
3042          if ($mode == 'template' && $store_db)
3043          {
3044              $filelist = filelist("{$root_path}template", '', 'html');
3045              $this->store_templates('insert', $id, $path, $filelist);
3046          }
3047  
3048          $db->sql_transaction('commit');
3049  
3050          $log = ($store_db) ? 'LOG_' . $l_type . '_ADD_DB' : 'LOG_' . $l_type . '_ADD_FS';
3051          add_log('admin', $log, $name);
3052  
3053          // Return store_db in case it had to be altered
3054          return $store_db;
3055      }
3056  
3057  }
3058  
3059  ?>


Generated: Wed Nov 22 00:35:05 2006 Cross-referenced by PHPXref 0.6