PageRenderTime 58ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/station/forum/includes/acp/acp_styles.php

https://github.com/bryanveloso/sayonarane
PHP | 3706 lines | 2884 code | 576 blank | 246 comment | 483 complexity | fb38823092ee51e47bc3a0b8af1275e3 MD5 | raw file
Possible License(s): AGPL-1.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: acp_styles.php 9056 2008-11-09 19:38:44Z toonarmy $
  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(3);
  36. $bitfield->set(8);
  37. $bitfield->set(9);
  38. $bitfield->set(11);
  39. $bitfield->set(12);
  40. define('TEMPLATE_BITFIELD', $bitfield->get_base64());
  41. unset($bitfield);
  42. $user->add_lang('acp/styles');
  43. $this->tpl_name = 'acp_styles';
  44. $this->page_title = 'ACP_CAT_STYLES';
  45. $action = request_var('action', '');
  46. $action = (isset($_POST['add'])) ? 'add' : $action;
  47. $style_id = request_var('id', 0);
  48. // Fill the configuration variables
  49. $this->style_cfg = $this->template_cfg = $this->theme_cfg = $this->imageset_cfg = '
  50. #
  51. # phpBB {MODE} configuration file
  52. #
  53. # @package phpBB3
  54. # @copyright (c) 2005 phpBB Group
  55. # @license http://opensource.org/licenses/gpl-license.php GNU Public License
  56. #
  57. #
  58. # At the left is the name, please do not change this
  59. # At the right the value is entered
  60. # For on/off options the valid values are on, off, 1, 0, true and false
  61. #
  62. # Values get trimmed, if you want to add a space in front or at the end of
  63. # the value, then enclose the value with single or double quotes.
  64. # Single and double quotes do not need to be escaped.
  65. #
  66. #
  67. # General Information about this {MODE}
  68. name = {NAME}
  69. copyright = {COPYRIGHT}
  70. version = {VERSION}
  71. ';
  72. $this->theme_cfg .= '
  73. # Some configuration options
  74. #
  75. # You have to turn this option on if you want to use the
  76. # path template variables ({T_IMAGESET_PATH} for example) within
  77. # your css file.
  78. # This is mostly the case if you want to use language specific
  79. # images within your css file.
  80. #
  81. parse_css_file = {PARSE_CSS_FILE}
  82. ';
  83. $this->template_cfg .= '
  84. # Some configuration options
  85. #
  86. # You can use this function to inherit templates from another template.
  87. # The template of the given name has to be installed.
  88. # Templates cannot inherit from inheriting templates.
  89. #';
  90. $this->imageset_keys = array(
  91. 'logos' => array(
  92. 'site_logo',
  93. ),
  94. 'buttons' => array(
  95. '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',
  96. ),
  97. 'icons' => array(
  98. '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',
  99. ),
  100. 'forums' => array(
  101. 'forum_link', 'forum_read', 'forum_read_locked', 'forum_read_subforum', 'forum_unread', 'forum_unread_locked', 'forum_unread_subforum', 'subforum_read', 'subforum_unread'
  102. ),
  103. 'folders' => array(
  104. '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',
  105. ),
  106. 'polls' => array(
  107. 'poll_left', 'poll_center', 'poll_right',
  108. ),
  109. 'ui' => array(
  110. 'upload_bar',
  111. ),
  112. 'user' => array(
  113. 'user_icon1', 'user_icon2', 'user_icon3', 'user_icon4', 'user_icon5', 'user_icon6', 'user_icon7', 'user_icon8', 'user_icon9', 'user_icon10',
  114. ),
  115. );
  116. // Execute overall actions
  117. switch ($action)
  118. {
  119. case 'delete':
  120. if ($style_id)
  121. {
  122. $this->remove($mode, $style_id);
  123. return;
  124. }
  125. break;
  126. case 'export':
  127. if ($style_id)
  128. {
  129. $this->export($mode, $style_id);
  130. return;
  131. }
  132. break;
  133. case 'install':
  134. $this->install($mode);
  135. return;
  136. break;
  137. case 'add':
  138. $this->add($mode);
  139. return;
  140. break;
  141. case 'details':
  142. if ($style_id)
  143. {
  144. $this->details($mode, $style_id);
  145. return;
  146. }
  147. break;
  148. case 'edit':
  149. if ($style_id)
  150. {
  151. switch ($mode)
  152. {
  153. case 'imageset':
  154. return $this->edit_imageset($style_id);
  155. case 'template':
  156. return $this->edit_template($style_id);
  157. case 'theme':
  158. return $this->edit_theme($style_id);
  159. }
  160. }
  161. break;
  162. case 'cache':
  163. if ($style_id)
  164. {
  165. switch ($mode)
  166. {
  167. case 'template':
  168. return $this->template_cache($style_id);
  169. }
  170. }
  171. break;
  172. }
  173. switch ($mode)
  174. {
  175. case 'style':
  176. switch ($action)
  177. {
  178. case 'activate':
  179. case 'deactivate':
  180. if ($style_id == $config['default_style'])
  181. {
  182. trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING);
  183. }
  184. $sql = 'UPDATE ' . STYLES_TABLE . '
  185. SET style_active = ' . (($action == 'activate') ? 1 : 0) . '
  186. WHERE style_id = ' . $style_id;
  187. $db->sql_query($sql);
  188. // Set style to default for any member using deactivated style
  189. if ($action == 'deactivate')
  190. {
  191. $sql = 'UPDATE ' . USERS_TABLE . '
  192. SET user_style = ' . $config['default_style'] . "
  193. WHERE user_style = $style_id";
  194. $db->sql_query($sql);
  195. $sql = 'UPDATE ' . FORUMS_TABLE . '
  196. SET forum_style = 0
  197. WHERE forum_style = ' . $style_id;
  198. $db->sql_query($sql);
  199. }
  200. break;
  201. }
  202. $this->frontend('style', array('details'), array('export', 'delete'));
  203. break;
  204. case 'template':
  205. switch ($action)
  206. {
  207. // Refresh template data stored in db and clear cache
  208. case 'refresh':
  209. $sql = 'SELECT *
  210. FROM ' . STYLES_TEMPLATE_TABLE . "
  211. WHERE template_id = $style_id";
  212. $result = $db->sql_query($sql);
  213. $template_row = $db->sql_fetchrow($result);
  214. $db->sql_freeresult($result);
  215. if (!$template_row)
  216. {
  217. trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
  218. }
  219. if (confirm_box(true))
  220. {
  221. $template_refreshed = '';
  222. // Only refresh database if the template is stored in the database
  223. if ($template_row['template_storedb'] && file_exists("{$phpbb_root_path}styles/{$template_row['template_path']}/template/"))
  224. {
  225. $filelist = array('' => array());
  226. $sql = 'SELECT template_filename, template_mtime
  227. FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
  228. WHERE template_id = $style_id";
  229. $result = $db->sql_query($sql);
  230. while ($row = $db->sql_fetchrow($result))
  231. {
  232. // if (@filemtime("{$phpbb_root_path}styles/{$template_row['template_path']}/template/" . $row['template_filename']) > $row['template_mtime'])
  233. // {
  234. // get folder info from the filename
  235. if (($slash_pos = strrpos($row['template_filename'], '/')) === false)
  236. {
  237. $filelist[''][] = $row['template_filename'];
  238. }
  239. else
  240. {
  241. $filelist[substr($row['template_filename'], 0, $slash_pos + 1)][] = substr($row['template_filename'], $slash_pos + 1, strlen($row['template_filename']) - $slash_pos - 1);
  242. }
  243. // }
  244. }
  245. $db->sql_freeresult($result);
  246. $this->store_templates('update', $style_id, $template_row['template_path'], $filelist);
  247. unset($filelist);
  248. $template_refreshed = $user->lang['TEMPLATE_REFRESHED'] . '<br />';
  249. add_log('admin', 'LOG_TEMPLATE_REFRESHED', $template_row['template_name']);
  250. }
  251. $this->clear_template_cache($template_row);
  252. trigger_error($template_refreshed . $user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action));
  253. }
  254. else
  255. {
  256. confirm_box(false, ($template_row['template_storedb']) ? $user->lang['CONFIRM_TEMPLATE_REFRESH'] : $user->lang['CONFIRM_TEMPLATE_CLEAR_CACHE'], build_hidden_fields(array(
  257. 'i' => $id,
  258. 'mode' => $mode,
  259. 'action' => $action,
  260. 'id' => $style_id
  261. )));
  262. }
  263. break;
  264. }
  265. $this->frontend('template', array('edit', 'cache', 'details'), array('refresh', 'export', 'delete'));
  266. break;
  267. case 'theme':
  268. switch ($action)
  269. {
  270. // Refresh theme data stored in the database
  271. case 'refresh':
  272. $sql = 'SELECT *
  273. FROM ' . STYLES_THEME_TABLE . "
  274. WHERE theme_id = $style_id";
  275. $result = $db->sql_query($sql);
  276. $theme_row = $db->sql_fetchrow($result);
  277. $db->sql_freeresult($result);
  278. if (!$theme_row)
  279. {
  280. trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
  281. }
  282. if (!$theme_row['theme_storedb'])
  283. {
  284. trigger_error($user->lang['THEME_ERR_REFRESH_FS'] . adm_back_link($this->u_action), E_USER_WARNING);
  285. }
  286. if (confirm_box(true))
  287. {
  288. if ($theme_row['theme_storedb'] && file_exists("{$phpbb_root_path}styles/{$theme_row['theme_path']}/theme/stylesheet.css"))
  289. {
  290. // Save CSS contents
  291. $sql_ary = array(
  292. 'theme_mtime' => (int) filemtime("{$phpbb_root_path}styles/{$theme_row['theme_path']}/theme/stylesheet.css"),
  293. 'theme_data' => $this->db_theme_data($theme_row)
  294. );
  295. $sql = 'UPDATE ' . STYLES_THEME_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
  296. WHERE theme_id = $style_id";
  297. $db->sql_query($sql);
  298. $cache->destroy('sql', STYLES_THEME_TABLE);
  299. add_log('admin', 'LOG_THEME_REFRESHED', $theme_row['theme_name']);
  300. trigger_error($user->lang['THEME_REFRESHED'] . adm_back_link($this->u_action));
  301. }
  302. }
  303. else
  304. {
  305. confirm_box(false, $user->lang['CONFIRM_THEME_REFRESH'], build_hidden_fields(array(
  306. 'i' => $id,
  307. 'mode' => $mode,
  308. 'action' => $action,
  309. 'id' => $style_id
  310. )));
  311. }
  312. break;
  313. }
  314. $this->frontend('theme', array('edit', 'details'), array('refresh', 'export', 'delete'));
  315. break;
  316. case 'imageset':
  317. switch ($action)
  318. {
  319. case 'refresh':
  320. $sql = 'SELECT *
  321. FROM ' . STYLES_IMAGESET_TABLE . "
  322. WHERE imageset_id = $style_id";
  323. $result = $db->sql_query($sql);
  324. $imageset_row = $db->sql_fetchrow($result);
  325. $db->sql_freeresult($result);
  326. if (!$imageset_row)
  327. {
  328. trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING);
  329. }
  330. if (confirm_box(true))
  331. {
  332. $sql_ary = array();
  333. $imageset_definitions = array();
  334. foreach ($this->imageset_keys as $topic => $key_array)
  335. {
  336. $imageset_definitions = array_merge($imageset_definitions, $key_array);
  337. }
  338. $cfg_data_imageset = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/imageset.cfg");
  339. $db->sql_transaction('begin');
  340. $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . '
  341. WHERE imageset_id = ' . $style_id;
  342. $result = $db->sql_query($sql);
  343. foreach ($cfg_data_imageset as $image_name => $value)
  344. {
  345. if (strpos($value, '*') !== false)
  346. {
  347. if (substr($value, -1, 1) === '*')
  348. {
  349. list($image_filename, $image_height) = explode('*', $value);
  350. $image_width = 0;
  351. }
  352. else
  353. {
  354. list($image_filename, $image_height, $image_width) = explode('*', $value);
  355. }
  356. }
  357. else
  358. {
  359. $image_filename = $value;
  360. $image_height = $image_width = 0;
  361. }
  362. if (strpos($image_name, 'img_') === 0 && $image_filename)
  363. {
  364. $image_name = substr($image_name, 4);
  365. if (in_array($image_name, $imageset_definitions))
  366. {
  367. $sql_ary[] = array(
  368. 'image_name' => (string) $image_name,
  369. 'image_filename' => (string) $image_filename,
  370. 'image_height' => (int) $image_height,
  371. 'image_width' => (int) $image_width,
  372. 'imageset_id' => (int) $style_id,
  373. 'image_lang' => '',
  374. );
  375. }
  376. }
  377. }
  378. $sql = 'SELECT lang_dir
  379. FROM ' . LANG_TABLE;
  380. $result = $db->sql_query($sql);
  381. while ($row = $db->sql_fetchrow($result))
  382. {
  383. if (@file_exists("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$row['lang_dir']}/imageset.cfg"))
  384. {
  385. $cfg_data_imageset_data = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$row['lang_dir']}/imageset.cfg");
  386. foreach ($cfg_data_imageset_data as $image_name => $value)
  387. {
  388. if (strpos($value, '*') !== false)
  389. {
  390. if (substr($value, -1, 1) === '*')
  391. {
  392. list($image_filename, $image_height) = explode('*', $value);
  393. $image_width = 0;
  394. }
  395. else
  396. {
  397. list($image_filename, $image_height, $image_width) = explode('*', $value);
  398. }
  399. }
  400. else
  401. {
  402. $image_filename = $value;
  403. $image_height = $image_width = 0;
  404. }
  405. if (strpos($image_name, 'img_') === 0 && $image_filename)
  406. {
  407. $image_name = substr($image_name, 4);
  408. if (in_array($image_name, $imageset_definitions))
  409. {
  410. $sql_ary[] = array(
  411. 'image_name' => (string) $image_name,
  412. 'image_filename' => (string) $image_filename,
  413. 'image_height' => (int) $image_height,
  414. 'image_width' => (int) $image_width,
  415. 'imageset_id' => (int) $style_id,
  416. 'image_lang' => (string) $row['lang_dir'],
  417. );
  418. }
  419. }
  420. }
  421. }
  422. }
  423. $db->sql_freeresult($result);
  424. $db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary);
  425. $db->sql_transaction('commit');
  426. $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE);
  427. add_log('admin', 'LOG_IMAGESET_REFRESHED', $imageset_row['imageset_name']);
  428. trigger_error($user->lang['IMAGESET_REFRESHED'] . adm_back_link($this->u_action));
  429. }
  430. else
  431. {
  432. confirm_box(false, $user->lang['CONFIRM_IMAGESET_REFRESH'], build_hidden_fields(array(
  433. 'i' => $id,
  434. 'mode' => $mode,
  435. 'action' => $action,
  436. 'id' => $style_id
  437. )));
  438. }
  439. break;
  440. }
  441. $this->frontend('imageset', array('edit', 'details'), array('refresh', 'export', 'delete'));
  442. break;
  443. }
  444. }
  445. /**
  446. * Build Frontend with supplied options
  447. */
  448. function frontend($mode, $options, $actions)
  449. {
  450. global $user, $template, $db, $config, $phpbb_root_path, $phpEx;
  451. $sql_from = '';
  452. $style_count = array();
  453. switch ($mode)
  454. {
  455. case 'style':
  456. $sql_from = STYLES_TABLE;
  457. $sql = 'SELECT user_style, COUNT(user_style) AS style_count
  458. FROM ' . USERS_TABLE . '
  459. GROUP BY user_style';
  460. $result = $db->sql_query($sql);
  461. while ($row = $db->sql_fetchrow($result))
  462. {
  463. $style_count[$row['user_style']] = $row['style_count'];
  464. }
  465. $db->sql_freeresult($result);
  466. break;
  467. case 'template':
  468. $sql_from = STYLES_TEMPLATE_TABLE;
  469. break;
  470. case 'theme':
  471. $sql_from = STYLES_THEME_TABLE;
  472. break;
  473. case 'imageset':
  474. $sql_from = STYLES_IMAGESET_TABLE;
  475. break;
  476. }
  477. $l_prefix = strtoupper($mode);
  478. $this->page_title = 'ACP_' . $l_prefix . 'S';
  479. $template->assign_vars(array(
  480. 'S_FRONTEND' => true,
  481. 'S_STYLE' => ($mode == 'style') ? true : false,
  482. 'L_TITLE' => $user->lang[$this->page_title],
  483. 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
  484. 'L_NAME' => $user->lang[$l_prefix . '_NAME'],
  485. 'L_INSTALLED' => $user->lang['INSTALLED_' . $l_prefix],
  486. 'L_UNINSTALLED' => $user->lang['UNINSTALLED_' . $l_prefix],
  487. 'L_NO_UNINSTALLED' => $user->lang['NO_UNINSTALLED_' . $l_prefix],
  488. 'L_CREATE' => $user->lang['CREATE_' . $l_prefix],
  489. 'U_ACTION' => $this->u_action,
  490. )
  491. );
  492. $sql = "SELECT *
  493. FROM $sql_from";
  494. $result = $db->sql_query($sql);
  495. $installed = array();
  496. $basis_options = '<option class="sep" value="">' . $user->lang['OPTIONAL_BASIS'] . '</option>';
  497. while ($row = $db->sql_fetchrow($result))
  498. {
  499. $installed[] = $row[$mode . '_name'];
  500. $basis_options .= '<option value="' . $row[$mode . '_id'] . '">' . $row[$mode . '_name'] . '</option>';
  501. $stylevis = ($mode == 'style' && !$row['style_active']) ? 'activate' : 'deactivate';
  502. $s_options = array();
  503. foreach ($options as $option)
  504. {
  505. $s_options[] = '<a href="' . $this->u_action . "&amp;action=$option&amp;id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>';
  506. }
  507. $s_actions = array();
  508. foreach ($actions as $option)
  509. {
  510. $s_actions[] = '<a href="' . $this->u_action . "&amp;action=$option&amp;id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>';
  511. }
  512. $template->assign_block_vars('installed', array(
  513. 'S_DEFAULT_STYLE' => ($mode == 'style' && $row['style_id'] == $config['default_style']) ? true : false,
  514. 'U_EDIT' => $this->u_action . '&amp;action=' . (($mode == 'style') ? 'details' : 'edit') . '&amp;id=' . $row[$mode . '_id'],
  515. 'U_STYLE_ACT_DEACT' => $this->u_action . '&amp;action=' . $stylevis . '&amp;id=' . $row[$mode . '_id'],
  516. 'L_STYLE_ACT_DEACT' => $user->lang['STYLE_' . strtoupper($stylevis)],
  517. 'S_OPTIONS' => implode(' | ', $s_options),
  518. 'S_ACTIONS' => implode(' | ', $s_actions),
  519. 'U_PREVIEW' => ($mode == 'style') ? append_sid("{$phpbb_root_path}index.$phpEx", "$mode=" . $row[$mode . '_id']) : '',
  520. 'NAME' => $row[$mode . '_name'],
  521. 'STYLE_COUNT' => ($mode == 'style' && isset($style_count[$row['style_id']])) ? $style_count[$row['style_id']] : 0,
  522. )
  523. );
  524. }
  525. $db->sql_freeresult($result);
  526. // Grab uninstalled items
  527. $new_ary = $cfg = array();
  528. $dp = @opendir("{$phpbb_root_path}styles");
  529. if ($dp)
  530. {
  531. while (($file = readdir($dp)) !== false)
  532. {
  533. $subpath = ($mode != 'style') ? "$mode/" : '';
  534. if ($file[0] != '.' && file_exists("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
  535. {
  536. if ($cfg = file("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
  537. {
  538. $items = parse_cfg_file('', $cfg);
  539. $name = (isset($items['name'])) ? trim($items['name']) : false;
  540. if ($name && !in_array($name, $installed))
  541. {
  542. $new_ary[] = array(
  543. 'path' => $file,
  544. 'name' => $name,
  545. 'copyright' => $items['copyright'],
  546. );
  547. }
  548. }
  549. }
  550. }
  551. closedir($dp);
  552. }
  553. unset($installed);
  554. if (sizeof($new_ary))
  555. {
  556. foreach ($new_ary as $cfg)
  557. {
  558. $template->assign_block_vars('uninstalled', array(
  559. 'NAME' => $cfg['name'],
  560. 'COPYRIGHT' => $cfg['copyright'],
  561. 'U_INSTALL' => $this->u_action . '&amp;action=install&amp;path=' . urlencode($cfg['path']))
  562. );
  563. }
  564. }
  565. unset($new_ary);
  566. $template->assign_vars(array(
  567. 'S_BASIS_OPTIONS' => $basis_options)
  568. );
  569. }
  570. /**
  571. * Provides a template editor which allows saving changes to template files on the filesystem or in the database.
  572. *
  573. * @param int $template_id specifies which template set is being edited
  574. */
  575. function edit_template($template_id)
  576. {
  577. global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode;
  578. if (defined('PHPBB_DISABLE_ACP_EDITOR'))
  579. {
  580. trigger_error($user->lang['EDITOR_DISABLED'] . adm_back_link($this->u_action));
  581. }
  582. $this->page_title = 'EDIT_TEMPLATE';
  583. $filelist = $filelist_cats = array();
  584. $template_data = utf8_normalize_nfc(request_var('template_data', '', true));
  585. $template_data = htmlspecialchars_decode($template_data);
  586. $template_file = utf8_normalize_nfc(request_var('template_file', '', true));
  587. $text_rows = max(5, min(999, request_var('text_rows', 20)));
  588. $save_changes = (isset($_POST['save'])) ? true : false;
  589. // make sure template_file path doesn't go upwards
  590. $template_file = str_replace('..', '.', $template_file);
  591. // Retrieve some information about the template
  592. $sql = 'SELECT template_storedb, template_path, template_name
  593. FROM ' . STYLES_TEMPLATE_TABLE . "
  594. WHERE template_id = $template_id";
  595. $result = $db->sql_query($sql);
  596. $template_info = $db->sql_fetchrow($result);
  597. $db->sql_freeresult($result);
  598. if (!$template_info)
  599. {
  600. trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
  601. }
  602. if ($save_changes && !check_form_key('acp_styles'))
  603. {
  604. trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
  605. }
  606. else if (!$save_changes)
  607. {
  608. add_form_key('acp_styles');
  609. }
  610. // save changes to the template if the user submitted any
  611. if ($save_changes && $template_file)
  612. {
  613. // Get the filesystem location of the current file
  614. $file = "{$phpbb_root_path}styles/{$template_info['template_path']}/template/$template_file";
  615. $additional = '';
  616. // If the template is stored on the filesystem try to write the file else store it in the database
  617. if (!$safe_mode && !$template_info['template_storedb'] && file_exists($file) && @is_writable($file))
  618. {
  619. if (!($fp = @fopen($file, 'wb')))
  620. {
  621. trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
  622. }
  623. fwrite($fp, $template_data);
  624. fclose($fp);
  625. }
  626. else
  627. {
  628. $db->sql_transaction('begin');
  629. // If it's not stored in the db yet, then update the template setting and store all template files in the db
  630. if (!$template_info['template_storedb'])
  631. {
  632. if ($this->get_super('template', $template_id))
  633. {
  634. $this->store_in_db('template', $super['template_id']);
  635. }
  636. else
  637. {
  638. $this->store_in_db('template', $template_id);
  639. }
  640. add_log('admin', 'LOG_TEMPLATE_EDIT_DETAILS', $template_info['template_name']);
  641. $additional .= '<br />' . $user->lang['EDIT_TEMPLATE_STORED_DB'];
  642. }
  643. // Update the template_data table entry for this template file
  644. $sql = 'UPDATE ' . STYLES_TEMPLATE_DATA_TABLE . "
  645. SET template_data = '" . $db->sql_escape($template_data) . "', template_mtime = " . time() . "
  646. WHERE template_id = $template_id
  647. AND template_filename = '" . $db->sql_escape($template_file) . "'";
  648. $db->sql_query($sql);
  649. $db->sql_transaction('commit');
  650. }
  651. // destroy the cached version of the template (filename without extension)
  652. $this->clear_template_cache($template_info, array(substr($template_file, 0, -5)));
  653. $cache->destroy('sql', STYLES_TABLE);
  654. add_log('admin', 'LOG_TEMPLATE_EDIT', $template_info['template_name'], $template_file);
  655. 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"));
  656. }
  657. // Generate a category array containing template filenames
  658. if (!$template_info['template_storedb'])
  659. {
  660. $template_path = "{$phpbb_root_path}styles/{$template_info['template_path']}/template";
  661. $filelist = filelist($template_path, '', 'html');
  662. $filelist[''] = array_diff($filelist[''], array('bbcode.html'));
  663. if ($template_file)
  664. {
  665. if (!file_exists($template_path . "/$template_file") || !($template_data = file_get_contents($template_path . "/$template_file")))
  666. {
  667. trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
  668. }
  669. }
  670. }
  671. else
  672. {
  673. $sql = 'SELECT *
  674. FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
  675. WHERE template_id = $template_id";
  676. $result = $db->sql_query($sql);
  677. $filelist = array('' => array());
  678. while ($row = $db->sql_fetchrow($result))
  679. {
  680. $file_info = pathinfo($row['template_filename']);
  681. if (($file_info['basename'] != 'bbcode') && ($file_info['extension'] == 'html'))
  682. {
  683. if (($file_info['dirname'] == '.') || empty($file_info['dirname']))
  684. {
  685. $filelist[''][] = $row['template_filename'];
  686. }
  687. else
  688. {
  689. $filelist[$file_info['dirname'] . '/'][] = $file_info['basename'];
  690. }
  691. }
  692. if ($row['template_filename'] == $template_file)
  693. {
  694. $template_data = $row['template_data'];
  695. }
  696. }
  697. $db->sql_freeresult($result);
  698. unset($file_info);
  699. }
  700. // Now create the categories
  701. $filelist_cats[''] = array();
  702. foreach ($filelist as $pathfile => $file_ary)
  703. {
  704. // Use the directory name as category name
  705. if (!empty($pathfile))
  706. {
  707. $filelist_cats[$pathfile] = array();
  708. foreach ($file_ary as $file)
  709. {
  710. $filelist_cats[$pathfile][$pathfile . $file] = $file;
  711. }
  712. }
  713. // or if it's in the main category use the word before the first underscore to group files
  714. else
  715. {
  716. $cats = array();
  717. foreach ($file_ary as $file)
  718. {
  719. $cats[] = substr($file, 0, strpos($file, '_'));
  720. $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file;
  721. }
  722. $cats = array_values(array_unique($cats));
  723. // we don't need any single element categories so put them into the misc '' category
  724. for ($i = 0, $n = sizeof($cats); $i < $n; $i++)
  725. {
  726. if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '')
  727. {
  728. $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]);
  729. unset($filelist_cats[$cats[$i]]);
  730. }
  731. }
  732. unset($cats);
  733. }
  734. }
  735. unset($filelist);
  736. // Generate list of categorised template files
  737. $tpl_options = '';
  738. ksort($filelist_cats);
  739. foreach ($filelist_cats as $category => $tpl_ary)
  740. {
  741. ksort($tpl_ary);
  742. if (!empty($category))
  743. {
  744. $tpl_options .= '<option class="sep" value="">' . $category . '</option>';
  745. }
  746. foreach ($tpl_ary as $filename => $file)
  747. {
  748. $selected = ($template_file == $filename) ? ' selected="selected"' : '';
  749. $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>';
  750. }
  751. }
  752. $template->assign_vars(array(
  753. 'S_EDIT_TEMPLATE' => true,
  754. 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $template_file)),
  755. 'S_TEMPLATES' => $tpl_options,
  756. 'U_ACTION' => $this->u_action . "&amp;action=edit&amp;id=$template_id&amp;text_rows=$text_rows",
  757. 'U_BACK' => $this->u_action,
  758. 'L_EDIT' => $user->lang['EDIT_TEMPLATE'],
  759. 'L_EDIT_EXPLAIN' => $user->lang['EDIT_TEMPLATE_EXPLAIN'],
  760. 'L_EDITOR' => $user->lang['TEMPLATE_EDITOR'],
  761. 'L_EDITOR_HEIGHT' => $user->lang['TEMPLATE_EDITOR_HEIGHT'],
  762. 'L_FILE' => $user->lang['TEMPLATE_FILE'],
  763. 'L_SELECT' => $user->lang['SELECT_TEMPLATE'],
  764. 'L_SELECTED' => $user->lang['SELECTED_TEMPLATE'],
  765. 'L_SELECTED_FILE' => $user->lang['SELECTED_TEMPLATE_FILE'],
  766. 'SELECTED_TEMPLATE' => $template_info['template_name'],
  767. 'TEMPLATE_FILE' => $template_file,
  768. 'TEMPLATE_DATA' => utf8_htmlspecialchars($template_data),
  769. 'TEXT_ROWS' => $text_rows)
  770. );
  771. }
  772. /**
  773. * Allows the admin to view cached versions of template files and clear single template cache files
  774. *
  775. * @param int $template_id specifies which template's cache is shown
  776. */
  777. function template_cache($template_id)
  778. {
  779. global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template;
  780. $source = str_replace('/', '.', request_var('source', ''));
  781. $file_ary = array_diff(request_var('delete', array('')), array(''));
  782. $submit = isset($_POST['submit']) ? true : false;
  783. $sql = 'SELECT *
  784. FROM ' . STYLES_TEMPLATE_TABLE . "
  785. WHERE template_id = $template_id";
  786. $result = $db->sql_query($sql);
  787. $template_row = $db->sql_fetchrow($result);
  788. $db->sql_freeresult($result);
  789. if (!$template_row)
  790. {
  791. trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
  792. }
  793. // User wants to delete one or more files ...
  794. if ($submit && $file_ary)
  795. {
  796. $this->clear_template_cache($template_row, $file_ary);
  797. trigger_error($user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action . "&amp;action=cache&amp;id=$template_id"));
  798. }
  799. $cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']);
  800. // Someone wants to see the cached source ... so we'll highlight it,
  801. // add line numbers and indent it appropriately. This could be nasty
  802. // on larger source files ...
  803. if ($source && file_exists("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx"))
  804. {
  805. adm_page_header($user->lang['TEMPLATE_CACHE']);
  806. $template->set_filenames(array(
  807. 'body' => 'viewsource.html')
  808. );
  809. $template->assign_vars(array(
  810. 'FILENAME' => str_replace('.', '/', $source) . '.html')
  811. );
  812. $code = str_replace(array("\r\n", "\r"), array("\n", "\n"), file_get_contents("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx"));
  813. $conf = array('highlight.bg', 'highlight.comment', 'highlight.default', 'highlight.html', 'highlight.keyword', 'highlight.string');
  814. foreach ($conf as $ini_var)
  815. {
  816. @ini_set($ini_var, str_replace('highlight.', 'syntax', $ini_var));
  817. }
  818. $marker = 'MARKER' . time();
  819. $code = highlight_string(str_replace("\n", $marker, $code), true);
  820. $code = str_replace($marker, "\n", $code);
  821. $str_from = array('<span style="color: ', '<font color="syntax', '</font>', '<code>', '</code>','[', ']', '.', ':');
  822. $str_to = array('<span class="', '<span class="syntax', '</span>', '', '', '&#91;', '&#93;', '&#46;', '&#58;');
  823. $code = str_replace($str_from, $str_to, $code);
  824. $code = preg_replace('#^(<span class="[a-z_]+">)\n?(.*?)\n?(</span>)$#ism', '$1$2$3', $code);
  825. $code = substr($code, strlen('<span class="syntaxhtml">'));
  826. $code = substr($code, 0, -1 * strlen('</ span>'));
  827. $code = explode("\n", $code);
  828. foreach ($code as $key => $line)
  829. {
  830. $template->assign_block_vars('source', array(
  831. 'LINENUM' => $key + 1,
  832. 'LINE' => preg_replace('#([^ ;])&nbsp;([^ &])#', '$1 $2', $line))
  833. );
  834. unset($code[$key]);
  835. }
  836. adm_page_footer();
  837. }
  838. $filemtime = array();
  839. if ($template_row['template_storedb'])
  840. {
  841. $ids = array();
  842. if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id'])
  843. {
  844. $ids[] = $template_row['template_inherits_id'];
  845. }
  846. $ids[] = $template_row['template_id'];
  847. $filemtime = array();
  848. $file_template_db = array();
  849. foreach ($ids as $id)
  850. {
  851. $sql = 'SELECT template_filename, template_mtime
  852. FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
  853. WHERE template_id = $id";
  854. $result = $db->sql_query($sql);
  855. while ($row = $db->sql_fetchrow($result))
  856. {
  857. $filemtime[$row['template_filename']] = $row['template_mtime'];
  858. $file_template_db[$row['template_filename']] = $id;
  859. }
  860. $db->sql_freeresult($result);
  861. }
  862. }
  863. // Get a list of cached template files and then retrieve additional information about them
  864. $file_ary = $this->template_cache_filelist($template_row['template_path']);
  865. foreach ($file_ary as $file)
  866. {
  867. $file = str_replace('/', '.', $file);
  868. // perform some dirty guessing to get the path right.
  869. // We assume that three dots in a row were '../'
  870. $tpl_file = str_replace('.', '/', $file);
  871. $tpl_file = str_replace('///', '../', $tpl_file);
  872. $filename = "{$cache_prefix}_$file.html.$phpEx";
  873. if (!file_exists("{$phpbb_root_path}cache/$filename"))
  874. {
  875. continue;
  876. }
  877. $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_path']}/template/$tpl_file.html";
  878. $inherited = false;
  879. if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id'])
  880. {
  881. if (!$template_row['template_storedb'])
  882. {
  883. if (!file_exists($file_tpl))
  884. {
  885. $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html";
  886. $inherited = true;
  887. }
  888. }
  889. else
  890. {
  891. if ($file_template_db[$file . '.html'] == $template_row['template_inherits_id'])
  892. {
  893. $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html";
  894. $inherited = true;
  895. }
  896. }
  897. }
  898. $template->assign_block_vars('file', array(
  899. 'U_VIEWSOURCE' => $this->u_action . "&amp;action=cache&amp;id=$template_id&amp;source=$file",
  900. 'CACHED' => $user->format_date(filemtime("{$phpbb_root_path}cache/$filename")),
  901. 'FILENAME' => $file,
  902. 'FILENAME_PATH' => $file_tpl,
  903. 'FILESIZE' => sprintf('%.1f ' . $user->lang['KIB'], filesize("{$phpbb_root_path}cache/$filename") / 1024),
  904. 'MODIFIED' => $user->format_date((!$template_row['template_storedb']) ? filemtime($file_tpl) : $filemtime[$file . '.html']))
  905. );
  906. }
  907. unset($filemtime);
  908. $template->assign_vars(array(
  909. 'S_CACHE' => true,
  910. 'S_TEMPLATE' => true,
  911. 'U_ACTION' => $this->u_action . "&amp;action=cache&amp;id=$template_id",
  912. 'U_BACK' => $this->u_action)
  913. );
  914. }
  915. /**
  916. * Provides a css editor and a basic easier to use stylesheet editing tool for less experienced (or lazy) users
  917. *
  918. * @param int $theme_id specifies which theme is being edited
  919. */
  920. function edit_theme($theme_id)
  921. {
  922. global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode;
  923. $this->page_title = 'EDIT_THEME';
  924. $filelist = $filelist_cats = array();
  925. $theme_data = utf8_normalize_nfc(request_var('template_data', '', true));
  926. $theme_data = htmlspecialchars_decode($theme_data);
  927. $theme_file = utf8_normalize_nfc(request_var('template_file', '', true));
  928. $text_rows = max(5, min(999, request_var('text_rows', 20)));
  929. $save_changes = (isset($_POST['save'])) ? true : false;
  930. // make sure theme_file path doesn't go upwards
  931. $theme_file = str_replace('..', '.', $theme_file);
  932. // Retrieve some information about the theme
  933. $sql = 'SELECT theme_storedb, theme_path, theme_name, theme_data
  934. FROM ' . STYLES_THEME_TABLE . "
  935. WHERE theme_id = $theme_id";
  936. $result = $db->sql_query($sql);
  937. if (!($theme_info = $db->sql_fetchrow($result)))
  938. {
  939. trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
  940. }
  941. $db->sql_freeresult($result);
  942. // save changes to the theme if the user submitted any
  943. if ($save_changes)
  944. {
  945. // Get the filesystem location of the current file
  946. $file = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme/$theme_file";
  947. $additional = '';
  948. $message = $user->lang['THEME_UPDATED'];
  949. // If the theme is stored on the filesystem try to write the file else store it in the database
  950. if (!$safe_mode && !$theme_info['theme_storedb'] && file_exists($file) && @is_writable($file))
  951. {
  952. if (!($fp = @fopen($file, 'wb')))
  953. {
  954. trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
  955. }
  956. fwrite($fp, $theme_data);
  957. fclose($fp);
  958. }
  959. else
  960. {
  961. // Write stylesheet to db
  962. $sql_ary = array(
  963. 'theme_mtime' => time(),
  964. 'theme_storedb' => 1,
  965. 'theme_data' => $this->db_theme_data($theme_info, $theme_data),
  966. );
  967. $sql = 'UPDATE ' . STYLES_THEME_TABLE . '
  968. SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
  969. WHERE theme_id = ' . $theme_id;
  970. $db->sql_query($sql);
  971. $cache->destroy('sql', STYLES_THEME_TABLE);
  972. // notify the user if the theme was not stored in the db before his modification
  973. if (!$theme_info['theme_storedb'])
  974. {
  975. add_log('admin', 'LOG_THEME_EDIT_DETAILS', $theme_info['theme_name']);
  976. $message .= '<br />' . $user->lang['EDIT_THEME_STORED_DB'];
  977. }
  978. }
  979. $cache->destroy('sql', STYLES_THEME_TABLE);
  980. add_log('admin', (!$theme_info['theme_storedb']) ? 'LOG_THEME_EDIT_FILE' : 'LOG_THEME_EDIT', $theme_info['theme_name'], (!$theme_info['theme_storedb']) ? $theme_file : '');
  981. 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"));
  982. }
  983. // Generate a category array containing theme filenames
  984. if (!$theme_info['theme_storedb'])
  985. {
  986. $theme_path = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme";
  987. $filelist = filelist($theme_path, '', 'css');
  988. if ($theme_file)
  989. {
  990. if (!file_exists($theme_path . "/$theme_file") || !($theme_data = file_get_contents($theme_path . "/$theme_file")))
  991. {
  992. trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
  993. }
  994. }
  995. }
  996. else
  997. {
  998. $theme_data = &$theme_info['theme_data'];
  999. }
  1000. // Now create the categories
  1001. $filelist_cats[''] = array();
  1002. foreach ($filelist as $pathfile => $file_ary)
  1003. {
  1004. // Use the directory name as category name
  1005. if (!empty($pathfile))
  1006. {
  1007. $filelist_cats[$pathfile] = array();
  1008. foreach ($file_ary as $file)
  1009. {
  1010. $filelist_cats[$pathfile][$pathfile . $file] = $file;
  1011. }
  1012. }
  1013. // or if it's in the main category use the word before the first underscore to group files
  1014. else
  1015. {
  1016. $cats = array();
  1017. foreach ($file_ary as $file)
  1018. {
  1019. $cats[] = substr($file, 0, strpos($file, '_'));
  1020. $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file;
  1021. }
  1022. $cats = array_values(array_unique($cats));
  1023. // we don't need any single element categories so put them into the misc '' category
  1024. for ($i = 0, $n = sizeof($cats); $i < $n; $i++)
  1025. {
  1026. if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '')
  1027. {
  1028. $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]);
  1029. unset($filelist_cats[$cats[$i]]);
  1030. }
  1031. }
  1032. unset($cats);
  1033. }
  1034. }
  1035. unset($filelist);
  1036. // Generate list of categorised theme files
  1037. $tpl_options = '';
  1038. ksort($filelist_cats);
  1039. foreach ($filelist_cats as $category => $tpl_ary)
  1040. {
  1041. ksort($tpl_ary);
  1042. if (!empty($category))
  1043. {
  1044. $tpl_options .= '<option class="sep" value="">' . $category . '</option>';
  1045. }
  1046. foreach ($tpl_ary as $filename => $file)
  1047. {
  1048. $selected = ($theme_file == $filename) ? ' selected="selected"' : '';
  1049. $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>';
  1050. }
  1051. }
  1052. $template->assign_vars(array(
  1053. 'S_EDIT_THEME' => true,
  1054. 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $theme_file)),
  1055. 'S_THEME_IN_DB' => $theme_info['theme_storedb'],
  1056. 'S_TEMPLATES' => $tpl_options,
  1057. 'U_ACTION' => $this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;text_rows=$text_rows",
  1058. 'U_BACK' => $this->u_action,
  1059. 'L_EDIT' => $user->lang['EDIT_THEME'],
  1060. 'L_EDIT_EXPLAIN' => $user->lang['EDIT_THEME_EXPLAIN'],
  1061. 'L_EDITOR' => $user->lang['THEME_EDITOR'],
  1062. 'L_EDITOR_HEIGHT' => $user->lang['THEME_EDITOR_HEIGHT'],
  1063. 'L_FILE' => $user->lang['THEME_FILE'],
  1064. 'L_SELECT' => $user->lang['SELECT_THEME'],
  1065. 'L_SELECTED' => $user->lang['SELECTED_THEME'],
  1066. 'L_SELECTED_FILE' => $user->lang['SELECTED_THEME_FILE'],
  1067. 'SELECTED_TEMPLATE' => $theme_info['theme_name'],
  1068. 'TEMPLATE_FILE' => $theme_file,
  1069. 'TEMPLATE_DATA' => utf8_htmlspecialchars($theme_data),
  1070. 'TEXT_ROWS' => $text_rows)
  1071. );
  1072. }
  1073. /**
  1074. * Edit imagesets
  1075. *
  1076. * @param int $imageset_id specifies which imageset is being edited
  1077. */
  1078. function edit_imageset($imageset_id)
  1079. {
  1080. global $db, $user, $phpbb_root_path, $cache, $template;
  1081. $this->page_title = 'EDIT_IMAGESET';
  1082. $update = (isset($_POST['update'])) ? true : false;
  1083. $imgname = request_var('imgname', '');
  1084. $imgpath = request_var('imgpath', '');
  1085. $imgsize = request_var('imgsize', false);
  1086. $imgwidth = request_var('imgwidth', 0);
  1087. $imgheight = request_var('imgheight', 0);
  1088. $imgname = preg_replace('#[^a-z0-9\-+_]#i', '', $imgname);
  1089. $imgpath = str_replace('..', '.', $imgpath);
  1090. if ($imageset_id)
  1091. {
  1092. $sql = 'SELECT imageset_path, imageset_name
  1093. FROM ' . STYLES_IMAGESET_TABLE . "
  1094. WHERE imageset_id = $imageset_id";
  1095. $result = $db->sql_query($sql);
  1096. $imageset_row = $db->sql_fetchrow($result);
  1097. $db->sql_freeresult($result);
  1098. $imageset_path = $imageset_row['imageset_path'];
  1099. $imageset_name = $imageset_row['imageset_name'];
  1100. $sql_extra = '';
  1101. if (strpos($imgname, '-') !== false)
  1102. {
  1103. list($imgname, $imgnamelang) = explode('-', $imgname);
  1104. $sql_extra = " AND image_lang IN ('" . $db->sql_escape($imgnamelang) . "', '')";
  1105. }
  1106. $sql = 'SELECT image_filename, image_width, image_height, image_lang, image_id
  1107. FROM ' . STYLES_IMAGESET_DATA_TABLE . "
  1108. WHERE imageset_id = $imageset_id
  1109. AND image_name = '" . $db->sql_escape($imgname) . "'$sql_extra";
  1110. $result = $db->sql_query($sql);
  1111. $imageset_data_row = $db->sql_fetchrow($result);
  1112. $db->sql_freeresult($result);
  1113. $image_filename = $imageset_data_row['image_filename'];
  1114. $image_width = $imageset_data_row['image_width'];
  1115. $image_height = $imageset_data_row['image_height'];
  1116. $image_lang = $imageset_data_row['image_lang'];
  1117. $image_id = $imageset_data_row['image_id'];
  1118. if (!$imageset_row)
  1119. {
  1120. trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING);
  1121. }
  1122. // Check to see whether the selected image exists in the table
  1123. $valid_name = ($update) ? false : true;
  1124. foreach ($this->imageset_keys as $category => $img_ary)
  1125. {
  1126. if (in_array($imgname, $img_ary))
  1127. {
  1128. $valid_name = true;
  1129. break;
  1130. }
  1131. }
  1132. if ($update && isset($_POST['imgpath']))
  1133. {
  1134. if ($valid_name)
  1135. {
  1136. // If imgwidth and imgheight are non-zero grab the actual size
  1137. // from the image itself ... we ignore width settings for the poll center image
  1138. $imgwidth = request_var('imgwidth', 0);
  1139. $imgheight = request_var('imgheight', 0);
  1140. $imglang = '';
  1141. if ($imgpath && !file_exists("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath"))
  1142. {
  1143. trigger_error($user->lang['NO_IMAGE_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING);
  1144. }
  1145. if ($imgsize && $imgpath)
  1146. {
  1147. if (!$imgwidth || !$imgheight)
  1148. {
  1149. list($imgwidth_file, $imgheight_file) = getimagesize("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath");
  1150. $imgwidth = ($imgwidth) ? $imgwidth : $imgwidth_file;
  1151. $imgheight = ($imgheight) ? $imgheight : $imgheight_file;
  1152. }
  1153. $imgwidth = ($imgname != 'poll_center') ? (int) $imgwidth : 0;
  1154. $imgheight = (int) $imgheight;
  1155. }
  1156. if (strpos($imgpath, '/') !== false)
  1157. {
  1158. list($imglang, $imgfilename) = explode('/', $imgpath);
  1159. }
  1160. else
  1161. {
  1162. $imgfilename = $imgpath;
  1163. }
  1164. $sql_ary = array(
  1165. 'image_filename' => (string) $imgfilename,
  1166. 'image_width' => (int) $imgwidth,
  1167. 'image_height' => (int) $imgheight,
  1168. 'image_lang' => (string) $imglang,
  1169. );
  1170. // already exists
  1171. if ($imageset_data_row)
  1172. {
  1173. $sql = 'UPDATE ' . STYLES_IMAGESET_DATA_TABLE . '
  1174. SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
  1175. WHERE image_id = $image_id";
  1176. $db->sql_query($sql);
  1177. }
  1178. // does not exist
  1179. else if (!$imageset_data_row)
  1180. {
  1181. $sql_ary['image_name'] = $imgname;
  1182. $sql_ary['imageset_id'] = (int) $imageset_id;
  1183. $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
  1184. }
  1185. $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE);
  1186. add_log('admin', 'LOG_IMAGESET_EDIT', $imageset_name);
  1187. $template->assign_var('SUCCESS', true);
  1188. $image_filename = $imgfilename;
  1189. $image_width = $imgwidth;
  1190. $image_height = $imgheight;
  1191. $image_lang = $imglang;
  1192. }
  1193. }
  1194. }
  1195. $imglang = '';
  1196. $imagesetlist = array('nolang' => array(), 'lang' => array());
  1197. $langs = array();
  1198. $dir = "{$phpbb_root_path}styles/$imageset_path/imageset";
  1199. $dp = @opendir($dir);
  1200. if ($dp)
  1201. {
  1202. while (($file = readdir($dp)) !== false)
  1203. {
  1204. if ($file[0] != '.' && strtoupper($file) != 'CVS' && !is_file($dir . '/' . $file) && !is_link($dir . '/' . $file))
  1205. {
  1206. $langs[] = $file;
  1207. }
  1208. else if (preg_match('#\.(?:gif|jpg|png)$#', $file))
  1209. {
  1210. $imagesetlist['nolang'][] = $file;
  1211. }
  1212. }
  1213. if ($sql_extra)
  1214. {
  1215. $dp2 = @opendir("$dir/$imgnamelang");
  1216. if ($dp2)
  1217. {
  1218. while (($file2 = readdir($dp2)) !== false)
  1219. {
  1220. if (preg_match('#\.(?:gif|jpg|png)$#', $file2))
  1221. {
  1222. $imagesetlist['lang'][] = "$imgnamelang/$file2";
  1223. }
  1224. }
  1225. closedir($dp2);
  1226. }
  1227. }
  1228. closedir($dp);
  1229. }
  1230. // Generate list of image options
  1231. $img_options = '';
  1232. foreach ($this->imageset_keys as $category => $img_ary)
  1233. {
  1234. $template->assign_block_vars('category', array(
  1235. 'NAME' => $user->lang['IMG_CAT_' . strtoupper($category)]
  1236. ));
  1237. foreach ($img_ary as $img)
  1238. {
  1239. if ($category == 'buttons')
  1240. {
  1241. foreach ($langs as $language)
  1242. {
  1243. $template->assign_block_vars('category.images', array(
  1244. 'SELECTED' => ($img == $imgname && $language == $imgnamelang),
  1245. 'VALUE' => $img . '-' . $language,
  1246. 'TEXT' => $user->lang['IMG_' . strtoupper($img)] . ' [ ' . $language . ' ]'
  1247. ));
  1248. }
  1249. }
  1250. else
  1251. {
  1252. $template->assign_block_vars('category.images', array(
  1253. 'SELECTED' => ($img == $imgname),
  1254. 'VALUE' => $img,
  1255. 'TEXT' => (($category == 'custom') ? $img : $user->lang['IMG_' . strtoupper($img)])
  1256. ));
  1257. }
  1258. }
  1259. }
  1260. // Make sure the list of possible images is sorted alphabetically
  1261. sort($imagesetlist['lang']);
  1262. sort($imagesetlist['nolang']);
  1263. $image_found = false;
  1264. $img_val = '';
  1265. foreach ($imagesetlist as $type => $img_ary)
  1266. {
  1267. if ($type !== 'lang' || $sql_extra)
  1268. {
  1269. $template->assign_block_vars('imagesetlist', array(
  1270. 'TYPE' => ($type == 'lang')
  1271. ));
  1272. }
  1273. foreach ($img_ary as $img)
  1274. {
  1275. $imgtext = preg_replace('/^([^\/]+\/)/', '', $img);
  1276. $selected = (!empty($imgname) && strpos($image_filename, $imgtext) !== false);
  1277. if ($selected)
  1278. {
  1279. $image_found = true;
  1280. $img_val = htmlspecialchars($img);
  1281. }
  1282. $template->assign_block_vars('imagesetlist.images', array(
  1283. 'SELECTED' => $selected,
  1284. 'TEXT' => $imgtext,
  1285. 'VALUE' => htmlspecialchars($img)
  1286. ));
  1287. }
  1288. }
  1289. $imgsize_bool = (!empty($imgname) && $image_width && $image_height) ? true : false;
  1290. $image_request = '../styles/' . $imageset_path . '/imageset/' . ($image_lang ? $imgnamelang . '/' : '') . $image_filename;
  1291. $template->assign_vars(array(
  1292. 'S_EDIT_IMAGESET' => true,
  1293. 'L_TITLE' => $user->lang[$this->page_title],
  1294. 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
  1295. 'IMAGE_OPTIONS' => $img_options,
  1296. 'IMAGE_SIZE' => $image_width,
  1297. 'IMAGE_HEIGHT' => $image_height,
  1298. 'IMAGE_REQUEST' => (empty($image_filename)) ? 'images/no_image.png' : $image_request,
  1299. 'U_ACTION' => $this->u_action . "&amp;action=edit&amp;id=$imageset_id",
  1300. 'U_BACK' => $this->u_action,
  1301. 'NAME' => $imageset_name,
  1302. 'A_NAME' => addslashes($imageset_name),
  1303. 'ERROR' => !$valid_name,
  1304. 'IMG_SRC' => ($image_found) ? '../styles/' . $imageset_path . '/imageset/' . $img_val : 'images/no_image.png',
  1305. 'IMAGE_SELECT' => $image_found
  1306. ));
  1307. }
  1308. /**
  1309. * Remove style/template/theme/imageset
  1310. */
  1311. function remove($mode, $style_id)
  1312. {
  1313. global $db, $template, $user, $phpbb_root_path, $cache, $config;
  1314. $new_id = request_var('new_id', 0);
  1315. $update = (isset($_POST['update'])) ? true : false;
  1316. $sql_where = '';
  1317. switch ($mode)
  1318. {
  1319. case 'style':
  1320. $sql_from = STYLES_TABLE;
  1321. $sql_select = 'style_name';
  1322. $sql_where = 'AND style_active = 1';
  1323. break;
  1324. case 'template':
  1325. $sql_from = STYLES_TEMPLATE_TABLE;
  1326. $sql_select = 'template_name, template_path, template_storedb';
  1327. break;
  1328. case 'theme':
  1329. $sql_from = STYLES_THEME_TABLE;
  1330. $sql_select = 'theme_name, theme_path, theme_storedb';
  1331. break;
  1332. case 'imageset':
  1333. $sql_from = STYLES_IMAGESET_TABLE;
  1334. $sql_select = 'imageset_name, imageset_path';
  1335. break;
  1336. }
  1337. if ($mode === 'template' && ($conflicts = $this->check_inheritance($mode, $style_id)))
  1338. {
  1339. $l_type = strtoupper($mode);
  1340. $msg = $user->lang[$l_type . '_DELETE_DEPENDENT'];
  1341. foreach ($conflicts as $id => $values)
  1342. {
  1343. $msg .= '<br />' . $values['template_name'];
  1344. }
  1345. trigger_error($msg . adm_back_link($this->u_action), E_USER_WARNING);
  1346. }
  1347. $l_prefix = strtoupper($mode);
  1348. $sql = "SELECT $sql_select
  1349. FROM $sql_from
  1350. WHERE {$mode}_id = $style_id";
  1351. $result = $db->sql_query($sql);
  1352. $style_row = $db->sql_fetchrow($result);
  1353. $db->sql_freeresult($result);
  1354. if (!$style_row)
  1355. {
  1356. trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
  1357. }
  1358. $sql = "SELECT {$mode}_id, {$mode}_name
  1359. FROM $sql_from
  1360. WHERE {$mode}_id <> $style_id
  1361. $sql_where
  1362. ORDER BY {$mode}_name ASC";
  1363. $result = $db->sql_query($sql);
  1364. $s_options = '';
  1365. if ($row = $db->sql_fetchrow($result))
  1366. {
  1367. do
  1368. {
  1369. $s_options .= '<option value="' . $row[$mode . '_id'] . '">' . $row[$mode . '_name'] . '</option>';
  1370. }
  1371. while ($row = $db->sql_fetchrow($result));
  1372. }
  1373. else
  1374. {
  1375. trigger_error($user->lang['ONLY_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
  1376. }
  1377. $db->sql_freeresult($result);
  1378. if ($u

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