1<?php
2/**
3 *  Xoops Functions
4 *
5 * You may not change or alter any portion of this comment or credits
6 * of supporting developers from this source code or any supporting source code
7 * which is considered copyrighted (c) material of the original comment or credit authors.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
13 * @license             GNU GPL 2 (http://www.gnu.org/licenses/gpl-2.0.html)
14 * @package             kernel
15 * @since               2.0.0
16 */
17
18defined('XOOPS_ROOT_PATH') || exit('Restricted access');
19
20/**
21 * xoops_getHandler()
22 *
23 * @param mixed $name
24 * @param mixed $optional
25 *
26 * @return XoopsObjectHandler|false
27 */
28function xoops_getHandler($name, $optional = false)
29{
30    static $handlers;
31    $name = strtolower(trim($name));
32    if (!isset($handlers[$name])) {
33        if (file_exists($hnd_file = XOOPS_ROOT_PATH . '/kernel/' . $name . '.php')) {
34            require_once $hnd_file;
35        }
36        $class = 'Xoops' . ucfirst($name) . 'Handler';
37        if (class_exists($class)) {
38            $xoopsDB         = XoopsDatabaseFactory::getDatabaseConnection();
39            $handlers[$name] = new $class($xoopsDB);
40        }
41    }
42    if (!isset($handlers[$name])) {
43        trigger_error('Class <strong>' . $class . '</strong> does not exist<br>Handler Name: ' . $name, $optional ? E_USER_WARNING : E_USER_ERROR);
44    }
45    if (isset($handlers[$name])) {
46        return $handlers[$name];
47    }
48    $inst = false;
49
50    return $inst;
51}
52
53/**
54 * xoops_getModuleHandler()
55 *
56 * @param mixed $name
57 * @param mixed $module_dir
58 * @param mixed $optional
59 * @return XoopsObjectHandler|false
60 */
61function xoops_getModuleHandler($name = null, $module_dir = null, $optional = false)
62{
63    static $handlers;
64    // if $module_dir is not specified
65    if (!isset($module_dir)) {
66        // if a module is loaded
67        if (isset($GLOBALS['xoopsModule']) && is_object($GLOBALS['xoopsModule'])) {
68            $module_dir = $GLOBALS['xoopsModule']->getVar('dirname', 'n');
69        } else {
70            trigger_error('No Module is loaded', E_USER_ERROR);
71        }
72    } else {
73        $module_dir = trim($module_dir);
74    }
75    $name = (!isset($name)) ? $module_dir : trim($name);
76    if (!isset($handlers[$module_dir][$name])) {
77        if (file_exists($hnd_file = XOOPS_ROOT_PATH . "/modules/{$module_dir}/class/{$name}.php")) {
78            include_once $hnd_file;
79        }
80        $class = ucfirst(strtolower($module_dir)) . ucfirst($name) . 'Handler';
81        if (class_exists($class)) {
82            $xoopsDB                      = XoopsDatabaseFactory::getDatabaseConnection();
83            $handlers[$module_dir][$name] = new $class($xoopsDB);
84        }
85    }
86    if (!isset($handlers[$module_dir][$name])) {
87        trigger_error('Handler does not exist<br>Module: ' . $module_dir . '<br>Name: ' . $name, $optional ? E_USER_WARNING : E_USER_ERROR);
88    }
89    if (isset($handlers[$module_dir][$name])) {
90        return $handlers[$module_dir][$name];
91    }
92    $inst = false;
93
94    return $inst;
95}
96
97/**
98 * XOOPS class loader wrapper
99 *
100 * Temporay solution for XOOPS 2.3
101 *
102 * @param string $name                                          Name of class to be loaded
103 * @param string $type                                          domain of the class, potential values:   core - located in /class/;
104 *                                                              framework - located in /Frameworks/;
105 *                                                              other - module class, located in /modules/[$type]/class/
106 *
107 * @return boolean
108 */
109function xoops_load($name, $type = 'core')
110{
111    if (!class_exists('XoopsLoad')) {
112        require_once XOOPS_ROOT_PATH . '/class/xoopsload.php';
113    }
114
115    return XoopsLoad::load($name, $type);
116}
117
118/**
119 * XOOPS language loader wrapper
120 *
121 * Temporay solution, not encouraged to use
122 *
123 * @param   string $name     Name of language file to be loaded, without extension
124 * @param   string $domain   Module dirname; global language file will be loaded if $domain is set to 'global' or not specified
125 * @param   string $language Language to be loaded, current language content will be loaded if not specified
126 * @return  boolean
127 * @todo    expand domain to multiple categories, e.g. module:system, framework:filter, etc.
128 *
129 */
130function xoops_loadLanguage($name, $domain = '', $language = null)
131{
132    /**
133     * Set pageType
134     */
135    if ($name === 'pagetype') {
136        $name = xoops_getOption('pagetype');
137    }
138    /**
139     * We must check later for an empty value. As xoops_getOption could be empty
140     */
141    if (empty($name)) {
142        return false;
143    }
144    $language = empty($language) ? $GLOBALS['xoopsConfig']['language'] : $language;
145    $path     = ((empty($domain) || 'global' === $domain) ? '' : "modules/{$domain}/") . 'language';
146    if (!file_exists($fileinc = $GLOBALS['xoops']->path("{$path}/{$language}/{$name}.php"))) {
147        if (!file_exists($fileinc = $GLOBALS['xoops']->path("{$path}/english/{$name}.php"))) {
148            return false;
149        }
150    }
151    $ret = include_once $fileinc;
152
153    return $ret;
154}
155
156/**
157 * YOU SHOULD BE CAREFUL WITH USING THIS METHOD SINCE IT WILL BE DEPRECATED
158 */
159/**
160 * xoops_getActiveModules()
161 *
162 * Get active modules from cache file
163 *
164 * @return array
165 */
166function xoops_getActiveModules()
167{
168    static $modules_active;
169    if (is_array($modules_active)) {
170        return $modules_active;
171    }
172    xoops_load('XoopsCache');
173    if (!$modules_active = XoopsCache::read('system_modules_active')) {
174        $modules_active = xoops_setActiveModules();
175    }
176
177    return $modules_active;
178}
179
180/**
181 * YOU SHOULD BE CAREFUL WITH USING THIS METHOD SINCE IT WILL BE DEPRECATED
182 */
183/**
184 * xoops_setActiveModules()
185 *
186 * Write active modules to cache file
187 *
188 * @return array
189 */
190function xoops_setActiveModules()
191{
192    xoops_load('XoopsCache');
193    /* @var XoopsModuleHandler $module_handler */
194    $module_handler = xoops_getHandler('module');
195    $modules_obj    = $module_handler->getObjects(new Criteria('isactive', 1));
196    $modules_active = array();
197    foreach (array_keys($modules_obj) as $key) {
198        $modules_active[] = $modules_obj[$key]->getVar('dirname');
199    }
200    unset($modules_obj);
201    XoopsCache::write('system_modules_active', $modules_active);
202
203    return $modules_active;
204}
205
206/**
207 * YOU SHOULD BE CAREFUL WITH USING THIS METHOD SINCE IT WILL BE DEPRECATED
208 */
209/**
210 * xoops_isActiveModule()
211 *
212 * Checks is module is installed and active
213 *
214 * @param $dirname
215 * @return bool
216 */
217function xoops_isActiveModule($dirname)
218{
219    return isset($dirname) && in_array($dirname, xoops_getActiveModules());
220}
221
222/**
223 * xoops_header()
224 *
225 * @param mixed $closehead
226 * @return void
227 */
228function xoops_header($closehead = true)
229{
230    global $xoopsConfig;
231
232    $themeSet = $xoopsConfig['theme_set'];
233    $themePath = XOOPS_THEME_PATH . '/' . $themeSet . '/';
234    $themeUrl = XOOPS_THEME_URL . '/' . $themeSet . '/';
235    include_once XOOPS_ROOT_PATH . '/class/template.php';
236    $headTpl = new \XoopsTpl();
237    $headTpl->assign(array(
238        'closeHead'      => (bool) $closehead,
239        'themeUrl'       => $themeUrl,
240        'xoops_langcode' => _LANGCODE,
241        'xoops_charset'  => _CHARSET,
242        'xoops_sitename' => $xoopsConfig['sitename'],
243        'xoops_url'      => XOOPS_URL,
244    ));
245
246    if (file_exists($themePath . 'theme_autorun.php')) {
247        include_once($themePath . 'theme_autorun.php');
248    }
249
250    $headItems = array();
251    $headItems[] = '<script type="text/javascript" src="' . XOOPS_URL . '/include/xoops.js"></script>';
252    $headItems[] = '<link rel="stylesheet" type="text/css" media="all" href="' . XOOPS_URL . '/xoops.css">';
253    $headItems[] = '<link rel="stylesheet" type="text/css" media="all" href="' . XOOPS_URL . '/media/font-awesome/css/font-awesome.min.css">';
254    $languageFile = 'language/' . $GLOBALS['xoopsConfig']['language'] . '/style.css';
255    if (file_exists($GLOBALS['xoops']->path($languageFile))) {
256        $headItems[] = '<link rel="stylesheet" type="text/css" media="all" href="' . $GLOBALS['xoops']->url($languageFile) . '">';
257    }
258    $themecss = xoops_getcss($xoopsConfig['theme_set']);
259    if ($themecss!=='') {
260        $headItems[] = '<link rel="stylesheet" type="text/css" media="all" href="' . $themecss . '">';
261    }
262    $headTpl->assign('headItems', $headItems);
263
264    if (!headers_sent()) {
265        header('Content-Type:text/html; charset=' . _CHARSET);
266        header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
267        header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
268        header('Cache-Control: no-store, no-cache, max-age=1, s-maxage=1, must-revalidate, post-check=0, pre-check=0');
269        header('Pragma: no-cache');
270    }
271
272    $output = $headTpl->fetch('db:system_popup_header.tpl');
273    echo $output;
274}
275
276/**
277 * xoops_footer
278 *
279 * @return void
280 */
281function xoops_footer()
282{
283    global $xoopsConfig;
284
285    $themeSet = $xoopsConfig['theme_set'];
286    $themePath = XOOPS_THEME_URL . '/' . $themeSet . '/';
287    include_once XOOPS_ROOT_PATH . '/class/template.php';
288    $footTpl = new \XoopsTpl();
289    $footTpl->assign(array(
290        'themePath'      => $themePath,
291        'xoops_langcode' => _LANGCODE,
292        'xoops_charset'  => _CHARSET,
293        'xoops_sitename' => $xoopsConfig['sitename'],
294        'xoops_url'      => XOOPS_URL,
295    ));
296    $output = $footTpl->fetch('db:system_popup_footer.tpl');
297    echo $output;
298    ob_end_flush();
299}
300
301/**
302 * xoops_error
303 *
304 * @param mixed  $msg
305 * @param string $title
306 * @return void
307 */
308function xoops_error($msg, $title = '')
309{
310    echo '<div class="errorMsg">';
311    if ($title != '') {
312        echo '<strong>' . $title . '</strong><br><br>';
313    }
314    if (is_object($msg)) {
315        $msg = (array)$msg;
316    }
317    if (is_array($msg)) {
318        foreach ($msg as $key => $value) {
319            if (is_numeric($key)) {
320                $key = '';
321            }
322            xoops_error($value, $key);
323        }
324    } else {
325        echo "<div>{$msg}</div>";
326    }
327    echo '</div>';
328}
329
330/**
331 * xoops_result
332 *
333 * @param mixed  $msg
334 * @param string $title
335 * @return void
336 */
337function xoops_result($msg, $title = '')
338{
339    echo '<div class="resultMsg">';
340    if ($title != '') {
341        echo '<strong>' . $title . '</strong><br><br>';
342    }
343    if (is_object($msg)) {
344        $msg = (array)$msg;
345    }
346    if (is_array($msg)) {
347        foreach ($msg as $key => $value) {
348            if (is_numeric($key)) {
349                $key = '';
350            }
351            xoops_result($value, $key);
352        }
353    } else {
354        echo "<div>{$msg}</div>";
355    }
356    echo '</div>';
357}
358
359/**
360 * xoops_confirm()
361 *
362 * @param mixed  $hiddens
363 * @param mixed  $action
364 * @param mixed  $msg
365 * @param string $submit
366 * @param mixed  $addtoken
367 * @return void
368 */
369function xoops_confirm($hiddens, $action, $msg, $submit = '', $addtoken = true)
370{
371    $submit = ($submit != '') ? trim($submit) : _SUBMIT;
372    echo '<div class="confirmMsg">' . $msg . '<br>
373          <form method="post" action="' . $action . '">';
374    foreach ($hiddens as $name => $value) {
375        if (is_array($value)) {
376            foreach ($value as $caption => $newvalue) {
377                echo '<input type="radio" name="' . $name . '" value="' . htmlspecialchars($newvalue) . '" /> ' . $caption;
378            }
379            echo '<br>';
380        } else {
381            echo '<input type="hidden" name="' . $name . '" value="' . htmlspecialchars($value) . '" />';
382        }
383    }
384    if ($addtoken != false) {
385        echo $GLOBALS['xoopsSecurity']->getTokenHTML();
386    }
387    echo '<input type="submit" class="btn btn-default" name="confirm_submit" value="' . $submit . '" title="' . $submit . '"/>
388          <input type="button" class="btn btn-default" name="confirm_back" value="' . _CANCEL . '" onclick="history.go(-1);" title="' . _CANCEL . '" />
389          </form>
390          </div>';
391}
392
393/**
394 * xoops_getUserTimestamp()
395 *
396 * @param mixed  $time
397 * @param string $timeoffset
398 * @return int
399 */
400function xoops_getUserTimestamp($time, $timeoffset = '')
401{
402    global $xoopsConfig, $xoopsUser;
403    if ($timeoffset == '') {
404        if ($xoopsUser) {
405            $timeoffset = $xoopsUser->getVar('timezone_offset');
406        } else {
407            $timeoffset = $xoopsConfig['default_TZ'];
408        }
409    }
410    $usertimestamp = (int)$time + ((float)$timeoffset - $xoopsConfig['server_TZ']) * 3600;
411
412    return $usertimestamp;
413}
414
415/**
416 * Function to display formatted times in user timezone
417 * @param        $time
418 * @param string $format
419 * @param string $timeoffset
420 * @return string
421 */
422function formatTimestamp($time, $format = 'l', $timeoffset = '')
423{
424    xoops_load('XoopsLocal');
425
426    return XoopsLocal::formatTimestamp($time, $format, $timeoffset);
427}
428
429/**
430 * Function to calculate server timestamp from user entered time (timestamp)
431 * @param      $timestamp
432 * @param null $userTZ
433 * @return
434 */
435function userTimeToServerTime($timestamp, $userTZ = null)
436{
437    global $xoopsConfig;
438    if (!isset($userTZ)) {
439        $userTZ = $xoopsConfig['default_TZ'];
440    }
441    $timestamp -= (($userTZ - $xoopsConfig['server_TZ']) * 3600);
442
443    return $timestamp;
444}
445
446/**
447 * xoops_makepass()
448 *
449 * @return string
450 */
451function xoops_makepass()
452{
453    $makepass  = '';
454    $syllables = array(
455        'er',
456        'in',
457        'tia',
458        'wol',
459        'fe',
460        'pre',
461        'vet',
462        'jo',
463        'nes',
464        'al',
465        'len',
466        'son',
467        'cha',
468        'ir',
469        'ler',
470        'bo',
471        'ok',
472        'tio',
473        'nar',
474        'sim',
475        'ple',
476        'bla',
477        'ten',
478        'toe',
479        'cho',
480        'co',
481        'lat',
482        'spe',
483        'ak',
484        'er',
485        'po',
486        'co',
487        'lor',
488        'pen',
489        'cil',
490        'li',
491        'ght',
492        'wh',
493        'at',
494        'the',
495        'he',
496        'ck',
497        'is',
498        'mam',
499        'bo',
500        'no',
501        'fi',
502        've',
503        'any',
504        'way',
505        'pol',
506        'iti',
507        'cs',
508        'ra',
509        'dio',
510        'sou',
511        'rce',
512        'sea',
513        'rch',
514        'pa',
515        'per',
516        'com',
517        'bo',
518        'sp',
519        'eak',
520        'st',
521        'fi',
522        'rst',
523        'gr',
524        'oup',
525        'boy',
526        'ea',
527        'gle',
528        'tr',
529        'ail',
530        'bi',
531        'ble',
532        'brb',
533        'pri',
534        'dee',
535        'kay',
536        'en',
537        'be',
538        'se');
539    for ($count = 1; $count <= 4; ++$count) {
540        if (mt_rand() % 10 == 1) {
541            $makepass .= sprintf('%0.0f', (mt_rand() % 50) + 1);
542        } else {
543            $makepass .= sprintf('%s', $syllables[mt_rand() % 62]);
544        }
545    }
546
547    return $makepass;
548}
549
550/**
551 * checkEmail()
552 *
553 * @param mixed $email
554 * @param mixed $antispam
555 * @return bool|mixed
556 */
557function checkEmail($email, $antispam = false)
558{
559    if (!$email || !preg_match('/^[^@]{1,64}@[^@]{1,255}$/', $email)) {
560        return false;
561    }
562    $email_array      = explode('@', $email);
563    $local_array      = explode('.', $email_array[0]);
564    $local_arrayCount = count($local_array);
565    for ($i = 0; $i < $local_arrayCount; ++$i) {
566        if (!preg_match("/^(([A-Za-z0-9!#$%&'*+\/\=?^_`{|}~-][A-Za-z0-9!#$%&'*+\/\=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$/", $local_array[$i])) {
567            return false;
568        }
569    }
570    if (!preg_match("/^\[?[0-9\.]+\]?$/", $email_array[1])) {
571        $domain_array = explode('.', $email_array[1]);
572        if (count($domain_array) < 2) {
573            return false; // Not enough parts to domain
574        }
575        for ($i = 0; $i < count($domain_array); ++$i) {
576            if (!preg_match("/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]+))$/", $domain_array[$i])) {
577                return false;
578            }
579        }
580    }
581    if ($antispam) {
582        $email = str_replace('@', ' at ', $email);
583        $email = str_replace('.', ' dot ', $email);
584    }
585
586    return $email;
587}
588
589/**
590 * formatURL()
591 *
592 * @param mixed $url
593 * @return mixed|string
594 */
595function formatURL($url)
596{
597    $url = trim($url);
598    if ($url != '') {
599        if ((!preg_match('/^http[s]*:\/\//i', $url)) && (!preg_match('/^ftp*:\/\//i', $url)) && (!preg_match('/^ed2k*:\/\//i', $url))) {
600            $url = 'http://' . $url;
601        }
602    }
603
604    return $url;
605}
606
607/**
608 * Function to get banner html tags for use in templates
609 */
610function xoops_getbanner()
611{
612    global $xoopsConfig;
613
614    $db      = XoopsDatabaseFactory::getDatabaseConnection();
615    $bresult = $db->query('SELECT COUNT(*) FROM ' . $db->prefix('banner'));
616    list($numrows) = $db->fetchRow($bresult);
617    if ($numrows > 1) {
618        --$numrows;
619        $bannum = mt_rand(0, $numrows);
620    } else {
621        $bannum = 0;
622    }
623    if ($numrows > 0) {
624        $bresult = $db->query('SELECT * FROM ' . $db->prefix('banner'), 1, $bannum);
625        list($bid, $cid, $imptotal, $impmade, $clicks, $imageurl, $clickurl, $date, $htmlbanner, $htmlcode) = $db->fetchRow($bresult);
626        if ($xoopsConfig['my_ip'] == xoops_getenv('REMOTE_ADDR')) {
627            // EMPTY
628        } else {
629            ++$impmade;
630            $db->queryF(sprintf('UPDATE %s SET impmade = %u WHERE bid = %u', $db->prefix('banner'), $impmade, $bid));
631            /**
632             * Check if this impression is the last one
633             */
634            if ($imptotal > 0 && $impmade >= $imptotal) {
635                $newid = $db->genId($db->prefix('bannerfinish') . '_bid_seq');
636                $sql   = sprintf('INSERT INTO %s (bid, cid, impressions, clicks, datestart, dateend) VALUES (%u, %u, %u, %u, %u, %u)', $db->prefix('bannerfinish'), $newid, $cid, $impmade, $clicks, $date, time());
637                $db->queryF($sql);
638                $db->queryF(sprintf('DELETE FROM %s WHERE bid = %u', $db->prefix('banner'), $bid));
639            }
640        }
641        /**
642         * Print the banner
643         */
644        $bannerobject = '';
645        if ($htmlbanner) {
646            if ($htmlcode) {
647                $bannerobject = $htmlcode;
648            } else {
649                $bannerobject = $bannerobject . '<div id="xo-bannerfix">';
650                // $bannerobject = $bannerobject . '<div id="xo-fixbanner">';
651                $bannerobject = $bannerobject . ' <iframe src=' . $imageurl . ' border="0" scrolling="no" allowtransparency="true" width="480px" height="60px" style="border:0" alt="' . $clickurl . ';"> </iframe>';
652                $bannerobject .= '</div>';
653                // $bannerobject .= '</div>';
654            }
655        } else {
656            $bannerobject = '<div id="xo-bannerfix">';
657            if (false !== stripos($imageurl, '.swf')) {
658                $bannerobject = $bannerobject . '<div id ="xo-fixbanner">' . '<a href="' . XOOPS_URL . '/banners.php?op=click&amp;bid=' . $bid . '" rel="external" title="' . $clickurl . '"></a></div>' . '<object type="application/x-shockwave-flash" width="468" height="60" data="' . $imageurl . '" style="z-index:100;">' . '<param name="movie" value="' . $imageurl . '" />' . '<param name="wmode" value="opaque" />' . '</object>';
659            } else {
660                $bannerobject = $bannerobject . '<a href="' . XOOPS_URL . '/banners.php?op=click&amp;bid=' . $bid . '" rel="external" title="' . $clickurl . '"><img src="' . $imageurl . '" alt="' . $clickurl . '" /></a>';
661            }
662
663            $bannerobject .= '</div>';
664        }
665
666        return $bannerobject;
667    }
668    return null;
669}
670
671/**
672 * Function to redirect a user to certain pages
673 * @param        $url
674 * @param int    $time
675 * @param string $message
676 * @param bool   $addredirect
677 * @param bool   $allowExternalLink
678 */
679function redirect_header($url, $time = 3, $message = '', $addredirect = true, $allowExternalLink = false)
680{
681    global $xoopsConfig, $xoopsLogger, $xoopsUserIsAdmin;
682
683    $xoopsPreload = XoopsPreload::getInstance();
684    $xoopsPreload->triggerEvent('core.include.functions.redirectheader.start', array($url, $time, $message, $addredirect, $allowExternalLink));
685    // under normal circumstance this event will exit, so listen for the .start above
686    $xoopsPreload->triggerEvent('core.include.functions.redirectheader', array($url, $time, $message, $addredirect, $allowExternalLink));
687
688    if (preg_match("/[\\0-\\31]|about:|script:/i", $url)) {
689        if (!preg_match('/^\b(java)?script:([\s]*)history\.go\(-\d*\)([\s]*[;]*[\s]*)$/si', $url)) {
690            $url = XOOPS_URL;
691        }
692    }
693    if (!$allowExternalLink && $pos = strpos($url, '://')) {
694        $xoopsLocation = substr(XOOPS_URL, strpos(XOOPS_URL, '://') + 3);
695        if (strcasecmp(substr($url, $pos + 3, strlen($xoopsLocation)), $xoopsLocation)) {
696            $url = XOOPS_URL;
697        }
698    }
699    if (defined('XOOPS_CPFUNC_LOADED')) {
700        $theme = 'default';
701    } else {
702        $theme = $xoopsConfig['theme_set'];
703    }
704
705    require_once XOOPS_ROOT_PATH . '/class/template.php';
706    require_once XOOPS_ROOT_PATH . '/class/theme.php';
707    $xoopsThemeFactory                = null;
708    $xoopsThemeFactory                = new xos_opal_ThemeFactory();
709    $xoopsThemeFactory->allowedThemes = $xoopsConfig['theme_set_allowed'];
710    $xoopsThemeFactory->defaultTheme  = $theme;
711    $xoTheme                          = $xoopsThemeFactory->createInstance(array(
712                                                                                'plugins'      => array(),
713                                                                                'renderBanner' => false));
714    $xoopsTpl                         = $xoTheme->template;
715    $xoopsTpl->assign(array(
716                          'xoops_theme'      => $theme,
717                          'xoops_imageurl'   => XOOPS_THEME_URL . '/' . $theme . '/',
718                          'xoops_themecss'   => xoops_getcss($theme),
719                          'xoops_requesturi' => htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES),
720                          'xoops_sitename'   => htmlspecialchars($xoopsConfig['sitename'], ENT_QUOTES),
721                          'xoops_slogan'     => htmlspecialchars($xoopsConfig['slogan'], ENT_QUOTES),
722                          'xoops_dirname'    => isset($xoopsModule) && is_object($xoopsModule) ? $xoopsModule->getVar('dirname') : 'system',
723                          'xoops_pagetitle'  => isset($xoopsModule) && is_object($xoopsModule) ? $xoopsModule->getVar('name') : htmlspecialchars($xoopsConfig['slogan'], ENT_QUOTES)));
724    if ($xoopsConfig['debug_mode'] == 2 && $xoopsUserIsAdmin) {
725        $xoopsTpl->assign('time', 300);
726        $xoopsTpl->assign('xoops_logdump', $xoopsLogger->dump());
727    } else {
728        $xoopsTpl->assign('time', (int)$time);
729    }
730    if (!empty($_SERVER['REQUEST_URI']) && $addredirect && false !== strpos($url, 'user.php')) {
731        if (false === strpos($url, '?')) {
732            $url .= '?xoops_redirect=' . urlencode($_SERVER['REQUEST_URI']);
733        } else {
734            $url .= '&amp;xoops_redirect=' . urlencode($_SERVER['REQUEST_URI']);
735        }
736    }
737    if (defined('SID') && SID && (!isset($_COOKIE[session_name()]) || ($xoopsConfig['use_mysession'] && $xoopsConfig['session_name'] != '' && !isset($_COOKIE[$xoopsConfig['session_name']])))) {
738        if (false === strpos($url, '?')) {
739            $url .= '?' . SID;
740        } else {
741            $url .= '&amp;' . SID;
742        }
743    }
744    $url = preg_replace('/&amp;/i', '&', htmlspecialchars($url, ENT_QUOTES));
745    $xoopsTpl->assign('url', $url);
746    $message = trim($message) != '' ? $message : _TAKINGBACK;
747    $xoopsTpl->assign('message', $message);
748    $xoopsTpl->assign('lang_ifnotreload', sprintf(_IFNOTRELOAD, $url));
749
750    $xoopsTpl->display('db:system_redirect.tpl');
751    exit();
752}
753
754/**
755 * xoops_getenv()
756 *
757 * @param mixed $key
758 * @return string
759 */
760function xoops_getenv($key)
761{
762    $ret = '';
763    if (array_key_exists($key, $_SERVER) && isset($_SERVER[$key])) {
764        $ret = $_SERVER[$key];
765
766        return $ret;
767    }
768    if (array_key_exists($key, $_ENV) && isset($_ENV[$key])) {
769        $ret = $_ENV[$key];
770
771        return $ret;
772    }
773
774    return $ret;
775}
776
777/**
778 * Function to get css file for a certain themeset
779 * @param string $theme
780 * @return string
781 */
782function xoops_getcss($theme = '')
783{
784    if ($theme == '') {
785        $theme = $GLOBALS['xoopsConfig']['theme_set'];
786    }
787    $uagent  = xoops_getenv('HTTP_USER_AGENT');
788    $str_css = 'styleNN.css';
789    if (false !== stripos($uagent, 'mac')) {
790        $str_css = 'styleMAC.css';
791    } elseif (preg_match("/MSIE (\d\.\d{1,2})/i", $uagent)) {
792        $str_css = 'style.css';
793    }
794    if (is_dir(XOOPS_THEME_PATH . '/' . $theme)) {
795        if (file_exists(XOOPS_THEME_PATH . '/' . $theme . '/' . $str_css)) {
796            return XOOPS_THEME_URL . '/' . $theme . '/' . $str_css;
797        } elseif (file_exists(XOOPS_THEME_PATH . '/' . $theme . '/style.css')) {
798            return XOOPS_THEME_URL . '/' . $theme . '/style.css';
799        }
800    }
801    if (is_dir(XOOPS_THEME_PATH . '/' . $theme . '/css')) {
802        if (file_exists(XOOPS_THEME_PATH . '/' . $theme . '/css/' . $str_css)) {
803            return XOOPS_THEME_URL . '/' . $theme . '/css/' . $str_css;
804        } elseif (file_exists(XOOPS_THEME_PATH . '/' . $theme . '/css/style.css')) {
805            return XOOPS_THEME_URL . '/' . $theme . '/css/style.css';
806        }
807    }
808
809    return '';
810}
811
812/**
813 * xoops_getMailer()
814 *
815 * @return \XoopsMailer|\XoopsMailerLocal
816 */
817function xoops_getMailer()
818{
819    static $mailer;
820    global $xoopsConfig;
821    if (is_object($mailer)) {
822        return $mailer;
823    }
824    include_once XOOPS_ROOT_PATH . '/class/xoopsmailer.php';
825    if (file_exists($file = XOOPS_ROOT_PATH . '/language/' . $xoopsConfig['language'] . '/xoopsmailerlocal.php')) {
826        include_once $file;
827    } elseif (file_exists($file = XOOPS_ROOT_PATH . '/language/english/xoopsmailerlocal.php')) {
828        include_once $file;
829    }
830    unset($mailer);
831    if (class_exists('XoopsMailerLocal')) {
832        $mailer = new XoopsMailerLocal();
833    } else {
834        $mailer = new XoopsMailer();
835    }
836
837    return $mailer;
838}
839
840/**
841 * xoops_getrank()
842 *
843 * @param integer $rank_id
844 * @param mixed   $posts
845 * @return
846 */
847function xoops_getrank($rank_id = 0, $posts = 0)
848{
849    $db      = XoopsDatabaseFactory::getDatabaseConnection();
850    $myts    = MyTextSanitizer::getInstance();
851    $rank_id = (int)$rank_id;
852    $posts   = (int)$posts;
853    if ($rank_id != 0) {
854        $sql = 'SELECT rank_title AS title, rank_image AS image FROM ' . $db->prefix('ranks') . ' WHERE rank_id = ' . $rank_id;
855    } else {
856        $sql = 'SELECT rank_title AS title, rank_image AS image FROM ' . $db->prefix('ranks') . ' WHERE rank_min <= ' . $posts . ' AND rank_max >= ' . $posts . ' AND rank_special = 0';
857    }
858    $rank          = $db->fetchArray($db->query($sql));
859    $rank['title'] = $myts->htmlSpecialChars($rank['title']);
860    $rank['id']    = $rank_id;
861
862    return $rank;
863}
864
865/**
866 * Returns the portion of string specified by the start and length parameters. If $trimmarker is supplied, it is appended to the return string. This function works fine with multi-byte characters if mb_* functions exist on the server.
867 *
868 * @param string $str
869 * @param int    $start
870 * @param int    $length
871 * @param string $trimmarker
872 * @return string
873 */
874function xoops_substr($str, $start, $length, $trimmarker = '...')
875{
876    xoops_load('XoopsLocal');
877
878    return XoopsLocal::substr($str, $start, $length, $trimmarker);
879}
880
881// RMV-NOTIFY
882// ################ Notification Helper Functions ##################
883// We want to be able to delete by module, by user, or by item.
884// How do we specify this??
885/**
886 * @param $module_id
887 *
888 * @return mixed
889 */
890function xoops_notification_deletebymodule($module_id)
891{
892    $notification_handler = xoops_getHandler('notification');
893
894    return $notification_handler->unsubscribeByModule($module_id);
895}
896
897/**
898 * xoops_notification_deletebyuser()
899 *
900 * @param mixed $user_id
901 * @return
902 */
903function xoops_notification_deletebyuser($user_id)
904{
905    $notification_handler = xoops_getHandler('notification');
906
907    return $notification_handler->unsubscribeByUser($user_id);
908}
909
910/**
911 * xoops_notification_deletebyitem()
912 *
913 * @param mixed $module_id
914 * @param mixed $category
915 * @param mixed $item_id
916 * @return
917 */
918function xoops_notification_deletebyitem($module_id, $category, $item_id)
919{
920    $notification_handler = xoops_getHandler('notification');
921
922    return $notification_handler->unsubscribeByItem($module_id, $category, $item_id);
923}
924
925/**
926 * xoops_comment_count()
927 *
928 * @param mixed $module_id
929 * @param mixed $item_id
930 * @return
931 */
932function xoops_comment_count($module_id, $item_id = null)
933{
934    $comment_handler = xoops_getHandler('comment');
935    $criteria        = new CriteriaCompo(new Criteria('com_modid', (int)$module_id));
936    if (isset($item_id)) {
937        $criteria->add(new Criteria('com_itemid', (int)$item_id));
938    }
939
940    return $comment_handler->getCount($criteria);
941}
942
943/**
944 * xoops_comment_delete()
945 *
946 * @param mixed $module_id
947 * @param mixed $item_id
948 * @return bool
949 */
950function xoops_comment_delete($module_id, $item_id)
951{
952    if ((int)$module_id > 0 && (int)$item_id > 0) {
953        $comment_handler = xoops_getHandler('comment');
954        $comments        = $comment_handler->getByItemId($module_id, $item_id);
955        if (is_array($comments)) {
956            $count       = count($comments);
957            $deleted_num = array();
958            for ($i = 0; $i < $count; ++$i) {
959                if (false !== $comment_handler->delete($comments[$i])) {
960                    // store poster ID and deleted post number into array for later use
961                    $poster_id = $comments[$i]->getVar('com_uid');
962                    if ($poster_id != 0) {
963                        $deleted_num[$poster_id] = !isset($deleted_num[$poster_id]) ? 1 : ($deleted_num[$poster_id] + 1);
964                    }
965                }
966            }
967            /* @var XoopsMemberHandler $member_handler */
968            $member_handler = xoops_getHandler('member');
969            foreach ($deleted_num as $user_id => $post_num) {
970                // update user posts
971                $com_poster = $member_handler->getUser($user_id);
972                if (is_object($com_poster)) {
973                    $member_handler->updateUserByField($com_poster, 'posts', $com_poster->getVar('posts') - $post_num);
974                }
975            }
976
977            return true;
978        }
979    }
980
981    return false;
982}
983
984/**
985 * xoops_groupperm_deletebymoditem()
986 *
987 * Group Permission Helper Functions
988 *
989 * @param mixed $module_id
990 * @param mixed $perm_name
991 * @param mixed $item_id
992 * @return bool
993 */
994function xoops_groupperm_deletebymoditem($module_id, $perm_name, $item_id = null)
995{
996    // do not allow system permissions to be deleted
997    if ((int)$module_id <= 1) {
998        return false;
999    }
1000    /* @var  XoopsGroupPermHandler $gperm_handler */
1001    $gperm_handler = xoops_getHandler('groupperm');
1002
1003    return $gperm_handler->deleteByModule($module_id, $perm_name, $item_id);
1004}
1005
1006/**
1007 * xoops_utf8_encode()
1008 *
1009 * @param mixed $text
1010 * @return string
1011 */
1012function xoops_utf8_encode(&$text)
1013{
1014    xoops_load('XoopsLocal');
1015
1016    return XoopsLocal::utf8_encode($text);
1017}
1018
1019/**
1020 * xoops_convert_encoding()
1021 *
1022 * @param mixed $text
1023 * @return string
1024 */
1025function xoops_convert_encoding(&$text)
1026{
1027    return xoops_utf8_encode($text);
1028}
1029
1030/**
1031 * xoops_trim()
1032 *
1033 * @param mixed $text
1034 * @return string
1035 */
1036function xoops_trim($text)
1037{
1038    xoops_load('XoopsLocal');
1039
1040    return XoopsLocal::trim($text);
1041}
1042
1043/**
1044 * YOU SHOULD NOT USE THIS METHOD, IT WILL BE REMOVED
1045 */
1046/**
1047 * xoops_getOption()
1048 *
1049 * @param mixed $option
1050 * @internal param string $type
1051 * @deprecated
1052 * @return string
1053 */
1054function xoops_getOption($option)
1055{
1056    $ret = '';
1057    if (isset($GLOBALS['xoopsOption'][$option])) {
1058        $ret = $GLOBALS['xoopsOption'][$option];
1059    }
1060
1061    return $ret;
1062}
1063
1064/**
1065 * YOU SHOULD NOT USE THIS METHOD, IT WILL BE REMOVED
1066 */
1067/**
1068 * xoops_getConfigOption()
1069 *
1070 * @param mixed  $option
1071 * @param array|string $type
1072 * @internal param string $dirname
1073 * @deprecated
1074 * @return bool
1075 */
1076function xoops_getConfigOption($option, $type = 'XOOPS_CONF')
1077{
1078    static $coreOptions = array();
1079
1080    if (is_array($coreOptions) && array_key_exists($option, $coreOptions)) {
1081        return $coreOptions[$option];
1082    }
1083    $ret            = false;
1084    /* @var XoopsConfigHandler $config_handler */
1085    $config_handler = xoops_getHandler('config');
1086    $configs        = $config_handler->getConfigsByCat(is_array($type) ? $type : constant($type));
1087    if ($configs) {
1088        if (isset($configs[$option])) {
1089            $ret = $configs[$option];
1090        }
1091    }
1092    $coreOptions[$option] = $ret;
1093
1094    return $ret;
1095}
1096
1097/**
1098 * YOU SHOULD NOT USE THIS METHOD, IT WILL BE REMOVED
1099 */
1100/**
1101 * xoops_setConfigOption()
1102 *
1103 * @param mixed $option
1104 * @param null  $new
1105 * @return void
1106@deprecated
1107 */
1108function xoops_setConfigOption($option, $new = null)
1109{
1110    if (isset($GLOBALS['xoopsConfig'][$option]) && null !== $new) {
1111        $GLOBALS['xoopsConfig'][$option] = $new;
1112    }
1113}
1114
1115/**
1116 * YOU SHOULD NOT USE THIS METHOD, IT WILL BE REMOVED
1117 */
1118/**
1119 * xoops_getModuleOption
1120 *
1121 * Method for module developers getting a module config item. This could be from any module requested.
1122 *
1123 * @param mixed  $option
1124 * @param string $dirname
1125 * @return bool
1126@deprecated
1127 */
1128function xoops_getModuleOption($option, $dirname = '')
1129{
1130    static $modOptions = array();
1131    if (is_array($modOptions) && isset($modOptions[$dirname][$option])) {
1132        return $modOptions[$dirname][$option];
1133    }
1134
1135    $ret            = false;
1136    /* @var XoopsModuleHandler $module_handler */
1137    $module_handler = xoops_getHandler('module');
1138    $module         = $module_handler->getByDirname($dirname);
1139    /* @var XoopsConfigHandler $config_handler */
1140    $config_handler = xoops_getHandler('config');
1141    if (is_object($module)) {
1142        $moduleConfig = $config_handler->getConfigsByCat(0, $module->getVar('mid'));
1143        if (isset($moduleConfig[$option])) {
1144            $ret = $moduleConfig[$option];
1145        }
1146    }
1147    $modOptions[$dirname][$option] = $ret;
1148
1149    return $ret;
1150}
1151
1152/**
1153 * Determine the base domain name for a URL. The primary use for this is to set the domain
1154 * used for cookies to represent any subdomains.
1155 *
1156 * The registrable domain is determined using the public suffix list. If the domain is not
1157 * registrable, an empty string is returned. This empty string can be used in setcookie()
1158 * as the domain, which restricts cookie to just the current host.
1159 *
1160 * @param string $url URL or hostname to process
1161 *
1162 * @return string the registrable domain or an empty string
1163 */
1164function xoops_getBaseDomain($url)
1165{
1166    $parts = parse_url($url);
1167    $host = '';
1168    if (!empty($parts['host'])) {
1169        $host = $parts['host'];
1170        if (strtolower($host) === 'localhost') {
1171            return 'localhost';
1172        }
1173        // bail if this is an IPv4 address (IPv6 will fail later)
1174        if (false !== filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
1175            return '';
1176        }
1177        $regdom = new \Geekwright\RegDom\RegisteredDomain();
1178        $host = $regdom->getRegisteredDomain($host);
1179    }
1180    return (null === $host) ? '' : $host;
1181}
1182
1183/**
1184 * YOU SHOULD NOT USE THIS METHOD, IT WILL BE REMOVED
1185 */
1186/**
1187 * Function to get the domain from a URL.
1188 *
1189 * @param string $url the URL to be stripped.
1190 * @return string
1191 * @deprecated
1192 */
1193function xoops_getUrlDomain($url)
1194{
1195    $domain = '';
1196    $_URL   = parse_url($url);
1197
1198    if (!empty($_URL) || !empty($_URL['host'])) {
1199        $domain = $_URL['host'];
1200    }
1201
1202    return $domain;
1203}
1204
1205include_once __DIR__ . '/functions.encoding.php';
1206include_once __DIR__ . '/functions.legacy.php';
1207