[ Index ] |
PHP Cross Reference of phpBB 3.0 Beta 3 |
[Summary view] [Print] [Text view]
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 . "&action=$option&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 . "&action=$option&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 . '&action=' . (($mode == 'style') ? 'details' : 'edit') . '&id=' . $row[$mode . '_id'], 519 'U_STYLE_ACT_DEACT' => $this->u_action . '&action=' . $stylevis . '&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 . '&action=install&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 . "&action=edit&id=$template_id&text_rows=$text_rows&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 . "&action=edit&id=$template_id&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 . "&action=cache&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>', '', '', '[', ']', '.', ':'); 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('#([^ ;]) ([^ &])#', '$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 . "&action=cache&id=$template_id&source=$file", 897 'UA_VIEWSOURCE' => str_replace('&', '&', $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 . "&action=cache&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 . "&action=edit&id=$theme_id&showcss=$show_css&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 . "&action=edit&id=$theme_id&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 . "&action=edit&id=$theme_id&css_class=$edit_class&showcss=$show_css&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') . '&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 . "&action=edit&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 . "&action=delete&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"' : '') . ' /> ' . $method . ' '; 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 . '&action=export&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 . '&action=details&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 . "&action=install&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 . '&action=add&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 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 22 00:35:05 2006 | Cross-referenced by PHPXref 0.6 |