]> git.vanrenterghem.biz Git - www.vanrenterghem.biz.git/blob - phpBB2/admin/xs_include.php
Baseline
[www.vanrenterghem.biz.git] / phpBB2 / admin / xs_include.php
1 <?php\r
2 \r
3 /***************************************************************************\r
4  *                               xs_include.php\r
5  *                               --------------\r
6  *   copyright            : (C) 2003 - 2005 CyberAlien\r
7  *   support              : http://www.phpbbstyles.com\r
8  *\r
9  *   version              : 2.3.1\r
10  *\r
11  *   file revision        : 77\r
12  *   project revision     : 78\r
13  *   last modified        : 05 Dec 2005  13:54:54\r
14  *\r
15  ***************************************************************************/\r
16 \r
17 /***************************************************************************\r
18  *\r
19  *   This program is free software; you can redistribute it and/or modify\r
20  *   it under the terms of the GNU General Public License as published by\r
21  *   the Free Software Foundation; either version 2 of the License, or\r
22  *   (at your option) any later version.\r
23  *\r
24  ***************************************************************************/\r
25 \r
26 if (!defined('IN_PHPBB') || !defined('IN_XS'))\r
27 {\r
28         die('Hacking attempt');\r
29 }\r
30 \r
31 if(defined('XS_INCLUDED'))\r
32 {\r
33         return;\r
34 }\r
35 define('XS_INCLUDED', true);\r
36 \r
37 \r
38 //\r
39 // include language file\r
40 //\r
41 \r
42 if(!defined('XS_LANG_INCLUDED'))\r
43 {\r
44         global $phpbb_root_path, $board_config, $phpEx, $lang;\r
45         $xs_lang_file = $phpbb_root_path . 'language/lang_' . $board_config['default_lang'] . '/lang_xs.'.$phpEx;\r
46         if( !@file_exists($xs_lang_file) )\r
47         {       // load english version if there is no translation to current language\r
48                 $xs_lang_file = $phpbb_root_path . 'language/lang_english/lang_xs.'.$phpEx;\r
49         }\r
50         include($xs_lang_file);\r
51         define('XS_LANG_INCLUDED', true);\r
52 }\r
53 \r
54 \r
55 define('XS_SHOWNAV_CONFIG', 0);\r
56 define('XS_SHOWNAV_INSTALL', 1);\r
57 define('XS_SHOWNAV_UNINSTALL', 2);\r
58 define('XS_SHOWNAV_DEFAULT', 3);\r
59 define('XS_SHOWNAV_CACHE', 4);\r
60 define('XS_SHOWNAV_IMPORT', 5);\r
61 define('XS_SHOWNAV_EXPORT', 6);\r
62 define('XS_SHOWNAV_CLONE', 7);\r
63 define('XS_SHOWNAV_DOWNLOAD', 8);\r
64 define('XS_SHOWNAV_EDITTPL', 9);\r
65 define('XS_SHOWNAV_EDITDB', 10);\r
66 define('XS_SHOWNAV_EXPORTDB', 11);\r
67 define('XS_SHOWNAV_UPDATES', 12);\r
68 define('XS_SHOWNAV_MAX', 13);\r
69 \r
70 global $xs_shownav_action;\r
71 $xs_shownav_action = array(\r
72         'config',\r
73         'install',\r
74         'uninstall',\r
75         'default',\r
76         'cache',\r
77         'import',\r
78         'export',\r
79         'clone',\r
80         'download',\r
81         'edittpl',\r
82         'editdb',\r
83         'exportdb',\r
84         'updates',\r
85         );\r
86 \r
87 \r
88 // override styles management in admin navigation\r
89 function xs_admin_override($modded = false)\r
90 {\r
91         if(defined('XS_ADMIN_OVERRIDE_FINISHED'))\r
92         {\r
93                 return;\r
94         }\r
95         define('XS_ADMIN_OVERRIDE_FINISHED', true);\r
96         global $module, $phpEx, $xs_shownav_action, $board_config, $lang;\r
97         // remove default phpBB styles management\r
98         if(isset($module['Styles']))\r
99         {\r
100                 $unset = array('Add_new', 'Create_new', 'Manage', 'Export');\r
101                 for($i=0; $i<count($unset); $i++)\r
102                 {\r
103                         if(isset($module['Styles'][$unset[$i]]))\r
104                         {\r
105                                 unset($module['Styles'][$unset[$i]]);\r
106                         }\r
107                 }\r
108                 $module['Styles']['Menu'] = 'xs_frameset.'.$phpEx.'?action=menu&showwarning=1';\r
109         }\r
110         // add new menu\r
111         $module_name = 'Extreme_Styles';\r
112         $module[$module_name]['Styles_Management'] = 'xs_frameset.'.$phpEx.'?action=menu';\r
113         for($i=0; $i<XS_SHOWNAV_MAX; $i++)\r
114         {\r
115                 $num = pow(2, $i);\r
116                 if($i != XS_SHOWNAV_DOWNLOAD && ($board_config['xs_shownav'] & $num) > 0)\r
117                 {\r
118                         $module[$module_name][$lang['xs_config_shownav'][$i]] = 'xs_frameset.'.$phpEx.'?action=' . $xs_shownav_action[$i];\r
119                 }\r
120         }\r
121         // add menu for style configuration\r
122         foreach($board_config as $var => $value)\r
123         {\r
124                 if(substr($var, 0, 9) === 'xs_style_')\r
125                 {\r
126                         $str = substr($var, 9);\r
127                         $module['Template_Config'][$str] = 'xs_frameset.'.$phpEx.'?action=style_config&tpl='.urlencode($str);\r
128                 }\r
129         }\r
130 }\r
131 \r
132 \r
133 if(!empty($setmodules))\r
134 {\r
135         if(@function_exists('jr_admin_get_module_list'))\r
136         {\r
137                 $tmp_mod = $module;\r
138                 global $module;\r
139                 $module = $tmp_mod;\r
140                 xs_admin_override(true);\r
141         }\r
142         return;\r
143 }\r
144 \r
145 //\r
146 // Global defines for eXtreme Styles mod administration panel\r
147 //\r
148 define('STYLE_HEADER_START', 'xs_style_01<xs>');\r
149 define('STYLE_HEADER_END', '</xs>');\r
150 define('STYLE_HEADER_VERSION', '1');\r
151 define('STYLE_EXTENSION', '.style');\r
152 define('TAR_HEADER_PACK', 'a100A8A8A8A12A12A8A1A100A6A2A32A32A8A8a155a12');\r
153 define('TAR_HEADER_UNPACK', 'a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix/a12extra');\r
154 define('XS_MAX_ITEMS_PER_STYLE', 32);\r
155 define('XS_TEMP_DIR', '../cache/');\r
156 define('XS_FTP_LOCAL', 'no_ftp');\r
157 define('XS_UPDATE_STYLE', 1);\r
158 define('XS_UPDATE_MOD', 2);\r
159 define('XS_UPDATE_PHPBB', 3);\r
160 define('XS_TPL_PATH', '../../xs_mod/tpl/');\r
161 define('XS_BACKUP_PREFIX', 'backup.');\r
162 define('XS_BACKUP_EXT', '.backup');\r
163 define('XS_MAX_TIMEOUT', 600); // maximum timeout for downloads/import/installation\r
164 \r
165 $xs_row_class = array('row1', 'row2');\r
166 \r
167 $template_dir = 'templates/';\r
168 \r
169 $template->assign_vars(array(\r
170         'XS_PATH'       => '../xs_mod/',\r
171         'XS_UL'         => '<table width="100%" cellspacing="0" cellpadding="2" border="0">',\r
172         'XS_UL2'        => '</table>',\r
173         'XS_LI'         => '<tr><td width="20" align="center" valign="middle"><img src="../xs_mod/images/dot.gif" border="0" alt="" /></td><td align="left" valign="middle" width="100%"><span class="gen">',\r
174         'XS_LI2'        => '</span></td></tr>',\r
175         'S_HIDDEN_FIELDS'       => '<input type="hidden" name="sid" value="' . $userdata['session_id'] . '" />',\r
176         ));\r
177 \r
178 if(!defined('NO_XS_HEADER'))\r
179 {\r
180         $template->set_filenames(array(\r
181                 'xs_header' => XS_TPL_PATH . 'xs_header.tpl',\r
182                 'xs_footer' => XS_TPL_PATH . 'xs_footer.tpl',\r
183                 ));\r
184         $template->preparse = 'xs_header';\r
185         $template->postparse = 'xs_footer';\r
186         $template->assign_block_vars('nav_left',array('ITEM' => '<a href="' . append_sid('xs_index.'.$phpEx) . '">' . $lang['xs_menu'] . '</a>'));\r
187 }\r
188 \r
189 \r
190 header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');\r
191 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');\r
192 \r
193 //\r
194 // Check compatibility with mods\r
195 //\r
196 if(isset($config->data) && $config->data === $board_config && isset($config->data['mod_cat_hierarchy']))\r
197 {\r
198         define('XS_MODS_CATEGORY_HIERARCHY210', true);\r
199 }\r
200 elseif(defined('CACHE_THEMES') && @function_exists('cache_themes'))\r
201 {\r
202         define('XS_MODS_CATEGORY_HIERARCHY', true);\r
203 }\r
204 if(isset($theme['theme_public']))\r
205 {\r
206         define('XS_MODS_ADMIN_TEMPLATES', true);\r
207 }\r
208 \r
209 \r
210 //\r
211 // Get FTP configuration\r
212 //\r
213 function get_ftp_config($action, $post = array(), $allow_local = false, $show_error = '')\r
214 {\r
215         global $template, $board_config, $db, $lang, $HTTP_POST_VARS, $HTTP_SERVER_VARS;\r
216         $board_config['xs_ftp_local'] = false;\r
217         // check if ftp can be used\r
218         if(!@function_exists('ftp_connect'))\r
219         {\r
220                 if($allow_local && xs_dir_writable('../templates/'))\r
221                 {\r
222                         $board_config['xs_ftp_local'] = true;\r
223                         return true;\r
224                 }\r
225                 xs_error($lang['xs_ftp_error_fatal']);\r
226         }\r
227         // check if we have configuration\r
228         if(!empty($HTTP_POST_VARS['get_ftp_config']))\r
229         {\r
230                 $vars = array('xs_ftp_host', 'xs_ftp_login', 'xs_ftp_path');\r
231                 for($i=0; $i<count($vars); $i++)\r
232                 {\r
233                         $var = $vars[$i];\r
234                         if($board_config[$var] !== $HTTP_POST_VARS[$var])\r
235                         {\r
236                                 $board_config[$var] = stripslashes($HTTP_POST_VARS[$var]);\r
237                                 $sql = "UPDATE " . CONFIG_TABLE . " SET config_value = '" . xs_sql($board_config[$var]) . "' WHERE config_name = '{$var}'";\r
238                                 $db->sql_query($sql);\r
239                         }\r
240                 }\r
241                 $board_config['xs_ftp_pass'] = stripslashes($HTTP_POST_VARS['xs_ftp_pass']);\r
242                 $board_config['xs_ftp_local'] = empty($HTTP_POST_VARS['xs_ftp_local']) ? false : true;\r
243                 // recache config table\r
244                 if(defined('XS_MODS_CATEGORY_HIERARCHY210'))\r
245                 {\r
246                         global $config;\r
247                         if ( !empty($config) )\r
248                         {\r
249                                 $config->read(true);\r
250                         }\r
251                 }\r
252                 return true;\r
253         }\r
254         // check ftp configuration\r
255         $xs_ftp_host = $board_config['xs_ftp_host'];\r
256         if(empty($xs_ftp_host))\r
257         {\r
258                 $str = $HTTP_SERVER_VARS['HTTP_HOST'];\r
259                 $template->assign_vars(array(\r
260                         'HOST_GUESS' => str_replace(array('{HOST}', '{CLICK}'), array($str, 'document.ftp.xs_ftp_host.value=\''.$str.'\''), $lang['xs_ftp_host_guess'])\r
261                         ));\r
262         }\r
263         $dir = getcwd();\r
264         $xs_ftp_login = $board_config['xs_ftp_login'];\r
265         if(empty($xs_ftp_login))\r
266         {\r
267                 if(substr($dir, 0, 6) === '/home/')\r
268                 {\r
269                         $str = substr($dir, 6);\r
270                         $pos = strpos($str, '/');\r
271                         if($pos)\r
272                         {\r
273                                 $str = substr($str, 0, $pos);\r
274                                 $template->assign_vars(array(\r
275                                         'LOGIN_GUESS' => str_replace(array('{LOGIN}', '{CLICK}'), array($str, 'document.ftp.xs_ftp_login.value=\''.$str.'\''), $lang['xs_ftp_login_guess'])\r
276                                 ));\r
277                         }\r
278                 }\r
279         }\r
280         $xs_ftp_path = $board_config['xs_ftp_path'];\r
281         if(empty($xs_ftp_path))\r
282         {\r
283                 if(substr($dir, 0, 6) === '/home/');\r
284                 $str = substr($dir, 6);\r
285                 $pos = strpos($str, '/');\r
286                 if($pos)\r
287                 {\r
288                         $str = substr($str, $pos + 1);\r
289                         $pos = strrpos($str, 'admin');\r
290                         if($pos)\r
291                         {\r
292                                 $str = substr($str, 0, $pos-1);\r
293                                 $template->assign_vars(array(\r
294                                         'PATH_GUESS' => str_replace(array('{PATH}', '{CLICK}'), array($str, 'document.ftp.xs_ftp_path.value=\''.$str.'\''), $lang['xs_ftp_path_guess'])\r
295                                 ));\r
296                         }\r
297                 }\r
298         }\r
299         if($allow_local && xs_dir_writable('../templates/'))\r
300         {\r
301                 $template->assign_block_vars('xs_ftp_local', array());\r
302         }\r
303         else\r
304         {\r
305                 $template->assign_block_vars('xs_ftp_nolocal', array());\r
306         }\r
307         $str = '<input type="hidden" name="get_ftp_config" value="1" />';\r
308         foreach($post as $var => $value)\r
309         {\r
310                 $str .= '<input type="hidden" name="' . htmlspecialchars($var) . '" value="' . htmlspecialchars($value) . '" />';\r
311         }\r
312         $template->assign_vars(array(\r
313                         'FORM_ACTION'           => $action,\r
314                         'S_EXTRA_FIELDS'        => $str,\r
315                         'XS_FTP_HOST'           => $xs_ftp_host,\r
316                         'XS_FTP_LOGIN'          => $xs_ftp_login,\r
317                         'XS_FTP_PATH'           => $xs_ftp_path,\r
318                 ));\r
319         if($show_error)\r
320         {\r
321                 $template->assign_block_vars('error', array('MSG' => $show_error));\r
322         }\r
323         $template->set_filenames(array('config' => XS_TPL_PATH . 'ftp.tpl'));\r
324         $template->pparse('config');\r
325         return false;\r
326 }\r
327 \r
328 // connect ftp\r
329 function xs_ftp_connect($action, $post = array(), $allow_local = false)\r
330 {\r
331         global $ftp, $board_config, $HTTP_POST_VARS, $phpEx, $lang, $template;\r
332         $HTTP_POST_VARS['get_ftp_config'] = '';\r
333         if($allow_local && !empty($board_config['xs_ftp_local']))\r
334         {\r
335                 $ftp = XS_FTP_LOCAL;\r
336                 return true;\r
337         }\r
338         $ftp = @ftp_connect($board_config['xs_ftp_host']);\r
339         if(!$ftp)\r
340         {\r
341                 get_ftp_config($action, $post, $allow_local, str_replace('{HOST}', $board_config['xs_ftp_host'], $lang['xs_ftp_error_connect']));\r
342         }\r
343         $res = @ftp_login($ftp, $board_config['xs_ftp_login'], $board_config['xs_ftp_pass']);\r
344         if(!$res)\r
345         {\r
346                 get_ftp_config($action, $post, $allow_local, $lang['xs_ftp_error_login']);\r
347         }\r
348         $res = @ftp_chdir($ftp, $board_config['xs_ftp_path']);\r
349         if(!$res)\r
350         {\r
351                 get_ftp_config($action, $post, $allow_local, str_replace('{DIR}', $board_config['xs_ftp_path'], $lang['xs_ftp_error_chdir']));\r
352         }\r
353         // check current directory\r
354         $current_dir = @ftp_pwd($ftp);\r
355         $list = @ftp_nlist($ftp, $current_dir);\r
356         for($i=0; $i<count($list); $i++)\r
357         {\r
358                 $list[$i] = strtolower(basename($list[$i]));\r
359         }\r
360         // check few files\r
361         $check = array('extension.inc', 'templates', 'xs_mod');\r
362         $found = array(false, false, false);\r
363         for($i=0; $i<count($list); $i++)\r
364         {\r
365                 for($j=0; $j<count($check); $j++)\r
366                 {\r
367                         if($list[$i] === $check[$j])\r
368                         {\r
369                                 $found[$j] = true;\r
370                         }\r
371                 }\r
372         }\r
373         $error = false;\r
374         for($i=0; $i<count($check); $i++)\r
375         {\r
376                 if(!$found[$i])\r
377                 {\r
378                         $error = true;\r
379                 }\r
380         }\r
381         if($error)\r
382         {\r
383                 get_ftp_config($action, $post, $allow_local, $lang['xs_ftp_error_nonphpbbdir']);\r
384         }\r
385         $HTTP_POST_VARS['get_ftp_config'] = '1';\r
386 }\r
387 \r
388 // get .style file header\r
389 function xs_get_style_header($filename, $str = '')\r
390 {\r
391         /*\r
392         header format (v0.01):\r
393         - header\r
394         - header size (4 bytes)\r
395         - file size (4 bytes)\r
396         - number of entries (1 byte)\r
397     - entries sizes (number_of_entries bytes)\r
398     - entries\r
399         - footer\r
400         - gzcompressed tar of style (no crc check in tar)\r
401 \r
402         entries:\r
403           - template name\r
404       - comment\r
405           - style names\r
406         */\r
407         global $xs_header_error, $lang;\r
408         $xs_header_error = '';\r
409         if(!$str)\r
410         {\r
411                 $f = @fopen($filename, 'rb');\r
412                 if(!$f)\r
413                 {\r
414                         $xs_header_error = $lang['xs_style_header_error_file'];\r
415                         return false;\r
416                 }\r
417                 $str = fread($f, 10240);\r
418                 fclose($f);\r
419         }\r
420         if(substr($str, 0, strlen(STYLE_HEADER_START)) !== STYLE_HEADER_START)\r
421         {\r
422                 if(substr($str, 0, 7) === 'error: ')\r
423                 {\r
424                         $xs_header_error = '<br /><br />' . $lang['xs_style_header_error_server'] . substr($str, 7);\r
425                 }\r
426                 else\r
427                 {\r
428                         $xs_header_error = $lang['xs_style_header_error_invalid'];\r
429                 }\r
430                 return false;\r
431         }\r
432         $start = strlen(STYLE_HEADER_START);\r
433         $str1 = substr($str, $start, 8);\r
434         $data = unpack('Nvar1/Nvar2', $str1);\r
435         $start += 8;\r
436         $header_size = $data['var1'];\r
437         $filesize = $data['var2'];\r
438         $total = ord($str{$start});\r
439         $start ++;\r
440         if($total < 3)\r
441         {\r
442                 $xs_header_error = $lang['xs_style_header_error_invalid'];\r
443                 return false;\r
444         }\r
445         $items_len = array();\r
446         for($i=0; $i<$total; $i++)\r
447         {\r
448                 $items_len[$i] = ord($str{$i+$start});\r
449         }\r
450         $start += $total;\r
451         $items = array();\r
452         $tpl = '';\r
453         for($i=0; $i<$total; $i++)\r
454         {\r
455                 $str1 = substr($str, $start, $items_len[$i]);\r
456                 if($i == 0)     $tpl = $str1;\r
457                 elseif($i == 1) $comment = $str1;\r
458                 else    $items[] = $str1;\r
459                 $start += $items_len[$i];\r
460         }\r
461         if(substr($str, $start, strlen(STYLE_HEADER_END)) !== STYLE_HEADER_END)\r
462         {\r
463                 $xs_header_error = $lang['xs_style_header_error_invalid'];\r
464                 return false;\r
465         }\r
466         return array(\r
467                 'template'      => $tpl,\r
468                 'styles'        => $items,\r
469                 'date'          => @filemtime($filename),\r
470                 'comment'       => $comment,\r
471                 'offset'        => $header_size,\r
472                 'filename'      => $filename,\r
473                 'filesize'      => $filesize,\r
474                 );\r
475 }\r
476 \r
477 \r
478 // check if cache is writable\r
479 function xs_check_cache($filename)\r
480 {\r
481         // check if filename is valid\r
482         global $str, $template, $lang;\r
483         if(substr($filename, 0, strlen($template->cachedir)) !== $template->cachedir)\r
484         {\r
485                 $str .= $lang['xs_check_filename'] . "<br />\n";\r
486                 return false;\r
487         }\r
488         else\r
489         {\r
490                 // try to open file\r
491                 $file = @fopen($filename, 'w');\r
492                 if(!$file)\r
493                 {\r
494                         $str .= sprintf($lang['xs_check_openfile1'], $filename) . "<br />\n";\r
495                         // try to create directories\r
496                         $dir = substr($filename, strlen($template->cachedir), strlen($filename));\r
497                         $dirs = explode('/', $dir);\r
498                         $path = $template->cachedir; \r
499                         @umask(0);\r
500                         if(!@is_dir($path))\r
501                         {\r
502                                 $str .= sprintf($lang['xs_check_nodir'], $path) . "<br />\n";\r
503                                 if(!@mkdir($path))\r
504                                 {\r
505                                         $str .= sprintf($lang['xs_check_nodir2'], $path) . "<br />\n";\r
506                                         return false;\r
507                                 }\r
508                                 else\r
509                                 {\r
510                                         $str .= sprintf($lang['xs_check_createddir'], $path) . "<br />\n";\r
511                                         @chmod($path, 0777);\r
512                                 }\r
513                         }\r
514                         else\r
515                         {\r
516                                 $str .= sprintf($lang['xs_check_dir'] , $path) . "<br />\n";\r
517                         }\r
518                         if(count($dirs) > 0)\r
519                         for($i=0; $i<count($dirs)-1; $i++)\r
520                         {\r
521                                 if($i>0)\r
522                                 {\r
523                                         $path .= '/';\r
524                                 }\r
525                                 $path .= $dirs[$i];\r
526                                 if(!@is_dir($path))\r
527                                 {\r
528                                         $str .= sprintf($lang['xs_check_nodir'], $path) . "<br />\n";\r
529                                         if(!@mkdir($path))\r
530                                         {\r
531                                                 $str .= sprintf($lang['xs_check_nodir2'], $path) . "<br />\n";\r
532                                                 return false;\r
533                                         }\r
534                                         else\r
535                                         {\r
536                                                 $str .= sprintf($lang['xs_check_createddir'], $path) . "<br />\n";\r
537                                                 @chmod($path, 0777);\r
538                                         }\r
539                                 }\r
540                                 else\r
541                                 {\r
542                                         $str .= sprintf($lang['xs_check_dir'] , $path) . "<br />\n";\r
543                                 }\r
544                         }\r
545                         // try to open file again after directories were created\r
546                         $file = @fopen($filename, 'w');\r
547                 }\r
548                 if(!$file)\r
549                 {\r
550                         $str .= sprintf($lang['xs_check_openfile2'], $filename) . "<br />\n";\r
551                         return false;\r
552                 }\r
553                 $str .= sprintf($lang['xs_check_ok'], $filename) . "<br />\n";\r
554                 fputs($file, '&nbsp;');\r
555                 fclose($file);\r
556                 @chmod($filename, 0777);\r
557                 return true;\r
558         }\r
559 }\r
560 \r
561 // run ftp commands\r
562 function ftp_myexec($list)\r
563 {\r
564         global $ftp, $ftp_error, $ftp_log, $ftp_host, $ftp_login, $ftp_pass, $lang;\r
565         $ftp_error = '';\r
566         $ftp_log = array();\r
567         if(empty($ftp))\r
568         {\r
569                 // checking ftp extensions\r
570                 if(!@function_exists('ftp_connect'))\r
571                 {\r
572                         $ftp_log[] = $ftp_error = $lang['xs_ftp_log_disabled'];\r
573                         return false;\r
574                 }\r
575                 // connect to server\r
576                 $ftp_log[] = str_replace('{HOST}', "{$ftp_login}:*@{$ftp_host}", $lang['xs_ftp_log_connecting']);\r
577                 $ftp = @ftp_connect($ftp_host);\r
578                 if(!$ftp)\r
579                 {\r
580                         $ftp_log[] = $ftp_error = str_replace('{HOST}', $ftp_host, $lang['xs_ftp_log_noconnect']);\r
581                         return false;\r
582                 }\r
583                 $ftp_log[] = $lang['xs_ftp_log_connected'];\r
584                 // logging in\r
585                 $logged_in = @ftp_login($ftp, $ftp_login, $ftp_pass);\r
586                 if(!$logged_in)\r
587                 {\r
588                         $ftp_log[] = $ftp_error = str_replace('{USER}', $ftp_login, $lang['xs_ftp_log_nologin']);\r
589                         @ftp_close($ftp);\r
590                         return false;\r
591                 }\r
592                 $ftp_log[] = $lang['xs_ftp_log_loggedin'];\r
593         }\r
594         if(!ftp_myexec2($ftp, $list))\r
595         {\r
596                 @ftp_close($ftp);\r
597                 return false;\r
598         }\r
599         @ftp_close($ftp);\r
600         $ftp_log[] = $lang['xs_ftp_log_end'];\r
601         return true;\r
602 }\r
603 \r
604 // remove all files via ftp\r
605 function ftp_remove_all($ftp)\r
606 {\r
607         // get current directory\r
608         $root_dir = @ftp_pwd($ftp);\r
609         // get list of files\r
610         $files = @ftp_nlist($ftp, $root_dir);\r
611         // remove files/directories\r
612         for($i=0; $i<count($files); $i++)\r
613         {\r
614                 $res = @ftp_chdir($ftp, $files[$i]);\r
615                 if($res)\r
616                 {\r
617                         ftp_remove_all($ftp);\r
618                         @ftp_chdir($ftp, $root_dir);\r
619                         @ftp_rmdir($ftp, $files[$i]);\r
620                 }\r
621                 else\r
622                 {\r
623                         if(!@ftp_delete($ftp, $files[$i]))\r
624                         {\r
625                                 @ftp_rmdir($ftp, $files[$i]);\r
626                         }\r
627                 }\r
628         }\r
629         // change directory back\r
630         @ftp_chdir($ftp, $root_dir);\r
631 }\r
632 \r
633 // execute ftp command. recursive.\r
634 function ftp_myexec2($ftp, $list)\r
635 {\r
636         global $ftp_log, $ftp_error, $lang;\r
637         // getting current directory\r
638         $root_dir = @ftp_pwd($ftp);\r
639         if($root_dir === false)\r
640         {\r
641                 $ftp_log[] = $ftp_error = $lang['xs_ftp_log_nopwd'];\r
642                 return false;\r
643         }\r
644         $current_dir = strlen($root_dir) ? $root_dir . '/' : '';\r
645         // run commands\r
646         for($i=0; $i<count($list); $i++)\r
647         {\r
648                 $item=$list[$i];\r
649                 if($item['command'] == 'mkdir')\r
650                 {\r
651                         // create new directory\r
652                         $res = @ftp_mkdir($ftp, $item['dir']);\r
653                         if(!$res)\r
654                         {\r
655                                 $ftp_log[] = $ftp_error = str_replace('{DIR}', $item['dir'], $lang['xs_ftp_log_nomkdir']);\r
656                                 if(empty($item['ignore']))\r
657                                 {\r
658                                         return false;\r
659                                 }\r
660                         }\r
661                         else\r
662                         {\r
663                                 $ftp_log[] = str_replace('{DIR}', $item['dir'], $lang['xs_ftp_log_mkdir']);\r
664                         }\r
665                 }\r
666                 elseif($item['command'] == 'chdir')\r
667                 {\r
668                         // change current directory\r
669                         $res = @ftp_chdir($ftp, $item['dir']);\r
670                         if(!$res)\r
671                         {\r
672                                 $ftp_log[] = $ftp_error = str_replace('{DIR}', $item['dir'], $lang['xs_ftp_log_nochdir']);\r
673                                 if(empty($item['ignore']))\r
674                                 {\r
675                                         return false;\r
676                                 }\r
677                         }\r
678                         else\r
679                         {\r
680                                 $ftp_log[] = str_replace('{DIR}', $item['dir'], $lang['xs_ftp_log_chdir']);\r
681                         }\r
682                 }\r
683                 elseif($item['command'] == 'cdup')\r
684                 {\r
685                         // change current directory\r
686                         $res = @ftp_cdup($ftp);\r
687                         if(!$res)\r
688                         {\r
689                                 $ftp_log[] = $ftp_error = str_replace('{DIR}', '..', $lang['xs_ftp_log_nochdir']);\r
690                                 if(empty($item['ignore']))\r
691                                 {\r
692                                         return false;\r
693                                 }\r
694                         }\r
695                         else\r
696                         {\r
697                                 $ftp_log[] = str_replace('{DIR}', '..', $lang['xs_ftp_log_chdir']);\r
698                         }\r
699                 }\r
700                 elseif($item['command'] == 'rmdir')\r
701                 {\r
702                         // remove directory\r
703                         $res = @ftp_rmdir($ftp, $item['dir']);\r
704                         if(!$res)\r
705                         {\r
706                                 $ftp_log[] = $ftp_error = str_replace('{DIR}', $item['dir'], $lang['xs_ftp_log_normdir']);\r
707                                 if(empty($item['ignore']))\r
708                                 {\r
709                                         return false;\r
710                                 }\r
711                         }\r
712                         else\r
713                         {\r
714                                 $ftp_log[] = str_replace('{DIR}', $item['dir'], $lang['xs_ftp_log_rmdir']);\r
715                         }\r
716                 }\r
717                 elseif($item['command'] == 'upload')\r
718                 {\r
719                         // upload file\r
720                         $res = @ftp_put($ftp, $current_dir . $item['remote'], $item['local'], FTP_BINARY);\r
721                         if(!$res)\r
722                         {\r
723                                 $ftp_log[] = $ftp_error = str_replace('{FILE}', $item['remote'], $lang['xs_ftp_log_noupload']);\r
724                                 if(empty($item['ignore']))\r
725                                 {\r
726                                         return false;\r
727                                 }\r
728                         }\r
729                         else\r
730                         {\r
731                                 $ftp_log[] = str_replace('{FILE}', $item['remote'], $lang['xs_ftp_log_upload']);\r
732                         }\r
733                 }\r
734                 elseif($item['command'] == 'chmod')\r
735                 {\r
736                         // upload file\r
737                         $res = @ftp_chmod($ftp, $item['mode'], $current_dir . $item['file']);\r
738                         if(!$res)\r
739                         {\r
740                                 $ftp_log[] = str_replace('{FILE}', $item['file'], $lang['xs_ftp_log_nochmod']);\r
741                                 if(empty($item['ignore']))\r
742                                 {\r
743                                         return false;\r
744                                 }\r
745                         }\r
746                         else\r
747                         {\r
748                                 $ftp_log[] = str_replace(array('{FILE}', '{MODE}'), array($item['file'], $item['mode']), $lang['xs_ftp_log_chmod']);\r
749                         }\r
750                 }\r
751                 elseif($item['command'] == 'exec')\r
752                 {\r
753                         $res = ftp_myexec2($ftp, $item['list']);\r
754                         if(!$res)\r
755                         {\r
756                                 return false;\r
757                         }\r
758                 }\r
759                 elseif($item['command'] == 'removeall')\r
760                 {\r
761                         ftp_remove_all($ftp);\r
762                 }\r
763                 else\r
764                 {\r
765                         $ftp_log[] = str_replace('{COMMAND}', $item['command'], $lang['xs_ftp_log_invalidcommand']);\r
766                         if(empty($item['ignore']))\r
767                         {\r
768                                 return false;\r
769                         }\r
770                 }\r
771         }\r
772         // changing current directory back\r
773         $ftp_log[] = str_replace('{DIR}', $root_dir, $lang['xs_ftp_log_chdir2']);\r
774         if(!@ftp_chdir($ftp, $root_dir))\r
775         {\r
776                 $ftp_log[] = $ftp_error = str_replace('{DIR}', $root_dir, $lang['xs_ftp_log_nochdir2']);\r
777                 return false;\r
778         }\r
779         return true;\r
780 }\r
781 \r
782 // return data from theme_info.cfg\r
783 function xs_get_themeinfo($tpl)\r
784 {\r
785         // Get contents of theme_info.cfg\r
786         // Run inside function to avoid theme_info.cfg accessing global variables\r
787         $tpl = str_replace(array('/', '\\'), array('', ''), $tpl);\r
788         include('../templates/' . $tpl . '/theme_info.cfg');\r
789         return isset($$tpl) ? $$tpl : array();\r
790 }\r
791 \r
792 // install style\r
793 function xs_install_style($tpl, $num)\r
794 {\r
795         global $db;\r
796         $data = xs_get_themeinfo($tpl);\r
797         if(empty($data[$num]))\r
798         {\r
799                 return false;\r
800         }\r
801         $data = $data[$num];\r
802         if(empty($data['style_name']))\r
803         {\r
804                 return false;\r
805         }\r
806         $sql = "SELECT themes_id FROM " . THEMES_TABLE . " WHERE style_name='" . xs_sql($data['style_name']) . "'";\r
807         if(!$result = $db->sql_query($sql))\r
808         {\r
809                 return false;\r
810         }\r
811         $row = $db->sql_fetchrow($result);\r
812         if(!empty($row['themes_id']))\r
813         {\r
814                 return false;\r
815         }\r
816         $vars = array();\r
817         $values = array();\r
818         foreach($data as $var => $value)\r
819         {\r
820                 $vars[] = xs_sql($var);\r
821                 $values[] = xs_sql(stripslashes($value));\r
822         }\r
823         $sql = "INSERT INTO " . THEMES_TABLE . " (" . implode(', ', $vars) . ") VALUES ('" . implode("', '", $values) . "')";\r
824         if(!$result = $db->sql_query($sql))\r
825         {\r
826                 return false;\r
827         }\r
828         // recache themes table\r
829         if(defined('XS_MODS_CATEGORY_HIERARCHY210'))\r
830         {\r
831                 global $themes;\r
832                 if ( empty($themes) )\r
833                 {\r
834                         $themes = new themes();\r
835                 }\r
836                 if ( !empty($themes) )\r
837                 {\r
838                         $themes->read(true);\r
839                 }\r
840         }\r
841         // add configuration\r
842         global $template;\r
843         if($template->add_config($tpl))\r
844         {\r
845                 define('REFRESH_NAVBAR', true);\r
846         }\r
847         return true;\r
848 }\r
849 \r
850 // generate theme_info.cfg for template\r
851 function xs_generate_themeinfo($theme_rowset, $export, $exportas, $total)\r
852 {\r
853         global $HTTP_POST_VARS;\r
854         $vars = array('template_name', 'style_name', 'head_stylesheet', 'body_background', 'body_bgcolor', 'body_text', 'body_link', 'body_vlink', 'body_alink', 'body_hlink', 'tr_color1', 'tr_color2', 'tr_color3', 'tr_class1', 'tr_class2', 'tr_class3', 'th_color1', 'th_color2', 'th_color3', 'th_class1', 'th_class2', 'th_class3', 'td_color1', 'td_color2', 'td_color3', 'td_class1', 'td_class2', 'td_class3', 'fontface1', 'fontface2', 'fontface3', 'fontsize1', 'fontsize2', 'fontsize3', 'fontcolor1', 'fontcolor2', 'fontcolor3', 'span_class1', 'span_class2', 'span_class3', 'img_size_poll', 'img_size_privmsg');\r
855         $theme_data = '<?php'."\n\n";\r
856         $theme_data .= "//\n// eXtreme Styles mod (compatible with phpBB 2.0.x) auto-generated theme config file for $exportas\n// Do not change anything in this file unless you know exactly what you are doing!\n//\n\n";\r
857         for($i = 0; $i < count($theme_rowset); $i++)\r
858         {\r
859                 $id = $theme_rowset[$i]['themes_id'];\r
860                 $theme_name = $theme_rowset[$i]['style_name'];\r
861                 for($j=0; $j<$total; $j++)\r
862                 {\r
863                         if(!empty($HTTP_POST_VARS['export_style_name_'.$j]) && $HTTP_POST_VARS['export_style_id_'.$j] == $id)\r
864                         {\r
865                                 $theme_name = stripslashes($HTTP_POST_VARS['export_style_name_'.$j]);\r
866                                 $theme_rowset[$i]['style_name'] = $theme_name;\r
867                         }\r
868                 }\r
869                 for($j=0; $j<count($vars); $j++)\r
870                 {\r
871                         $key = $vars[$j];\r
872                         $val = $theme_rowset[$i][$key];\r
873                         if($key === 'style_name')\r
874                         {\r
875                                 $theme_data .= '${\'' . $exportas . "'}[$i]['$key'] = \"" . str_replace(array("'", '"'), array("\'", "\\\""), $theme_name) . "\";\n";\r
876                         }\r
877                         elseif($key === 'template_name')\r
878                         {\r
879                                 $theme_data .= '${\'' . $exportas . "'}[$i]['$key'] = \"" . str_replace(array("'", '"'), array("\'", "\\\""), $exportas) . "\";\n";\r
880                         }\r
881                         else\r
882                         {\r
883                                 $theme_data .= '${\'' . $exportas . "'}[$i]['$key'] = \"" . str_replace(array("'", '"'), array("\'", "\\\""), str_replace($export, $exportas, $val)) . "\";\n";\r
884                         }\r
885                 }\r
886                 $theme_data .= "\n";\r
887         }\r
888         $theme_data .= '?' . '>'; // Done this to prevent highlighting editors getting confused!\r
889         return $theme_data;\r
890 }\r
891 \r
892 // Checks if directory is writable\r
893 function xs_dir_writable($dir)\r
894 {\r
895         $filename = 'tmp_' . time();\r
896         $f = @fopen($dir . $filename, 'wb');\r
897         if($f)\r
898         {\r
899                 fclose($f);\r
900                 @unlink($dir . $filename);\r
901                 return true;\r
902         }\r
903         return false;\r
904 }\r
905 \r
906 // Write to file. Create directory if necessary\r
907 function xs_write_file($filename, $data)\r
908 {\r
909         $f = @fopen($filename, 'wb');\r
910         if(!$f)\r
911         {\r
912                 // try to create directories\r
913                 $pos = strrpos($filename, '/');\r
914                 if(!$pos)\r
915                 {\r
916                         return false;\r
917                 }\r
918                 $dir = substr($filename, 0, $pos);\r
919                 xs_create_dir($dir);\r
920                 $f = @fopen($filename, 'wb');\r
921                 if(!$f)\r
922                 {\r
923                         return false;\r
924                 }\r
925         }\r
926         fwrite($f, $data);\r
927         fclose($f);\r
928         @chmod($filename, 0777);\r
929         return true;\r
930 }\r
931 \r
932 // Create local directory\r
933 function xs_create_dir($dir)\r
934 {\r
935         if(!$dir)\r
936         {\r
937                 return false;\r
938         }\r
939         // remove trailing /\r
940         if(substr($dir, strlen($dir) - 1) === '/')\r
941         {\r
942                 $dir = substr($dir, 0, strlen($dir) - 1);\r
943                 if(!$dir)\r
944                 {\r
945                         return false;\r
946                 }\r
947         }\r
948         if($dir === '.' || $dir === '..')\r
949         {\r
950                 return false;\r
951         }\r
952         $res = @mkdir($dir, 0777);\r
953         if($res)\r
954         {\r
955                 return true;\r
956         }\r
957         // try to create previous directory\r
958         $pos = strrpos($dir, '/');\r
959         if(!$pos)\r
960         {\r
961                 return false;\r
962         }\r
963         $dir1 = substr($dir, 0, $pos);\r
964         $dir2 = substr($dir, $pos+1);\r
965         if($dir2 === '.' || $dir2 === '..')\r
966         {\r
967                 return false;\r
968         }\r
969         if(!xs_create_dir($dir1))\r
970         {\r
971                 return false;\r
972         }\r
973         $res = @mkdir($dir2, 0777);\r
974         return $res ? true : false;\r
975 }\r
976 \r
977 // replacement for in_array() (because of compatibility problems)\r
978 function xs_in_array($needle, $haystack)\r
979 {\r
980         for($i=0; $i<sizeof($haystack); $i++)\r
981         {\r
982                 if($haystack[$i] == $needle)\r
983                 {\r
984                         return true;\r
985                 }\r
986         }\r
987         return false;\r
988 }\r
989 \r
990 // show error and exit\r
991 function xs_error($error, $line = 0, $file = '')\r
992 {\r
993         global $template, $lang;\r
994         if($line || $file)\r
995         {\r
996                 $error = basename($file) . '(' . $line . '): ' . $error;\r
997         }\r
998         $template->set_filenames(array('errormsg' => XS_TPL_PATH . 'message.tpl'));\r
999         $template->assign_vars(array(\r
1000                         'MESSAGE_TITLE' => $lang['Error'],\r
1001                         'MESSAGE_TEXT'  => $error\r
1002                 ));\r
1003         $template->pparse('errormsg');\r
1004         xs_exit();\r
1005 }\r
1006 \r
1007 // show message and exit\r
1008 function xs_message($title, $message)\r
1009 {\r
1010         global $template;\r
1011         $template->set_filenames(array('msg' => XS_TPL_PATH . 'message.tpl'));\r
1012         $template->assign_vars(array(\r
1013                         'MESSAGE_TITLE' => $title,\r
1014                         'MESSAGE_TEXT'  => $message\r
1015                 ));\r
1016         $template->pparse('msg');\r
1017         xs_exit();\r
1018 }\r
1019 \r
1020 // pack style to .style\r
1021 function pack_style($name, $newname, $themes, $comment)\r
1022 {\r
1023         /*\r
1024         header format (v0.01):\r
1025         - header\r
1026         - header size (4 bytes)\r
1027         - file size (4 bytes)\r
1028         - number of entries (1 byte)\r
1029     - entries sizes (number_of_entries bytes)\r
1030     - entries\r
1031         - footer\r
1032         - gzcompressed tar of style (no crc check in tar)\r
1033 \r
1034         entries:\r
1035           - template name\r
1036       - comment\r
1037           - style names\r
1038         */\r
1039         global $phpbb_root_path, $template_dir;\r
1040         $data = gzcompress(pack_dir($phpbb_root_path . $template_dir . $name, '', $name, $newname));\r
1041         $items_data = chr(strlen($newname)) . chr(strlen($comment));\r
1042         $items_str = $newname . $comment;\r
1043         for($i=0; $i<count($themes); $i++)\r
1044         {\r
1045                 $str = $themes[$i]['style_name'];\r
1046                 $items_data .= chr(strlen($str));\r
1047                 $items_str .= $str;\r
1048         }\r
1049         $header_size = strlen(STYLE_HEADER_START) + 8 + 1 + strlen($items_data) + strlen($items_str) + strlen(STYLE_HEADER_END);\r
1050         $filesize = $header_size + strlen($data);\r
1051         $header = STYLE_HEADER_START . pack('NN', $header_size, $filesize) . chr(strlen($items_data)) . $items_data . $items_str . STYLE_HEADER_END;\r
1052         return $header . $data;\r
1053 }\r
1054 \r
1055 // pack directory\r
1056 function pack_dir($dir1, $dir2, $search, $replace)\r
1057 {\r
1058         global $pack_error, $pack_list, $pack_replace, $lang;\r
1059         // replacements in content\r
1060         $search2 = array('templates/'.$search.'/'.$search, 'templates/'.$search);\r
1061         $replace2 = array('templates/'.$replace.'/'.$replace, 'templates/'.$replace);\r
1062         // replacements in filename\r
1063         $search3 = './'.$search;\r
1064         $replace3 = './'.$replace;\r
1065         if($pack_error)\r
1066         {\r
1067                 return '';\r
1068         }\r
1069         $dir = $dir1 . '/' . $dir2;\r
1070         $res = @opendir($dir);\r
1071         $str = '';\r
1072         if(!$res)\r
1073         {\r
1074                 $pack_error = str_replace('{DIR}', $lang['xs_export_no_open_dir'], $dir);\r
1075                 return '';\r
1076         }\r
1077         // get list of files/directories\r
1078         $files = array();\r
1079         $subdir = array();\r
1080         while(($file = readdir($res)) !== false)\r
1081         {\r
1082                 if($file !== '.' && $file !== '..')\r
1083                 {\r
1084                         if(@is_dir($dir . '/' . $file))\r
1085                         {\r
1086                                 $subdir[] = $file;\r
1087                         }\r
1088                         elseif(@is_file($dir . '/' . $file))\r
1089                         {\r
1090                                 $files[] = $file;\r
1091                         }\r
1092                 }\r
1093         }\r
1094         closedir($res);\r
1095         // add current directory\r
1096         $base_dir = ($dir2 ? $dir2 : '.') . '/';\r
1097         $header = array(\r
1098                 'filename'      => $base_dir,\r
1099                 'mode'          => '40777',\r
1100                 'uid'           => '0',\r
1101                 'gid'           => '0',\r
1102                 'size'          => decoct(0),\r
1103                 'mtime'         => decoct(@filemtime($dir)),\r
1104                 'checksum'      => '0', // ignore checksum\r
1105                 'typeflag'      => '5',\r
1106                 'link'          => '',\r
1107                 'magic'         => "ustar",\r
1108                 'version'       => '',\r
1109                 'uname'         => 'user',\r
1110                 'gname'         => 'group',\r
1111                 'devmajor'      => '',\r
1112                 'devminor'      => '',\r
1113                 'prefix'        => '',\r
1114                 'extra'         => ''\r
1115                 );\r
1116         $header_str = pack(TAR_HEADER_PACK, $header['filename'], $header['mode'], $header['uid'], $header['gid'], $header['size'], $header['mtime'], $header['checksum'], $header['typeflag'], $header['linkname'], $header['magic'], $header['version'], $header['uname'], $header['gname'], $header['devmajor'], $header['devminor'], $header['prefix'], $header['extra']);\r
1117         $file_str = '';\r
1118         $extra_str = '';\r
1119         $str .= $header_str . $file_str . $extra_str;\r
1120         // add all files\r
1121         for($i=0; $i<count($files); $i++)\r
1122         {\r
1123                 $file = $files[$i];\r
1124                 $header['filename'] = $base_dir . $file;\r
1125                 $pack_list[] = $header['filename'];\r
1126                 if(isset($pack_replace[$header['filename']]))\r
1127                 {\r
1128                         $file_str = $pack_replace[$header['filename']];\r
1129                         $file_size = strlen($file_str);\r
1130                 }\r
1131                 else\r
1132                 {\r
1133                         $f = @fopen($dir . '/' . $file, 'rb');\r
1134                         if(!$f)\r
1135                         {\r
1136                                 $pack_error = str_replace('{FILE}', $dir . '/' . $file, $lang['xs_export_no_open_file']);\r
1137                                 return '';\r
1138                         }\r
1139                         $file_size = @filesize($dir . '/' . $file);\r
1140                         if($file_size)\r
1141                         {\r
1142                                 $file_str = fread($f, $file_size);\r
1143                         }\r
1144                         else\r
1145                         {\r
1146                                 $file_str = '';\r
1147                         }\r
1148                         if(strlen($file_str) != $file_size)\r
1149                         {\r
1150                                 $pack_error = str_replace('{FILE}', $dir . '/' . $file, $lang['xs_export_no_read_file']);\r
1151                                 return '';\r
1152                         }\r
1153                         fclose($f);\r
1154                         if($search !== $replace)\r
1155                         {\r
1156                                 $file_str = str_replace($search2, $replace2, $file_str);\r
1157                         }\r
1158                 }\r
1159                 if($search !== $replace && substr($header['filename'], strlen($header['filename']) - 4) !== '.tpl')\r
1160                 {\r
1161                         if(substr($header['filename'], 0, strlen($search)) === $search)\r
1162                         {       \r
1163                                 $header['filename'] = $replace . substr($header['filename'], strlen($search));\r
1164                         }\r
1165                         elseif(substr($header['filename'], 0, strlen($search3)) === $search3)\r
1166                         {       \r
1167                                 $header['filename'] = $replace3 . substr($header['filename'], strlen($search3));\r
1168                         }\r
1169                 }\r
1170 /*              echo 'filename: ', $header['filename'], '<br />';\r
1171                 if($header['filename'] === './overall_header.tpl')\r
1172                 {\r
1173                         echo 'overall_header.tpl:<br /><hr />', nl2br(htmlspecialchars($file_str)), '<br /><hr /><br />';\r
1174                 }*/\r
1175                 $size = strlen($file_str);\r
1176                 $header['size'] = decoct($size);\r
1177                 $header['typeflag'] = '0';\r
1178                 $header['mode'] = '100666';\r
1179                 $full_size = floor(($size + 511) / 512) * 512;\r
1180                 $extra_str = $full_size > $size ? str_repeat("\0", $full_size - $size) : '';\r
1181                 $header_str = pack(TAR_HEADER_PACK, $header['filename'], $header['mode'], $header['uid'], $header['gid'], $header['size'], $header['mtime'], $header['checksum'], $header['typeflag'], $header['linkname'], $header['magic'], $header['version'], $header['uname'], $header['gname'], $header['devmajor'], $header['devminor'], $header['prefix'], $header['extra']);\r
1182                 $str .= $header_str . $file_str . $extra_str;\r
1183         }\r
1184         // add all directories\r
1185         for($i=0; $i<count($subdir); $i++)\r
1186         {\r
1187                 $str .= pack_dir($dir1, $dir2 ? $dir2 . '/' . $subdir[$i] : $subdir[$i], $search, $replace);\r
1188         }\r
1189         if(!$dir2)\r
1190         {\r
1191                 $str .= str_repeat("\0", 1024);\r
1192         }\r
1193         return $str;\r
1194 }\r
1195 \r
1196 // save export configuration\r
1197 function set_export_method($method, $data)\r
1198 {\r
1199         global $db, $board_config;\r
1200         $data['method'] = $method;\r
1201         $str = xs_sql(serialize($data));\r
1202         $sql = isset($board_config['xs_export_data']) ? "UPDATE " . CONFIG_TABLE . " SET config_value='{$str}' WHERE config_name='xs_export_data'" : "INSERT INTO " . CONFIG_TABLE . " (config_name, config_value) VALUES ('xs_export_data', '{$str}')";\r
1203         $db->sql_query($sql);\r
1204 }\r
1205 \r
1206 // send file\r
1207 function xs_download_file($filename, $content, $content_type = '')\r
1208 {\r
1209         if(empty($content_type))\r
1210         {\r
1211                 $content_type = 'application/unknown';\r
1212         }\r
1213         header('Content-Type: ' . $content_type);\r
1214         header('Content-Length: ' . strlen($content));\r
1215         header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');\r
1216         if($filename)\r
1217         {\r
1218                 header('Content-Disposition: inline; filename="' . $filename . '"');\r
1219         }\r
1220         header('Cache-Control: must-revalidate, post-check=0, pre-check=0');\r
1221         header('Pragma: public');\r
1222         echo $content;\r
1223 }\r
1224 \r
1225 // strip slashes for sql\r
1226 function xs_sql($sql, $strip = false)\r
1227 {\r
1228         if($strip)\r
1229         {\r
1230                 $sql = stripslashes($sql);\r
1231         }\r
1232         return str_replace('\\\'', '\'\'', addslashes($sql));\r
1233 }\r
1234 \r
1235 // clean template name\r
1236 function xs_tpl_name($name)\r
1237 {\r
1238         return str_replace(array('\\', '/', "'", '"'), array('','','',''), $name);\r
1239 }\r
1240 \r
1241 // close database and maybe do some other stuff\r
1242 function xs_exit()\r
1243 {\r
1244         global $db;\r
1245         if(isset($db))\r
1246         {\r
1247                 $db->sql_close();\r
1248         }\r
1249         exit;\r
1250 }\r
1251 \r
1252 // check directory name/filename\r
1253 function xs_fix_dir($dir)\r
1254 {\r
1255         $dir = str_replace('\\', '/', $dir);\r
1256         $dir = str_replace('../', './', $dir);\r
1257         while(strlen($dir > 1) && substr($dir, strlen($dir) - 2) === '..')\r
1258         {\r
1259                 $dir = substr($dir, 0, strlen($dir) - 1);\r
1260         }\r
1261         return $dir;\r
1262 }\r
1263 \r
1264 ?>