PageRenderTime 72ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/forum/includes/acp/acp_styles.php

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