source: trunk/forum/includes/acp/acp_styles.php

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