PageRenderTime 396ms CodeModel.GetById 36ms RepoModel.GetById 1ms app.codeStats 1ms

/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

Large files files are truncated, but you can click here to view the full file

  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_…

Large files files are truncated, but you can click here to view the full file