Guest User

Untitled

a guest
Feb 8th, 2014
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 118.90 KB | None | 0 0
  1. <?php
  2. /**
  3. *
  4. * @package acp
  5. * @version $Id$
  6. * @copyright (c) 2005 phpBB Group
  7. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  8. *
  9. */
  10.  
  11. /**
  12. * @ignore
  13. */
  14. if (!defined('IN_PHPBB'))
  15. {
  16. exit;
  17. }
  18.  
  19. /**
  20. * @package acp
  21. */
  22. class acp_styles
  23. {
  24. var $u_action;
  25.  
  26. var $style_cfg;
  27. var $template_cfg;
  28. var $theme_cfg;
  29. var $imageset_cfg;
  30. var $imageset_keys;
  31.  
  32. function main($id, $mode)
  33. {
  34. global $db, $user, $auth, $template, $cache;
  35. global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
  36.  
  37. // Hardcoded template bitfield to add for new templates
  38. $bitfield = new bitfield();
  39. $bitfield->set(0);
  40. $bitfield->set(1);
  41. $bitfield->set(2);
  42. $bitfield->set(3);
  43. $bitfield->set(4);
  44. $bitfield->set(8);
  45. $bitfield->set(9);
  46. $bitfield->set(11);
  47. $bitfield->set(12);
  48. define('TEMPLATE_BITFIELD', $bitfield->get_base64());
  49. unset($bitfield);
  50.  
  51. $user->add_lang(array('acp/styles', 'mods/im'));
  52.  
  53. $this->tpl_name = 'acp_styles';
  54. $this->page_title = 'ACP_CAT_STYLES';
  55.  
  56. $action = request_var('action', '');
  57. $action = (isset($_POST['add'])) ? 'add' : $action;
  58. $style_id = request_var('id', 0);
  59.  
  60. // Fill the configuration variables
  61. $this->style_cfg = $this->template_cfg = $this->theme_cfg = $this->imageset_cfg = '
  62. #
  63. # phpBB {MODE} configuration file
  64. #
  65. # @package phpBB3
  66. # @copyright (c) 2005 phpBB Group
  67. # @license http://opensource.org/licenses/gpl-license.php GNU Public License
  68. #
  69. #
  70. # At the left is the name, please do not change this
  71. # At the right the value is entered
  72. # For on/off options the valid values are on, off, 1, 0, true and false
  73. #
  74. # Values get trimmed, if you want to add a space in front or at the end of
  75. # the value, then enclose the value with single or double quotes.
  76. # Single and double quotes do not need to be escaped.
  77. #
  78. #
  79.  
  80. # General Information about this {MODE}
  81. name = {NAME}
  82. copyright = {COPYRIGHT}
  83. version = {VERSION}
  84. ';
  85.  
  86. $this->theme_cfg .= '
  87. # Some configuration options
  88.  
  89. #
  90. # You have to turn this option on if you want to use the
  91. # path template variables ({T_IMAGESET_PATH} for example) within
  92. # your css file.
  93. # This is mostly the case if you want to use language specific
  94. # images within your css file.
  95. #
  96. parse_css_file = {PARSE_CSS_FILE}
  97. ';
  98.  
  99. $this->template_cfg .= '
  100. # Some configuration options
  101.  
  102. # Template inheritance
  103. # See http://blog.phpbb.com/2008/07/31/templating-just-got-easier/
  104. # Set value to empty or this template name to ignore template inheritance.
  105. inherit_from = {INHERIT_FROM}
  106. ';
  107.  
  108. $this->imageset_keys = array(
  109. 'logos' => array(
  110. 'site_logo',
  111. ),
  112. 'buttons' => array
  113. 'icon_back_top', 'icon_contact_aim', 'icon_contact_email', 'icon_contact_icq', 'icon_contact_gg', 'icon_contact_tlen', 'icon_contact_skype', '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',
  114. ),
  115. 'icons' => array(
  116. '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',
  117. ),
  118. 'forums' => array(
  119. 'forum_link', 'forum_read', 'forum_read_locked', 'forum_read_subforum', 'forum_unread', 'forum_unread_locked', 'forum_unread_subforum', 'subforum_read', 'subforum_unread'
  120. ),
  121. 'folders' => array(
  122. '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',
  123. ),
  124. 'polls' => array(
  125. 'poll_left', 'poll_center', 'poll_right',
  126. ),
  127. 'ui' => array(
  128. 'upload_bar',
  129. ),
  130. 'user' => array(
  131. 'user_icon1', 'user_icon2', 'user_icon3', 'user_icon4', 'user_icon5', 'user_icon6', 'user_icon7', 'user_icon8', 'user_icon9', 'user_icon10',
  132. ),
  133. );
  134.  
  135. // Execute overall actions
  136. switch ($action)
  137. {
  138. case 'delete':
  139. if ($style_id)
  140. {
  141. $this->remove($mode, $style_id);
  142. return;
  143. }
  144. break;
  145.  
  146. case 'export':
  147. if ($style_id)
  148. {
  149. $this->export($mode, $style_id);
  150. return;
  151. }
  152. break;
  153.  
  154. case 'install':
  155. $this->install($mode);
  156. return;
  157. break;
  158.  
  159. case 'add':
  160. $this->add($mode);
  161. return;
  162. break;
  163.  
  164. case 'details':
  165. if ($style_id)
  166. {
  167. $this->details($mode, $style_id);
  168. return;
  169. }
  170. break;
  171.  
  172. case 'edit':
  173. if ($style_id)
  174. {
  175. switch ($mode)
  176. {
  177. case 'imageset':
  178. return $this->edit_imageset($style_id);
  179. case 'template':
  180. return $this->edit_template($style_id);
  181. case 'theme':
  182. return $this->edit_theme($style_id);
  183. }
  184. }
  185. break;
  186.  
  187. case 'cache':
  188. if ($style_id)
  189. {
  190. switch ($mode)
  191. {
  192. case 'template':
  193. return $this->template_cache($style_id);
  194. }
  195. }
  196. break;
  197. }
  198.  
  199. switch ($mode)
  200. {
  201. case 'style':
  202.  
  203. switch ($action)
  204. {
  205. case 'activate':
  206. case 'deactivate':
  207.  
  208. if ($style_id == $config['default_style'])
  209. {
  210. trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING);
  211. }
  212.  
  213. if (($action == 'deactivate' && confirm_box(true)) || $action == 'activate')
  214. {
  215. $sql = 'UPDATE ' . STYLES_TABLE . '
  216. SET style_active = ' . (($action == 'activate') ? 1 : 0) . '
  217. WHERE style_id = ' . $style_id;
  218. $db->sql_query($sql);
  219.  
  220. // Set style to default for any member using deactivated style
  221. if ($action == 'deactivate')
  222. {
  223. $sql = 'UPDATE ' . USERS_TABLE . '
  224. SET user_style = ' . $config['default_style'] . "
  225. WHERE user_style = $style_id";
  226. $db->sql_query($sql);
  227.  
  228. $sql = 'UPDATE ' . FORUMS_TABLE . '
  229. SET forum_style = 0
  230. WHERE forum_style = ' . $style_id;
  231. $db->sql_query($sql);
  232. }
  233. }
  234. else if ($action == 'deactivate')
  235. {
  236. $s_hidden_fields = array(
  237. 'i' => $id,
  238. 'mode' => $mode,
  239. 'action' => $action,
  240. 'style_id' => $style_id,
  241. );
  242. confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields));
  243. }
  244. break;
  245. }
  246.  
  247. $this->frontend('style', array('details'), array('export', 'delete'));
  248. break;
  249.  
  250. case 'template':
  251.  
  252. switch ($action)
  253. {
  254. // Refresh template data stored in db and clear cache
  255. case 'refresh':
  256.  
  257. $sql = 'SELECT *
  258. FROM ' . STYLES_TEMPLATE_TABLE . "
  259. WHERE template_id = $style_id";
  260. $result = $db->sql_query($sql);
  261. $template_row = $db->sql_fetchrow($result);
  262. $db->sql_freeresult($result);
  263.  
  264. if (!$template_row)
  265. {
  266. trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
  267. }
  268.  
  269. if (confirm_box(true))
  270. {
  271. $template_refreshed = '';
  272.  
  273. // Only refresh database if the template is stored in the database
  274. if ($template_row['template_storedb'] && file_exists("{$phpbb_root_path}styles/{$template_row['template_path']}/template/"))
  275. {
  276. $filelist = array('' => array());
  277.  
  278. $sql = 'SELECT template_filename, template_mtime
  279. FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
  280. WHERE template_id = $style_id";
  281. $result = $db->sql_query($sql);
  282.  
  283. while ($row = $db->sql_fetchrow($result))
  284. {
  285. // if (@filemtime("{$phpbb_root_path}styles/{$template_row['template_path']}/template/" . $row['template_filename']) > $row['template_mtime'])
  286. // {
  287. // get folder info from the filename
  288. if (($slash_pos = strrpos($row['template_filename'], '/')) === false)
  289. {
  290. $filelist[''][] = $row['template_filename'];
  291. }
  292. else
  293. {
  294. $filelist[substr($row['template_filename'], 0, $slash_pos + 1)][] = substr($row['template_filename'], $slash_pos + 1, strlen($row['template_filename']) - $slash_pos - 1);
  295. }
  296. // }
  297. }
  298. $db->sql_freeresult($result);
  299.  
  300. $this->store_templates('update', $style_id, $template_row['template_path'], $filelist);
  301. unset($filelist);
  302.  
  303. $template_refreshed = $user->lang['TEMPLATE_REFRESHED'] . '<br />';
  304. add_log('admin', 'LOG_TEMPLATE_REFRESHED', $template_row['template_name']);
  305. }
  306.  
  307. $this->clear_template_cache($template_row);
  308.  
  309. trigger_error($template_refreshed . $user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action));
  310. }
  311. else
  312. {
  313. confirm_box(false, ($template_row['template_storedb']) ? $user->lang['CONFIRM_TEMPLATE_REFRESH'] : $user->lang['CONFIRM_TEMPLATE_CLEAR_CACHE'], build_hidden_fields(array(
  314. 'i' => $id,
  315. 'mode' => $mode,
  316. 'action' => $action,
  317. 'id' => $style_id
  318. )));
  319. }
  320.  
  321. break;
  322. }
  323.  
  324. $this->frontend('template', array('edit', 'cache', 'details'), array('refresh', 'export', 'delete'));
  325. break;
  326.  
  327. case 'theme':
  328.  
  329. switch ($action)
  330. {
  331. // Refresh theme data stored in the database
  332. case 'refresh':
  333.  
  334. $sql = 'SELECT *
  335. FROM ' . STYLES_THEME_TABLE . "
  336. WHERE theme_id = $style_id";
  337. $result = $db->sql_query($sql);
  338. $theme_row = $db->sql_fetchrow($result);
  339. $db->sql_freeresult($result);
  340.  
  341. if (!$theme_row)
  342. {
  343. trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
  344. }
  345.  
  346. if (!$theme_row['theme_storedb'])
  347. {
  348. trigger_error($user->lang['THEME_ERR_REFRESH_FS'] . adm_back_link($this->u_action), E_USER_WARNING);
  349. }
  350.  
  351. if (confirm_box(true))
  352. {
  353. if ($theme_row['theme_storedb'] && file_exists("{$phpbb_root_path}styles/{$theme_row['theme_path']}/theme/stylesheet.css"))
  354. {
  355. // Save CSS contents
  356. $sql_ary = array(
  357. 'theme_mtime' => (int) filemtime("{$phpbb_root_path}styles/{$theme_row['theme_path']}/theme/stylesheet.css"),
  358. 'theme_data' => $this->db_theme_data($theme_row)
  359. );
  360.  
  361. $sql = 'UPDATE ' . STYLES_THEME_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
  362. WHERE theme_id = $style_id";
  363. $db->sql_query($sql);
  364.  
  365. $cache->destroy('sql', STYLES_THEME_TABLE);
  366.  
  367. add_log('admin', 'LOG_THEME_REFRESHED', $theme_row['theme_name']);
  368. trigger_error($user->lang['THEME_REFRESHED'] . adm_back_link($this->u_action));
  369. }
  370. }
  371. else
  372. {
  373. confirm_box(false, $user->lang['CONFIRM_THEME_REFRESH'], build_hidden_fields(array(
  374. 'i' => $id,
  375. 'mode' => $mode,
  376. 'action' => $action,
  377. 'id' => $style_id
  378. )));
  379. }
  380. break;
  381. }
  382.  
  383. $this->frontend('theme', array('edit', 'details'), array('refresh', 'export', 'delete'));
  384. break;
  385.  
  386. case 'imageset':
  387.  
  388. switch ($action)
  389. {
  390. case 'refresh':
  391.  
  392. $sql = 'SELECT *
  393. FROM ' . STYLES_IMAGESET_TABLE . "
  394. WHERE imageset_id = $style_id";
  395. $result = $db->sql_query($sql);
  396. $imageset_row = $db->sql_fetchrow($result);
  397. $db->sql_freeresult($result);
  398.  
  399. if (!$imageset_row)
  400. {
  401. trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING);
  402. }
  403.  
  404. if (confirm_box(true))
  405. {
  406. $sql_ary = array();
  407.  
  408. $imageset_definitions = array();
  409. foreach ($this->imageset_keys as $topic => $key_array)
  410. {
  411. $imageset_definitions = array_merge($imageset_definitions, $key_array);
  412. }
  413.  
  414. $cfg_data_imageset = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/imageset.cfg");
  415.  
  416. $db->sql_transaction('begin');
  417.  
  418. $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . '
  419. WHERE imageset_id = ' . $style_id;
  420. $result = $db->sql_query($sql);
  421.  
  422. foreach ($cfg_data_imageset as $image_name => $value)
  423. {
  424. if (strpos($value, '*') !== false)
  425. {
  426. if (substr($value, -1, 1) === '*')
  427. {
  428. list($image_filename, $image_height) = explode('*', $value);
  429. $image_width = 0;
  430. }
  431. else
  432. {
  433. list($image_filename, $image_height, $image_width) = explode('*', $value);
  434. }
  435. }
  436. else
  437. {
  438. $image_filename = $value;
  439. $image_height = $image_width = 0;
  440. }
  441.  
  442. if (strpos($image_name, 'img_') === 0 && $image_filename)
  443. {
  444. $image_name = substr($image_name, 4);
  445. if (in_array($image_name, $imageset_definitions))
  446. {
  447. $sql_ary[] = array(
  448. 'image_name' => (string) $image_name,
  449. 'image_filename' => (string) $image_filename,
  450. 'image_height' => (int) $image_height,
  451. 'image_width' => (int) $image_width,
  452. 'imageset_id' => (int) $style_id,
  453. 'image_lang' => '',
  454. );
  455. }
  456. }
  457. }
  458.  
  459. $sql = 'SELECT lang_dir
  460. FROM ' . LANG_TABLE;
  461. $result = $db->sql_query($sql);
  462.  
  463. while ($row = $db->sql_fetchrow($result))
  464. {
  465. if (@file_exists("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$row['lang_dir']}/imageset.cfg"))
  466. {
  467. $cfg_data_imageset_data = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$row['lang_dir']}/imageset.cfg");
  468. foreach ($cfg_data_imageset_data as $image_name => $value)
  469. {
  470. if (strpos($value, '*') !== false)
  471. {
  472. if (substr($value, -1, 1) === '*')
  473. {
  474. list($image_filename, $image_height) = explode('*', $value);
  475. $image_width = 0;
  476. }
  477. else
  478. {
  479. list($image_filename, $image_height, $image_width) = explode('*', $value);
  480. }
  481. }
  482. else
  483. {
  484. $image_filename = $value;
  485. $image_height = $image_width = 0;
  486. }
  487.  
  488. if (strpos($image_name, 'img_') === 0 && $image_filename)
  489. {
  490. $image_name = substr($image_name, 4);
  491. if (in_array($image_name, $imageset_definitions))
  492. {
  493. $sql_ary[] = array(
  494. 'image_name' => (string) $image_name,
  495. 'image_filename' => (string) $image_filename,
  496. 'image_height' => (int) $image_height,
  497. 'image_width' => (int) $image_width,
  498. 'imageset_id' => (int) $style_id,
  499. 'image_lang' => (string) $row['lang_dir'],
  500. );
  501. }
  502. }
  503. }
  504. }
  505. }
  506. $db->sql_freeresult($result);
  507.  
  508. $db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary);
  509.  
  510. $db->sql_transaction('commit');
  511.  
  512. $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE);
  513. $cache->destroy('imageset_site_logo_md5');
  514.  
  515. add_log('admin', 'LOG_IMAGESET_REFRESHED', $imageset_row['imageset_name']);
  516. trigger_error($user->lang['IMAGESET_REFRESHED'] . adm_back_link($this->u_action));
  517. }
  518. else
  519. {
  520. confirm_box(false, $user->lang['CONFIRM_IMAGESET_REFRESH'], build_hidden_fields(array(
  521. 'i' => $id,
  522. 'mode' => $mode,
  523. 'action' => $action,
  524. 'id' => $style_id
  525. )));
  526. }
  527. break;
  528. }
  529.  
  530. $this->frontend('imageset', array('edit', 'details'), array('refresh', 'export', 'delete'));
  531. break;
  532. }
  533. }
  534.  
  535. /**
  536. * Build Frontend with supplied options
  537. */
  538. function frontend($mode, $options, $actions)
  539. {
  540. global $user, $template, $db, $config, $phpbb_root_path, $phpEx;
  541.  
  542. $sql_from = '';
  543. $sql_sort = 'LOWER(' . $mode . '_name)';
  544. $style_count = array();
  545.  
  546. switch ($mode)
  547. {
  548. case 'style':
  549. $sql_from = STYLES_TABLE;
  550. $sql_sort = 'style_active DESC, ' . $sql_sort;
  551.  
  552. $sql = 'SELECT user_style, COUNT(user_style) AS style_count
  553. FROM ' . USERS_TABLE . '
  554. GROUP BY user_style';
  555. $result = $db->sql_query($sql);
  556.  
  557. while ($row = $db->sql_fetchrow($result))
  558. {
  559. $style_count[$row['user_style']] = $row['style_count'];
  560. }
  561. $db->sql_freeresult($result);
  562.  
  563. break;
  564.  
  565. case 'template':
  566. $sql_from = STYLES_TEMPLATE_TABLE;
  567. break;
  568.  
  569. case 'theme':
  570. $sql_from = STYLES_THEME_TABLE;
  571. break;
  572.  
  573. case 'imageset':
  574. $sql_from = STYLES_IMAGESET_TABLE;
  575. break;
  576.  
  577. default:
  578. trigger_error($user->lang['NO_MODE'] . adm_back_link($this->u_action), E_USER_WARNING);
  579. }
  580.  
  581. $l_prefix = strtoupper($mode);
  582.  
  583. $this->page_title = 'ACP_' . $l_prefix . 'S';
  584.  
  585. $template->assign_vars(array(
  586. 'S_FRONTEND' => true,
  587. 'S_STYLE' => ($mode == 'style') ? true : false,
  588.  
  589. 'L_TITLE' => $user->lang[$this->page_title],
  590. 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
  591. 'L_NAME' => $user->lang[$l_prefix . '_NAME'],
  592. 'L_INSTALLED' => $user->lang['INSTALLED_' . $l_prefix],
  593. 'L_UNINSTALLED' => $user->lang['UNINSTALLED_' . $l_prefix],
  594. 'L_NO_UNINSTALLED' => $user->lang['NO_UNINSTALLED_' . $l_prefix],
  595. 'L_CREATE' => $user->lang['CREATE_' . $l_prefix],
  596.  
  597. 'U_ACTION' => $this->u_action,
  598. )
  599. );
  600.  
  601. $sql = "SELECT *
  602. FROM $sql_from
  603. ORDER BY $sql_sort ASC";
  604. $result = $db->sql_query($sql);
  605.  
  606. $installed = array();
  607.  
  608. $basis_options = '<option class="sep" value="">' . $user->lang['OPTIONAL_BASIS'] . '</option>';
  609. while ($row = $db->sql_fetchrow($result))
  610. {
  611. $installed[] = $row[$mode . '_name'];
  612. $basis_options .= '<option value="' . $row[$mode . '_id'] . '">' . $row[$mode . '_name'] . '</option>';
  613.  
  614. $stylevis = ($mode == 'style' && !$row['style_active']) ? 'activate' : 'deactivate';
  615.  
  616. $s_options = array();
  617. foreach ($options as $option)
  618. {
  619. $s_options[] = '<a href="' . $this->u_action . "&amp;action=$option&amp;id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>';
  620. }
  621.  
  622. $s_actions = array();
  623. foreach ($actions as $option)
  624. {
  625. $s_actions[] = '<a href="' . $this->u_action . "&amp;action=$option&amp;id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>';
  626. }
  627.  
  628. $template->assign_block_vars('installed', array(
  629. 'S_DEFAULT_STYLE' => ($mode == 'style' && $row['style_id'] == $config['default_style']) ? true : false,
  630. 'U_EDIT' => $this->u_action . '&amp;action=' . (($mode == 'style') ? 'details' : 'edit') . '&amp;id=' . $row[$mode . '_id'],
  631. 'U_STYLE_ACT_DEACT' => $this->u_action . '&amp;action=' . $stylevis . '&amp;id=' . $row[$mode . '_id'],
  632. 'L_STYLE_ACT_DEACT' => $user->lang['STYLE_' . strtoupper($stylevis)],
  633. 'S_OPTIONS' => implode(' | ', $s_options),
  634. 'S_ACTIONS' => implode(' | ', $s_actions),
  635. 'U_PREVIEW' => ($mode == 'style') ? append_sid("{$phpbb_root_path}index.$phpEx", "$mode=" . $row[$mode . '_id']) : '',
  636.  
  637. 'NAME' => $row[$mode . '_name'],
  638. 'STYLE_COUNT' => ($mode == 'style' && isset($style_count[$row['style_id']])) ? $style_count[$row['style_id']] : 0,
  639.  
  640. 'S_INACTIVE' => ($mode == 'style' && !$row['style_active']) ? true : false,
  641. )
  642. );
  643. }
  644. $db->sql_freeresult($result);
  645.  
  646. // Grab uninstalled items
  647. $new_ary = $cfg = array();
  648.  
  649. $dp = @opendir("{$phpbb_root_path}styles");
  650.  
  651. if ($dp)
  652. {
  653. while (($file = readdir($dp)) !== false)
  654. {
  655. if ($file[0] == '.' || !is_dir($phpbb_root_path . 'styles/' . $file))
  656. {
  657. continue;
  658. }
  659.  
  660. $subpath = ($mode != 'style') ? "$mode/" : '';
  661. if (file_exists("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
  662. {
  663. if ($cfg = file("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
  664. {
  665. $items = parse_cfg_file('', $cfg);
  666. $name = (isset($items['name'])) ? trim($items['name']) : false;
  667.  
  668. if ($name && !in_array($name, $installed))
  669. {
  670. // The array key is used for sorting later on.
  671. // $file is appended because $name doesn't have to be unique.
  672. $new_ary[$name . $file] = array(
  673. 'path' => $file,
  674. 'name' => $name,
  675. 'copyright' => $items['copyright'],
  676. );
  677. }
  678. }
  679. }
  680. }
  681. closedir($dp);
  682. }
  683.  
  684. unset($installed);
  685.  
  686. if (sizeof($new_ary))
  687. {
  688. ksort($new_ary);
  689.  
  690. foreach ($new_ary as $cfg)
  691. {
  692. $template->assign_block_vars('uninstalled', array(
  693. 'NAME' => $cfg['name'],
  694. 'COPYRIGHT' => $cfg['copyright'],
  695. 'U_INSTALL' => $this->u_action . '&amp;action=install&amp;path=' . urlencode($cfg['path']))
  696. );
  697. }
  698. }
  699. unset($new_ary);
  700.  
  701. $template->assign_vars(array(
  702. 'S_BASIS_OPTIONS' => $basis_options)
  703. );
  704.  
  705. }
  706.  
  707. /**
  708. * Provides a template editor which allows saving changes to template files on the filesystem or in the database.
  709. *
  710. * @param int $template_id specifies which template set is being edited
  711. */
  712. function edit_template($template_id)
  713. {
  714. global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode;
  715.  
  716. if (defined('PHPBB_DISABLE_ACP_EDITOR'))
  717. {
  718. trigger_error($user->lang['EDITOR_DISABLED'] . adm_back_link($this->u_action));
  719. }
  720.  
  721. $this->page_title = 'EDIT_TEMPLATE';
  722.  
  723. $filelist = $filelist_cats = array();
  724.  
  725. $template_data = utf8_normalize_nfc(request_var('template_data', '', true));
  726. $template_data = htmlspecialchars_decode($template_data);
  727. $template_file = utf8_normalize_nfc(request_var('template_file', '', true));
  728. $text_rows = max(5, min(999, request_var('text_rows', 20)));
  729. $save_changes = (isset($_POST['save'])) ? true : false;
  730.  
  731. // make sure template_file path doesn't go upwards
  732. $template_file = preg_replace('#\.{2,}#', '.', $template_file);
  733.  
  734. // Retrieve some information about the template
  735. $sql = 'SELECT template_storedb, template_path, template_name
  736. FROM ' . STYLES_TEMPLATE_TABLE . "
  737. WHERE template_id = $template_id";
  738. $result = $db->sql_query($sql);
  739. $template_info = $db->sql_fetchrow($result);
  740. $db->sql_freeresult($result);
  741.  
  742. if (!$template_info)
  743. {
  744. trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
  745. }
  746.  
  747. if ($save_changes && !check_form_key('acp_styles'))
  748. {
  749. trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
  750. }
  751. else if (!$save_changes)
  752. {
  753. add_form_key('acp_styles');
  754. }
  755.  
  756. // save changes to the template if the user submitted any
  757. if ($save_changes && $template_file)
  758. {
  759. // Get the filesystem location of the current file
  760. $file = "{$phpbb_root_path}styles/{$template_info['template_path']}/template/$template_file";
  761. $additional = '';
  762.  
  763. // If the template is stored on the filesystem try to write the file else store it in the database
  764. if (!$safe_mode && !$template_info['template_storedb'] && file_exists($file) && phpbb_is_writable($file))
  765. {
  766. if (!($fp = @fopen($file, 'wb')))
  767. {
  768. // File exists and is writeable, but still not able to be written to
  769. trigger_error(sprintf($user->lang['TEMPLATE_FILE_NOT_WRITABLE'], htmlspecialchars($template_file)) . adm_back_link($this->u_action), E_USER_WARNING);
  770. }
  771. fwrite($fp, $template_data);
  772. fclose($fp);
  773. }
  774. else
  775. {
  776. $db->sql_transaction('begin');
  777.  
  778. // If it's not stored in the db yet, then update the template setting and store all template files in the db
  779. if (!$template_info['template_storedb'])
  780. {
  781. if ($super = $this->get_super('template', $template_id))
  782. {
  783. $this->store_in_db('template', $super['template_id']);
  784. }
  785. else
  786. {
  787. $this->store_in_db('template', $template_id);
  788. }
  789.  
  790. add_log('admin', 'LOG_TEMPLATE_EDIT_DETAILS', $template_info['template_name']);
  791. $additional .= '<br />' . $user->lang['EDIT_TEMPLATE_STORED_DB'];
  792. }
  793.  
  794. // Update the template_data table entry for this template file
  795. $sql = 'UPDATE ' . STYLES_TEMPLATE_DATA_TABLE . "
  796. SET template_data = '" . $db->sql_escape($template_data) . "', template_mtime = " . time() . "
  797. WHERE template_id = $template_id
  798. AND template_filename = '" . $db->sql_escape($template_file) . "'";
  799. $db->sql_query($sql);
  800.  
  801. $db->sql_transaction('commit');
  802. }
  803.  
  804. // destroy the cached version of the template (filename without extension)
  805. $this->clear_template_cache($template_info, array(substr($template_file, 0, -5)));
  806.  
  807. $cache->destroy('sql', STYLES_TABLE);
  808.  
  809. add_log('admin', 'LOG_TEMPLATE_EDIT', $template_info['template_name'], $template_file);
  810. trigger_error($user->lang['TEMPLATE_FILE_UPDATED'] . $additional . adm_back_link($this->u_action . "&amp;action=edit&amp;id=$template_id&amp;text_rows=$text_rows&amp;template_file=$template_file"));
  811. }
  812.  
  813. // Generate a category array containing template filenames
  814. if (!$template_info['template_storedb'])
  815. {
  816. $template_path = "{$phpbb_root_path}styles/{$template_info['template_path']}/template";
  817.  
  818. $filelist = filelist($template_path, '', 'html');
  819. $filelist[''] = array_diff($filelist[''], array('bbcode.html'));
  820.  
  821. if ($template_file)
  822. {
  823. if (!file_exists($template_path . "/$template_file") || !($template_data = file_get_contents($template_path . "/$template_file")))
  824. {
  825. trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
  826. }
  827. }
  828. }
  829. else
  830. {
  831. $sql = 'SELECT *
  832. FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
  833. WHERE template_id = $template_id";
  834. $result = $db->sql_query($sql);
  835.  
  836. $filelist = array('' => array());
  837. while ($row = $db->sql_fetchrow($result))
  838. {
  839. $file_info = pathinfo($row['template_filename']);
  840.  
  841. if (($file_info['basename'] != 'bbcode') && ($file_info['extension'] == 'html'))
  842. {
  843. if (($file_info['dirname'] == '.') || empty($file_info['dirname']))
  844. {
  845. $filelist[''][] = $row['template_filename'];
  846. }
  847. else
  848. {
  849. $filelist[$file_info['dirname'] . '/'][] = $file_info['basename'];
  850. }
  851. }
  852.  
  853. if ($row['template_filename'] == $template_file)
  854. {
  855. $template_data = $row['template_data'];
  856. }
  857. }
  858. $db->sql_freeresult($result);
  859. unset($file_info);
  860. }
  861.  
  862. if (empty($filelist['']))
  863. {
  864. trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
  865. }
  866.  
  867. // Now create the categories
  868. $filelist_cats[''] = array();
  869. foreach ($filelist as $pathfile => $file_ary)
  870. {
  871. // Use the directory name as category name
  872. if (!empty($pathfile))
  873. {
  874. $filelist_cats[$pathfile] = array();
  875. foreach ($file_ary as $file)
  876. {
  877. $filelist_cats[$pathfile][$pathfile . $file] = $file;
  878. }
  879. }
  880. // or if it's in the main category use the word before the first underscore to group files
  881. else
  882. {
  883. $cats = array();
  884. foreach ($file_ary as $file)
  885. {
  886. $cats[] = substr($file, 0, strpos($file, '_'));
  887. $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file;
  888. }
  889.  
  890. $cats = array_values(array_unique($cats));
  891.  
  892. // we don't need any single element categories so put them into the misc '' category
  893. for ($i = 0, $n = sizeof($cats); $i < $n; $i++)
  894. {
  895. if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '')
  896. {
  897. $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]);
  898. unset($filelist_cats[$cats[$i]]);
  899. }
  900. }
  901. unset($cats);
  902. }
  903. }
  904. unset($filelist);
  905.  
  906. // Generate list of categorised template files
  907. $tpl_options = '';
  908. ksort($filelist_cats);
  909. foreach ($filelist_cats as $category => $tpl_ary)
  910. {
  911. ksort($tpl_ary);
  912.  
  913. if (!empty($category))
  914. {
  915. $tpl_options .= '<option class="sep" value="">' . $category . '</option>';
  916. }
  917.  
  918. foreach ($tpl_ary as $filename => $file)
  919. {
  920. $selected = ($template_file == $filename) ? ' selected="selected"' : '';
  921. $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>';
  922. }
  923. }
  924.  
  925. $template->assign_vars(array(
  926. 'S_EDIT_TEMPLATE' => true,
  927. 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $template_file)),
  928. 'S_TEMPLATES' => $tpl_options,
  929.  
  930. 'U_ACTION' => $this->u_action . "&amp;action=edit&amp;id=$template_id&amp;text_rows=$text_rows",
  931. 'U_BACK' => $this->u_action,
  932.  
  933. 'L_EDIT' => $user->lang['EDIT_TEMPLATE'],
  934. 'L_EDIT_EXPLAIN' => $user->lang['EDIT_TEMPLATE_EXPLAIN'],
  935. 'L_EDITOR' => $user->lang['TEMPLATE_EDITOR'],
  936. 'L_EDITOR_HEIGHT' => $user->lang['TEMPLATE_EDITOR_HEIGHT'],
  937. 'L_FILE' => $user->lang['TEMPLATE_FILE'],
  938. 'L_SELECT' => $user->lang['SELECT_TEMPLATE'],
  939. 'L_SELECTED' => $user->lang['SELECTED_TEMPLATE'],
  940. 'L_SELECTED_FILE' => $user->lang['SELECTED_TEMPLATE_FILE'],
  941.  
  942. 'SELECTED_TEMPLATE' => $template_info['template_name'],
  943. 'TEMPLATE_FILE' => $template_file,
  944. 'TEMPLATE_DATA' => utf8_htmlspecialchars($template_data),
  945. 'TEXT_ROWS' => $text_rows)
  946. );
  947. }
  948.  
  949. /**
  950. * Allows the admin to view cached versions of template files and clear single template cache files
  951. *
  952. * @param int $template_id specifies which template's cache is shown
  953. */
  954. function template_cache($template_id)
  955. {
  956. global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template;
  957.  
  958. $source = str_replace('/', '.', request_var('source', ''));
  959. $file_ary = array_diff(request_var('delete', array('')), array(''));
  960. $submit = isset($_POST['submit']) ? true : false;
  961.  
  962. $sql = 'SELECT *
  963. FROM ' . STYLES_TEMPLATE_TABLE . "
  964. WHERE template_id = $template_id";
  965. $result = $db->sql_query($sql);
  966. $template_row = $db->sql_fetchrow($result);
  967. $db->sql_freeresult($result);
  968.  
  969. if (!$template_row)
  970. {
  971. trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
  972. }
  973.  
  974. // User wants to delete one or more files ...
  975. if ($submit && $file_ary)
  976. {
  977. $this->clear_template_cache($template_row, $file_ary);
  978. trigger_error($user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action . "&amp;action=cache&amp;id=$template_id"));
  979. }
  980.  
  981. $cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']);
  982.  
  983. // Someone wants to see the cached source ... so we'll highlight it,
  984. // add line numbers and indent it appropriately. This could be nasty
  985. // on larger source files ...
  986. if ($source && file_exists("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx"))
  987. {
  988. adm_page_header($user->lang['TEMPLATE_CACHE']);
  989.  
  990. $template->set_filenames(array(
  991. 'body' => 'viewsource.html')
  992. );
  993.  
  994. $template->assign_vars(array(
  995. 'FILENAME' => str_replace('.', '/', $source) . '.html')
  996. );
  997.  
  998. $code = str_replace(array("\r\n", "\r"), array("\n", "\n"), file_get_contents("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx"));
  999.  
  1000. $conf = array('highlight.bg', 'highlight.comment', 'highlight.default', 'highlight.html', 'highlight.keyword', 'highlight.string');
  1001. foreach ($conf as $ini_var)
  1002. {
  1003. @ini_set($ini_var, str_replace('highlight.', 'syntax', $ini_var));
  1004. }
  1005.  
  1006. $marker = 'MARKER' . time();
  1007. $code = highlight_string(str_replace("\n", $marker, $code), true);
  1008. $code = str_replace($marker, "\n", $code);
  1009. $str_from = array('<span style="color: ', '<font color="syntax', '</font>', '<code>', '</code>','[', ']', '.', ':');
  1010. $str_to = array('<span class="', '<span class="syntax', '</span>', '', '', '&#91;', '&#93;', '&#46;', '&#58;');
  1011.  
  1012. $code = str_replace($str_from, $str_to, $code);
  1013. $code = preg_replace('#^(<span class="[a-z_]+">)\n?(.*?)\n?(</span>)$#ism', '$1$2$3', $code);
  1014. $code = substr($code, strlen('<span class="syntaxhtml">'));
  1015. $code = substr($code, 0, -1 * strlen('</ span>'));
  1016. $code = explode("\n", $code);
  1017.  
  1018. foreach ($code as $key => $line)
  1019. {
  1020. $template->assign_block_vars('source', array(
  1021. 'LINENUM' => $key + 1,
  1022. 'LINE' => preg_replace('#([^ ;])&nbsp;([^ &])#', '$1 $2', $line))
  1023. );
  1024. unset($code[$key]);
  1025. }
  1026.  
  1027. adm_page_footer();
  1028. }
  1029.  
  1030. $filemtime = array();
  1031. if ($template_row['template_storedb'])
  1032. {
  1033. $ids = array();
  1034. if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id'])
  1035. {
  1036. $ids[] = $template_row['template_inherits_id'];
  1037. }
  1038. $ids[] = $template_row['template_id'];
  1039.  
  1040. $filemtime = array();
  1041. $file_template_db = array();
  1042.  
  1043. foreach ($ids as $id)
  1044. {
  1045. $sql = 'SELECT template_filename, template_mtime
  1046. FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
  1047. WHERE template_id = $id";
  1048. $result = $db->sql_query($sql);
  1049.  
  1050. while ($row = $db->sql_fetchrow($result))
  1051. {
  1052. $filemtime[$row['template_filename']] = $row['template_mtime'];
  1053. $file_template_db[$row['template_filename']] = $id;
  1054. }
  1055. $db->sql_freeresult($result);
  1056. }
  1057. }
  1058.  
  1059. // Get a list of cached template files and then retrieve additional information about them
  1060. $file_ary = $this->template_cache_filelist($template_row['template_path']);
  1061.  
  1062. foreach ($file_ary as $file)
  1063. {
  1064. $file = str_replace('/', '.', $file);
  1065.  
  1066. // perform some dirty guessing to get the path right.
  1067. // We assume that three dots in a row were '../'
  1068. $tpl_file = str_replace('.', '/', $file);
  1069. $tpl_file = str_replace('///', '../', $tpl_file);
  1070.  
  1071. $filename = "{$cache_prefix}_$file.html.$phpEx";
  1072.  
  1073. if (!file_exists("{$phpbb_root_path}cache/$filename"))
  1074. {
  1075. continue;
  1076. }
  1077.  
  1078. $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_path']}/template/$tpl_file.html";
  1079. $inherited = false;
  1080.  
  1081. if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id'])
  1082. {
  1083. if (!$template_row['template_storedb'])
  1084. {
  1085. if (!file_exists($file_tpl))
  1086. {
  1087. $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html";
  1088. $inherited = true;
  1089. }
  1090. }
  1091. else
  1092. {
  1093. if ($file_template_db[$file . '.html'] == $template_row['template_inherits_id'])
  1094. {
  1095. $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html";
  1096. $inherited = true;
  1097. }
  1098. }
  1099. }
  1100.  
  1101. // Correct the filename if it is stored in database and the file is in a subfolder.
  1102. if ($template_row['template_storedb'])
  1103. {
  1104. $file = str_replace('.', '/', $file);
  1105. }
  1106.  
  1107. $template->assign_block_vars('file', array(
  1108. 'U_VIEWSOURCE' => $this->u_action . "&amp;action=cache&amp;id=$template_id&amp;source=$file",
  1109.  
  1110. 'CACHED' => $user->format_date(filemtime("{$phpbb_root_path}cache/$filename")),
  1111. 'FILENAME' => $file,
  1112. 'FILENAME_PATH' => $file_tpl,
  1113. 'FILESIZE' => get_formatted_filesize(filesize("{$phpbb_root_path}cache/$filename")),
  1114. 'MODIFIED' => $user->format_date((!$template_row['template_storedb']) ? filemtime($file_tpl) : $filemtime[$file . '.html']))
  1115. );
  1116. }
  1117. unset($filemtime);
  1118.  
  1119. $template->assign_vars(array(
  1120. 'S_CACHE' => true,
  1121. 'S_TEMPLATE' => true,
  1122.  
  1123. 'U_ACTION' => $this->u_action . "&amp;action=cache&amp;id=$template_id",
  1124. 'U_BACK' => $this->u_action)
  1125. );
  1126. }
  1127.  
  1128. /**
  1129. * Provides a css editor and a basic easier to use stylesheet editing tool for less experienced (or lazy) users
  1130. *
  1131. * @param int $theme_id specifies which theme is being edited
  1132. */
  1133. function edit_theme($theme_id)
  1134. {
  1135. global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode;
  1136.  
  1137. $this->page_title = 'EDIT_THEME';
  1138.  
  1139. $filelist = $filelist_cats = array();
  1140.  
  1141. $theme_data = utf8_normalize_nfc(request_var('template_data', '', true));
  1142. $theme_data = htmlspecialchars_decode($theme_data);
  1143. $theme_file = utf8_normalize_nfc(request_var('template_file', '', true));
  1144. $text_rows = max(5, min(999, request_var('text_rows', 20)));
  1145. $save_changes = (isset($_POST['save'])) ? true : false;
  1146.  
  1147. // make sure theme_file path doesn't go upwards
  1148. $theme_file = str_replace('..', '.', $theme_file);
  1149.  
  1150. // Retrieve some information about the theme
  1151. $sql = 'SELECT theme_storedb, theme_path, theme_name, theme_data
  1152. FROM ' . STYLES_THEME_TABLE . "
  1153. WHERE theme_id = $theme_id";
  1154. $result = $db->sql_query($sql);
  1155.  
  1156. if (!($theme_info = $db->sql_fetchrow($result)))
  1157. {
  1158. trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
  1159. }
  1160. $db->sql_freeresult($result);
  1161.  
  1162. // save changes to the theme if the user submitted any
  1163. if ($save_changes)
  1164. {
  1165. // Get the filesystem location of the current file
  1166. $file = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme/$theme_file";
  1167. $additional = '';
  1168. $message = $user->lang['THEME_UPDATED'];
  1169.  
  1170. // If the theme is stored on the filesystem try to write the file else store it in the database
  1171. if (!$safe_mode && !$theme_info['theme_storedb'] && file_exists($file) && phpbb_is_writable($file))
  1172. {
  1173. if (!($fp = @fopen($file, 'wb')))
  1174. {
  1175. trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
  1176. }
  1177. fwrite($fp, $theme_data);
  1178. fclose($fp);
  1179. }
  1180. else
  1181. {
  1182. // Write stylesheet to db
  1183. $sql_ary = array(
  1184. 'theme_mtime' => time(),
  1185. 'theme_storedb' => 1,
  1186. 'theme_data' => $this->db_theme_data($theme_info, $theme_data),
  1187. );
  1188. $sql = 'UPDATE ' . STYLES_THEME_TABLE . '
  1189. SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
  1190. WHERE theme_id = ' . $theme_id;
  1191. $db->sql_query($sql);
  1192.  
  1193. $cache->destroy('sql', STYLES_THEME_TABLE);
  1194.  
  1195. // notify the user if the theme was not stored in the db before his modification
  1196. if (!$theme_info['theme_storedb'])
  1197. {
  1198. add_log('admin', 'LOG_THEME_EDIT_DETAILS', $theme_info['theme_name']);
  1199. $message .= '<br />' . $user->lang['EDIT_THEME_STORED_DB'];
  1200. }
  1201. }
  1202. $cache->destroy('sql', STYLES_THEME_TABLE);
  1203. add_log('admin', (!$theme_info['theme_storedb']) ? 'LOG_THEME_EDIT_FILE' : 'LOG_THEME_EDIT', $theme_info['theme_name'], (!$theme_info['theme_storedb']) ? $theme_file : '');
  1204.  
  1205. trigger_error($message . adm_back_link($this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;template_file=$theme_file&amp;text_rows=$text_rows"));
  1206. }
  1207.  
  1208. // Generate a category array containing theme filenames
  1209. if (!$theme_info['theme_storedb'])
  1210. {
  1211. $theme_path = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme";
  1212.  
  1213. $filelist = filelist($theme_path, '', 'css');
  1214.  
  1215. if ($theme_file)
  1216. {
  1217. if (!file_exists($theme_path . "/$theme_file") || !($theme_data = file_get_contents($theme_path . "/$theme_file")))
  1218. {
  1219. trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
  1220. }
  1221. }
  1222. }
  1223. else
  1224. {
  1225. $theme_data = &$theme_info['theme_data'];
  1226. }
  1227.  
  1228. // Now create the categories
  1229. $filelist_cats[''] = array();
  1230. foreach ($filelist as $pathfile => $file_ary)
  1231. {
  1232. // Use the directory name as category name
  1233. if (!empty($pathfile))
  1234. {
  1235. $filelist_cats[$pathfile] = array();
  1236. foreach ($file_ary as $file)
  1237. {
  1238. $filelist_cats[$pathfile][$pathfile . $file] = $file;
  1239. }
  1240. }
  1241. // or if it's in the main category use the word before the first underscore to group files
  1242. else
  1243. {
  1244. $cats = array();
  1245. foreach ($file_ary as $file)
  1246. {
  1247. $cats[] = substr($file, 0, strpos($file, '_'));
  1248. $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file;
  1249. }
  1250.  
  1251. $cats = array_values(array_unique($cats));
  1252.  
  1253. // we don't need any single element categories so put them into the misc '' category
  1254. for ($i = 0, $n = sizeof($cats); $i < $n; $i++)
  1255. {
  1256. if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '')
  1257. {
  1258. $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]);
  1259. unset($filelist_cats[$cats[$i]]);
  1260. }
  1261. }
  1262. unset($cats);
  1263. }
  1264. }
  1265. unset($filelist);
  1266.  
  1267. // Generate list of categorised theme files
  1268. $tpl_options = '';
  1269. ksort($filelist_cats);
  1270. foreach ($filelist_cats as $category => $tpl_ary)
  1271. {
  1272. ksort($tpl_ary);
  1273.  
  1274. if (!empty($category))
  1275. {
  1276. $tpl_options .= '<option class="sep" value="">' . $category . '</option>';
  1277. }
  1278.  
  1279. foreach ($tpl_ary as $filename => $file)
  1280. {
  1281. $selected = ($theme_file == $filename) ? ' selected="selected"' : '';
  1282. $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>';
  1283. }
  1284. }
  1285.  
  1286. $template->assign_vars(array(
  1287. 'S_EDIT_THEME' => true,
  1288. 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $theme_file)),
  1289. 'S_THEME_IN_DB' => $theme_info['theme_storedb'],
  1290. 'S_TEMPLATES' => $tpl_options,
  1291.  
  1292. 'U_ACTION' => $this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;text_rows=$text_rows",
  1293. 'U_BACK' => $this->u_action,
  1294.  
  1295. 'L_EDIT' => $user->lang['EDIT_THEME'],
  1296. 'L_EDIT_EXPLAIN' => $user->lang['EDIT_THEME_EXPLAIN'],
  1297. 'L_EDITOR' => $user->lang['THEME_EDITOR'],
  1298. 'L_EDITOR_HEIGHT' => $user->lang['THEME_EDITOR_HEIGHT'],
  1299. 'L_FILE' => $user->lang['THEME_FILE'],
  1300. 'L_SELECT' => $user->lang['SELECT_THEME'],
  1301. 'L_SELECTED' => $user->lang['SELECTED_THEME'],
  1302. 'L_SELECTED_FILE' => $user->lang['SELECTED_THEME_FILE'],
  1303.  
  1304. 'SELECTED_TEMPLATE' => $theme_info['theme_name'],
  1305. 'TEMPLATE_FILE' => $theme_file,
  1306. 'TEMPLATE_DATA' => utf8_htmlspecialchars($theme_data),
  1307. 'TEXT_ROWS' => $text_rows)
  1308. );
  1309. }
  1310.  
  1311. /**
  1312. * Edit imagesets
  1313. *
  1314. * @param int $imageset_id specifies which imageset is being edited
  1315. */
  1316. function edit_imageset($imageset_id)
  1317. {
  1318. global $db, $user, $phpbb_root_path, $cache, $template;
  1319.  
  1320. $this->page_title = 'EDIT_IMAGESET';
  1321.  
  1322. if (!$imageset_id)
  1323. {
  1324. trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING);
  1325. }
  1326.  
  1327. $update = (isset($_POST['update'])) ? true : false;
  1328.  
  1329. $imgname = request_var('imgname', 'site_logo');
  1330. $imgname = preg_replace('#[^a-z0-9\-+_]#i', '', $imgname);
  1331. $sql_extra = $imgnamelang = '';
  1332.  
  1333. $sql = 'SELECT imageset_path, imageset_name
  1334. FROM ' . STYLES_IMAGESET_TABLE . "
  1335. WHERE imageset_id = $imageset_id";
  1336. $result = $db->sql_query($sql);
  1337. $imageset_row = $db->sql_fetchrow($result);
  1338. $db->sql_freeresult($result);
  1339.  
  1340. if (!$imageset_row)
  1341. {
  1342. trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING);
  1343. }
  1344.  
  1345. $imageset_path = $imageset_row['imageset_path'];
  1346. $imageset_name = $imageset_row['imageset_name'];
  1347.  
  1348. if (strpos($imgname, '-') !== false)
  1349. {
  1350. list($imgname, $imgnamelang) = explode('-', $imgname);
  1351. $sql_extra = " AND image_lang IN ('" . $db->sql_escape($imgnamelang) . "', '')";
  1352. }
  1353.  
  1354. $sql = 'SELECT image_filename, image_width, image_height, image_lang, image_id
  1355. FROM ' . STYLES_IMAGESET_DATA_TABLE . "
  1356. WHERE imageset_id = $imageset_id
  1357. AND image_name = '" . $db->sql_escape($imgname) . "'$sql_extra";
  1358. $result = $db->sql_query($sql);
  1359. $imageset_data_row = $db->sql_fetchrow($result);
  1360. $db->sql_freeresult($result);
  1361.  
  1362. $image_filename = $imageset_data_row['image_filename'];
  1363. $image_width = $imageset_data_row['image_width'];
  1364. $image_height = $imageset_data_row['image_height'];
  1365. $image_lang = $imageset_data_row['image_lang'];
  1366. $image_id = $imageset_data_row['image_id'];
  1367. $imgsize = ($imageset_data_row['image_width'] && $imageset_data_row['image_height']) ? 1 : 0;
  1368.  
  1369. // Check to see whether the selected image exists in the table
  1370. $valid_name = ($update) ? false : true;
  1371.  
  1372. foreach ($this->imageset_keys as $category => $img_ary)
  1373. {
  1374. if (in_array($imgname, $img_ary))
  1375. {
  1376. $valid_name = true;
  1377. break;
  1378. }
  1379. }
  1380.  
  1381. if ($update && isset($_POST['imgpath']) && $valid_name)
  1382. {
  1383. // If imgwidth and imgheight are non-zero grab the actual size
  1384. // from the image itself ... we ignore width settings for the poll center image
  1385. $imgwidth = request_var('imgwidth', 0);
  1386. $imgheight = request_var('imgheight', 0);
  1387. $imgsize = request_var('imgsize', 0);
  1388. $imgpath = request_var('imgpath', '');
  1389. $imgpath = str_replace('..', '.', $imgpath);
  1390.  
  1391. // If no dimensions selected, we reset width and height to 0 ;)
  1392. if (!$imgsize)
  1393. {
  1394. $imgwidth = $imgheight = 0;
  1395. }
  1396.  
  1397. $imglang = '';
  1398.  
  1399. if ($imgpath && !file_exists("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath"))
  1400. {
  1401. trigger_error($user->lang['NO_IMAGE_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING);
  1402. }
  1403.  
  1404. // Determine width/height. If dimensions included and no width/height given, we detect them automatically...
  1405. if ($imgsize && $imgpath)
  1406. {
  1407. if (!$imgwidth || !$imgheight)
  1408. {
  1409. list($imgwidth_file, $imgheight_file) = getimagesize("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath");
  1410. $imgwidth = ($imgwidth) ? $imgwidth : $imgwidth_file;
  1411. $imgheight = ($imgheight) ? $imgheight : $imgheight_file;
  1412. }
  1413. $imgwidth = ($imgname != 'poll_center') ? (int) $imgwidth : 0;
  1414. $imgheight = (int) $imgheight;
  1415. }
  1416.  
  1417. if (strpos($imgpath, '/') !== false)
  1418. {
  1419. list($imglang, $imgfilename) = explode('/', $imgpath);
  1420. }
  1421. else
  1422. {
  1423. $imgfilename = $imgpath;
  1424. }
  1425.  
  1426. $sql_ary = array(
  1427. 'image_filename' => (string) $imgfilename,
  1428. 'image_width' => (int) $imgwidth,
  1429. 'image_height' => (int) $imgheight,
  1430. 'image_lang' => (string) $imglang,
  1431. );
  1432.  
  1433. // already exists
  1434. if ($imageset_data_row)
  1435. {
  1436. $sql = 'UPDATE ' . STYLES_IMAGESET_DATA_TABLE . '
  1437. SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
  1438. WHERE image_id = $image_id";
  1439. $db->sql_query($sql);
  1440. }
  1441. // does not exist
  1442. else if (!$imageset_data_row)
  1443. {
  1444. $sql_ary['image_name'] = $imgname;
  1445. $sql_ary['imageset_id'] = (int) $imageset_id;
  1446. $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
  1447. }
  1448.  
  1449. $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE);
  1450.  
  1451. add_log('admin', 'LOG_IMAGESET_EDIT', $imageset_name);
  1452.  
  1453. $template->assign_var('SUCCESS', true);
  1454.  
  1455. $image_filename = $imgfilename;
  1456. $image_width = $imgwidth;
  1457. $image_height = $imgheight;
  1458. $image_lang = $imglang;
  1459. }
  1460.  
  1461. $imglang = '';
  1462. $imagesetlist = array('nolang' => array(), 'lang' => array());
  1463. $langs = array();
  1464.  
  1465. $dir = "{$phpbb_root_path}styles/$imageset_path/imageset";
  1466. $dp = @opendir($dir);
  1467.  
  1468. if ($dp)
  1469. {
  1470. while (($file = readdir($dp)) !== false)
  1471. {
  1472. if ($file[0] != '.' && strtoupper($file) != 'CVS' && !is_file($dir . '/' . $file) && !is_link($dir . '/' . $file))
  1473. {
  1474. $langs[] = $file;
  1475. }
  1476. else if (preg_match('#\.(?:gif|jpg|png)$#', $file))
  1477. {
  1478. $imagesetlist['nolang'][] = $file;
  1479. }
  1480. }
  1481.  
  1482. if ($sql_extra)
  1483. {
  1484. $dp2 = @opendir("$dir/$imgnamelang");
  1485.  
  1486. if ($dp2)
  1487. {
  1488. while (($file2 = readdir($dp2)) !== false)
  1489. {
  1490. if (preg_match('#\.(?:gif|jpg|png)$#', $file2))
  1491. {
  1492. $imagesetlist['lang'][] = "$imgnamelang/$file2";
  1493. }
  1494. }
  1495. closedir($dp2);
  1496. }
  1497. }
  1498. closedir($dp);
  1499. }
  1500.  
  1501. // Generate list of image options
  1502. $img_options = '';
  1503. foreach ($this->imageset_keys as $category => $img_ary)
  1504. {
  1505. $template->assign_block_vars('category', array(
  1506. 'NAME' => $user->lang['IMG_CAT_' . strtoupper($category)]
  1507. ));
  1508.  
  1509. foreach ($img_ary as $img)
  1510. {
  1511. if ($category == 'buttons')
  1512. {
  1513. foreach ($langs as $language)
  1514. {
  1515. $template->assign_block_vars('category.images', array(
  1516. 'SELECTED' => ($img == $imgname && $language == $imgnamelang),
  1517. 'VALUE' => $img . '-' . $language,
  1518. 'TEXT' => $user->lang['IMG_' . strtoupper($img)] . ' [ ' . $language . ' ]'
  1519. ));
  1520. }
  1521. }
  1522. else
  1523. {
  1524. $template->assign_block_vars('category.images', array(
  1525. 'SELECTED' => ($img == $imgname),
  1526. 'VALUE' => $img,
  1527. 'TEXT' => (($category == 'custom') ? $img : $user->lang['IMG_' . strtoupper($img)])
  1528. ));
  1529. }
  1530. }
  1531. }
  1532.  
  1533. // Make sure the list of possible images is sorted alphabetically
  1534. sort($imagesetlist['lang']);
  1535. sort($imagesetlist['nolang']);
  1536.  
  1537. $image_found = false;
  1538. $img_val = '';
  1539. foreach ($imagesetlist as $type => $img_ary)
  1540. {
  1541. if ($type !== 'lang' || $sql_extra)
  1542. {
  1543. $template->assign_block_vars('imagesetlist', array(
  1544. 'TYPE' => ($type == 'lang')
  1545. ));
  1546. }
  1547.  
  1548. foreach ($img_ary as $img)
  1549. {
  1550. $imgtext = preg_replace('/^([^\/]+\/)/', '', $img);
  1551. $selected = (!empty($imgname) && strpos($image_filename, $imgtext) !== false);
  1552. if ($selected)
  1553. {
  1554. $image_found = true;
  1555. $img_val = htmlspecialchars($img);
  1556. }
  1557. $template->assign_block_vars('imagesetlist.images', array(
  1558. 'SELECTED' => $selected,
  1559. 'TEXT' => $imgtext,
  1560. 'VALUE' => htmlspecialchars($img)
  1561. ));
  1562. }
  1563. }
  1564.  
  1565. $imgsize_bool = (!empty($imgname) && $image_width && $image_height) ? true : false;
  1566. $image_request = '../styles/' . $imageset_path . '/imageset/' . ($image_lang ? $imgnamelang . '/' : '') . $image_filename;
  1567.  
  1568. $template->assign_vars(array(
  1569. 'S_EDIT_IMAGESET' => true,
  1570. 'L_TITLE' => $user->lang[$this->page_title],
  1571. 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
  1572. 'IMAGE_OPTIONS' => $img_options,
  1573. 'IMAGE_SIZE' => $image_width,
  1574. 'IMAGE_HEIGHT' => $image_height,
  1575. 'IMAGE_REQUEST' => (empty($image_filename)) ? 'images/no_image.png' : $image_request,
  1576. 'U_ACTION' => $this->u_action . "&amp;action=edit&amp;id=$imageset_id",
  1577. 'U_BACK' => $this->u_action,
  1578. 'NAME' => $imageset_name,
  1579. 'A_NAME' => addslashes($imageset_name),
  1580. 'PATH' => $imageset_path,
  1581. 'A_PATH' => addslashes($imageset_path),
  1582. 'ERROR' => !$valid_name,
  1583. 'IMG_SRC' => ($image_found) ? '../styles/' . $imageset_path . '/imageset/' . $img_val : 'images/no_image.png',
  1584. 'IMAGE_SELECT' => $image_found
  1585. ));
  1586. }
  1587.  
  1588. /**
  1589. * Remove style/template/theme/imageset
  1590. */
  1591. function remove($mode, $style_id)
  1592. {
  1593. global $db, $template, $user, $phpbb_root_path, $cache, $config;
  1594.  
  1595. $new_id = request_var('new_id', 0);
  1596. $update = (isset($_POST['update'])) ? true : false;
  1597. $sql_where = '';
  1598.  
  1599. switch ($mode)
  1600. {
  1601. case 'style':
  1602. $sql_from = STYLES_TABLE;
  1603. $sql_select = 'style_id, style_name, template_id, theme_id, imageset_id';
  1604. $sql_where = 'AND style_active = 1';
  1605. break;
  1606.  
  1607. case 'template':
  1608. $sql_from = STYLES_TEMPLATE_TABLE;
  1609. $sql_select = 'template_id, template_name, template_path, template_storedb';
  1610. break;
  1611.  
  1612. case 'theme':
  1613. $sql_from = STYLES_THEME_TABLE;
  1614. $sql_select = 'theme_id, theme_name, theme_path, theme_storedb';
  1615. break;
  1616.  
  1617. case 'imageset':
  1618. $sql_from = STYLES_IMAGESET_TABLE;
  1619. $sql_select = 'imageset_id, imageset_name, imageset_path';
  1620. break;
  1621. }
  1622.  
  1623. if ($mode === 'template' && ($conflicts = $this->check_inheritance($mode, $style_id)))
  1624. {
  1625. $l_type = strtoupper($mode);
  1626. $msg = $user->lang[$l_type . '_DELETE_DEPENDENT'];
  1627. foreach ($conflicts as $id => $values)
  1628. {
  1629. $msg .= '<br />' . $values['template_name'];
  1630. }
  1631.  
  1632. trigger_error($msg . adm_back_link($this->u_action), E_USER_WARNING);
  1633. }
  1634.  
  1635. $l_prefix = strtoupper($mode);
  1636.  
  1637. $sql = "SELECT $sql_select
  1638. FROM $sql_from
  1639. WHERE {$mode}_id = $style_id";
  1640. $result = $db->sql_query($sql);
  1641. $style_row = $db->sql_fetchrow($result);
  1642. $db->sql_freeresult($result);
  1643.  
  1644. if (!$style_row)
  1645. {
  1646. trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
  1647. }
  1648.  
  1649. $s_only_component = $this->display_component_options($mode, $style_row[$mode . '_id'], $style_row);
  1650.  
  1651. if ($s_only_component)
  1652. {
  1653. trigger_error($user->lang['ONLY_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
  1654. }
  1655.  
  1656. if ($update)
  1657. {
  1658. if ($mode == 'style')
  1659. {
  1660. $sql = "DELETE FROM $sql_from
  1661. WHERE {$mode}_id = $style_id";
  1662. $db->sql_query($sql);
  1663.  
  1664. $sql = 'UPDATE ' . USERS_TABLE . "
  1665. SET user_style = $new_id
  1666. WHERE user_style = $style_id";
  1667. $db->sql_query($sql);
  1668.  
  1669. $sql = 'UPDATE ' . FORUMS_TABLE . "
  1670. SET forum_style = $new_id
  1671. WHERE forum_style = $style_id";
  1672. $db->sql_query($sql);
  1673.  
  1674. if ($style_id == $config['default_style'])
  1675. {
  1676. set_config('default_style', $new_id);
  1677. }
  1678.  
  1679. // Remove the components
  1680. $components = array('template', 'theme', 'imageset');
  1681. foreach ($components as $component)
  1682. {
  1683. $new_id = request_var('new_' . $component . '_id', 0);
  1684. $component_id = $style_row[$component . '_id'];
  1685. $this->remove_component($component, $component_id, $new_id, $style_id);
  1686. }
  1687. }
  1688. else
  1689. {
  1690. $this->remove_component($mode, $style_id, $new_id);
  1691. }
  1692.  
  1693. $cache->destroy('sql', STYLES_TABLE);
  1694.  
  1695. add_log('admin', 'LOG_' . $l_prefix . '_DELETE', $style_row[$mode . '_name']);
  1696. $message = ($mode != 'style') ? $l_prefix . '_DELETED_FS' : $l_prefix . '_DELETED';
  1697. trigger_error($user->lang[$message] . adm_back_link($this->u_action));
  1698. }
  1699.  
  1700. $this->page_title = 'DELETE_' . $l_prefix;
  1701.  
  1702. $template->assign_vars(array(
  1703. 'S_DELETE' => true,
  1704.  
  1705. 'L_TITLE' => $user->lang[$this->page_title],
  1706. 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
  1707. 'L_NAME' => $user->lang[$l_prefix . '_NAME'],
  1708. 'L_REPLACE' => $user->lang['REPLACE_' . $l_prefix],
  1709. 'L_REPLACE_EXPLAIN' => $user->lang['REPLACE_' . $l_prefix . '_EXPLAIN'],
  1710.  
  1711. 'U_ACTION' => $this->u_action . "&amp;action=delete&amp;id=$style_id",
  1712. 'U_BACK' => $this->u_action,
  1713.  
  1714. 'NAME' => $style_row[$mode . '_name'],
  1715. )
  1716. );
  1717.  
  1718. if ($mode == 'style')
  1719. {
  1720. $template->assign_vars(array(
  1721. 'S_DELETE_STYLE' => true,
  1722. ));
  1723. }
  1724. }
  1725.  
  1726. /**
  1727. * Remove template/theme/imageset entry from the database
  1728. */
  1729. function remove_component($component, $component_id, $new_id, $style_id = false)
  1730. {
  1731. global $db;
  1732.  
  1733. if (($new_id == 0) || ($component === 'template' && ($conflicts = $this->check_inheritance($component, $component_id))))
  1734. {
  1735. // We can not delete the template, as the user wants to keep the component or an other template is inheriting from this one.
  1736. return;
  1737. }
  1738.  
  1739. $component_in_use = array();
  1740. if ($component != 'style')
  1741. {
  1742. $component_in_use = $this->component_in_use($component, $component_id, $style_id);
  1743. }
  1744.  
  1745. if (($new_id == -1) && !empty($component_in_use))
  1746. {
  1747. // We can not delete the component, as it is still in use
  1748. return;
  1749. }
  1750.  
  1751. if ($component == 'imageset')
  1752. {
  1753. $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . "
  1754. WHERE imageset_id = $component_id";
  1755. $db->sql_query($sql);
  1756. }
  1757.  
  1758. switch ($component)
  1759. {
  1760. case 'template':
  1761. $sql_from = STYLES_TEMPLATE_TABLE;
  1762. break;
  1763.  
  1764. case 'theme':
  1765. $sql_from = STYLES_THEME_TABLE;
  1766. break;
  1767.  
  1768. case 'imageset':
  1769. $sql_from = STYLES_IMAGESET_TABLE;;
  1770. break;
  1771. }
  1772.  
  1773. $sql = "DELETE FROM $sql_from
  1774. WHERE {$component}_id = $component_id";
  1775. $db->sql_query($sql);
  1776.  
  1777. $sql = 'UPDATE ' . STYLES_TABLE . "
  1778. SET {$component}_id = $new_id
  1779. WHERE {$component}_id = $component_id";
  1780. $db->sql_query($sql);
  1781. }
  1782.  
  1783. /**
  1784. * Display the options which can be used to replace a style/template/theme/imageset
  1785. *
  1786. * @return boolean Returns true if the component is the only component and can not be deleted.
  1787. */
  1788. function display_component_options($component, $component_id, $style_row = false, $style_id = false)
  1789. {
  1790. global $db, $template, $user;
  1791.  
  1792. $is_only_component = true;
  1793. $component_in_use = array();
  1794. if ($component != 'style')
  1795. {
  1796. $component_in_use = $this->component_in_use($component, $component_id, $style_id);
  1797. }
  1798.  
  1799. $sql_where = '';
  1800. switch ($component)
  1801. {
  1802. case 'style':
  1803. $sql_from = STYLES_TABLE;
  1804. $sql_where = 'WHERE style_active = 1';
  1805. break;
  1806.  
  1807. case 'template':
  1808. $sql_from = STYLES_TEMPLATE_TABLE;
  1809. $sql_where = 'WHERE template_inherits_id <> ' . $component_id;
  1810. break;
  1811.  
  1812. case 'theme':
  1813. $sql_from = STYLES_THEME_TABLE;
  1814. break;
  1815.  
  1816. case 'imageset':
  1817. $sql_from = STYLES_IMAGESET_TABLE;
  1818. break;
  1819. }
  1820.  
  1821. $s_options = '';
  1822. if (($component != 'style') && empty($component_in_use))
  1823. {
  1824. // If it is not in use, there must be another component
  1825. $is_only_component = false;
  1826.  
  1827. $sql = "SELECT {$component}_id, {$component}_name
  1828. FROM $sql_from
  1829. WHERE {$component}_id = {$component_id}";
  1830. $result = $db->sql_query($sql);
  1831. $row = $db->sql_fetchrow($result);
  1832. $db->sql_freeresult($result);
  1833.  
  1834. $s_options .= '<option value="-1" selected="selected">' . $user->lang['DELETE_' . strtoupper($component)] . '</option>';
  1835. $s_options .= '<option value="0">' . sprintf($user->lang['KEEP_' . strtoupper($component)], $row[$component . '_name']) . '</option>';
  1836. }
  1837. else
  1838. {
  1839. $sql = "SELECT {$component}_id, {$component}_name
  1840. FROM $sql_from
  1841. $sql_where
  1842. ORDER BY {$component}_name ASC";
  1843. $result = $db->sql_query($sql);
  1844.  
  1845. $s_keep_option = $s_options = '';
  1846. while ($row = $db->sql_fetchrow($result))
  1847. {
  1848. if ($row[$component . '_id'] != $component_id)
  1849. {
  1850. $is_only_component = false;
  1851. $s_options .= '<option value="' . $row[$component . '_id'] . '">' . sprintf($user->lang['REPLACE_WITH_OPTION'], $row[$component . '_name']) . '</option>';
  1852. }
  1853. else if ($component != 'style')
  1854. {
  1855. $s_keep_option = '<option value="0" selected="selected">' . sprintf($user->lang['KEEP_' . strtoupper($component)], $row[$component . '_name']) . '</option>';
  1856. }
  1857. }
  1858. $db->sql_freeresult($result);
  1859. $s_options = $s_keep_option . $s_options;
  1860. }
  1861.  
  1862. if (!$style_row)
  1863. {
  1864. $template->assign_var('S_REPLACE_' . strtoupper($component) . '_OPTIONS', $s_options);
  1865. }
  1866. else
  1867. {
  1868. $template->assign_var('S_REPLACE_OPTIONS', $s_options);
  1869. if ($component == 'style')
  1870. {
  1871. $components = array('template', 'theme', 'imageset');
  1872. foreach ($components as $component)
  1873. {
  1874. $this->display_component_options($component, $style_row[$component . '_id'], false, $component_id, true);
  1875. }
  1876. }
  1877. }
  1878.  
  1879. return $is_only_component;
  1880. }
  1881.  
  1882. /**
  1883. * Check whether the component is still used by another style or component
  1884. */
  1885. function component_in_use($component, $component_id, $style_id = false)
  1886. {
  1887. global $db;
  1888.  
  1889. $component_in_use = array();
  1890.  
  1891. if ($style_id)
  1892. {
  1893. $sql = 'SELECT style_id, style_name
  1894. FROM ' . STYLES_TABLE . "
  1895. WHERE {$component}_id = {$component_id}
  1896. AND style_id <> {$style_id}
  1897. ORDER BY style_name ASC";
  1898. }
  1899. else
  1900. {
  1901. $sql = 'SELECT style_id, style_name
  1902. FROM ' . STYLES_TABLE . "
  1903. WHERE {$component}_id = {$component_id}
  1904. ORDER BY style_name ASC";
  1905. }
  1906. $result = $db->sql_query($sql);
  1907. while ($row = $db->sql_fetchrow($result))
  1908. {
  1909. $component_in_use[] = $row['style_name'];
  1910. }
  1911. $db->sql_freeresult($result);
  1912.  
  1913. if ($component === 'template' && ($conflicts = $this->check_inheritance($component, $component_id)))
  1914. {
  1915. foreach ($conflicts as $temp_id => $conflict_data)
  1916. {
  1917. $component_in_use[] = $conflict_data['template_name'];
  1918. }
  1919. }
  1920.  
  1921. return $component_in_use;
  1922. }
  1923.  
  1924. /**
  1925. * Export style or style elements
  1926. */
  1927. function export($mode, $style_id)
  1928. {
  1929. global $db, $template, $user, $phpbb_root_path, $cache, $phpEx, $config;
  1930.  
  1931. $update = (isset($_POST['update'])) ? true : false;
  1932.  
  1933. $inc_template = request_var('inc_template', 0);
  1934. $inc_theme = request_var('inc_theme', 0);
  1935. $inc_imageset = request_var('inc_imageset', 0);
  1936. $store = request_var('store', 0);
  1937. $format = request_var('format', '');
  1938.  
  1939. $error = array();
  1940. $methods = array('tar');
  1941.  
  1942. $available_methods = array('tar.gz' => 'zlib', 'tar.bz2' => 'bz2', 'zip' => 'zlib');
  1943. foreach ($available_methods as $type => $module)
  1944. {
  1945. if (!@extension_loaded($module))
  1946. {
  1947. continue;
  1948. }
  1949.  
  1950. $methods[] = $type;
  1951. }
  1952.  
  1953. if (!in_array($format, $methods))
  1954. {
  1955. $format = 'tar';
  1956. }
  1957.  
  1958. switch ($mode)
  1959. {
  1960. case 'style':
  1961. if ($update && ($inc_template + $inc_theme + $inc_imageset) < 1)
  1962. {
  1963. $error[] = $user->lang['STYLE_ERR_MORE_ELEMENTS'];
  1964. }
  1965.  
  1966. $name = 'style_name';
  1967.  
  1968. $sql_select = 's.style_id, s.style_name, s.style_copyright';
  1969. $sql_select .= ($inc_template) ? ', t.*' : ', t.template_name';
  1970. $sql_select .= ($inc_theme) ? ', c.*' : ', c.theme_name';
  1971. $sql_select .= ($inc_imageset) ? ', i.*' : ', i.imageset_name';
  1972. $sql_from = STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . ' i';
  1973. $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";
  1974.  
  1975. $l_prefix = 'STYLE';
  1976. break;
  1977.  
  1978. case 'template':
  1979. $name = 'template_name';
  1980.  
  1981. $sql_select = '*';
  1982. $sql_from = STYLES_TEMPLATE_TABLE;
  1983. $sql_where = "template_id = $style_id";
  1984.  
  1985. $l_prefix = 'TEMPLATE';
  1986. break;
  1987.  
  1988. case 'theme':
  1989. $name = 'theme_name';
  1990.  
  1991. $sql_select = '*';
  1992. $sql_from = STYLES_THEME_TABLE;
  1993. $sql_where = "theme_id = $style_id";
  1994.  
  1995. $l_prefix = 'THEME';
  1996. break;
  1997.  
  1998. case 'imageset':
  1999. $name = 'imageset_name';
  2000.  
  2001. $sql_select = '*';
  2002. $sql_from = STYLES_IMAGESET_TABLE;
  2003. $sql_where = "imageset_id = $style_id";
  2004.  
  2005. $l_prefix = 'IMAGESET';
  2006. break;
  2007. }
  2008.  
  2009. if ($update && !sizeof($error))
  2010. {
  2011. $sql = "SELECT $sql_select
  2012. FROM $sql_from
  2013. WHERE $sql_where";
  2014. $result = $db->sql_query($sql);
  2015. $style_row = $db->sql_fetchrow($result);
  2016. $db->sql_freeresult($result);
  2017.  
  2018. if (!$style_row)
  2019. {
  2020. trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
  2021. }
  2022.  
  2023. $var_ary = array('style_id', 'style_name', 'style_copyright', 'template_id', 'template_name', 'template_path', 'template_copyright', 'template_storedb', 'template_inherits_id', 'bbcode_bitfield', 'theme_id', 'theme_name', 'theme_path', 'theme_copyright', 'theme_storedb', 'theme_mtime', 'theme_data', 'imageset_id', 'imageset_name', 'imageset_path', 'imageset_copyright');
  2024.  
  2025. foreach ($var_ary as $var)
  2026. {
  2027. if (!isset($style_row[$var]))
  2028. {
  2029. $style_row[$var] = '';
  2030. }
  2031. }
  2032.  
  2033. $files = $data = array();
  2034.  
  2035. if ($mode == 'style')
  2036. {
  2037. $style_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['style_name'], $style_row['style_copyright'], $config['version']), $this->style_cfg);
  2038.  
  2039. $style_cfg .= (!$inc_template) ? "\nrequired_template = {$style_row['template_name']}" : '';
  2040. $style_cfg .= (!$inc_theme) ? "\nrequired_theme = {$style_row['theme_name']}" : '';
  2041. $style_cfg .= (!$inc_imageset) ? "\nrequired_imageset = {$style_row['imageset_name']}" : '';
  2042.  
  2043. $data[] = array(
  2044. 'src' => $style_cfg,
  2045. 'prefix' => 'style.cfg'
  2046. );
  2047.  
  2048. unset($style_cfg);
  2049. }
  2050.  
  2051. // Export template core code
  2052. if ($mode == 'template' || $inc_template)
  2053. {
  2054. $use_template_name = $style_row['template_name'];
  2055.  
  2056. // Add the inherit from variable, depending on it's use...
  2057. if ($style_row['template_inherits_id'])
  2058. {
  2059. // Get the template name
  2060. $sql = 'SELECT template_name
  2061. FROM ' . STYLES_TEMPLATE_TABLE . '
  2062. WHERE template_id = ' . (int) $style_row['template_inherits_id'];
  2063. $result = $db->sql_query($sql);
  2064. $use_template_name = (string) $db->sql_fetchfield('template_name');
  2065. $db->sql_freeresult($result);
  2066. }
  2067.  
  2068. $template_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}', '{INHERIT_FROM}'), array($mode, $style_row['template_name'], $style_row['template_copyright'], $config['version'], $use_template_name), $this->template_cfg);
  2069.  
  2070. $template_cfg .= "\n\nbbcode_bitfield = {$style_row['bbcode_bitfield']}";
  2071.  
  2072. $data[] = array(
  2073. 'src' => $template_cfg,
  2074. 'prefix' => 'template/template.cfg'
  2075. );
  2076.  
  2077. // This is potentially nasty memory-wise ...
  2078. if (!$style_row['template_storedb'])
  2079. {
  2080. $files[] = array(
  2081. 'src' => "styles/{$style_row['template_path']}/template/",
  2082. 'prefix-' => "styles/{$style_row['template_path']}/",
  2083. 'prefix+' => false,
  2084. 'exclude' => 'template.cfg'
  2085. );
  2086. }
  2087. else
  2088. {
  2089. $sql = 'SELECT template_filename, template_data
  2090. FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
  2091. WHERE template_id = {$style_row['template_id']}";
  2092. $result = $db->sql_query($sql);
  2093.  
  2094. while ($row = $db->sql_fetchrow($result))
  2095. {
  2096. $data[] = array(
  2097. 'src' => $row['template_data'],
  2098. 'prefix' => 'template/' . $row['template_filename']
  2099. );
  2100. }
  2101. $db->sql_freeresult($result);
  2102. }
  2103. unset($template_cfg);
  2104. }
  2105.  
  2106. // Export theme core code
  2107. if ($mode == 'theme' || $inc_theme)
  2108. {
  2109. $theme_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['theme_name'], $style_row['theme_copyright'], $config['version']), $this->theme_cfg);
  2110.  
  2111. // Read old cfg file
  2112. $items = $cache->obtain_cfg_items($style_row);
  2113. $items = $items['theme'];
  2114.  
  2115. if (!isset($items['parse_css_file']))
  2116. {
  2117. $items['parse_css_file'] = 'off';
  2118. }
  2119.  
  2120. $theme_cfg = str_replace(array('{PARSE_CSS_FILE}'), array($items['parse_css_file']), $theme_cfg);
  2121.  
  2122. $files[] = array(
  2123. 'src' => "styles/{$style_row['theme_path']}/theme/",
  2124. 'prefix-' => "styles/{$style_row['theme_path']}/",
  2125. 'prefix+' => false,
  2126. 'exclude' => ($style_row['theme_storedb']) ? 'stylesheet.css,theme.cfg' : 'theme.cfg'
  2127. );
  2128.  
  2129. $data[] = array(
  2130. 'src' => $theme_cfg,
  2131. 'prefix' => 'theme/theme.cfg'
  2132. );
  2133.  
  2134. if ($style_row['theme_storedb'])
  2135. {
  2136. $data[] = array(
  2137. 'src' => $style_row['theme_data'],
  2138. 'prefix' => 'theme/stylesheet.css'
  2139. );
  2140. }
  2141.  
  2142. unset($items, $theme_cfg);
  2143. }
  2144.  
  2145. // Export imageset core code
  2146. if ($mode == 'imageset' || $inc_imageset)
  2147. {
  2148. $imageset_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['imageset_name'], $style_row['imageset_copyright'], $config['version']), $this->imageset_cfg);
  2149.  
  2150. $imageset_main = array();
  2151.  
  2152. $sql = 'SELECT image_filename, image_name, image_height, image_width
  2153. FROM ' . STYLES_IMAGESET_DATA_TABLE . "
  2154. WHERE imageset_id = $style_id
  2155. AND image_lang = ''";
  2156. $result = $db->sql_query($sql);
  2157. while ($row = $db->sql_fetchrow($result))
  2158. {
  2159. $imageset_main[$row['image_name']] = $row['image_filename'] . ($row['image_height'] ? '*' . $row['image_height']: '') . ($row['image_width'] ? '*' . $row['image_width']: '');
  2160. }
  2161. $db->sql_freeresult($result);
  2162.  
  2163. foreach ($this->imageset_keys as $topic => $key_array)
  2164. {
  2165. foreach ($key_array as $key)
  2166. {
  2167. if (isset($imageset_main[$key]))
  2168. {
  2169. $imageset_cfg .= "\nimg_" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $imageset_main[$key]);
  2170. }
  2171. }
  2172. }
  2173.  
  2174. $files[] = array(
  2175. 'src' => "styles/{$style_row['imageset_path']}/imageset/",
  2176. 'prefix-' => "styles/{$style_row['imageset_path']}/",
  2177. 'prefix+' => false,
  2178. 'exclude' => 'imageset.cfg'
  2179. );
  2180.  
  2181. $data[] = array(
  2182. 'src' => trim($imageset_cfg),
  2183. 'prefix' => 'imageset/imageset.cfg'
  2184. );
  2185.  
  2186. end($data);
  2187.  
  2188. $imageset_root = "{$phpbb_root_path}styles/{$style_row['imageset_path']}/imageset/";
  2189.  
  2190. if ($dh = @opendir($imageset_root))
  2191. {
  2192. while (($fname = readdir($dh)) !== false)
  2193. {
  2194. if ($fname[0] != '.' && $fname != 'CVS' && is_dir("$imageset_root$fname"))
  2195. {
  2196. $files[key($files)]['exclude'] .= ',' . $fname . '/imageset.cfg';
  2197. }
  2198. }
  2199. closedir($dh);
  2200. }
  2201.  
  2202. $imageset_lang = array();
  2203.  
  2204. $sql = 'SELECT image_filename, image_name, image_height, image_width, image_lang
  2205. FROM ' . STYLES_IMAGESET_DATA_TABLE . "
  2206. WHERE imageset_id = $style_id
  2207. AND image_lang <> ''";
  2208. $result = $db->sql_query($sql);
  2209. while ($row = $db->sql_fetchrow($result))
  2210. {
  2211. $imageset_lang[$row['image_lang']][$row['image_name']] = $row['image_filename'] . ($row['image_height'] ? '*' . $row['image_height']: '') . ($row['image_width'] ? '*' . $row['image_width']: '');
  2212. }
  2213. $db->sql_freeresult($result);
  2214.  
  2215. foreach ($imageset_lang as $lang => $imageset_localized)
  2216. {
  2217. $imageset_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['imageset_name'], $style_row['imageset_copyright'], $config['version']), $this->imageset_cfg);
  2218.  
  2219. foreach ($this->imageset_keys as $topic => $key_array)
  2220. {
  2221. foreach ($key_array as $key)
  2222. {
  2223. if (isset($imageset_localized[$key]))
  2224. {
  2225. $imageset_cfg .= "\nimg_" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $imageset_localized[$key]);
  2226. }
  2227. }
  2228. }
  2229.  
  2230. $data[] = array(
  2231. 'src' => trim($imageset_cfg),
  2232. 'prefix' => 'imageset/' . $lang . '/imageset.cfg'
  2233. );
  2234. }
  2235.  
  2236. unset($imageset_cfg);
  2237. }
  2238.  
  2239. switch ($format)
  2240. {
  2241. case 'tar':
  2242. $ext = '.tar';
  2243. break;
  2244.  
  2245. case 'zip':
  2246. $ext = '.zip';
  2247. break;
  2248.  
  2249. case 'tar.gz':
  2250. $ext = '.tar.gz';
  2251. break;
  2252.  
  2253. case 'tar.bz2':
  2254. $ext = '.tar.bz2';
  2255. break;
  2256.  
  2257. default:
  2258. $error[] = $user->lang[$l_prefix . '_ERR_ARCHIVE'];
  2259. }
  2260.  
  2261. if (!sizeof($error))
  2262. {
  2263. include($phpbb_root_path . 'includes/functions_compress.' . $phpEx);
  2264.  
  2265. if ($mode == 'style')
  2266. {
  2267. $path = preg_replace('#[^\w-]+#', '_', $style_row['style_name']);
  2268. }
  2269. else
  2270. {
  2271. $path = $style_row[$mode . '_path'];
  2272. }
  2273.  
  2274. if ($format == 'zip')
  2275. {
  2276. $compress = new compress_zip('w', $phpbb_root_path . "store/$path$ext");
  2277. }
  2278. else
  2279. {
  2280. $compress = new compress_tar('w', $phpbb_root_path . "store/$path$ext", $ext);
  2281. }
  2282.  
  2283. if (sizeof($files))
  2284. {
  2285. foreach ($files as $file_ary)
  2286. {
  2287. $compress->add_file($file_ary['src'], $file_ary['prefix-'], $file_ary['prefix+'], $file_ary['exclude']);
  2288. }
  2289. }
  2290.  
  2291. if (sizeof($data))
  2292. {
  2293. foreach ($data as $data_ary)
  2294. {
  2295. $compress->add_data($data_ary['src'], $data_ary['prefix']);
  2296. }
  2297. }
  2298.  
  2299. $compress->close();
  2300.  
  2301. add_log('admin', 'LOG_' . $l_prefix . '_EXPORT', $style_row[$mode . '_name']);
  2302.  
  2303. if (!$store)
  2304. {
  2305. $compress->download($path);
  2306. @unlink("{$phpbb_root_path}store/$path$ext");
  2307. exit;
  2308. }
  2309.  
  2310. trigger_error(sprintf($user->lang[$l_prefix . '_EXPORTED'], "store/$path$ext") . adm_back_link($this->u_action));
  2311. }
  2312. }
  2313.  
  2314. $sql = "SELECT {$mode}_id, {$mode}_name
  2315. FROM " . (($mode == 'style') ? STYLES_TABLE : $sql_from) . "
  2316. WHERE {$mode}_id = $style_id";
  2317. $result = $db->sql_query($sql);
  2318. $style_row = $db->sql_fetchrow($result);
  2319. $db->sql_freeresult($result);
  2320.  
  2321. if (!$style_row)
  2322. {
  2323. trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
  2324. }
  2325.  
  2326. $this->page_title = $l_prefix . '_EXPORT';
  2327.  
  2328. $format_buttons = '';
  2329. foreach ($methods as $method)
  2330. {
  2331. $format_buttons .= '<label><input type="radio"' . ((!$format_buttons) ? ' id="format"' : '') . ' class="radio" value="' . $method . '" name="format"' . (($method == $format) ? ' checked="checked"' : '') . ' /> ' . $method . '</label>';
  2332. }
  2333.  
  2334. $template->assign_vars(array(
  2335. 'S_EXPORT' => true,
  2336. 'S_ERROR_MSG' => (sizeof($error)) ? true : false,
  2337. 'S_STYLE' => ($mode == 'style') ? true : false,
  2338.  
  2339. 'L_TITLE' => $user->lang[$this->page_title],
  2340. 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
  2341. 'L_NAME' => $user->lang[$l_prefix . '_NAME'],
  2342.  
  2343. 'U_ACTION' => $this->u_action . '&amp;action=export&amp;id=' . $style_id,
  2344. 'U_BACK' => $this->u_action,
  2345.  
  2346. 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '',
  2347. 'NAME' => $style_row[$mode . '_name'],
  2348. 'FORMAT_BUTTONS' => $format_buttons)
  2349. );
  2350. }
  2351.  
  2352. /**
  2353. * Display details
  2354. */
  2355. function details($mode, $style_id)
  2356. {
  2357. global $template, $db, $config, $user, $safe_mode, $cache, $phpbb_root_path;
  2358.  
  2359. $update = (isset($_POST['update'])) ? true : false;
  2360. $l_type = strtoupper($mode);
  2361.  
  2362. $error = array();
  2363. $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE);
  2364.  
  2365. switch ($mode)
  2366. {
  2367. case 'style':
  2368. $sql_from = STYLES_TABLE;
  2369. break;
  2370.  
  2371. case 'template':
  2372. $sql_from = STYLES_TEMPLATE_TABLE;
  2373. break;
  2374.  
  2375. case 'theme':
  2376. $sql_from = STYLES_THEME_TABLE;
  2377. break;
  2378.  
  2379. case 'imageset':
  2380. $sql_from = STYLES_IMAGESET_TABLE;
  2381. break;
  2382. }
  2383.  
  2384. $sql = "SELECT *
  2385. FROM $sql_from
  2386. WHERE {$mode}_id = $style_id";
  2387. $result = $db->sql_query($sql);
  2388. $style_row = $db->sql_fetchrow($result);
  2389. $db->sql_freeresult($result);
  2390.  
  2391. if (!$style_row)
  2392. {
  2393. trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING);
  2394. }
  2395.  
  2396. $style_row['style_default'] = ($mode == 'style' && $config['default_style'] == $style_id) ? 1 : 0;
  2397.  
  2398. if ($update)
  2399. {
  2400. $name = utf8_normalize_nfc(request_var('name', '', true));
  2401. $copyright = utf8_normalize_nfc(request_var('copyright', '', true));
  2402.  
  2403. $template_id = request_var('template_id', 0);
  2404. $theme_id = request_var('theme_id', 0);
  2405. $imageset_id = request_var('imageset_id', 0);
  2406.  
  2407. $style_active = request_var('style_active', 0);
  2408. $style_default = request_var('style_default', 0);
  2409. $store_db = request_var('store_db', 0);
  2410.  
  2411. // If the admin selected the style to be the default style, but forgot to activate it... we will do it for him
  2412. if ($style_default)
  2413. {
  2414. $style_active = 1;
  2415. }
  2416.  
  2417. $sql = "SELECT {$mode}_id, {$mode}_name
  2418. FROM $sql_from
  2419. WHERE {$mode}_id <> $style_id
  2420. AND LOWER({$mode}_name) = '" . $db->sql_escape(strtolower($name)) . "'";
  2421. $result = $db->sql_query($sql);
  2422. $conflict = $db->sql_fetchrow($result);
  2423. $db->sql_freeresult($result);
  2424.  
  2425. if ($mode == 'style' && (!$template_id || !$theme_id || !$imageset_id))
  2426. {
  2427. $error[] = $user->lang['STYLE_ERR_NO_IDS'];
  2428. }
  2429.  
  2430. if ($mode == 'style' && $style_row['style_active'] && !$style_active && $config['default_style'] == $style_id)
  2431. {
  2432. $error[] = $user->lang['DEACTIVATE_DEFAULT'];
  2433. }
  2434.  
  2435. if (!$name || $conflict)
  2436. {
  2437. $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME'];
  2438. }
  2439.  
  2440. if ($mode === 'theme' || $mode === 'template')
  2441. {
  2442. // a rather elaborate check we have to do here once to avoid trouble later
  2443. $check = "{$phpbb_root_path}styles/" . $style_row["{$mode}_path"] . (($mode === 'theme') ? '/theme/stylesheet.css' : '/template');
  2444. if (($style_row["{$mode}_storedb"] != $store_db) && !$store_db && ($safe_mode || !phpbb_is_writable($check)))
  2445. {
  2446. $error[] = $user->lang['EDIT_' . strtoupper($mode) . '_STORED_DB'];
  2447. $store_db = 1;
  2448. }
  2449.  
  2450. // themes which have to be parsed have to go into db
  2451. if ($mode == 'theme')
  2452. {
  2453. $cfg = parse_cfg_file("{$phpbb_root_path}styles/" . $style_row["{$mode}_path"] . "/theme/theme.cfg");
  2454.  
  2455. if (isset($cfg['parse_css_file']) && $cfg['parse_css_file'] && !$store_db)
  2456. {
  2457. $error[] = $user->lang['EDIT_THEME_STORE_PARSED'];
  2458. $store_db = 1;
  2459. }
  2460. }
  2461. }
  2462.  
  2463. if (!sizeof($error))
  2464. {
  2465. // Check length settings
  2466. if (utf8_strlen($name) > 30)
  2467. {
  2468. $error[] = $user->lang[$l_type . '_ERR_NAME_LONG'];
  2469. }
  2470.  
  2471. if (utf8_strlen($copyright) > 60)
  2472. {
  2473. $error[] = $user->lang[$l_type . '_ERR_COPY_LONG'];
  2474. }
  2475. }
  2476. }
  2477.  
  2478. if ($update && sizeof($error))
  2479. {
  2480. $style_row = array_merge($style_row, array(
  2481. 'template_id' => $template_id,
  2482. 'theme_id' => $theme_id,
  2483. 'imageset_id' => $imageset_id,
  2484. 'style_active' => $style_active,
  2485. $mode . '_storedb' => $store_db,
  2486. $mode . '_name' => $name,
  2487. $mode . '_copyright' => $copyright)
  2488. );
  2489. }
  2490.  
  2491. // User has submitted form and no errors have occurred
  2492. if ($update && !sizeof($error))
  2493. {
  2494. $sql_ary = array(
  2495. $mode . '_name' => $name,
  2496. $mode . '_copyright' => $copyright
  2497. );
  2498.  
  2499. switch ($mode)
  2500. {
  2501. case 'style':
  2502.  
  2503. $sql_ary += array(
  2504. 'template_id' => (int) $template_id,
  2505. 'theme_id' => (int) $theme_id,
  2506. 'imageset_id' => (int) $imageset_id,
  2507. 'style_active' => (int) $style_active,
  2508. );
  2509. break;
  2510.  
  2511. case 'imageset':
  2512. break;
  2513.  
  2514. case 'theme':
  2515.  
  2516. if ($style_row['theme_storedb'] != $store_db)
  2517. {
  2518. $theme_data = '';
  2519.  
  2520. if (!$style_row['theme_storedb'])
  2521. {
  2522. $theme_data = $this->db_theme_data($style_row);
  2523. }
  2524. else if (!$store_db && !$safe_mode && phpbb_is_writable("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css"))
  2525. {
  2526. $store_db = 1;
  2527. $theme_data = $style_row['theme_data'];
  2528.  
  2529. if ($fp = @fopen("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css", 'wb'))
  2530. {
  2531. $store_db = (@fwrite($fp, str_replace("styles/{$style_row['theme_path']}/theme/", './', $theme_data))) ? 0 : 1;
  2532. }
  2533. fclose($fp);
  2534. }
  2535.  
  2536. $sql_ary += array(
  2537. 'theme_mtime' => ($store_db) ? filemtime("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css") : 0,
  2538. 'theme_storedb' => $store_db,
  2539. 'theme_data' => ($store_db) ? $theme_data : '',
  2540. );
  2541. }
  2542. break;
  2543.  
  2544. case 'template':
  2545.  
  2546. if ($style_row['template_storedb'] != $store_db)
  2547. {
  2548. if ($super = $this->get_super($mode, $style_row['template_id']))
  2549. {
  2550. $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name']));
  2551. $sql_ary = array();
  2552. }
  2553. else
  2554. {
  2555. if (!$store_db && !$safe_mode && phpbb_is_writable("{$phpbb_root_path}styles/{$style_row['template_path']}/template"))
  2556. {
  2557. $err = $this->store_in_fs('template', $style_row['template_id']);
  2558. if ($err)
  2559. {
  2560. $error += $err;
  2561. }
  2562. }
  2563. else if ($store_db)
  2564. {
  2565. $this->store_in_db('template', $style_row['template_id']);
  2566. }
  2567. else
  2568. {
  2569. // We no longer store within the db, but are also not able to update the file structure
  2570. // Since the admin want to switch this, we adhere to his decision. But we also need to remove the cache
  2571. $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
  2572. WHERE template_id = $style_id";
  2573. $db->sql_query($sql);
  2574. }
  2575.  
  2576. $sql_ary += array(
  2577. 'template_storedb' => $store_db,
  2578. );
  2579. }
  2580. }
  2581. break;
  2582. }
  2583.  
  2584. if (sizeof($sql_ary))
  2585. {
  2586. $sql = "UPDATE $sql_from
  2587. SET " . $db->sql_build_array('UPDATE', $sql_ary) . "
  2588. WHERE {$mode}_id = $style_id";
  2589. $db->sql_query($sql);
  2590.  
  2591. // Making this the default style?
  2592. if ($mode == 'style' && $style_default)
  2593. {
  2594. set_config('default_style', $style_id);
  2595. }
  2596. }
  2597.  
  2598. $cache->destroy('sql', STYLES_TABLE);
  2599.  
  2600. add_log('admin', 'LOG_' . $l_type . '_EDIT_DETAILS', $name);
  2601. if (sizeof($error))
  2602. {
  2603. trigger_error(implode('<br />', $error) . adm_back_link($this->u_action), E_USER_WARNING);
  2604. }
  2605. else
  2606. {
  2607. trigger_error($user->lang[$l_type . '_DETAILS_UPDATED'] . adm_back_link($this->u_action));
  2608. }
  2609. }
  2610.  
  2611. if ($mode == 'style')
  2612. {
  2613. foreach ($element_ary as $element => $table)
  2614. {
  2615. $sql = "SELECT {$element}_id, {$element}_name
  2616. FROM $table
  2617. ORDER BY {$element}_id ASC";
  2618. $result = $db->sql_query($sql);
  2619.  
  2620. ${$element . '_options'} = '';
  2621. while ($row = $db->sql_fetchrow($result))
  2622. {
  2623. $selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : '';
  2624. ${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>';
  2625. }
  2626. $db->sql_freeresult($result);
  2627. }
  2628. }
  2629.  
  2630. if ($mode == 'template')
  2631. {
  2632. $super = array();
  2633. if (isset($style_row[$mode . '_inherits_id']) && $style_row['template_inherits_id'])
  2634. {
  2635. $super = $this->get_super($mode, $style_row['template_id']);
  2636. }
  2637. }
  2638.  
  2639. $this->page_title = 'EDIT_DETAILS_' . $l_type;
  2640.  
  2641. $template->assign_vars(array(
  2642. 'S_DETAILS' => true,
  2643. 'S_ERROR_MSG' => (sizeof($error)) ? true : false,
  2644. 'S_STYLE' => ($mode == 'style') ? true : false,
  2645. 'S_TEMPLATE' => ($mode == 'template') ? true : false,
  2646. 'S_THEME' => ($mode == 'theme') ? true : false,
  2647. 'S_IMAGESET' => ($mode == 'imageset') ? true : false,
  2648. 'S_STORE_DB' => (isset($style_row[$mode . '_storedb'])) ? $style_row[$mode . '_storedb'] : 0,
  2649. 'S_STORE_DB_DISABLED' => (isset($style_row[$mode . '_inherits_id'])) ? $style_row[$mode . '_inherits_id'] : 0,
  2650. 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0,
  2651. 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0,
  2652. 'S_SUPERTEMPLATE' => (isset($style_row[$mode . '_inherits_id']) && $style_row[$mode . '_inherits_id']) ? $super['template_name'] : 0,
  2653.  
  2654. 'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '',
  2655. 'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '',
  2656. 'S_IMAGESET_OPTIONS' => ($mode == 'style') ? $imageset_options : '',
  2657.  
  2658. 'U_ACTION' => $this->u_action . '&amp;action=details&amp;id=' . $style_id,
  2659. 'U_BACK' => $this->u_action,
  2660.  
  2661. 'L_TITLE' => $user->lang[$this->page_title],
  2662. 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
  2663. 'L_NAME' => $user->lang[$l_type . '_NAME'],
  2664. 'L_LOCATION' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '',
  2665. 'L_LOCATION_EXPLAIN' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '',
  2666.  
  2667. 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '',
  2668. 'NAME' => $style_row[$mode . '_name'],
  2669. 'COPYRIGHT' => $style_row[$mode . '_copyright'],
  2670. )
  2671. );
  2672. }
  2673.  
  2674. /**
  2675. * Load css file contents
  2676. */
  2677. function load_css_file($path, $filename)
  2678. {
  2679. global $phpbb_root_path;
  2680.  
  2681. $file = "{$phpbb_root_path}styles/$path/theme/$filename";
  2682.  
  2683. if (file_exists($file) && ($content = file_get_contents($file)))
  2684. {
  2685. $content = trim($content);
  2686. }
  2687. else
  2688. {
  2689. $content = '';
  2690. }
  2691. if (defined('DEBUG'))
  2692. {
  2693. $content = "/* BEGIN @include $filename */ \n $content \n /* END @include $filename */ \n";
  2694. }
  2695.  
  2696. return $content;
  2697. }
  2698.  
  2699. /**
  2700. * Returns a string containing the value that should be used for the theme_data column in the theme database table.
  2701. * Includes contents of files loaded via @import
  2702. *
  2703. * @param array $theme_row is an associative array containing the theme's current database entry
  2704. * @param mixed $stylesheet can either be the new content for the stylesheet or false to load from the standard file
  2705. * @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']}"
  2706. *
  2707. * @return string Stylesheet data for theme_data column in the theme table
  2708. */
  2709. function db_theme_data($theme_row, $stylesheet = false, $root_path = '')
  2710. {
  2711. global $phpbb_root_path;
  2712.  
  2713. if (!$root_path)
  2714. {
  2715. $root_path = $phpbb_root_path . 'styles/' . $theme_row['theme_path'];
  2716. }
  2717.  
  2718. if (!$stylesheet)
  2719. {
  2720. $stylesheet = '';
  2721. if (file_exists($root_path . '/theme/stylesheet.css'))
  2722. {
  2723. $stylesheet = file_get_contents($root_path . '/theme/stylesheet.css');
  2724. }
  2725. }
  2726.  
  2727. // Match CSS imports
  2728. $matches = array();
  2729. preg_match_all('/@import url\((["\'])(.*)\1\);/i', $stylesheet, $matches);
  2730.  
  2731. // remove commented stylesheets (very simple parser, allows only whitespace
  2732. // around an @import statement)
  2733. preg_match_all('#/\*\s*@import url\((["\'])(.*)\1\);\s\*/#i', $stylesheet, $commented);
  2734. $matches[2] = array_diff($matches[2], $commented[2]);
  2735.  
  2736. if (sizeof($matches))
  2737. {
  2738. foreach ($matches[0] as $idx => $match)
  2739. {
  2740. if (isset($matches[2][$idx]))
  2741. {
  2742. $stylesheet = str_replace($match, acp_styles::load_css_file($theme_row['theme_path'], $matches[2][$idx]), $stylesheet);
  2743. }
  2744. }
  2745. }
  2746.  
  2747. // adjust paths
  2748. return str_replace('./', 'styles/' . $theme_row['theme_path'] . '/theme/', $stylesheet);
  2749. }
  2750.  
  2751. /**
  2752. * Store template files into db
  2753. */
  2754. function store_templates($mode, $style_id, $template_path, $filelist)
  2755. {
  2756. global $phpbb_root_path, $phpEx, $db;
  2757.  
  2758. $template_path = $template_path . '/template/';
  2759. $includes = array();
  2760. foreach ($filelist as $pathfile => $file_ary)
  2761. {
  2762. foreach ($file_ary as $file)
  2763. {
  2764. if (!($fp = @fopen("{$phpbb_root_path}styles/$template_path$pathfile$file", 'r')))
  2765. {
  2766. trigger_error("Could not open {$phpbb_root_path}styles/$template_path$pathfile$file", E_USER_ERROR);
  2767. }
  2768.  
  2769. $filesize = filesize("{$phpbb_root_path}styles/$template_path$pathfile$file");
  2770.  
  2771. if ($filesize)
  2772. {
  2773. $template_data = fread($fp, $filesize);
  2774. }
  2775.  
  2776. fclose($fp);
  2777.  
  2778. if (!$filesize)
  2779. {
  2780. // File is empty
  2781. continue;
  2782. }
  2783.  
  2784. if (preg_match_all('#<!-- INCLUDE (.*?\.html) -->#is', $template_data, $matches))
  2785. {
  2786. foreach ($matches[1] as $match)
  2787. {
  2788. $includes[trim($match)][] = $file;
  2789. }
  2790. }
  2791. }
  2792. }
  2793.  
  2794. foreach ($filelist as $pathfile => $file_ary)
  2795. {
  2796. foreach ($file_ary as $file)
  2797. {
  2798. // Skip index.
  2799. if (strpos($file, 'index.') === 0)
  2800. {
  2801. continue;
  2802. }
  2803.  
  2804. // We could do this using extended inserts ... but that could be one
  2805. // heck of a lot of data ...
  2806. $sql_ary = array(
  2807. 'template_id' => (int) $style_id,
  2808. 'template_filename' => "$pathfile$file",
  2809. 'template_included' => (isset($includes[$file])) ? implode(':', $includes[$file]) . ':' : '',
  2810. 'template_mtime' => (int) filemtime("{$phpbb_root_path}styles/$template_path$pathfile$file"),
  2811. 'template_data' => (string) file_get_contents("{$phpbb_root_path}styles/$template_path$pathfile$file"),
  2812. );
  2813.  
  2814. if ($mode == 'insert')
  2815. {
  2816. $sql = 'INSERT INTO ' . STYLES_TEMPLATE_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
  2817. }
  2818. else
  2819. {
  2820. $sql = 'UPDATE ' . STYLES_TEMPLATE_DATA_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
  2821. WHERE template_id = $style_id
  2822. AND template_filename = '" . $db->sql_escape("$pathfile$file") . "'";
  2823. }
  2824. $db->sql_query($sql);
  2825. }
  2826. }
  2827. }
  2828.  
  2829. /**
  2830. * Returns an array containing all template filenames for one template that are currently cached.
  2831. *
  2832. * @param string $template_path contains the name of the template's folder in /styles/
  2833. *
  2834. * @return array of filenames that exist in /styles/$template_path/template/ (without extension!)
  2835. */
  2836. function template_cache_filelist($template_path)
  2837. {
  2838. global $phpbb_root_path, $phpEx, $user;
  2839.  
  2840. $cache_prefix = 'tpl_' . str_replace('_', '-', $template_path);
  2841.  
  2842. if (!($dp = @opendir("{$phpbb_root_path}cache")))
  2843. {
  2844. trigger_error($user->lang['TEMPLATE_ERR_CACHE_READ'] . adm_back_link($this->u_action), E_USER_WARNING);
  2845. }
  2846.  
  2847. $file_ary = array();
  2848. while ($file = readdir($dp))
  2849. {
  2850. if ($file[0] == '.')
  2851. {
  2852. continue;
  2853. }
  2854.  
  2855. if (is_file($phpbb_root_path . 'cache/' . $file) && (strpos($file, $cache_prefix) === 0))
  2856. {
  2857. $file_ary[] = str_replace('.', '/', preg_replace('#^' . preg_quote($cache_prefix, '#') . '_(.*?)\.html\.' . $phpEx . '$#i', '\1', $file));
  2858. }
  2859. }
  2860. closedir($dp);
  2861.  
  2862. return $file_ary;
  2863. }
  2864.  
  2865. /**
  2866. * Destroys cached versions of template files
  2867. *
  2868. * @param array $template_row contains the template's row in the STYLES_TEMPLATE_TABLE database table
  2869. * @param mixed $file_ary is optional and may contain an array of template file names which should be refreshed in the cache.
  2870. * The file names should be the original template file names and not the cache file names.
  2871. */
  2872. function clear_template_cache($template_row, $file_ary = false)
  2873. {
  2874. global $phpbb_root_path, $phpEx, $user;
  2875.  
  2876. $cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']);
  2877.  
  2878. if (!$file_ary || !is_array($file_ary))
  2879. {
  2880. $file_ary = $this->template_cache_filelist($template_row['template_path']);
  2881. $log_file_list = $user->lang['ALL_FILES'];
  2882. }
  2883. else
  2884. {
  2885. $log_file_list = implode(', ', $file_ary);
  2886. }
  2887.  
  2888. foreach ($file_ary as $file)
  2889. {
  2890. $file = str_replace('/', '.', $file);
  2891.  
  2892. $file = "{$phpbb_root_path}cache/{$cache_prefix}_$file.html.$phpEx";
  2893. if (file_exists($file) && is_file($file))
  2894. {
  2895. @unlink($file);
  2896. }
  2897. }
  2898. unset($file_ary);
  2899.  
  2900. add_log('admin', 'LOG_TEMPLATE_CACHE_CLEARED', $template_row['template_name'], $log_file_list);
  2901. }
  2902.  
  2903. /**
  2904. * Install Style/Template/Theme/Imageset
  2905. */
  2906. function install($mode)
  2907. {
  2908. global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template;
  2909.  
  2910. $l_type = strtoupper($mode);
  2911.  
  2912. $error = $installcfg = $style_row = array();
  2913. $root_path = $cfg_file = '';
  2914. $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE);
  2915.  
  2916. $install_path = request_var('path', '');
  2917. $update = (isset($_POST['update'])) ? true : false;
  2918.  
  2919. // Installing, obtain cfg file contents
  2920. if ($install_path)
  2921. {
  2922. $root_path = $phpbb_root_path . 'styles/' . $install_path . '/';
  2923. $cfg_file = ($mode == 'style') ? "$root_path$mode.cfg" : "$root_path$mode/$mode.cfg";
  2924.  
  2925. if (!file_exists($cfg_file))
  2926. {
  2927. $error[] = $user->lang[$l_type . '_ERR_NOT_' . $l_type];
  2928. }
  2929. else
  2930. {
  2931. $installcfg = parse_cfg_file($cfg_file);
  2932. }
  2933. }
  2934.  
  2935. // Installing
  2936. if (sizeof($installcfg))
  2937. {
  2938. $name = $installcfg['name'];
  2939. $copyright = $installcfg['copyright'];
  2940. $version = $installcfg['version'];
  2941.  
  2942. $style_row = array(
  2943. $mode . '_id' => 0,
  2944. $mode . '_name' => '',
  2945. $mode . '_copyright' => ''
  2946. );
  2947.  
  2948. switch ($mode)
  2949. {
  2950. case 'style':
  2951.  
  2952. $style_row = array(
  2953. 'style_id' => 0,
  2954. 'style_name' => $installcfg['name'],
  2955. 'style_copyright' => $installcfg['copyright']
  2956. );
  2957.  
  2958. $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false;
  2959. $reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false;
  2960. $reqd_imageset = (isset($installcfg['required_imageset'])) ? $installcfg['required_imageset'] : false;
  2961.  
  2962. // Check to see if each element is already installed, if it is grab the id
  2963. foreach ($element_ary as $element => $table)
  2964. {
  2965. $style_row = array_merge($style_row, array(
  2966. $element . '_id' => 0,
  2967. $element . '_name' => '',
  2968. $element . '_copyright' => '')
  2969. );
  2970.  
  2971. $this->test_installed($element, $error, (${'reqd_' . $element}) ? $phpbb_root_path . 'styles/' . $reqd_template . '/' : $root_path, ${'reqd_' . $element}, $style_row[$element . '_id'], $style_row[$element . '_name'], $style_row[$element . '_copyright']);
  2972.  
  2973. if (!$style_row[$element . '_name'])
  2974. {
  2975. $style_row[$element . '_name'] = $reqd_template;
  2976. }
  2977.  
  2978. // Merge other information to installcfg... if present
  2979. $cfg_file = $phpbb_root_path . 'styles/' . $install_path . '/' . $element . '/' . $element . '.cfg';
  2980.  
  2981. if (file_exists($cfg_file))
  2982. {
  2983. $cfg_contents = parse_cfg_file($cfg_file);
  2984.  
  2985. // Merge only specific things. We may need them later.
  2986. foreach (array('inherit_from', 'parse_css_file') as $key)
  2987. {
  2988. if (!empty($cfg_contents[$key]) && !isset($installcfg[$key]))
  2989. {
  2990. $installcfg[$key] = $cfg_contents[$key];
  2991. }
  2992. }
  2993. }
  2994. }
  2995.  
  2996. break;
  2997.  
  2998. case 'template':
  2999. $this->test_installed('template', $error, $root_path, false, $style_row['template_id'], $style_row['template_name'], $style_row['template_copyright']);
  3000. break;
  3001.  
  3002. case 'theme':
  3003. $this->test_installed('theme', $error, $root_path, false, $style_row['theme_id'], $style_row['theme_name'], $style_row['theme_copyright']);
  3004. break;
  3005.  
  3006. case 'imageset':
  3007. $this->test_installed('imageset', $error, $root_path, false, $style_row['imageset_id'], $style_row['imageset_name'], $style_row['imageset_copyright']);
  3008. break;
  3009. }
  3010. }
  3011. else
  3012. {
  3013. trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING);
  3014. }
  3015.  
  3016. $style_row['store_db'] = request_var('store_db', 0);
  3017. $style_row['style_active'] = request_var('style_active', 1);
  3018. $style_row['style_default'] = request_var('style_default', 0);
  3019.  
  3020. // User has submitted form and no errors have occurred
  3021. if ($update && !sizeof($error))
  3022. {
  3023. if ($mode == 'style')
  3024. {
  3025. foreach ($element_ary as $element => $table)
  3026. {
  3027. ${$element . '_root_path'} = (${'reqd_' . $element}) ? $phpbb_root_path . 'styles/' . ${'reqd_' . $element} . '/' : false;
  3028. ${$element . '_path'} = (${'reqd_' . $element}) ? ${'reqd_' . $element} : false;
  3029. }
  3030. $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, $template_root_path, $template_path, $theme_root_path, $theme_path, $imageset_root_path, $imageset_path);
  3031. }
  3032. else
  3033. {
  3034. $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']);
  3035. }
  3036.  
  3037. if (!sizeof($error))
  3038. {
  3039. $cache->destroy('sql', STYLES_TABLE);
  3040.  
  3041. $message = ($style_row['store_db']) ? '_ADDED_DB' : '_ADDED';
  3042. trigger_error($user->lang[$l_type . $message] . adm_back_link($this->u_action));
  3043. }
  3044. }
  3045.  
  3046. $this->page_title = 'INSTALL_' . $l_type;
  3047.  
  3048. $template->assign_vars(array(
  3049. 'S_DETAILS' => true,
  3050. 'S_INSTALL' => true,
  3051. 'S_ERROR_MSG' => (sizeof($error)) ? true : false,
  3052. 'S_LOCATION' => (isset($installcfg['inherit_from']) && $installcfg['inherit_from']) ? false : true,
  3053. 'S_STYLE' => ($mode == 'style') ? true : false,
  3054. 'S_TEMPLATE' => ($mode == 'template') ? true : false,
  3055. 'S_SUPERTEMPLATE' => (isset($installcfg['inherit_from'])) ? $installcfg['inherit_from'] : '',
  3056. 'S_THEME' => ($mode == 'theme') ? true : false,
  3057.  
  3058. 'S_STORE_DB' => (isset($style_row[$mode . '_storedb'])) ? $style_row[$mode . '_storedb'] : 0,
  3059. 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0,
  3060. 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0,
  3061.  
  3062. 'U_ACTION' => $this->u_action . "&amp;action=install&amp;path=" . urlencode($install_path),
  3063. 'U_BACK' => $this->u_action,
  3064.  
  3065. 'L_TITLE' => $user->lang[$this->page_title],
  3066. 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
  3067. 'L_NAME' => $user->lang[$l_type . '_NAME'],
  3068. 'L_LOCATION' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '',
  3069. 'L_LOCATION_EXPLAIN' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '',
  3070.  
  3071. 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '',
  3072. 'NAME' => $style_row[$mode . '_name'],
  3073. 'COPYRIGHT' => $style_row[$mode . '_copyright'],
  3074. 'TEMPLATE_NAME' => ($mode == 'style') ? $style_row['template_name'] : '',
  3075. 'THEME_NAME' => ($mode == 'style') ? $style_row['theme_name'] : '',
  3076. 'IMAGESET_NAME' => ($mode == 'style') ? $style_row['imageset_name'] : '')
  3077. );
  3078. }
  3079.  
  3080. /**
  3081. * Add new style
  3082. */
  3083. function add($mode)
  3084. {
  3085. global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template;
  3086.  
  3087. $l_type = strtoupper($mode);
  3088. $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE);
  3089. $error = array();
  3090.  
  3091. $style_row = array(
  3092. $mode . '_name' => utf8_normalize_nfc(request_var('name', '', true)),
  3093. $mode . '_copyright' => utf8_normalize_nfc(request_var('copyright', '', true)),
  3094. 'template_id' => 0,
  3095. 'theme_id' => 0,
  3096. 'imageset_id' => 0,
  3097. 'store_db' => request_var('store_db', 0),
  3098. 'style_active' => request_var('style_active', 1),
  3099. 'style_default' => request_var('style_default', 0),
  3100. );
  3101.  
  3102. $basis = request_var('basis', 0);
  3103. $update = (isset($_POST['update'])) ? true : false;
  3104.  
  3105. if ($basis)
  3106. {
  3107. switch ($mode)
  3108. {
  3109. case 'style':
  3110. $sql_select = 'template_id, theme_id, imageset_id';
  3111. $sql_from = STYLES_TABLE;
  3112. break;
  3113.  
  3114. case 'template':
  3115. $sql_select = 'template_id';
  3116. $sql_from = STYLES_TEMPLATE_TABLE;
  3117. break;
  3118.  
  3119. case 'theme':
  3120. $sql_select = 'theme_id';
  3121. $sql_from = STYLES_THEME_TABLE;
  3122. break;
  3123.  
  3124. case 'imageset':
  3125. $sql_select = 'imageset_id';
  3126. $sql_from = STYLES_IMAGESET_TABLE;
  3127. break;
  3128. }
  3129.  
  3130. $sql = "SELECT $sql_select
  3131. FROM $sql_from
  3132. WHERE {$mode}_id = $basis";
  3133. $result = $db->sql_query($sql);
  3134. $row = $db->sql_fetchrow($result);
  3135. $db->sql_freeresult($result);
  3136.  
  3137. if (!$row)
  3138. {
  3139. $error[] = $user->lang['NO_' . $l_type];
  3140. }
  3141.  
  3142. if (!sizeof($error))
  3143. {
  3144. $style_row['template_id'] = (isset($row['template_id'])) ? $row['template_id'] : $style_row['template_id'];
  3145. $style_row['theme_id'] = (isset($row['theme_id'])) ? $row['theme_id'] : $style_row['theme_id'];
  3146. $style_row['imageset_id'] = (isset($row['imageset_id'])) ? $row['imageset_id'] : $style_row['imageset_id'];
  3147. }
  3148. }
  3149.  
  3150. if ($update)
  3151. {
  3152. $style_row['template_id'] = request_var('template_id', $style_row['template_id']);
  3153. $style_row['theme_id'] = request_var('theme_id', $style_row['theme_id']);
  3154. $style_row['imageset_id'] = request_var('imageset_id', $style_row['imageset_id']);
  3155.  
  3156. if ($mode == 'style' && (!$style_row['template_id'] || !$style_row['theme_id'] || !$style_row['imageset_id']))
  3157. {
  3158. $error[] = $user->lang['STYLE_ERR_NO_IDS'];
  3159. }
  3160. }
  3161.  
  3162. // User has submitted form and no errors have occurred
  3163. if ($update && !sizeof($error))
  3164. {
  3165. if ($mode == 'style')
  3166. {
  3167. $style_row['style_id'] = 0;
  3168.  
  3169. $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);
  3170. }
  3171.  
  3172. if (!sizeof($error))
  3173. {
  3174. $cache->destroy('sql', STYLES_TABLE);
  3175.  
  3176. $message = ($style_row['store_db']) ? '_ADDED_DB' : '_ADDED';
  3177. trigger_error($user->lang[$l_type . $message] . adm_back_link($this->u_action));
  3178. }
  3179. }
  3180.  
  3181. if ($mode == 'style')
  3182. {
  3183. foreach ($element_ary as $element => $table)
  3184. {
  3185. $sql = "SELECT {$element}_id, {$element}_name
  3186. FROM $table
  3187. ORDER BY {$element}_id ASC";
  3188. $result = $db->sql_query($sql);
  3189.  
  3190. ${$element . '_options'} = '';
  3191. while ($row = $db->sql_fetchrow($result))
  3192. {
  3193. $selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : '';
  3194. ${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>';
  3195. }
  3196. $db->sql_freeresult($result);
  3197. }
  3198. }
  3199.  
  3200. $this->page_title = 'ADD_' . $l_type;
  3201.  
  3202. $template->assign_vars(array(
  3203. 'S_DETAILS' => true,
  3204. 'S_ADD' => true,
  3205. 'S_ERROR_MSG' => (sizeof($error)) ? true : false,
  3206. 'S_STYLE' => ($mode == 'style') ? true : false,
  3207. 'S_TEMPLATE' => ($mode == 'template') ? true : false,
  3208. 'S_THEME' => ($mode == 'theme') ? true : false,
  3209. 'S_BASIS' => ($basis) ? true : false,
  3210.  
  3211. 'S_STORE_DB' => (isset($style_row['storedb'])) ? $style_row['storedb'] : 0,
  3212. 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0,
  3213. 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0,
  3214. 'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '',
  3215. 'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '',
  3216. 'S_IMAGESET_OPTIONS' => ($mode == 'style') ? $imageset_options : '',
  3217.  
  3218. 'U_ACTION' => $this->u_action . '&amp;action=add&amp;basis=' . $basis,
  3219. 'U_BACK' => $this->u_action,
  3220.  
  3221. 'L_TITLE' => $user->lang[$this->page_title],
  3222. 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
  3223. 'L_NAME' => $user->lang[$l_type . '_NAME'],
  3224. 'L_LOCATION' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '',
  3225. 'L_LOCATION_EXPLAIN' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '',
  3226.  
  3227. 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '',
  3228. 'NAME' => $style_row[$mode . '_name'],
  3229. 'COPYRIGHT' => $style_row[$mode . '_copyright'])
  3230. );
  3231.  
  3232. }
  3233.  
  3234. /**
  3235.  
  3236. $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false;
  3237. $reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false;
  3238. $reqd_imageset = (isset($installcfg['required_imageset'])) ? $installcfg['required_imageset'] : false;
  3239.  
  3240. // Check to see if each element is already installed, if it is grab the id
  3241. foreach ($element_ary as $element => $table)
  3242. {
  3243. $style_row = array_merge($style_row, array(
  3244. $element . '_id' => 0,
  3245. $element . '_name' => '',
  3246. $element . '_copyright' => '')
  3247. );
  3248.  
  3249. $this->test_installed($element, $error, $root_path, ${'reqd_' . $element}, $style_row[$element . '_id'], $style_row[$element . '_name'], $style_row[$element . '_copyright']);
  3250. * Is this element installed? If not, grab its cfg details
  3251. */
  3252. function test_installed($element, &$error, $root_path, $reqd_name, &$id, &$name, &$copyright)
  3253. {
  3254. global $db, $user;
  3255.  
  3256. switch ($element)
  3257. {
  3258. case 'template':
  3259. $sql_from = STYLES_TEMPLATE_TABLE;
  3260. break;
  3261.  
  3262. case 'theme':
  3263. $sql_from = STYLES_THEME_TABLE;
  3264. break;
  3265.  
  3266. case 'imageset':
  3267. $sql_from = STYLES_IMAGESET_TABLE;
  3268. break;
  3269. }
  3270.  
  3271. $l_element = strtoupper($element);
  3272.  
  3273. $chk_name = ($reqd_name !== false) ? $reqd_name : $name;
  3274.  
  3275. $sql = "SELECT {$element}_id, {$element}_name
  3276. FROM $sql_from
  3277. WHERE {$element}_name = '" . $db->sql_escape($chk_name) . "'";
  3278. $result = $db->sql_query($sql);
  3279.  
  3280. if ($row = $db->sql_fetchrow($result))
  3281. {
  3282. $name = $row[$element . '_name'];
  3283. $id = $row[$element . '_id'];
  3284. }
  3285. else
  3286. {
  3287. if (!($cfg = @file("$root_path$element/$element.cfg")))
  3288. {
  3289. $error[] = sprintf($user->lang['REQUIRES_' . $l_element], $reqd_name);
  3290. return false;
  3291. }
  3292.  
  3293. $cfg = parse_cfg_file("$root_path$element/$element.cfg", $cfg);
  3294.  
  3295. $name = $cfg['name'];
  3296. $copyright = $cfg['copyright'];
  3297. $id = 0;
  3298.  
  3299. unset($cfg);
  3300. }
  3301. $db->sql_freeresult($result);
  3302. }
  3303.  
  3304. /**
  3305. * Install/Add style
  3306. */
  3307. function install_style(&$error, $action, $root_path, &$id, $name, $path, $copyright, $active, $default, &$style_row, $template_root_path = false, $template_path = false, $theme_root_path = false, $theme_path = false, $imageset_root_path = false, $imageset_path = false)
  3308. {
  3309. global $config, $db, $user;
  3310.  
  3311. $element_ary = array('template', 'theme', 'imageset');
  3312.  
  3313. if (!$name)
  3314. {
  3315. $error[] = $user->lang['STYLE_ERR_STYLE_NAME'];
  3316. }
  3317.  
  3318. // Check length settings
  3319. if (utf8_strlen($name) > 30)
  3320. {
  3321. $error[] = $user->lang['STYLE_ERR_NAME_LONG'];
  3322. }
  3323.  
  3324. if (utf8_strlen($copyright) > 60)
  3325. {
  3326. $error[] = $user->lang['STYLE_ERR_COPY_LONG'];
  3327. }
  3328.  
  3329. // Check if the name already exist
  3330. $sql = 'SELECT style_id
  3331. FROM ' . STYLES_TABLE . "
  3332. WHERE style_name = '" . $db->sql_escape($name) . "'";
  3333. $result = $db->sql_query($sql);
  3334. $row = $db->sql_fetchrow($result);
  3335. $db->sql_freeresult($result);
  3336.  
  3337. if ($row)
  3338. {
  3339. $error[] = $user->lang['STYLE_ERR_NAME_EXIST'];
  3340. }
  3341.  
  3342. if (sizeof($error))
  3343. {
  3344. return false;
  3345. }
  3346.  
  3347. foreach ($element_ary as $element)
  3348. {
  3349. // Zero id value ... need to install element ... run usual checks
  3350. // and do the install if necessary
  3351. if (!$style_row[$element . '_id'])
  3352. {
  3353. $this->install_element($element, $error, $action, (${$element . '_root_path'}) ? ${$element . '_root_path'} : $root_path, $style_row[$element . '_id'], $style_row[$element . '_name'], (${$element . '_path'}) ? ${$element . '_path'} : $path, $style_row[$element . '_copyright']);
  3354. }
  3355. }
  3356.  
  3357. if (!$style_row['template_id'] || !$style_row['theme_id'] || !$style_row['imageset_id'])
  3358. {
  3359. $error[] = $user->lang['STYLE_ERR_NO_IDS'];
  3360. }
  3361.  
  3362. if (sizeof($error))
  3363. {
  3364. return false;
  3365. }
  3366.  
  3367. $db->sql_transaction('begin');
  3368.  
  3369. $sql_ary = array(
  3370. 'style_name' => $name,
  3371. 'style_copyright' => $copyright,
  3372. 'style_active' => (int) $active,
  3373. 'template_id' => (int) $style_row['template_id'],
  3374. 'theme_id' => (int) $style_row['theme_id'],
  3375. 'imageset_id' => (int) $style_row['imageset_id'],
  3376. );
  3377.  
  3378. $sql = 'INSERT INTO ' . STYLES_TABLE . '
  3379. ' . $db->sql_build_array('INSERT', $sql_ary);
  3380. $db->sql_query($sql);
  3381.  
  3382. $id = $db->sql_nextid();
  3383.  
  3384. if ($default)
  3385. {
  3386. $sql = 'UPDATE ' . USERS_TABLE . "
  3387. SET user_style = $id
  3388. WHERE user_style = " . $config['default_style'];
  3389. $db->sql_query($sql);
  3390.  
  3391. set_config('default_style', $id);
  3392. }
  3393.  
  3394. $db->sql_transaction('commit');
  3395.  
  3396. add_log('admin', 'LOG_STYLE_ADD', $name);
  3397. }
  3398.  
  3399. /**
  3400. * Install/add an element, doing various checks as we go
  3401. */
  3402. function install_element($mode, &$error, $action, $root_path, &$id, $name, $path, $copyright, $store_db = 0)
  3403. {
  3404. global $phpbb_root_path, $db, $user;
  3405.  
  3406. // we parse the cfg here (again)
  3407. $cfg_data = parse_cfg_file("$root_path$mode/$mode.cfg");
  3408.  
  3409. switch ($mode)
  3410. {
  3411. case 'template':
  3412. $sql_from = STYLES_TEMPLATE_TABLE;
  3413. break;
  3414.  
  3415. case 'theme':
  3416. $sql_from = STYLES_THEME_TABLE;
  3417. break;
  3418.  
  3419. case 'imageset':
  3420. $sql_from = STYLES_IMAGESET_TABLE;
  3421. break;
  3422. }
  3423.  
  3424. $l_type = strtoupper($mode);
  3425.  
  3426. if (!$name)
  3427. {
  3428. $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME'];
  3429. }
  3430.  
  3431. // Check length settings
  3432. if (utf8_strlen($name) > 30)
  3433. {
  3434. $error[] = $user->lang[$l_type . '_ERR_NAME_LONG'];
  3435. }
  3436.  
  3437. if (utf8_strlen($copyright) > 60)
  3438. {
  3439. $error[] = $user->lang[$l_type . '_ERR_COPY_LONG'];
  3440. }
  3441.  
  3442. // Check if the name already exist
  3443. $sql = "SELECT {$mode}_id
  3444. FROM $sql_from
  3445. WHERE {$mode}_name = '" . $db->sql_escape($name) . "'";
  3446. $result = $db->sql_query($sql);
  3447. $row = $db->sql_fetchrow($result);
  3448. $db->sql_freeresult($result);
  3449.  
  3450. if ($row)
  3451. {
  3452. // If it exist, we just use the style on installation
  3453. if ($action == 'install')
  3454. {
  3455. $id = $row[$mode . '_id'];
  3456. return false;
  3457. }
  3458.  
  3459. $error[] = $user->lang[$l_type . '_ERR_NAME_EXIST'];
  3460. }
  3461.  
  3462. if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from'])
  3463. {
  3464. if ($mode === 'template')
  3465. {
  3466. $select_bf = ', bbcode_bitfield';
  3467. }
  3468. else
  3469. {
  3470. $select_bf = '';
  3471. }
  3472.  
  3473. $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path, {$mode}_storedb $select_bf
  3474. FROM $sql_from
  3475. WHERE {$mode}_name = '" . $db->sql_escape($cfg_data['inherit_from']) . "'
  3476. AND {$mode}_inherits_id = 0";
  3477. $result = $db->sql_query($sql);
  3478. $row = $db->sql_fetchrow($result);
  3479. $db->sql_freeresult($result);
  3480. if (!$row)
  3481. {
  3482. $error[] = sprintf($user->lang[$l_type . '_ERR_REQUIRED_OR_INCOMPLETE'], $cfg_data['inherit_from']);
  3483. }
  3484. else
  3485. {
  3486. $inherit_id = $row["{$mode}_id"];
  3487. $inherit_path = $row["{$mode}_path"];
  3488. $inherit_bf = ($mode === 'template') ? $row["bbcode_bitfield"] : false;
  3489. $cfg_data['store_db'] = $row["{$mode}_storedb"];
  3490. $store_db = $row["{$mode}_storedb"];
  3491. }
  3492. }
  3493. else
  3494. {
  3495. $inherit_id = 0;
  3496. $inherit_path = '';
  3497. $inherit_bf = false;
  3498. }
  3499.  
  3500. if (sizeof($error))
  3501. {
  3502. return false;
  3503. }
  3504.  
  3505. $sql_ary = array(
  3506. $mode . '_name' => $name,
  3507. $mode . '_copyright' => $copyright,
  3508. $mode . '_path' => $path,
  3509. );
  3510.  
  3511. switch ($mode)
  3512. {
  3513. case 'template':
  3514. // We check if the template author defined a different bitfield
  3515. if (!empty($cfg_data['template_bitfield']))
  3516. {
  3517. $sql_ary['bbcode_bitfield'] = $cfg_data['template_bitfield'];
  3518. }
  3519. else if ($inherit_bf)
  3520. {
  3521. $sql_ary['bbcode_bitfield'] = $inherit_bf;
  3522. }
  3523. else
  3524. {
  3525. $sql_ary['bbcode_bitfield'] = TEMPLATE_BITFIELD;
  3526. }
  3527.  
  3528. // We set a pre-defined bitfield here which we may use further in 3.2
  3529. $sql_ary += array(
  3530. 'template_storedb' => $store_db,
  3531. );
  3532. if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from'])
  3533. {
  3534. $sql_ary += array(
  3535. 'template_inherits_id' => $inherit_id,
  3536. 'template_inherit_path' => $inherit_path,
  3537. );
  3538. }
  3539. break;
  3540.  
  3541. case 'theme':
  3542. // We are only interested in the theme configuration for now
  3543.  
  3544. if (isset($cfg_data['parse_css_file']) && $cfg_data['parse_css_file'])
  3545. {
  3546. $store_db = 1;
  3547. }
  3548.  
  3549. $sql_ary += array(
  3550. 'theme_storedb' => $store_db,
  3551. 'theme_data' => ($store_db) ? $this->db_theme_data($sql_ary, false, $root_path) : '',
  3552. 'theme_mtime' => (int) filemtime("{$phpbb_root_path}styles/$path/theme/stylesheet.css")
  3553. );
  3554. break;
  3555.  
  3556. // all the heavy lifting is done later
  3557. case 'imageset':
  3558. break;
  3559. }
  3560.  
  3561. $db->sql_transaction('begin');
  3562.  
  3563. $sql = "INSERT INTO $sql_from
  3564. " . $db->sql_build_array('INSERT', $sql_ary);
  3565. $db->sql_query($sql);
  3566.  
  3567. $id = $db->sql_nextid();
  3568.  
  3569. if ($mode == 'template' && $store_db)
  3570. {
  3571. $filelist = filelist("{$root_path}template", '', 'html');
  3572. $this->store_templates('insert', $id, $path, $filelist);
  3573. }
  3574. else if ($mode == 'imageset')
  3575. {
  3576. $cfg_data = parse_cfg_file("$root_path$mode/imageset.cfg");
  3577.  
  3578. $imageset_definitions = array();
  3579. foreach ($this->imageset_keys as $topic => $key_array)
  3580. {
  3581. $imageset_definitions = array_merge($imageset_definitions, $key_array);
  3582. }
  3583.  
  3584. foreach ($cfg_data as $key => $value)
  3585. {
  3586. if (strpos($value, '*') !== false)
  3587. {
  3588. if (substr($value, -1, 1) === '*')
  3589. {
  3590. list($image_filename, $image_height) = explode('*', $value);
  3591. $image_width = 0;
  3592. }
  3593. else
  3594. {
  3595. list($image_filename, $image_height, $image_width) = explode('*', $value);
  3596. }
  3597. }
  3598. else
  3599. {
  3600. $image_filename = $value;
  3601. $image_height = $image_width = 0;
  3602. }
  3603.  
  3604. if (strpos($key, 'img_') === 0 && $image_filename)
  3605. {
  3606. $key = substr($key, 4);
  3607. if (in_array($key, $imageset_definitions))
  3608. {
  3609. $sql_ary = array(
  3610. 'image_name' => $key,
  3611. 'image_filename' => str_replace('{PATH}', "styles/$path/imageset/", trim($image_filename)),
  3612. 'image_height' => (int) $image_height,
  3613. 'image_width' => (int) $image_width,
  3614. 'imageset_id' => (int) $id,
  3615. 'image_lang' => '',
  3616. );
  3617. $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
  3618. }
  3619. }
  3620. }
  3621. unset($cfg_data);
  3622.  
  3623. $sql = 'SELECT lang_dir
  3624. FROM ' . LANG_TABLE;
  3625. $result = $db->sql_query($sql);
  3626.  
  3627. while ($row = $db->sql_fetchrow($result))
  3628. {
  3629. if (@file_exists("$root_path$mode/{$row['lang_dir']}/imageset.cfg"))
  3630. {
  3631. $cfg_data_imageset_data = parse_cfg_file("$root_path$mode/{$row['lang_dir']}/imageset.cfg");
  3632. foreach ($cfg_data_imageset_data as $image_name => $value)
  3633. {
  3634. if (strpos($value, '*') !== false)
  3635. {
  3636. if (substr($value, -1, 1) === '*')
  3637. {
  3638. list($image_filename, $image_height) = explode('*', $value);
  3639. $image_width = 0;
  3640. }
  3641. else
  3642. {
  3643. list($image_filename, $image_height, $image_width) = explode('*', $value);
  3644. }
  3645. }
  3646. else
  3647. {
  3648. $image_filename = $value;
  3649. $image_height = $image_width = 0;
  3650. }
  3651.  
  3652. if (strpos($image_name, 'img_') === 0 && $image_filename)
  3653. {
  3654. $image_name = substr($image_name, 4);
  3655. if (in_array($image_name, $imageset_definitions))
  3656. {
  3657. $sql_ary = array(
  3658. 'image_name' => $image_name,
  3659. 'image_filename' => $image_filename,
  3660. 'image_height' => (int) $image_height,
  3661. 'image_width' => (int) $image_width,
  3662. 'imageset_id' => (int) $id,
  3663. 'image_lang' => $row['lang_dir'],
  3664. );
  3665. $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
  3666. }
  3667. }
  3668. }
  3669. unset($cfg_data_imageset_data);
  3670. }
  3671. }
  3672. $db->sql_freeresult($result);
  3673. }
  3674.  
  3675. $db->sql_transaction('commit');
  3676.  
  3677. $log = ($store_db) ? 'LOG_' . $l_type . '_ADD_DB' : 'LOG_' . $l_type . '_ADD_FS';
  3678. add_log('admin', $log, $name);
  3679.  
  3680. // Return store_db in case it had to be altered
  3681. return $store_db;
  3682. }
  3683.  
  3684. /**
  3685. * Checks downwards dependencies
  3686. *
  3687. * @access public
  3688. * @param string $mode The element type to check - only template is supported
  3689. * @param int $id The template id
  3690. * @returns false if no component inherits, array with name, path and id for each subtemplate otherwise
  3691. */
  3692. function check_inheritance($mode, $id)
  3693. {
  3694. global $db;
  3695.  
  3696. $l_type = strtoupper($mode);
  3697.  
  3698. switch ($mode)
  3699. {
  3700. case 'template':
  3701. $sql_from = STYLES_TEMPLATE_TABLE;
  3702. break;
  3703.  
  3704. case 'theme':
  3705. $sql_from = STYLES_THEME_TABLE;
  3706. break;
  3707.  
  3708. case 'imageset':
  3709. $sql_from = STYLES_IMAGESET_TABLE;
  3710. break;
  3711. }
  3712.  
  3713. $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path
  3714. FROM $sql_from
  3715. WHERE {$mode}_inherits_id = " . (int) $id;
  3716. $result = $db->sql_query($sql);
  3717.  
  3718. $names = array();
  3719. while ($row = $db->sql_fetchrow($result))
  3720. {
  3721.  
  3722. $names[$row["{$mode}_id"]] = array(
  3723. "{$mode}_id" => $row["{$mode}_id"],
  3724. "{$mode}_name" => $row["{$mode}_name"],
  3725. "{$mode}_path" => $row["{$mode}_path"],
  3726. );
  3727. }
  3728. $db->sql_freeresult($result);
  3729.  
  3730. if (sizeof($names))
  3731. {
  3732. return $names;
  3733. }
  3734. else
  3735. {
  3736. return false;
  3737. }
  3738. }
  3739.  
  3740. /**
  3741. * Checks upwards dependencies
  3742. *
  3743. * @access public
  3744. * @param string $mode The element type to check - only template is supported
  3745. * @param int $id The template id
  3746. * @returns false if the component does not inherit, array with name, path and id otherwise
  3747. */
  3748. function get_super($mode, $id)
  3749. {
  3750. global $db;
  3751.  
  3752. $l_type = strtoupper($mode);
  3753.  
  3754. switch ($mode)
  3755. {
  3756. case 'template':
  3757. $sql_from = STYLES_TEMPLATE_TABLE;
  3758. break;
  3759.  
  3760. case 'theme':
  3761. $sql_from = STYLES_THEME_TABLE;
  3762. break;
  3763.  
  3764. case 'imageset':
  3765. $sql_from = STYLES_IMAGESET_TABLE;
  3766. break;
  3767. }
  3768.  
  3769. $sql = "SELECT {$mode}_inherits_id
  3770. FROM $sql_from
  3771. WHERE {$mode}_id = " . (int) $id;
  3772. $result = $db->sql_query_limit($sql, 1);
  3773.  
  3774. if ($row = $db->sql_fetchrow($result))
  3775. {
  3776. $db->sql_freeresult($result);
  3777. }
  3778. else
  3779. {
  3780. return false;
  3781. }
  3782.  
  3783. $super_id = $row["{$mode}_inherits_id"];
  3784.  
  3785. $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path
  3786. FROM $sql_from
  3787. WHERE {$mode}_id = " . (int) $super_id;
  3788.  
  3789. $result = $db->sql_query_limit($sql, 1);
  3790. if ($row = $db->sql_fetchrow($result))
  3791. {
  3792. $db->sql_freeresult($result);
  3793. return $row;
  3794. }
  3795.  
  3796. return false;
  3797. }
  3798.  
  3799. /**
  3800. * Moves a template set and its subtemplates to the database
  3801. *
  3802. * @access public
  3803. * @param string $mode The component to move - only template is supported
  3804. * @param int $id The template id
  3805. */
  3806. function store_in_db($mode, $id)
  3807. {
  3808. global $db, $user;
  3809.  
  3810. $error = array();
  3811. $l_type = strtoupper($mode);
  3812. if ($super = $this->get_super($mode, $id))
  3813. {
  3814. $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name']));
  3815. return $error;
  3816. }
  3817.  
  3818. $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path
  3819. FROM " . STYLES_TEMPLATE_TABLE . '
  3820. WHERE template_id = ' . (int) $id;
  3821.  
  3822. $result = $db->sql_query_limit($sql, 1);
  3823. if ($row = $db->sql_fetchrow($result))
  3824. {
  3825. $db->sql_freeresult($result);
  3826. $subs = $this->check_inheritance($mode, $id);
  3827.  
  3828. $this->_store_in_db($mode, $id, $row["{$mode}_path"]);
  3829. if ($subs && sizeof($subs))
  3830. {
  3831. foreach ($subs as $sub_id => $sub)
  3832. {
  3833. if ($err = $this->_store_in_db($mode, $sub["{$mode}_id"], $sub["{$mode}_path"]))
  3834. {
  3835. $error[] = $err;
  3836. }
  3837. }
  3838. }
  3839. }
  3840. if (sizeof($error))
  3841. {
  3842. return $error;
  3843. }
  3844.  
  3845. return false;
  3846. }
  3847.  
  3848. /**
  3849. * Moves a template set to the database
  3850. *
  3851. * @access private
  3852. * @param string $mode The component to move - only template is supported
  3853. * @param int $id The template id
  3854. * @param string $path TThe path to the template files
  3855. */
  3856. function _store_in_db($mode, $id, $path)
  3857. {
  3858. global $phpbb_root_path, $db;
  3859.  
  3860. $filelist = filelist("{$phpbb_root_path}styles/{$path}/template", '', 'html');
  3861. $this->store_templates('insert', $id, $path, $filelist);
  3862.  
  3863. // Okay, we do the query here -shouldn't be triggered often.
  3864. $sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . '
  3865. SET template_storedb = 1
  3866. WHERE template_id = ' . $id;
  3867. $db->sql_query($sql);
  3868. }
  3869.  
  3870. /**
  3871. * Moves a template set and its subtemplates to the filesystem
  3872. *
  3873. * @access public
  3874. * @param string $mode The component to move - only template is supported
  3875. * @param int $id The template id
  3876. */
  3877. function store_in_fs($mode, $id)
  3878. {
  3879. global $db, $user;
  3880.  
  3881. $error = array();
  3882. $l_type = strtoupper($mode);
  3883. if ($super = $this->get_super($mode, $id))
  3884. {
  3885. $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name']));
  3886. return($error);
  3887. }
  3888.  
  3889. $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path
  3890. FROM " . STYLES_TEMPLATE_TABLE . '
  3891. WHERE template_id = ' . (int) $id;
  3892.  
  3893. $result = $db->sql_query_limit($sql, 1);
  3894. if ($row = $db->sql_fetchrow($result))
  3895. {
  3896. $db->sql_freeresult($result);
  3897. if (!sizeof($error))
  3898. {
  3899. $subs = $this->check_inheritance($mode, $id);
  3900.  
  3901. $this->_store_in_fs($mode, $id, $row["{$mode}_path"]);
  3902.  
  3903. if ($subs && sizeof($subs))
  3904. {
  3905. foreach ($subs as $sub_id => $sub)
  3906. {
  3907. $this->_store_in_fs($mode, $sub["{$mode}_id"], $sub["{$mode}_path"]);
  3908. }
  3909. }
  3910. }
  3911. if (sizeof($error))
  3912. {
  3913. $this->store_in_db($id, $mode);
  3914. return $error;
  3915. }
  3916. }
  3917. return false;
  3918. }
  3919.  
  3920. /**
  3921. * Moves a template set to the filesystem
  3922. *
  3923. * @access private
  3924. * @param string $mode The component to move - only template is supported
  3925. * @param int $id The template id
  3926. * @param string $path The path to the template
  3927. */
  3928. function _store_in_fs($mode, $id, $path)
  3929. {
  3930. global $phpbb_root_path, $db, $user, $safe_mode;
  3931.  
  3932. $store_db = 0;
  3933. $error = array();
  3934. if (!$safe_mode && phpbb_is_writable("{$phpbb_root_path}styles/{$path}/template"))
  3935. {
  3936. $sql = 'SELECT *
  3937. FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
  3938. WHERE template_id = $id";
  3939. $result = $db->sql_query($sql);
  3940.  
  3941. while ($row = $db->sql_fetchrow($result))
  3942. {
  3943. if (!($fp = @fopen("{$phpbb_root_path}styles/{$path}/template/" . $row['template_filename'], 'wb')))
  3944. {
  3945. $store_db = 1;
  3946. $error[] = $user->lang['EDIT_TEMPLATE_STORED_DB'];
  3947. break;
  3948. }
  3949.  
  3950. fwrite($fp, $row['template_data']);
  3951. fclose($fp);
  3952. }
  3953. $db->sql_freeresult($result);
  3954.  
  3955. if (!$store_db)
  3956. {
  3957. $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
  3958. WHERE template_id = $id";
  3959. $db->sql_query($sql);
  3960. }
  3961. }
  3962. if (sizeof($error))
  3963. {
  3964. return $error;
  3965. }
  3966. $sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . '
  3967. SET template_storedb = 0
  3968. WHERE template_id = ' . $id;
  3969. $db->sql_query($sql);
  3970.  
  3971. return false;
  3972. }
  3973.  
  3974. }
  3975.  
  3976. ?>
Add Comment
Please, Sign In to add comment