source: forum/includes/acp/acp_styles.php@ 651

Last change on this file since 651 was 651, checked in by aleg, 15 years ago

Změněná cesta k GM a Char logům pro realmy 4 a 7.

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