phpBB
Statistics
| Revision:

root / trunk / phpBB / includes / functions_module.php

History | View | Annotate | Download (24.7 kB)

1 5114 acydburn
<?php
2 8146 acydburn
/**
3 5114 acydburn
*
4 5114 acydburn
* @package phpBB3
5 8146 acydburn
* @copyright (c) 2005 phpBB Group
6 11653 git-gate
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
7 5114 acydburn
*
8 5114 acydburn
*/
9 5016 psotfx
10 5114 acydburn
/**
11 8146 acydburn
* @ignore
12 8146 acydburn
*/
13 8146 acydburn
if (!defined('IN_PHPBB'))
14 8146 acydburn
{
15 8146 acydburn
        exit;
16 8146 acydburn
}
17 8146 acydburn
18 8146 acydburn
/**
19 5252 acydburn
* Class handling all types of 'plugins' (a future term)
20 5612 acydburn
* @package phpBB3
21 5114 acydburn
*/
22 5252 acydburn
class p_master
23 5016 psotfx
{
24 5252 acydburn
        var $p_id;
25 5252 acydburn
        var $p_class;
26 5252 acydburn
        var $p_name;
27 5252 acydburn
        var $p_mode;
28 5252 acydburn
        var $p_parent;
29 5252 acydburn
30 9095 acydburn
        var $include_path = false;
31 6135 acydburn
        var $active_module = false;
32 6920 acydburn
        var $active_module_row_id = false;
33 6015 acydburn
        var $acl_forum_id = false;
34 5016 psotfx
        var $module_ary = array();
35 5016 psotfx
36 5252 acydburn
        /**
37 9095 acydburn
        * Constuctor
38 9095 acydburn
        * Set module include path
39 9095 acydburn
        */
40 9095 acydburn
        function p_master($include_path = false)
41 9095 acydburn
        {
42 9095 acydburn
                global $phpbb_root_path;
43 9095 acydburn
44 9095 acydburn
                $this->include_path = ($include_path !== false) ? $include_path : $phpbb_root_path . 'includes/';
45 9095 acydburn
46 9095 acydburn
                // Make sure the path ends with /
47 9095 acydburn
                if (substr($this->include_path, -1) !== '/')
48 9095 acydburn
                {
49 9095 acydburn
                        $this->include_path .= '/';
50 9095 acydburn
                }
51 9095 acydburn
        }
52 9095 acydburn
53 9095 acydburn
        /**
54 9095 acydburn
        * Set custom include path for modules
55 9095 acydburn
        * Schema for inclusion is include_path . modulebase
56 9095 acydburn
        *
57 9095 acydburn
        * @param string $include_path include path to be used.
58 9095 acydburn
        * @access public
59 9095 acydburn
        */
60 9095 acydburn
        function set_custom_include_path($include_path)
61 9095 acydburn
        {
62 9095 acydburn
                $this->include_path = $include_path;
63 9095 acydburn
64 9095 acydburn
                // Make sure the path ends with /
65 9095 acydburn
                if (substr($this->include_path, -1) !== '/')
66 9095 acydburn
                {
67 9095 acydburn
                        $this->include_path .= '/';
68 9095 acydburn
                }
69 9095 acydburn
        }
70 9095 acydburn
71 9095 acydburn
        /**
72 5252 acydburn
        * List modules
73 5252 acydburn
        *
74 5252 acydburn
        * This creates a list, stored in $this->module_ary of all available
75 5252 acydburn
        * modules for the given class (ucp, mcp and acp). Additionally
76 5252 acydburn
        * $this->module_y_ary is created with indentation information for
77 5252 acydburn
        * displaying the module list appropriately. Only modules for which
78 5252 acydburn
        * the user has access rights are included in these lists.
79 5252 acydburn
        */
80 5252 acydburn
        function list_modules($p_class)
81 5016 psotfx
        {
82 5612 acydburn
                global $auth, $db, $user, $cache;
83 5252 acydburn
                global $config, $phpbb_root_path, $phpEx;
84 5016 psotfx
85 5252 acydburn
                // Sanitise for future path use, it's escaped as appropriate for queries
86 5252 acydburn
                $this->p_class = str_replace(array('.', '/', '\\'), '', basename($p_class));
87 5016 psotfx
88 5612 acydburn
                // Get cached modules
89 5920 acydburn
                if (($this->module_cache = $cache->get('_modules_' . $this->p_class)) === false)
90 5268 acydburn
                {
91 5558 acydburn
                        // Get modules
92 5268 acydburn
                        $sql = 'SELECT *
93 5268 acydburn
                                FROM ' . MODULES_TABLE . "
94 5612 acydburn
                                WHERE module_class = '" . $db->sql_escape($this->p_class) . "'
95 5268 acydburn
                                ORDER BY left_id ASC";
96 5268 acydburn
                        $result = $db->sql_query($sql);
97 8347 acydburn
98 5558 acydburn
                        $rows = array();
99 5268 acydburn
                        while ($row = $db->sql_fetchrow($result))
100 5268 acydburn
                        {
101 5558 acydburn
                                $rows[$row['module_id']] = $row;
102 5268 acydburn
                        }
103 5612 acydburn
                        $db->sql_freeresult($result);
104 5517 acydburn
105 5558 acydburn
                        $this->module_cache = array();
106 5558 acydburn
                        foreach ($rows as $module_id => $row)
107 5268 acydburn
                        {
108 5558 acydburn
                                $this->module_cache['modules'][] = $row;
109 5558 acydburn
                                $this->module_cache['parents'][$row['module_id']] = $this->get_parents($row['parent_id'], $row['left_id'], $row['right_id'], $rows);
110 5268 acydburn
                        }
111 5558 acydburn
                        unset($rows);
112 5268 acydburn
113 5612 acydburn
                        $cache->put('_modules_' . $this->p_class, $this->module_cache);
114 5268 acydburn
                }
115 5268 acydburn
116 6803 acydburn
                if (empty($this->module_cache))
117 6803 acydburn
                {
118 6803 acydburn
                        $this->module_cache = array('modules' => array(), 'parents' => array());
119 6803 acydburn
                }
120 6803 acydburn
121 5558 acydburn
                // We "could" build a true tree with this function - maybe mod authors want to use this...
122 5558 acydburn
                // Functions for traversing and manipulating the tree are not available though
123 5558 acydburn
                // We might re-structure the module system to use true trees in 3.2.x...
124 5558 acydburn
                // $tree = $this->build_tree($this->module_cache['modules'], $this->module_cache['parents']);
125 5252 acydburn
126 5558 acydburn
                // Clean up module cache array to only let survive modules the user can access
127 5558 acydburn
                $right_id = false;
128 5408 acydburn
                foreach ($this->module_cache['modules'] as $key => $row)
129 5016 psotfx
                {
130 5408 acydburn
                        // Not allowed to view module?
131 5408 acydburn
                        if (!$this->module_auth($row['module_auth']))
132 5016 psotfx
                        {
133 5517 acydburn
                                unset($this->module_cache['modules'][$key]);
134 5408 acydburn
                                continue;
135 5016 psotfx
                        }
136 5016 psotfx
137 5252 acydburn
                        // Category with no members, ignore
138 6177 acydburn
                        if (!$row['module_basename'] && ($row['left_id'] + 1 == $row['right_id']))
139 5016 psotfx
                        {
140 5558 acydburn
                                unset($this->module_cache['modules'][$key]);
141 5016 psotfx
                                continue;
142 5016 psotfx
                        }
143 5016 psotfx
144 5558 acydburn
                        // Skip branch
145 5558 acydburn
                        if ($right_id !== false)
146 5408 acydburn
                        {
147 5558 acydburn
                                if ($row['left_id'] < $right_id)
148 5408 acydburn
                                {
149 5558 acydburn
                                        unset($this->module_cache['modules'][$key]);
150 5408 acydburn
                                        continue;
151 5408 acydburn
                                }
152 8347 acydburn
153 5558 acydburn
                                $right_id = false;
154 5408 acydburn
                        }
155 5408 acydburn
156 5376 acydburn
                        // Not enabled?
157 5376 acydburn
                        if (!$row['module_enabled'])
158 5376 acydburn
                        {
159 5376 acydburn
                                // If category is disabled then disable every child too
160 5558 acydburn
                                unset($this->module_cache['modules'][$key]);
161 5558 acydburn
                                $right_id = $row['right_id'];
162 5376 acydburn
                                continue;
163 5376 acydburn
                        }
164 5558 acydburn
                }
165 5558 acydburn
166 5558 acydburn
                // Re-index (this is needed, else we are not able to array_slice later)
167 5558 acydburn
                $this->module_cache['modules'] = array_merge($this->module_cache['modules']);
168 5558 acydburn
169 7819 acydburn
                // Include MOD _info files for populating language entries within the menus
170 7938 acydburn
                $this->add_mod_info($this->p_class);
171 7819 acydburn
172 5558 acydburn
                // Now build the module array, but exclude completely empty categories...
173 5558 acydburn
                $right_id = false;
174 5558 acydburn
                $names = array();
175 5558 acydburn
176 5558 acydburn
                foreach ($this->module_cache['modules'] as $key => $row)
177 5558 acydburn
                {
178 5558 acydburn
                        // Skip branch
179 5558 acydburn
                        if ($right_id !== false)
180 5376 acydburn
                        {
181 5558 acydburn
                                if ($row['left_id'] < $right_id)
182 5376 acydburn
                                {
183 5376 acydburn
                                        continue;
184 5376 acydburn
                                }
185 8347 acydburn
186 5558 acydburn
                                $right_id = false;
187 5376 acydburn
                        }
188 5376 acydburn
189 5558 acydburn
                        // Category with no members on their way down (we have to check every level)
190 6177 acydburn
                        if (!$row['module_basename'])
191 5016 psotfx
                        {
192 5558 acydburn
                                $empty_category = true;
193 5558 acydburn
194 5558 acydburn
                                // We go through the branch and look for an activated module
195 5558 acydburn
                                foreach (array_slice($this->module_cache['modules'], $key + 1) as $temp_row)
196 5252 acydburn
                                {
197 5558 acydburn
                                        if ($temp_row['left_id'] > $row['left_id'] && $temp_row['left_id'] < $row['right_id'])
198 5558 acydburn
                                        {
199 6012 acydburn
                                                // Module there
200 6177 acydburn
                                                if ($temp_row['module_basename'] && $temp_row['module_enabled'])
201 5558 acydburn
                                                {
202 5558 acydburn
                                                        $empty_category = false;
203 5558 acydburn
                                                        break;
204 5558 acydburn
                                                }
205 5558 acydburn
                                                continue;
206 5558 acydburn
                                        }
207 5558 acydburn
                                        break;
208 5252 acydburn
                                }
209 5558 acydburn
210 5558 acydburn
                                // Skip the branch
211 5558 acydburn
                                if ($empty_category)
212 5252 acydburn
                                {
213 5558 acydburn
                                        $right_id = $row['right_id'];
214 5558 acydburn
                                        continue;
215 5252 acydburn
                                }
216 5016 psotfx
                        }
217 5016 psotfx
218 5558 acydburn
                        $depth = sizeof($this->module_cache['parents'][$row['module_id']]);
219 5016 psotfx
220 5325 acydburn
                        // We need to prefix the functions to not create a naming conflict
221 6787 acydburn
222 5767 acydburn
                        // Function for building 'url_extra'
223 11557 git-gate
                        $short_name = $this->get_short_name($row['module_basename']);
224 5305 grahamje
225 11557 git-gate
                        $url_func = '_module_' . $short_name . '_url';
226 11557 git-gate
227 5767 acydburn
                        // Function for building the language name
228 11557 git-gate
                        $lang_func = '_module_' . $short_name . '_lang';
229 5767 acydburn
230 5767 acydburn
                        // Custom function for calling parameters on module init (for example assigning template variables)
231 11557 git-gate
                        $custom_func = '_module_' . $short_name;
232 5767 acydburn
233 6177 acydburn
                        $names[$row['module_basename'] . '_' . $row['module_mode']][] = true;
234 8347 acydburn
235 5767 acydburn
                        $module_row = array(
236 5268 acydburn
                                'depth'                => $depth,
237 5016 psotfx
238 5268 acydburn
                                'id'                => (int) $row['module_id'],
239 5268 acydburn
                                'parent'        => (int) $row['parent_id'],
240 5268 acydburn
                                'cat'                => ($row['right_id'] > $row['left_id'] + 1) ? true : false,
241 5016 psotfx
242 6177 acydburn
                                'is_duplicate'        => ($row['module_basename'] && sizeof($names[$row['module_basename'] . '_' . $row['module_mode']]) > 1) ? true : false,
243 5558 acydburn
244 6177 acydburn
                                'name'                => (string) $row['module_basename'],
245 5268 acydburn
                                'mode'                => (string) $row['module_mode'],
246 5295 acydburn
                                'display'        => (int) $row['module_display'],
247 5305 grahamje
248 6787 acydburn
                                'url_extra'        => (function_exists($url_func)) ? $url_func($row['module_mode'], $row) : '',
249 8347 acydburn
250 6177 acydburn
                                'lang'                => ($row['module_basename'] && function_exists($lang_func)) ? $lang_func($row['module_mode'], $row['module_langname']) : ((!empty($user->lang[$row['module_langname']])) ? $user->lang[$row['module_langname']] : $row['module_langname']),
251 5268 acydburn
                                'langname'        => $row['module_langname'],
252 5252 acydburn
253 5268 acydburn
                                'left'                => $row['left_id'],
254 5268 acydburn
                                'right'                => $row['right_id'],
255 5268 acydburn
                        );
256 5767 acydburn
257 5767 acydburn
                        if (function_exists($custom_func))
258 5767 acydburn
                        {
259 5767 acydburn
                                $custom_func($row['module_mode'], $module_row);
260 5767 acydburn
                        }
261 5767 acydburn
262 5767 acydburn
                        $this->module_ary[] = $module_row;
263 5252 acydburn
                }
264 5268 acydburn
265 5558 acydburn
                unset($this->module_cache['modules'], $names);
266 5252 acydburn
        }
267 5252 acydburn
268 5408 acydburn
        /**
269 6920 acydburn
        * Check if a certain main module is accessible/loaded
270 6920 acydburn
        * By giving the module mode you are able to additionally check for only one mode within the main module
271 6920 acydburn
        *
272 6920 acydburn
        * @param string $module_basename The module base name, for example logs, reports, main (for the mcp).
273 6920 acydburn
        * @param mixed $module_mode The module mode to check. If provided the mode will be checked in addition for presence.
274 6920 acydburn
        *
275 6920 acydburn
        * @return bool Returns true if module is loaded and accessible, else returns false
276 6920 acydburn
        */
277 6920 acydburn
        function loaded($module_basename, $module_mode = false)
278 6920 acydburn
        {
279 11557 git-gate
                if (!$this->is_full_class($module_basename))
280 11557 git-gate
                {
281 11557 git-gate
                        $module_basename = $this->p_class . '_' . $module_basename;
282 11557 git-gate
                }
283 11557 git-gate
284 6920 acydburn
                if (empty($this->loaded_cache))
285 6920 acydburn
                {
286 6920 acydburn
                        $this->loaded_cache = array();
287 6920 acydburn
288 6920 acydburn
                        foreach ($this->module_ary as $row)
289 6920 acydburn
                        {
290 6920 acydburn
                                if (!$row['name'])
291 6920 acydburn
                                {
292 6920 acydburn
                                        continue;
293 6920 acydburn
                                }
294 6920 acydburn
295 6920 acydburn
                                if (!isset($this->loaded_cache[$row['name']]))
296 6920 acydburn
                                {
297 6920 acydburn
                                        $this->loaded_cache[$row['name']] = array();
298 6920 acydburn
                                }
299 6920 acydburn
300 6920 acydburn
                                if (!$row['mode'])
301 6920 acydburn
                                {
302 6920 acydburn
                                        continue;
303 6920 acydburn
                                }
304 6920 acydburn
305 6920 acydburn
                                $this->loaded_cache[$row['name']][$row['mode']] = true;
306 6920 acydburn
                        }
307 6920 acydburn
                }
308 6920 acydburn
309 6920 acydburn
                if ($module_mode === false)
310 6920 acydburn
                {
311 6920 acydburn
                        return (isset($this->loaded_cache[$module_basename])) ? true : false;
312 6920 acydburn
                }
313 6920 acydburn
314 6920 acydburn
                return (!empty($this->loaded_cache[$module_basename][$module_mode])) ? true : false;
315 6920 acydburn
        }
316 6920 acydburn
317 6920 acydburn
        /**
318 5408 acydburn
        * Check module authorisation
319 5408 acydburn
        */
320 6628 acydburn
        function module_auth($module_auth, $forum_id = false)
321 5408 acydburn
        {
322 5408 acydburn
                global $auth, $config;
323 10801 git-gate
                global $request;
324 6628 acydburn
325 5408 acydburn
                $module_auth = trim($module_auth);
326 5408 acydburn
327 5408 acydburn
                // Generally allowed to access module if module_auth is empty
328 5408 acydburn
                if (!$module_auth)
329 5408 acydburn
                {
330 5408 acydburn
                        return true;
331 5408 acydburn
                }
332 5408 acydburn
333 6614 acydburn
                // With the code below we make sure only those elements get eval'd we really want to be checked
334 6614 acydburn
                preg_match_all('/(?:
335 6614 acydburn
                        "[^"\\\\]*(?:\\\\.[^"\\\\]*)*"         |
336 6614 acydburn
                        \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'     |
337 6614 acydburn
                        [(),]                                  |
338 6614 acydburn
                        [^\s(),]+)/x', $module_auth, $match);
339 6614 acydburn
340 6614 acydburn
                $tokens = $match[0];
341 6614 acydburn
                for ($i = 0, $size = sizeof($tokens); $i < $size; $i++)
342 6614 acydburn
                {
343 6614 acydburn
                        $token = &$tokens[$i];
344 6614 acydburn
345 6614 acydburn
                        switch ($token)
346 6614 acydburn
                        {
347 6614 acydburn
                                case ')':
348 6614 acydburn
                                case '(':
349 6614 acydburn
                                case '&&':
350 6614 acydburn
                                case '||':
351 6619 acydburn
                                case ',':
352 6614 acydburn
                                break;
353 6614 acydburn
354 6614 acydburn
                                default:
355 8347 acydburn
                                        if (!preg_match('#(?:acl_([a-z0-9_]+)(,\$id)?)|(?:\$id)|(?:aclf_([a-z0-9_]+))|(?:cfg_([a-z0-9_]+))|(?:request_([a-zA-Z0-9_]+))#', $token))
356 6614 acydburn
                                        {
357 6614 acydburn
                                                $token = '';
358 6614 acydburn
                                        }
359 6614 acydburn
                                break;
360 6614 acydburn
                        }
361 6614 acydburn
                }
362 6619 acydburn
363 6614 acydburn
                $module_auth = implode(' ', $tokens);
364 6614 acydburn
365 6619 acydburn
                // Make sure $id seperation is working fine
366 6619 acydburn
                $module_auth = str_replace(' , ', ',', $module_auth);
367 6619 acydburn
368 6628 acydburn
                $forum_id = ($forum_id === false) ? $this->acl_forum_id : $forum_id;
369 6628 acydburn
370 5408 acydburn
                $is_auth = false;
371 10801 git-gate
                eval('$is_auth = (int) (' . preg_replace(array('#acl_([a-z0-9_]+)(,\$id)?#', '#\$id#', '#aclf_([a-z0-9_]+)#', '#cfg_([a-z0-9_]+)#', '#request_([a-zA-Z0-9_]+)#'), array('(int) $auth->acl_get(\'\\1\'\\2)', '(int) $forum_id', '(int) $auth->acl_getf_global(\'\\1\')', '(int) $config[\'\\1\']', '$request->variable(\'\\1\', false)'), $module_auth) . ');');
372 5432 grahamje
373 5408 acydburn
                return $is_auth;
374 5408 acydburn
        }
375 5408 acydburn
376 5558 acydburn
        /**
377 5558 acydburn
        * Set active module
378 5558 acydburn
        */
379 5252 acydburn
        function set_active($id = false, $mode = false)
380 5252 acydburn
        {
381 5558 acydburn
                $icat = false;
382 6135 acydburn
                $this->active_module = false;
383 5558 acydburn
384 5558 acydburn
                if (request_var('icat', ''))
385 5558 acydburn
                {
386 5558 acydburn
                        $icat = $id;
387 5558 acydburn
                        $id = request_var('icat', '');
388 5558 acydburn
                }
389 5558 acydburn
390 11557 git-gate
                if ($id && !is_numeric($id) && !$this->is_full_class($id))
391 11557 git-gate
                {
392 11557 git-gate
                        $id = $this->p_class . '_' . $id;
393 11557 git-gate
                }
394 11557 git-gate
395 5252 acydburn
                $category = false;
396 6135 acydburn
                foreach ($this->module_ary as $row_id => $item_ary)
397 5252 acydburn
                {
398 5016 psotfx
                        // If this is a module and it's selected, active
399 5016 psotfx
                        // If this is a category and the module is the first within it, active
400 5252 acydburn
                        // If this is a module and no mode selected, select first mode
401 5016 psotfx
                        // If no category or module selected, go active for first module in first category
402 5408 acydburn
                        if (
403 11557 git-gate
                                (($item_ary['name'] === $id || $item_ary['name'] === $this->p_class . '_' . $id || $item_ary['id'] === (int) $id) && (($item_ary['mode'] == $mode && !$item_ary['cat']) || ($icat && $item_ary['cat']))) ||
404 6511 acydburn
                                ($item_ary['parent'] === $category && !$item_ary['cat'] && !$icat && $item_ary['display']) ||
405 11557 git-gate
                                (($item_ary['name'] === $id || $item_ary['name'] === $this->p_class . '_' . $id || $item_ary['id'] === (int) $id) && !$mode && !$item_ary['cat']) ||
406 6511 acydburn
                                (!$id && !$mode && !$item_ary['cat'] && $item_ary['display'])
407 5252 acydburn
                                )
408 5016 psotfx
                        {
409 6135 acydburn
                                if ($item_ary['cat'])
410 5558 acydburn
                                {
411 5558 acydburn
                                        $id = $icat;
412 5558 acydburn
                                        $icat = false;
413 5558 acydburn
414 5558 acydburn
                                        continue;
415 5558 acydburn
                                }
416 5558 acydburn
417 6135 acydburn
                                $this->p_id                = $item_ary['id'];
418 6135 acydburn
                                $this->p_parent        = $item_ary['parent'];
419 6135 acydburn
                                $this->p_name        = $item_ary['name'];
420 6135 acydburn
                                $this->p_mode         = $item_ary['mode'];
421 6135 acydburn
                                $this->p_left        = $item_ary['left'];
422 6135 acydburn
                                $this->p_right        = $item_ary['right'];
423 5016 psotfx
424 5268 acydburn
                                $this->module_cache['parents'] = $this->module_cache['parents'][$this->p_id];
425 6135 acydburn
                                $this->active_module = $item_ary['id'];
426 6920 acydburn
                                $this->active_module_row_id = $row_id;
427 5268 acydburn
428 5252 acydburn
                                break;
429 5016 psotfx
                        }
430 6135 acydburn
                        else if (($item_ary['cat'] && $item_ary['id'] === (int) $id) || ($item_ary['parent'] === $category && $item_ary['cat']))
431 5016 psotfx
                        {
432 6135 acydburn
                                $category = $item_ary['id'];
433 5016 psotfx
                        }
434 5016 psotfx
                }
435 5016 psotfx
        }
436 5016 psotfx
437 5252 acydburn
        /**
438 5252 acydburn
        * Loads currently active module
439 5252 acydburn
        *
440 5252 acydburn
        * This method loads a given module, passing it the relevant id and mode.
441 11666 git-gate
        *
442 11666 git-gate
        * @param string $mode mode, as passed through to the module
443 5252 acydburn
        */
444 5995 acydburn
        function load_active($mode = false, $module_url = false, $execute_module = true)
445 5016 psotfx
        {
446 6015 acydburn
                global $phpbb_root_path, $phpbb_admin_path, $phpEx, $user;
447 5016 psotfx
448 9095 acydburn
                $module_path = $this->include_path . $this->p_class;
449 5558 acydburn
                $icat = request_var('icat', '');
450 5252 acydburn
451 6135 acydburn
                if ($this->active_module === false)
452 6135 acydburn
                {
453 6135 acydburn
                        trigger_error('Module not accessible', E_USER_ERROR);
454 6135 acydburn
                }
455 6135 acydburn
456 11557 git-gate
                // new modules use the full class names, old ones are always called <type>_<name>, e.g. acp_board
457 11557 git-gate
                if (!class_exists($this->p_name))
458 5016 psotfx
                {
459 11557 git-gate
                        if (!file_exists("$module_path/{$this->p_name}.$phpEx"))
460 5252 acydburn
                        {
461 11557 git-gate
                                trigger_error("Cannot find module $module_path/{$this->p_name}.$phpEx", E_USER_ERROR);
462 5252 acydburn
                        }
463 5016 psotfx
464 11557 git-gate
                        include("$module_path/{$this->p_name}.$phpEx");
465 5252 acydburn
466 11557 git-gate
                        if (!class_exists($this->p_name))
467 5016 psotfx
                        {
468 11557 git-gate
                                trigger_error("Module file $module_path/{$this->p_name}.$phpEx does not contain correct class [{$this->p_name}]", E_USER_ERROR);
469 5252 acydburn
                        }
470 11557 git-gate
                }
471 5016 psotfx
472 11557 git-gate
                if (!empty($mode))
473 11557 git-gate
                {
474 11557 git-gate
                        $this->p_mode = $mode;
475 11557 git-gate
                }
476 5252 acydburn
477 11557 git-gate
                // Create a new instance of the desired module ...
478 11557 git-gate
                $class_name = $this->p_name;
479 5252 acydburn
480 11557 git-gate
                $this->module = new $class_name($this);
481 5252 acydburn
482 11557 git-gate
                // We pre-define the action parameter we are using all over the place
483 11557 git-gate
                if (defined('IN_ADMIN'))
484 11557 git-gate
                {
485 11557 git-gate
                        // Is first module automatically enabled a duplicate and the category not passed yet?
486 11557 git-gate
                        if (!$icat && $this->module_ary[$this->active_module_row_id]['is_duplicate'])
487 5633 acydburn
                        {
488 11557 git-gate
                                $icat = $this->module_ary[$this->active_module_row_id]['parent'];
489 11557 git-gate
                        }
490 6920 acydburn
491 11557 git-gate
                        // Not being able to overwrite ;)
492 11557 git-gate
                        $this->module->u_action = append_sid("{$phpbb_admin_path}index.$phpEx", "i={$this->p_name}") . (($icat) ? '&amp;icat=' . $icat : '') . "&amp;mode={$this->p_mode}";
493 11557 git-gate
                }
494 11557 git-gate
                else
495 11557 git-gate
                {
496 11557 git-gate
                        // If user specified the module url we will use it...
497 11557 git-gate
                        if ($module_url !== false)
498 11557 git-gate
                        {
499 11557 git-gate
                                $this->module->u_action = $module_url;
500 5633 acydburn
                        }
501 5633 acydburn
                        else
502 5633 acydburn
                        {
503 11557 git-gate
                                $this->module->u_action = $phpbb_root_path . (($user->page['page_dir']) ? $user->page['page_dir'] . '/' : '') . $user->page['page_name'];
504 5633 acydburn
                        }
505 5558 acydburn
506 11557 git-gate
                        $this->module->u_action = append_sid($this->module->u_action, "i={$this->p_name}") . (($icat) ? '&amp;icat=' . $icat : '') . "&amp;mode={$this->p_mode}";
507 11557 git-gate
                }
508 6920 acydburn
509 11557 git-gate
                // Add url_extra parameter to u_action url
510 11557 git-gate
                if (!empty($this->module_ary) && $this->active_module !== false && $this->module_ary[$this->active_module_row_id]['url_extra'])
511 11557 git-gate
                {
512 11557 git-gate
                        $this->module->u_action .= $this->module_ary[$this->active_module_row_id]['url_extra'];
513 11557 git-gate
                }
514 5252 acydburn
515 11557 git-gate
                // Assign the module path for re-usage
516 11557 git-gate
                $this->module->module_path = $module_path . '/';
517 5995 acydburn
518 11557 git-gate
                // Execute the main method for the new instance, we send the module id and mode as parameters
519 11557 git-gate
                // Users are able to call the main method after this function to be able to assign additional parameters manually
520 11557 git-gate
                if ($execute_module)
521 11557 git-gate
                {
522 11557 git-gate
                        $short_name = preg_replace("#^{$this->p_class}_#", '', $this->p_name);
523 11557 git-gate
                        $this->module->main($short_name, $this->p_mode);
524 5016 psotfx
                }
525 5016 psotfx
        }
526 5016 psotfx
527 5558 acydburn
        /**
528 7384 acydburn
        * Appending url parameter to the currently active module.
529 7384 acydburn
        *
530 7384 acydburn
        * This function is called for adding specific url parameters while executing the current module.
531 7384 acydburn
        * It is doing the same as the _module_{name}_url() function, apart from being able to be called after
532 7384 acydburn
        * having dynamically parsed specific parameters. This allows more freedom in choosing additional parameters.
533 7384 acydburn
        * One example can be seen in /includes/mcp/mcp_notes.php - $this->p_master->adjust_url() call.
534 7384 acydburn
        *
535 7384 acydburn
        * @param string $url_extra Extra url parameters, e.g.: &amp;u=$user_id
536 7384 acydburn
        *
537 7384 acydburn
        */
538 7384 acydburn
        function adjust_url($url_extra)
539 7384 acydburn
        {
540 7384 acydburn
                if (empty($this->module_ary[$this->active_module_row_id]))
541 7384 acydburn
                {
542 7384 acydburn
                        return;
543 7384 acydburn
                }
544 7384 acydburn
545 7384 acydburn
                $row = &$this->module_ary[$this->active_module_row_id];
546 7384 acydburn
547 7384 acydburn
                // We check for the same url_extra in $row['url_extra'] to overcome doubled additions...
548 7384 acydburn
                if (strpos($row['url_extra'], $url_extra) === false)
549 7384 acydburn
                {
550 7384 acydburn
                        $row['url_extra'] .= $url_extra;
551 7384 acydburn
                }
552 7384 acydburn
        }
553 7384 acydburn
554 7384 acydburn
        /**
555 7229 davidmj
        * Check if a module is active
556 7229 davidmj
        */
557 7232 acydburn
        function is_active($id, $mode = false)
558 7229 davidmj
        {
559 7232 acydburn
                // If we find a name by this id and being enabled we have our active one...
560 7229 davidmj
                foreach ($this->module_ary as $row_id => $item_ary)
561 7229 davidmj
                {
562 11557 git-gate
                        if (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && $item_ary['display'] || $item_ary['name'] === $this->p_class . '_' . $id)
563 7229 davidmj
                        {
564 7232 acydburn
                                if ($mode === false || $mode === $item_ary['mode'])
565 7229 davidmj
                                {
566 7232 acydburn
                                        return true;
567 7229 davidmj
                                }
568 7229 davidmj
                        }
569 7229 davidmj
                }
570 7232 acydburn
571 7232 acydburn
                return false;
572 7229 davidmj
        }
573 7229 davidmj
574 7229 davidmj
        /**
575 5558 acydburn
        * Get parents
576 5558 acydburn
        */
577 5517 acydburn
        function get_parents($parent_id, $left_id, $right_id, &$all_parents)
578 5268 acydburn
        {
579 5268 acydburn
                global $db;
580 5268 acydburn
581 5268 acydburn
                $parents = array();
582 5268 acydburn
583 5268 acydburn
                if ($parent_id > 0)
584 5268 acydburn
                {
585 5517 acydburn
                        foreach ($all_parents as $module_id => $row)
586 5517 acydburn
                        {
587 5517 acydburn
                                if ($row['left_id'] < $left_id && $row['right_id'] > $right_id)
588 5517 acydburn
                                {
589 5517 acydburn
                                        $parents[$module_id] = $row['parent_id'];
590 5517 acydburn
                                }
591 5268 acydburn
592 5517 acydburn
                                if ($row['left_id'] > $left_id)
593 5517 acydburn
                                {
594 5517 acydburn
                                        break;
595 5517 acydburn
                                }
596 5268 acydburn
                        }
597 5268 acydburn
                }
598 5268 acydburn
599 5268 acydburn
                return $parents;
600 5268 acydburn
        }
601 5558 acydburn
602 5558 acydburn
        /**
603 5558 acydburn
        * Get tree branch
604 5558 acydburn
        */
605 5558 acydburn
        function get_branch($left_id, $right_id, $remaining)
606 5558 acydburn
        {
607 5558 acydburn
                $branch = array();
608 5558 acydburn
609 5558 acydburn
                foreach ($remaining as $key => $row)
610 5558 acydburn
                {
611 5558 acydburn
                        if ($row['left_id'] > $left_id && $row['left_id'] < $right_id)
612 5558 acydburn
                        {
613 5558 acydburn
                                $branch[] = $row;
614 5558 acydburn
                                continue;
615 5558 acydburn
                        }
616 5558 acydburn
                        break;
617 5558 acydburn
                }
618 6015 acydburn
619 5558 acydburn
                return $branch;
620 5558 acydburn
        }
621 5558 acydburn
622 5558 acydburn
        /**
623 5558 acydburn
        * Build true binary tree from given array
624 5995 acydburn
        * Not in use
625 5558 acydburn
        */
626 5558 acydburn
        function build_tree(&$modules, &$parents)
627 5558 acydburn
        {
628 5558 acydburn
                $tree = array();
629 5558 acydburn
630 5558 acydburn
                foreach ($modules as $row)
631 5558 acydburn
                {
632 5558 acydburn
                        $branch = &$tree;
633 5558 acydburn
634 5558 acydburn
                        if ($row['parent_id'])
635 5558 acydburn
                        {
636 5558 acydburn
                                // Go through the tree to find our branch
637 5558 acydburn
                                $parent_tree = $parents[$row['module_id']];
638 6015 acydburn
639 5558 acydburn
                                foreach ($parent_tree as $id => $value)
640 5558 acydburn
                                {
641 5558 acydburn
                                        if (!isset($branch[$id]) && isset($branch['child']))
642 5558 acydburn
                                        {
643 5558 acydburn
                                                $branch = &$branch['child'];
644 5558 acydburn
                                        }
645 5558 acydburn
                                        $branch = &$branch[$id];
646 5558 acydburn
                                }
647 5558 acydburn
                                $branch = &$branch['child'];
648 5558 acydburn
                        }
649 5558 acydburn
650 5558 acydburn
                        $branch[$row['module_id']] = $row;
651 5558 acydburn
                        if (!isset($branch[$row['module_id']]['child']))
652 5558 acydburn
                        {
653 5558 acydburn
                                $branch[$row['module_id']]['child'] = array();
654 5558 acydburn
                        }
655 5558 acydburn
                }
656 6015 acydburn
657 5558 acydburn
                return $tree;
658 5558 acydburn
        }
659 5558 acydburn
660 5558 acydburn
        /**
661 5558 acydburn
        * Build navigation structure
662 5558 acydburn
        */
663 5252 acydburn
        function assign_tpl_vars($module_url)
664 5016 psotfx
        {
665 5272 acydburn
                global $template;
666 5016 psotfx
667 6013 acydburn
                $current_id = $right_id = false;
668 5558 acydburn
669 5995 acydburn
                // Make sure the module_url has a question mark set, effectively determining the delimiter to use
670 5995 acydburn
                $delim = (strpos($module_url, '?') === false) ? '?' : '&amp;';
671 5995 acydburn
672 5252 acydburn
                $current_padding = $current_depth = 0;
673 5016 psotfx
                $linear_offset         = 'l_block1';
674 5016 psotfx
                $tabular_offset = 't_block2';
675 5016 psotfx
676 5016 psotfx
                // Generate the list of modules, we'll do this in two ways ...
677 5016 psotfx
                // 1) In a linear fashion
678 5016 psotfx
                // 2) In a combined tabbed + linear fashion ... tabs for the categories
679 5016 psotfx
                //    and a linear list for subcategories/items
680 6135 acydburn
                foreach ($this->module_ary as $row_id => $item_ary)
681 5016 psotfx
                {
682 6013 acydburn
                        // Skip hidden modules
683 6135 acydburn
                        if (!$item_ary['display'])
684 5295 acydburn
                        {
685 5295 acydburn
                                continue;
686 5295 acydburn
                        }
687 5295 acydburn
688 6013 acydburn
                        // Skip branch
689 6013 acydburn
                        if ($right_id !== false)
690 6013 acydburn
                        {
691 6135 acydburn
                                if ($item_ary['left'] < $right_id)
692 6013 acydburn
                                {
693 6013 acydburn
                                        continue;
694 6013 acydburn
                                }
695 6013 acydburn
696 6013 acydburn
                                $right_id = false;
697 6013 acydburn
                        }
698 6013 acydburn
699 6013 acydburn
                        // Category with no members on their way down (we have to check every level)
700 6135 acydburn
                        if (!$item_ary['name'])
701 6013 acydburn
                        {
702 6013 acydburn
                                $empty_category = true;
703 6013 acydburn
704 6013 acydburn
                                // We go through the branch and look for an activated module
705 6013 acydburn
                                foreach (array_slice($this->module_ary, $row_id + 1) as $temp_row)
706 6013 acydburn
                                {
707 6135 acydburn
                                        if ($temp_row['left'] > $item_ary['left'] && $temp_row['left'] < $item_ary['right'])
708 6013 acydburn
                                        {
709 6013 acydburn
                                                // Module there and displayed?
710 6013 acydburn
                                                if ($temp_row['name'] && $temp_row['display'])
711 6013 acydburn
                                                {
712 6013 acydburn
                                                        $empty_category = false;
713 6013 acydburn
                                                        break;
714 6013 acydburn
                                                }
715 6013 acydburn
                                                continue;
716 6013 acydburn
                                        }
717 6013 acydburn
                                        break;
718 6013 acydburn
                                }
719 6013 acydburn
720 6013 acydburn
                                // Skip the branch
721 6013 acydburn
                                if ($empty_category)
722 6013 acydburn
                                {
723 6135 acydburn
                                        $right_id = $item_ary['right'];
724 6013 acydburn
                                        continue;
725 6013 acydburn
                                }
726 6013 acydburn
                        }
727 6013 acydburn
728 5558 acydburn
                        // Select first id we can get
729 8350 acydburn
                        if (!$current_id && (isset($this->module_cache['parents'][$item_ary['id']]) || $item_ary['id'] == $this->p_id))
730 5558 acydburn
                        {
731 6135 acydburn
                                $current_id = $item_ary['id'];
732 5558 acydburn
                        }
733 5558 acydburn
734 6135 acydburn
                        $depth = $item_ary['depth'];
735 5016 psotfx
736 5252 acydburn
                        if ($depth > $current_depth)
737 5016 psotfx
                        {
738 5252 acydburn
                                $linear_offset = $linear_offset . '.l_block' . ($depth + 1);
739 5252 acydburn
                                $tabular_offset = ($depth + 1 > 2) ? $tabular_offset . '.t_block' . ($depth + 1) : $tabular_offset;
740 5016 psotfx
                        }
741 5252 acydburn
                        else if ($depth < $current_depth)
742 5016 psotfx
                        {
743 5252 acydburn
                                for ($i = $current_depth - $depth; $i > 0; $i--)
744 5016 psotfx
                                {
745 5016 psotfx
                                        $linear_offset = substr($linear_offset, 0, strrpos($linear_offset, '.'));
746 5252 acydburn
                                        $tabular_offset = ($i + $depth > 1) ? substr($tabular_offset, 0, strrpos($tabular_offset, '.')) : $tabular_offset;
747 5016 psotfx
                                }
748 5016 psotfx
                        }
749 5016 psotfx
750 6135 acydburn
                        $u_title = $module_url . $delim . 'i=' . (($item_ary['cat']) ? $item_ary['id'] : $item_ary['name'] . (($item_ary['is_duplicate']) ? '&amp;icat=' . $current_id : '') . '&amp;mode=' . $item_ary['mode']);
751 5995 acydburn
752 6787 acydburn
                        // Was not allowed in categories before - /*!$item_ary['cat'] && */
753 6787 acydburn
                        $u_title .= (isset($item_ary['url_extra'])) ? $item_ary['url_extra'] : '';
754 6787 acydburn
755 5016 psotfx
                        // Only output a categories items if it's currently selected
756 6135 acydburn
                        if (!$depth || ($depth && (in_array($item_ary['parent'], array_values($this->module_cache['parents'])) || $item_ary['parent'] == $this->p_parent)))
757 5016 psotfx
                        {
758 5252 acydburn
                                $use_tabular_offset = (!$depth) ? 't_block1' : $tabular_offset;
759 5995 acydburn
760 5268 acydburn
                                $tpl_ary = array(
761 6135 acydburn
                                        'L_TITLE'                => $item_ary['lang'],
762 8350 acydburn
                                        'S_SELECTED'        => (isset($this->module_cache['parents'][$item_ary['id']]) || $item_ary['id'] == $this->p_id) ? true : false,
763 5295 acydburn
                                        'U_TITLE'                => $u_title
764 5268 acydburn
                                );
765 5268 acydburn
766 6135 acydburn
                                $template->assign_block_vars($use_tabular_offset, array_merge($tpl_ary, array_change_key_case($item_ary, CASE_UPPER)));
767 5016 psotfx
                        }
768 5016 psotfx
769 5268 acydburn
                        $tpl_ary = array(
770 6135 acydburn
                                'L_TITLE'                => $item_ary['lang'],
771 8350 acydburn
                                'S_SELECTED'        => (isset($this->module_cache['parents'][$item_ary['id']]) || $item_ary['id'] == $this->p_id) ? true : false,
772 5295 acydburn
                                'U_TITLE'                => $u_title
773 5268 acydburn
                        );
774 5252 acydburn
775 6135 acydburn
                        $template->assign_block_vars($linear_offset, array_merge($tpl_ary, array_change_key_case($item_ary, CASE_UPPER)));
776 5268 acydburn
777 5252 acydburn
                        $current_depth = $depth;
778 5016 psotfx
                }
779 5252 acydburn
        }
780 5016 psotfx
781 5252 acydburn
        /**
782 5252 acydburn
        * Returns desired template name
783 5252 acydburn
        */
784 5252 acydburn
        function get_tpl_name()
785 5252 acydburn
        {
786 5252 acydburn
                return $this->module->tpl_name . '.html';
787 5252 acydburn
        }
788 5252 acydburn
789 5252 acydburn
        /**
790 5310 acydburn
        * Returns the desired page title
791 5310 acydburn
        */
792 5310 acydburn
        function get_page_title()
793 5310 acydburn
        {
794 5310 acydburn
                global $user;
795 5310 acydburn
796 5313 acydburn
                if (!isset($this->module->page_title))
797 5313 acydburn
                {
798 5313 acydburn
                        return '';
799 5313 acydburn
                }
800 5313 acydburn
801 5310 acydburn
                return (isset($user->lang[$this->module->page_title])) ? $user->lang[$this->module->page_title] : $this->module->page_title;
802 5310 acydburn
        }
803 5310 acydburn
804 5310 acydburn
        /**
805 5252 acydburn
        * Load module as the current active one without the need for registering it
806 11666 git-gate
        *
807 11666 git-gate
        * @param string $class module class (acp/mcp/ucp)
808 11666 git-gate
        * @param string $name module name (class name of the module, or its basename
809 11666 git-gate
    *                     phpbb_ext_foo_acp_bar_module, ucp_zebra or zebra)
810 11666 git-gate
        * @param string $mode mode, as passed through to the module
811 11666 git-gate
        *
812 5252 acydburn
        */
813 5252 acydburn
        function load($class, $name, $mode = false)
814 5252 acydburn
        {
815 11666 git-gate
                // new modules use the full class names, old ones are always called <class>_<name>, e.g. acp_board
816 11666 git-gate
                // in the latter case this function may be called as load('acp', 'board')
817 11666 git-gate
                if (!class_exists($name) && substr($name, 0, strlen($class) + 1) !== $class . '_')
818 11666 git-gate
                {
819 11666 git-gate
                        $name = $class . '_' . $name;
820 11666 git-gate
                }
821 11666 git-gate
822 5252 acydburn
                $this->p_class = $class;
823 5252 acydburn
                $this->p_name = $name;
824 6135 acydburn
825 6135 acydburn
                // Set active module to true instead of using the id
826 6135 acydburn
                $this->active_module = true;
827 6135 acydburn
828 5252 acydburn
                $this->load_active($mode);
829 5252 acydburn
        }
830 5252 acydburn
831 5252 acydburn
        /**
832 5252 acydburn
        * Display module
833 5252 acydburn
        */
834 6054 acydburn
        function display($page_title, $display_online_list = true)
835 5252 acydburn
        {
836 5319 acydburn
                global $template, $user;
837 5252 acydburn
838 5252 acydburn
                // Generate the page
839 5319 acydburn
                if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
840 5319 acydburn
                {
841 5319 acydburn
                        adm_page_header($page_title);
842 5319 acydburn
                }
843 5319 acydburn
                else
844 5319 acydburn
                {
845 6054 acydburn
                        page_header($page_title, $display_online_list);
846 5319 acydburn
                }
847 5016 psotfx
848 5016 psotfx
                $template->set_filenames(array(
849 5252 acydburn
                        'body' => $this->get_tpl_name())
850 5016 psotfx
                );
851 5016 psotfx
852 5319 acydburn
                if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
853 5319 acydburn
                {
854 5319 acydburn
                        adm_page_footer();
855 5319 acydburn
                }
856 5319 acydburn
                else
857 5319 acydburn
                {
858 5319 acydburn
                        page_footer();
859 5319 acydburn
                }
860 5016 psotfx
        }
861 5305 grahamje
862 5305 grahamje
        /**
863 5305 grahamje
        * Toggle whether this module will be displayed or not
864 5305 grahamje
        */
865 5570 naderman
        function set_display($id, $mode = false, $display = true)
866 5305 grahamje
        {
867 6135 acydburn
                foreach ($this->module_ary as $row_id => $item_ary)
868 5305 grahamje
                {
869 11557 git-gate
                        if (($item_ary['name'] === $id || $item_ary['name'] === $this->p_class . '_' . $id || $item_ary['id'] === (int) $id) && (!$mode || $item_ary['mode'] === $mode))
870 5305 grahamje
                        {
871 5305 grahamje
                                $this->module_ary[$row_id]['display'] = (int) $display;
872 5305 grahamje
                        }
873 5305 grahamje
                }
874 5305 grahamje
        }
875 7938 acydburn
876 7938 acydburn
        /**
877 7938 acydburn
        * Add custom MOD info language file
878 7938 acydburn
        */
879 7938 acydburn
        function add_mod_info($module_class)
880 7938 acydburn
        {
881 7938 acydburn
                global $user, $phpEx;
882 7938 acydburn
883 11557 git-gate
                global $phpbb_extension_manager;
884 7938 acydburn
885 11557 git-gate
                $finder = $phpbb_extension_manager->get_finder();
886 7938 acydburn
887 11557 git-gate
                $lang_files = $finder
888 11557 git-gate
                        ->prefix('info_' . strtolower($module_class) . '_')
889 11557 git-gate
                        ->suffix(".$phpEx")
890 11557 git-gate
                        ->extension_directory('/language/' . $user->lang_name)
891 11557 git-gate
                        ->core_path('language/' . $user->lang_name . '/mods/')
892 11557 git-gate
                        ->find();
893 7938 acydburn
894 11557 git-gate
                foreach ($lang_files as $lang_file => $ext_name)
895 11557 git-gate
                {
896 11557 git-gate
                        $user->add_lang_ext($ext_name, $lang_file);
897 7938 acydburn
                }
898 7938 acydburn
        }
899 11557 git-gate
900 11557 git-gate
        /**
901 11557 git-gate
        * Retrieve shortened module basename for legacy basenames (with xcp_ prefix)
902 11557 git-gate
        *
903 11557 git-gate
        * @param string $basename A module basename
904 11557 git-gate
        * @return string The basename if it starts with phpbb_ or the basename with
905 11557 git-gate
        *                the current p_class (e.g. acp_) stripped.
906 11557 git-gate
        */
907 11557 git-gate
        protected function get_short_name($basename)
908 11557 git-gate
        {
909 11557 git-gate
                if (substr($basename, 0, 6) === 'phpbb_')
910 11557 git-gate
                {
911 11557 git-gate
                        return $basename;
912 11557 git-gate
                }
913 11557 git-gate
914 11557 git-gate
                // strip xcp_ prefix from old classes
915 11557 git-gate
                return substr($basename, strlen($this->p_class) + 1);
916 11557 git-gate
        }
917 11557 git-gate
918 11557 git-gate
        /**
919 11557 git-gate
        * Checks whether the given module basename is a correct class name
920 11557 git-gate
        *
921 11557 git-gate
        * @param string $basename A module basename
922 11557 git-gate
        * @return bool True if the basename starts with phpbb_ or (x)cp_, false otherwise
923 11557 git-gate
        */
924 11557 git-gate
        protected function is_full_class($basename)
925 11557 git-gate
        {
926 11672 git-gate
                return (preg_match('/^(phpbb|ucp|mcp|acp)_/', $basename));
927 11557 git-gate
        }
928 5252 acydburn
}