Location: PHPKode > projects > Gnew > Gnew-2013.1/includes/functions.php
<?php
// -----------------------------------------------------------------------------
// $Id: functions.php 706 2013-04-01 14:08:41Z raoul $
//
// Copyright (C) 2013 Raoul Proença
// License: GNU GPL version 3 (see copying.txt file)
// Website: http://www.gnew.fr/
// -----------------------------------------------------------------------------
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.
// -----------------------------------------------------------------------------

function add_slashes(&$data)
{
    if (is_array($data))
    {
        foreach ($data as $key => $value)
        {
            $data[$key] = (is_array($value)) ? add_slashes($value) : addslashes($value);
        }
    }
    return $data;
}

function array_search_column($search, $array, $column = null)
{
    foreach ($array as $key => $value)
    {
        if (($search === $value) || (is_array($value) && (!empty($column) && $search === $value[$column])))
        {
            return $key;
        }
    }
    return false;
}

function array_sort_column(&$tmp, $column, $sort = SORT_ASC)
{
    if (is_array($tmp))
    {
        foreach ($tmp as $key => $value)
        {
            $array[$key] = $value[$column];
        }
        array_multisort($array, $sort, $tmp);
    }
    return $tmp;
}

function check_email($email)
{
    // local-part : http://tools.ietf.org/html/rfc5322#section-3.2.3
    // domain : http://tools.ietf.org/html/rfc1034#section-3.5
    // No special characters ( ) < > [ ] : ; @ \ , or comments or ' character allowed
    return preg_match('`[a-z0-9!#$%&*+\-/=?^_\`{|}~](\.?[a-z0-9!#$%&*+\-/=?^_\`{|}~])*@[a-z](-?[a-z0-9])*(\.[a-z](-?[a-z0-9])*)+`i', $email);
}

function check_version()
{
    // Check for a new version only 3 times per session
    // $_SESSION['check_version'] = 0 when users log in
    if ($_SESSION['check_version'] < 3)
    {
        $latest = @file_get_contents('http://www.gnew.fr/files/LATEST');
        if ($latest == false)
        {
            $version = $GLOBALS['lang']['ERROR_VERSION_CHECK'];
        }
        else
        {
            $version = (GNEW_VERSION != $latest) ? sprintf($GLOBALS['lang']['GNEW_AVAILABLE'], $latest) : '';
        }
        $_SESSION['check_version']++;
    }
    else
    {
        $version = '';
    }
    return $version;
}

function close_tags($str)
{
    // http://www.w3.org/TR/html4/index/elements.html
    preg_match_all('`<(a|abbr|acronym|address|applet|b|bdo|big|blockquote|body|button|caption|center|cite|code|colgroup|dd|del|dfn|dir|div|dl|dt|em|fieldset|font|form|frameset|h1|h2|h3|h4|h5|h6|head|html|i|iframe|ins|kbd|label|legend|li|map|menu|noframes|noscript|object|ol|optgroup|option|p|pre|q|s|samp|script|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|u|ul|var)(?: [^>]+)*(?<!/)>`i', $str, $opened_matches);
    preg_match_all('`</(a|abbr|acronym|address|applet|b|bdo|big|blockquote|body|button|caption|center|cite|code|colgroup|dd|del|dfn|dir|div|dl|dt|em|fieldset|font|form|frameset|h1|h2|h3|h4|h5|h6|head|html|i|iframe|ins|kbd|label|legend|li|map|menu|noframes|noscript|object|ol|optgroup|option|p|pre|q|s|samp|script|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|u|ul|var)>`i', $str, $closed_matches);
    $num_opened_matches = count($opened_matches[0]);
    $num_closed_matches = count($closed_matches[0]);
    if ($num_opened_matches > $num_closed_matches)
    {
        for ($i = 0; $i < ($num_opened_matches - $num_closed_matches); $i++)
        {
            $str = $str . '</' . $opened_matches[1][$i] . '>';
        }
    }
    return $str;
}

function cut_text($str, $url, $query = null)
{
    $plain = $str;

    // HTML entities are replaced by a * character
    $plain = preg_replace('`&[^;\s]+;`', '*', $plain);

    // HTML tags are removed
    // http://www.w3.org/TR/html4/index/elements.html
    $plain = preg_replace('`<(a|abbr|acronym|address|applet|b|bdo|big|blockquote|body|button|caption|center|cite|code|colgroup|dd|del|dfn|dir|div|dl|dt|em|fieldset|font|form|frameset|h1|h2|h3|h4|h5|h6|head|html|i|iframe|ins|kbd|label|legend|li|map|menu|noframes|noscript|object|ol|optgroup|option|p|pre|q|s|samp|script|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|u|ul|var)( [^>]+)*(?<!/)>`i', '', $plain);
    $plain = preg_replace('`</(a|abbr|acronym|address|applet|b|bdo|big|blockquote|body|button|caption|center|cite|code|colgroup|dd|del|dfn|dir|div|dl|dt|em|fieldset|font|form|frameset|h1|h2|h3|h4|h5|h6|head|html|i|iframe|ins|kbd|label|legend|li|map|menu|noframes|noscript|object|ol|optgroup|option|p|pre|q|s|samp|script|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|u|ul|var)>`i', '', $plain);

    // Empty HTML tags are removed
    $plain = preg_replace('`<(area|base|basefont|br|col|frame|hr|img|input|isindex|link|meta|param) ?(.*)/>`iU', '', $plain);

    $chars = '';
    if ((strlen($plain) > $GLOBALS['settings']['max_texts_length']) && empty($_GET[$query]))
    {
        $a = $b = $c = $closed_key = $empty_key = $entities_key = $offset = $opened_key = 0;
        $html = array();

        // HTML entities
        preg_match_all('`&[^;\s]+;`', $str, $entities, PREG_OFFSET_CAPTURE);

        // HTML tags
        preg_match_all('`<(?:a|abbr|acronym|address|applet|b|bdo|big|blockquote|body|button|caption|center|cite|code|colgroup|dd|del|dfn|dir|div|dl|dt|em|fieldset|font|form|frameset|h1|h2|h3|h4|h5|h6|head|html|i|iframe|ins|kbd|label|legend|li|map|menu|noframes|noscript|object|ol|optgroup|option|p|pre|q|s|samp|script|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|u|ul|var)(?: [^>]+)*(?<!/)>`i', $str, $opened_matches, PREG_OFFSET_CAPTURE);
        $num_opened_matches = count($opened_matches[0]);
        for ($x = 0; $x < $num_opened_matches; $x++)
        {
            if (array_key_exists($x, $opened_matches[0]))
            {
                $opened[0][$a][0] = $opened_matches[0][$x][0];
                $opened[0][$a][1] = $opened_matches[0][$x][1];
                $a++;
            }
        }

        preg_match_all('`</(?:a|abbr|acronym|address|applet|b|bdo|big|blockquote|body|button|caption|center|cite|code|colgroup|dd|del|dfn|dir|div|dl|dt|em|fieldset|font|form|frameset|h1|h2|h3|h4|h5|h6|head|html|i|iframe|ins|kbd|label|legend|li|map|menu|noframes|noscript|object|ol|optgroup|option|p|pre|q|s|samp|script|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|u|ul|var)>`i', $str, $closed_matches, PREG_OFFSET_CAPTURE);
        $num_closed_matches = count($closed_matches[0]);
        for ($y = 0; $y < $num_closed_matches; $y++)
        {
            if (array_key_exists($y, $closed_matches[0]))
            {
                $closed[0][$b][0] = $closed_matches[0][$y][0];
                $closed[0][$b][1] = $closed_matches[0][$y][1];
                $b++;
            }
        }
        array_sort_column($opened[0], 1);
        array_sort_column($closed[0], 1);

        // Empty HTML tags
        preg_match_all('`<(?:area|base|basefont|br|col|frame|hr|img|input|isindex|link|meta|param) ?(?:.*)/>`iU', $str, $empty_matches, PREG_OFFSET_CAPTURE);
        $num_empty_matches = count($empty_matches[0]);
        for ($z = 0; $z < $num_empty_matches; $z++)
        {
            if (array_key_exists($z, $empty_matches[0]))
            {
                $empty[0][$c][0] = $empty_matches[0][$z][0];
                $empty[0][$c][1] = $empty_matches[0][$z][1];
                $c++;
            }
        }
        array_sort_column($empty[0], 1);

        $num_closed = count($closed[0]);
        $num_empty = count($empty[0]);
        $num_entities = count($entities[0]);
        $num_opened = count($opened[0]);
        for ($i = 0; ; $i++)
        {
            if ($i < ($GLOBALS['settings']['max_texts_length'] + $offset))
            {
                if ($num_entities > 0)
                {
                    if (array_key_exists($entities_key, $entities[0]))
                    {
                        if ($entities[0][$entities_key][1] == $i)
                        {
                            if (!array_key_exists($i, $html))
                            {
                                $offset += strlen($entities[0][$entities_key][0]) - 1;
                            }
                            $entities_key++;
                        }
                    }
                }
                if ($num_opened > 0)
                {
                    if (array_key_exists($opened_key, $opened[0]))
                    {
                        if ($opened[0][$opened_key][1] == $i)
                        {
                            $length = strlen($opened[0][$opened_key][0]);
                            for ($j = 0; $j < $length; $j++)
                            {
                                $html[$i + $j] = true;
                            }
                            $offset += $length;
                            $opened_key++;
                        }
                    }
                }
                if ($num_closed > 0)
                {
                    if (array_key_exists($closed_key, $closed[0]))
                    {
                        if ($closed[0][$closed_key][1] == $i)
                        {
                            $length = strlen($closed[0][$closed_key][0]);
                            for ($j = 0; $j < $length; $j++)
                            {
                                $html[$i + $j] = true;
                            }
                            $offset += $length;
                            $closed_key++;
                        }
                    }
                }
                if ($num_empty > 0)
                {
                    if (array_key_exists($empty_key, $empty[0]))
                    {
                        if ($empty[0][$empty_key][1] == $i)
                        {
                            $length = strlen($empty[0][$empty_key][0]);
                            for ($j = 0; $j < $length; $j++)
                            {
                                $html[$i + $j] = true;
                            }
                            $offset += $length;
                            $empty_key++;
                        }
                    }
                }
            }
            else
            {
                break;
            }
            $chars .= $str{$i};
        }
        $str = $chars;
        $str = close_tags($str) . ' [ <a href="' . $url . '" title="' . $GLOBALS['lang']['READ_MORE'] . '">' . $GLOBALS['lang']['READ_MORE'] . '</a> ]';
    }
    return $str;
}

function do_bbcodes($str)
{
    preg_match_all('`\[(?!/)[^\]]+\]`', $str, $opened_matches);
    preg_match_all('`\[/[^\]]+\]`', $str, $closed_matches);
    $num_opened_matches = count($opened_matches[0]);
    $num_closed_matches = count($closed_matches[0]);
    $opened = array('[left]' => '<span style="display: block; text-align: left;">',
                    '[right]' => '<span style="display: block; text-align: right;">',
                    '[center]' => '<span style="display: block; text-align: center;">',
                    '[justify]' => '<span style="display: block; text-align: justify;">',
                    '[b]' => '<span style="font-weight: bold">',
                    '[i]' => '<span style="font-style: italic">',
                    '[u]' => '<span style="text-decoration: underline">',
                    '[s]' => '<span style="text-decoration: line-through">',
                    '[ol]' => '<ol>',
                    '[ul]' => '<ul>',
                    '[*]' => '<li>',
                    '[quote]' => '<span class="quoteText">');
    $closed = array('[/left]' => '</span>',
                    '[/right]' => '</span>',
                    '[/center]' => '</span>',
                    '[/justify]' => '</span>',
                    '[/b]' => '</span>',
                    '[/i]' => '</span>',
                    '[/u]' => '</span>',
                    '[/s]' => '</span>',
                    '[/color]' => '</span>',
                    '[/size]' => '</span>',
                    '[/ol]' => '</ol>',
                    '[/ul]' => '</ul>',
                    '[/*]' => '</li>',
                    '[/quote]' => '</span>',
                    '[/url]' => '</a>');
    for ($i = ($num_opened_matches - 1); $i >= 0; $i--)
    {
        $str = preg_replace('`\[color=(#[0-9a-f]{3,6}|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow)\]`ie', "'<span style=\"color: ' . strtolower('\\1') . '\">'", $str);
        $str = preg_replace('`\[size=([1-2]?[0-9](px|pt)|smaller|larger)\]`ie', "'<span style=\"font-size: ' . strtolower('\\1') . '\">'", $str);
        $str = preg_replace('`\[url=#([a-z0-9-_:.]+)\]`', '<a id="\\1">', $str);
        $str = preg_replace('`\[url=(\w+://[^ "\n\r\t\]]+)\]`', '<a href="\\1" title="\\1">', $str);
        $str = preg_replace('`\[email=([a-z0-9!#$%&\'*+\-/=?^_\`{|}~](\.?[a-z0-9!#$%&\'*+\-/=?^_\`{|}~])*@[a-z](-?[a-z0-9])*(\.[a-z](-?[a-z0-9])*)+)\]`i', '<a href="mailto:\\1" title="\\1">\\1</a>', $str);
        $str = preg_replace('`\[quote=([^\]]+)\]`', '<span class="quoteHeader">\\1</span><span class="quoteText">', $str);
        $str = preg_replace('`\[audio=(\w+://[^ "\n\r\t\]]+\.(aac|AAC|m3a|M3A|mp3|MP3|mpega|MPEGA|mpga|MPGA|oga|OGA|ogg|OGG|spx|SPX|wav|WAV|weba|WEBA))\]`', '<audio src="\\1" controls="controls" preload="metadata">' . $GLOBALS['lang']['ERROR_UNSUPPORTED_MEDIA_TYPE'] . '</audio>', $str);
        $str = preg_replace('`\[image=(\w+://[^ "\n\r\t\]]+)\]`', '<img src="\\1" alt="\\1" title="\\1" />', $str);
        $str = preg_replace('`\[video=(\w+://[^ "\n\r\t\]]+\.(mp4|MP4|mp4v|MP4V|mpg4|MPG4|ogv|OGV|webm|WEBM))\]`', '<video src="\\1" controls="controls" preload="metadata">' . $GLOBALS['lang']['ERROR_UNSUPPORTED_MEDIA_TYPE'] . '</video>', $str);
        if (array_key_exists($opened_matches[0][$i], $opened))
        {
            $str = str_replace($opened_matches[0][$i], $opened[$opened_matches[0][$i]], $str);
        }
    }
    for ($j = 0; $j < $num_closed_matches; $j++)
    {
        if (array_key_exists($closed_matches[0][$j], $closed))
        {
            $str = str_replace($closed_matches[0][$j], $closed[$closed_matches[0][$j]], $str);
        }
    }
    $str = preg_replace('`\[code\](.+)\[/code\]`esU', "'<!-- GNEW_CODE_START --><span class=\"quoteHeader\">Code:</span><span class=\"quoteCode\">' . format_code('\\1') . '</span><!-- GNEW_CODE_END -->'", $str);
    return $str;
}

function do_emoticons($str)
{
    $GLOBALS['sql']->query('SELECT emoticon_code, emoticon_image
                            FROM ' . TABLE_EMOTICONS);
    while ($table_emoticons = $GLOBALS['sql']->fetch())
    {
        $str = preg_replace('` (' . preg_quote($table_emoticons['emoticon_code']) . ') `', ' <img src="' . $table_emoticons['emoticon_image'] . '" alt="\\1" title="\\1" /> ', $str);
    }
    return $str;
}

function do_html($str)
{
    $chars = '';
    $a = $b = $c = $bbcodes_key = $closed_key = $empty_key = $entities_key = $opened_key = $offset = 0;
    $html = array();
    $out_entities = $out_tags = true;

    // BBcodes
    preg_match_all('`\[(?!/)(left|right|center|justify|b|i|u|s|color|size|ol|ul|\*|url|email|quote|code|audios|images|videos)(?:=[^\]]+)?\](?:[^\[]+\[/\1\])?`s', $str, $bbcodes, PREG_OFFSET_CAPTURE);

    // HTML entities
    preg_match_all('`&[^;\s]+;`', $str, $entities, PREG_OFFSET_CAPTURE);

    // HTML tags
    // http://www.w3.org/TR/html4/index/elements.html
    preg_match_all('`<(?:a|abbr|acronym|address|applet|b|bdo|big|blockquote|body|button|caption|center|cite|code|colgroup|dd|del|dfn|dir|div|dl|dt|em|fieldset|font|form|frameset|h1|h2|h3|h4|h5|h6|head|html|i|iframe|ins|kbd|label|legend|li|map|menu|noframes|noscript|object|ol|optgroup|option|p|pre|q|s|samp|script|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|u|ul|var)(?: [^>]+)*(?<!/)>`i', $str, $opened_matches, PREG_OFFSET_CAPTURE);
    $num_opened_matches = count($opened_matches[0]);
    for ($x = 0; $x < $num_opened_matches; $x++)
    {
        if (array_key_exists($x, $opened_matches[0]))
        {
            $opened[0][$a][0] = $opened_matches[0][$x][0];
            $opened[0][$a][1] = $opened_matches[0][$x][1];
            $a++;
        }
    }

    preg_match_all('`</(?:a|abbr|acronym|address|applet|b|bdo|big|blockquote|body|button|caption|center|cite|code|colgroup|dd|del|dfn|dir|div|dl|dt|em|fieldset|font|form|frameset|h1|h2|h3|h4|h5|h6|head|html|i|iframe|ins|kbd|label|legend|li|map|menu|noframes|noscript|object|ol|optgroup|option|p|pre|q|s|samp|script|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|u|ul|var)>`i', $str, $closed_matches, PREG_OFFSET_CAPTURE);
    $num_closed_matches = count($closed_matches[0]);
    for ($y = 0; $y < $num_closed_matches; $y++)
    {
        if (array_key_exists($y, $closed_matches[0]))
        {
            $closed[0][$b][0] = $closed_matches[0][$y][0];
            $closed[0][$b][1] = $closed_matches[0][$y][1];
            $b++;
        }
    }
    array_sort_column($opened[0], 1);
    array_sort_column($closed[0], 1);

    // Empty HTML tags
    preg_match_all('`<(?:area|base|basefont|br|col|frame|hr|img|input|isindex|link|meta|param) ?(?:.*)/>`iU', $str, $empty_matches, PREG_OFFSET_CAPTURE);
    $num_empty_matches = count($empty_matches[0]);
    for ($z = 0; $z < $num_empty_matches; $z++)
    {
        if (array_key_exists($z, $empty_matches[0]))
        {
            $empty[0][$c][0] = $empty_matches[0][$z][0];
            $empty[0][$c][1] = $empty_matches[0][$z][1];
            $c++;
        }
    }
    array_sort_column($empty[0], 1);

    $num_bbcodes = count($bbcodes[0]);
    $num_closed = count($closed[0]);
    $num_empty = count($empty[0]);
    $num_entities = count($entities[0]);
    $num_opened = count($opened[0]);
    $str_length = strlen($str);
    for ($i = 0; $i < $str_length; $i++)
    {
        // BBcodes
        if ($str{$i} == '[')
        {
            if ($num_bbcodes > 0)
            {
                if (array_key_exists($bbcodes_key, $bbcodes[0]))
                {
                    if ($bbcodes[0][$bbcodes_key][1] == $i)
                    {
                        $length = strlen($bbcodes[0][$bbcodes_key][0]);
                        for ($j = 0; $j < $length; $j++)
                        {
                            $html[$i + $j] = false;
                        }
                        $bbcodes_key++;
                    }
                }
            }
            $chars .= $str{$i};
        }
        // HTML entities start
        elseif ($str{$i} == '&')
        {
            if ($num_entities > 0)
            {
                if (array_key_exists($entities_key, $entities[0]))
                {
                    if ($entities[0][$entities_key][1] == $i)
                    {
                        $offset = strlen($entities[0][$entities_key][0]);
                        $out_entities = false;
                        $entities_key++;
                    }
                }
            }
            if ($out_entities || (array_key_exists($i, $html) && $html[$i] == false))
            {
                $chars .= utf8_entities($str{$i});
            }
            else
            {
                $chars .= $str{$i};
            }
        }
        // HTML entities end
        elseif ($str{$i} == ';')
        {
            $chars .= $str{$i};
            if ($num_entities > 0)
            {
                if (array_key_exists(($entities_key - 1), $entities[0]))
                {
                    if ($entities[0][($entities_key - 1)][1] == ($i - $offset + 1))
                    {
                        $out_entities = true;
                    }
                }
            }
        }
        // HTML tags start
        elseif ($str{$i} == '<')
        {
            if ($num_opened > 0)
            {
                if (array_key_exists($opened_key, $opened[0]))
                {
                    if ($opened[0][$opened_key][1] == $i)
                    {
                        // Tags attributes
                        preg_match_all('`\s[a-z]+="(.*)"(?=\s(?!")|>)`U', $opened[0][$opened_key][0], $opened_attributes, PREG_OFFSET_CAPTURE);
                        $num_opened_attributes = count($opened_attributes[1]);
                        if ($num_opened_attributes > 0)
                        {
                            for ($j = 0; $j < $num_opened_attributes; $j++)
                            {
                                $length = strlen($opened_attributes[1][$j][0]);
                                for ($k = 0; $k < $length; $k++)
                                {
                                    $html[($i + $opened_attributes[1][$j][1]) + $k] = false;
                                }
                            }
                        }
                        $offset = strlen($opened[0][$opened_key][0]);
                        $out_tags = false;
                        $opened_key++;
                    }
                }
            }
            if ($num_closed > 0)
            {
                if (array_key_exists($closed_key, $closed[0]))
                {
                    if ($closed[0][$closed_key][1] == $i)
                    {
                        $offset = strlen($closed[0][$closed_key][0]);
                        $out_tags = false;
                        $closed_key++;
                    }
                }
            }
            if ($num_empty > 0)
            {
                if (array_key_exists($empty_key, $empty[0]))
                {
                    if ($empty[0][$empty_key][1] == $i)
                    {
                        // Tags attributes
                        preg_match_all('`\s[a-z]+="(.*)"(?=\s(?!")|\s(?=/))`U', $empty[0][$empty_key][0], $empty_attributes, PREG_OFFSET_CAPTURE);
                        $num_empty_attributes = count($empty_attributes[1]);
                        if ($num_empty_attributes > 0)
                        {
                            for ($j = 0; $j < $num_empty_attributes; $j++)
                            {
                                $length = strlen($empty_attributes[1][$j][0]);
                                for ($k = 0; $k < $length; $k++)
                                {
                                    $html[($i + $empty_attributes[1][$j][1]) + $k] = false;
                                }
                            }
                        }
                        $offset = strlen($empty[0][$empty_key][0]);
                        $out_tags = false;
                        $empty_key++;
                    }
                }
            }
            if ($out_tags || (array_key_exists($i, $html) && $html[$i] == false))
            {
                $chars .= utf8_entities($str{$i});
            }
            else
            {
                $chars .= $str{$i};
            }
        }
        // HTML tags end
        elseif ($str{$i} == '>')
        {
            if ($out_tags || (array_key_exists($i, $html) && $html[$i] == false))
            {
                $chars .= utf8_entities($str{$i});
            }
            else
            {
                $chars .= $str{$i};
            }
            if ($num_opened > 0)
            {
                if (array_key_exists(($opened_key - 1), $opened[0]))
                {
                    if ($opened[0][($opened_key - 1)][1] == ($i - $offset + 1))
                    {
                        $out_tags = true;
                    }
                }
            }
            if ($num_closed > 0)
            {
                if (array_key_exists(($closed_key - 1), $closed[0]))
                {
                    if ($closed[0][($closed_key - 1)][1] == ($i - $offset + 1))
                    {
                        $out_tags = true;
                    }
                }
            }
            if ($num_empty > 0)
            {
                if (array_key_exists(($empty_key - 1), $empty[0]))
                {
                    if ($empty[0][($empty_key - 1)][1] == ($i - $offset + 1))
                    {
                        $out_tags = true;
                    }
                }
            }
        }
        // Single quote
        elseif ($str{$i} == "'")
        {
            if ($out_tags || (array_key_exists($i, $html) && $html[$i] == false))
            {
                $chars .= utf8_entities($str{$i});
            }
            else
            {
                $chars .= $str{$i};
            }
        }
        // Double quote
        elseif ($str{$i} == '"')
        {
            if ($out_tags || (array_key_exists($i, $html) && $html[$i] == false))
            {
                $chars .= utf8_entities($str{$i});
            }
            else
            {
                $chars .= $str{$i};
            }
        }
        // Other chars
        else
        {
            $ascii1 = ord($str{$i});
            // 1 byte character
            if ($ascii1 < 128)
            {
                $chars .= utf8_entities($str{$i});
            }
            // 2 bytes character
            if ($ascii1 > 193 && $ascii1 < 224)
            {
                if (isset($str{$i + 1}))
                {
                    $ascii2 = ord($str{$i + 1});
                    if ($ascii2 > 127 && $ascii2 < 192)
                    {
                        $chars .= utf8_entities($str{$i} . $str{$i + 1});
                        $i++;
                    }
                }
            }
            // 3 bytes character
            if ($ascii1 > 223 && $ascii1 < 240)
            {
                if (isset($str{$i + 1}) && isset($str{$i + 2}))
                {
                    $ascii2 = ord($str{$i + 1});
                    $ascii3 = ord($str{$i + 2});
                    if (($ascii1 == 224 && ($ascii2 > 159 && $ascii2 < 192)) ||
                        ($ascii1 == 237 && ($ascii2 > 127 && $ascii2 < 160)) ||
                        ($ascii1 != 224 && $ascii1 != 237 && ($ascii2 > 127 && $ascii2 < 192)))
                    {
                        $chars .= utf8_entities($str{$i} . $str{$i + 1} . $str{$i + 2});
                        $i += 2;
                    }
                }
            }
            // 4 bytes character
            if ($ascii1 > 239 && $ascii1 < 245)
            {
                if (isset($str{$i + 1}) && isset($str{$i + 2}) && isset($str{$i + 3}))
                {
                    $ascii2 = ord($str{$i + 1});
                    $ascii3 = ord($str{$i + 2});
                    $ascii4 = ord($str{$i + 3});
                    if (($ascii1 == 240 && ($ascii2 > 143 && $ascii2 < 192)) ||
                        ($ascii1 == 244 && ($ascii2 > 127 && $ascii2 < 144)) ||
                        ($ascii1 != 240 && $ascii1 != 244 && ($ascii2 > 127 && $ascii2 < 192)))
                    {
                        $chars .= utf8_entities($str{$i} . $str{$i + 1} . $str{$i + 2} . $str{$i + 3});
                        $i += 3;
                    }
                }
            }
        }
    }
    return $chars;
}

function error_template($str)
{
    // store_form_data();
    $GLOBALS['template']->set_file('error', 'error.htpl');
    $GLOBALS['template']->set_var('ERROR', $str);
    $GLOBALS['template']->parse('error');
}

function format_code($str)
{
    // highlight_string() function will convert &, < and > chars to HTML entities
    $str = utf8_chars($str);

    // Syntax highlighting of the string
    $str = highlight_string('<?php ' . $str . ' ?>', true);

    // Back to HTML entities (UTF-8 string: /u modifier)
    $str = preg_replace('`([^>&])(?=[^>]*<)`eu', "utf8_entities('\\1')", $str);

    // Fix double quotes escaped by backslashes (/e modifier)
    $str = preg_replace('`&#92;(?=&#34;)`', '', $str);

    // Clean highlighted string
    $str = preg_replace('`(#[0-9a-f]{3,6}|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow)(?=[^<]*>)`ei', "strtolower('\\0')", $str);
    $str = preg_replace('`(<span style="color: #[0-9a-f]{3,6}">[^<]+)?&nbsp;</span><span style="color: #[0-9a-f]{3,6}">\?&gt;(</span>)`', '\\1\\2', $str);
    $search = array("\n", "\r", "\t", '&lt;?php&nbsp;', '&nbsp;?&gt;', '<code>', '</code>');
    $replace = array('', '', '&nbsp;&nbsp;&nbsp;&nbsp;', '', '', '', '');
    $str = str_replace($search, $replace, $str);
    $str = preg_replace('`<span style="color: #[0-9a-f]{3,6}"></span>`', '', $str);

    // Line numbers
    $lines = explode('<br />', $str);
    $num_lines = count($lines);
    if ($num_lines > 1)
    {
        $code = '';
        for ($i = 0; $i < $num_lines; $i++)
        {
            if ($i > 0)
            {
                $code .= '<br />';
            }
            $code .= sprintf('<span class="codeLine">%s</span>%s', $i + 1, $lines[$i]);
        }
    }
    else
    {
        $code = $str;
    }
    return $code;
}

function format_date($str)
{
    $date_offset = get_date_offset();
    $elapsed = (time() + $date_offset) - $str;
    if ($elapsed >= 0 && $elapsed < 60)
    {
        return sprintf($elapsed > 1 ? $GLOBALS['lang']['SECONDS_AGO'] : $GLOBALS['lang']['SECOND_AGO'], $elapsed);
    }
    elseif ($elapsed >= 60 && $elapsed < 3600)
    {
        $minutes = floor($elapsed / 60);
        return sprintf($minutes > 1 ? $GLOBALS['lang']['MINUTES_AGO'] : $GLOBALS['lang']['MINUTE_AGO'], $minutes);
    }
    elseif ($elapsed >= 3600 && $elapsed < 86400)
    {
        $hours = floor($elapsed / 3600);
        return sprintf($hours > 1 ? $GLOBALS['lang']['HOURS_AGO'] : $GLOBALS['lang']['HOUR_AGO'], $hours);
    }
    else
    {
        $date_format = get_date_format();
        $creation = date($date_format, ($str + $date_offset));
        return sprintf($GLOBALS['lang']['ON'], $creation);
    }
}

function get_audios_list()
{
    $dir = './../medias/audios';
    $elements = array();
    $i = 0;
    if (is_dir($dir))
    {
        if ($handle = opendir($dir))
        {
            while (($file = readdir($handle)) !== false)
            {
                if ($file != '.' && $file != '..')
                {
                    if (is_dir($dir . '/' . $file) || preg_match('`\.(aac|m3a|mp3|mpega|mpga|oga|ogg|spx|wav|weba)$`i', $file))
                    {
                        $file_length = utf8_strlen($file);
                        $name = $dir . '/' . $file;
                        $elements[$i] = '<a href="' . $name . '" class="monospace" title="' . $file . '">' . (ceil($file_length / 2) > 10 ? utf8_substr($file, 0, 10) . '...' . utf8_substr($file, ($file_length - 10), $file_length) : $file) . '</a> <a href="./../admin/medias.php?action=delete_media&amp;file=' . $name . '"><img src="./../images/admin/delete.png" alt="' . $GLOBALS['lang']['DELETE'] . '" title="' . $GLOBALS['lang']['DELETE'] . '" /></a>';
                        $i++;
                    }
                }
            }
            closedir ($handle);
        }
    }
    sort($elements);

    $list = '';
    $num_elements = count($elements);
    for ($j = 0; $j < $num_elements; $j++)
    {
        $list .= $elements[$j] . '<br />';
    }
    return $list;
}

function get_date_format()
{
    if (isset($GLOBALS['users']['user_date_format']))
    {
        $date_format = $GLOBALS['users']['user_date_format'];
    }
    elseif (isset($_COOKIE['gnew_date_format']))
    {
        $date_format = $_COOKIE['gnew_date_format'];
    }
    else
    {
        $date_format = $GLOBALS['settings']['date_format'];
    }
    return $date_format;
}

function get_date_offset()
{
    if (isset($GLOBALS['users']['user_date_offset']))
    {
        $date_offset = $GLOBALS['users']['user_date_offset'] * 3600;
    }
    elseif (isset($_COOKIE['gnew_date_offset']))
    {
        $date_offset = $_COOKIE['gnew_date_offset'] * 3600;
    }
    else
    {
        $date_offset = $GLOBALS['settings']['date_offset'] * 3600;
    }
    return $date_offset;
}

function get_emoticons_list($id)
{
    $list = '';
    $GLOBALS['sql']->query('SELECT emoticon_code, emoticon_image
                            FROM ' . TABLE_EMOTICONS . '
                            ORDER BY emoticon_id');
    while ($table_emoticons = $GLOBALS['sql']->fetch())
    {
        if ($GLOBALS['settings']['allow_emoticons'])
        {
            $list .= '<img src="' . $table_emoticons['emoticon_image'] . '" alt="' . $table_emoticons['emoticon_code'] . '" title="' . $table_emoticons['emoticon_code'] . '" onclick="insert(\' ' . str_replace('&#39;', '\&#39;', $table_emoticons['emoticon_code']) . ' \',\'\',' . $id . ')" style="cursor: pointer" />';
        }
        else
        {
            $list = '';
        }
    }
    return $list;
}

function get_images_list()
{
    $dir = './../medias/images';
    $elements = array();
    $i = 0;
    if (is_dir($dir))
    {
        if ($handle = opendir($dir))
        {
            while (($file = readdir($handle)) !== false)
            {
                if ($file != '.' && $file != '..')
                {
                    if (is_dir($dir . '/' . $file) || preg_match('`\.(gif|jpg|jpeg|png)$`i', $file))
                    {
                        $file_length = utf8_strlen($file);
                        $name = $dir . '/' . $file;
                        $elements[$i] = '<a href="' . $name . '" class="monospace" title="' . $file . '">' . (ceil($file_length / 2) > 10 ? utf8_substr($file, 0, 10) . '...' . utf8_substr($file, ($file_length - 10), $file_length) : $file) . '</a> <a href="./../admin/medias.php?action=delete_media&amp;file=' . $name . '"><img src="./../images/admin/delete.png" alt="' . $GLOBALS['lang']['DELETE'] . '" title="' . $GLOBALS['lang']['DELETE'] . '" /></a>';
                        $i++;
                    }
                }
            }
            closedir ($handle);
        }
    }
    sort($elements);

    $list = '';
    $num_elements = count($elements);
    for ($j = 0; $j < $num_elements; $j++)
    {
        $list .= $elements[$j] . '<br />';
    }
    return $list;
}

function get_language()
{
    if ($GLOBALS['settings']['language_unique'])
    {
        $language = $GLOBALS['settings']['language'];
    }
    elseif (isset($GLOBALS['users']['user_language']))
    {
        $language = $GLOBALS['users']['user_language'];
    }
    elseif (isset($_COOKIE['gnew_language']))
    {
        $language = $_COOKIE['gnew_language'];
    }
    elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
    {
        if (strtolower(substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2)) === 'en')
        {
            $language = 'english';
        }
        elseif (strtolower(substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2)) === 'fr')
        {
            $language = 'french';
        }
        else
        {
            $language = $GLOBALS['settings']['language'];
        }
    }
    else
    {
        $language = $GLOBALS['settings']['language'];
    }
    return $language;
}

function get_languages_list()
{
    $dir = './../languages';
    $i = 0;
    $list = array();
    if (is_dir($dir))
    {
        if ($handle = opendir($dir))
        {
            while (($file = readdir($handle)) !== false)
            {
                if (preg_match('`\.php$`', $file))
                {
                    $list[$i] = substr($file, 0, -4);
                    $i++;
                }
            }
            closedir ($handle);
        }
    }
    sort($list);
    return $list;
}

function get_online_users()
{
    $num_anonymous = $num_users = 0;
    // Sessions are updated for periods of 2 minutes. With session_expiry
    // we can detect active users in the last 2 minutes.
    $GLOBALS['sql']->query('SELECT session_data
                            FROM ' . TABLE_SESSIONS . '
                            WHERE session_expiry > \'' . time() . '\'');
    while ($table_sessions = $GLOBALS['sql']->fetch())
    {
        if (preg_match('`user_id\|i:[1-9]{1}[0-9]{0,9};`', $table_sessions['session_data']))
        {
            $num_users++;
        }
        else
        {
            $num_anonymous++;
        }
    }
    $online_users = sprintf($GLOBALS['lang']['ONLINE_USERS'], $num_anonymous, $num_users);
    return $online_users;
}

function get_pages_list($query, $num_pages)
{
    $pages_limit = $GLOBALS['settings']['pages_limit'];
    $lists_limit = ceil($num_pages / $pages_limit);

    if (empty($_GET['list']) || !string_is_int($_GET['list']))
    {
        $_GET['list'] = 1;
        
    }
    if (!empty($_GET['list']))
    {
        $current_list = ceil($_GET['page'] / $pages_limit);
    }

    $list = '';
    $next_list = $current_list + 1;
    $next_page = $_GET['page'] + 1;
    $previous_list = $current_list - 1;
    $previous_page = $_GET['page'] - 1;
    $first_lists_page = ($pages_limit * $previous_list) + 1;
    $last_lists_page = $pages_limit * $current_list;

    if ($num_pages > 1 && $_GET['page'] > 1)
    {
        // << link
        $list .= '<a href="' . $query . 'page=1&amp;list=1" title="1">&#8810;</a> ';

        // < link
        if ($_GET['page'] == $first_lists_page)
        {
            $list .= '<a href="' . $query . 'page=' . $previous_page . '&amp;list=' . $previous_list . '" title="' . $GLOBALS['lang']['PREVIOUS_PAGE'] . '">&#8826;</a> ';
        }
        else
        {
            $list .= '<a href="' . $query . 'page=' . $previous_page . '&amp;list=' . $current_list . '" title="' . $GLOBALS['lang']['PREVIOUS_PAGE'] . '">&#8826;</a> ';
        }
    }

    // - link
    if ($current_list > 1)
    {
        $list .= '<a href="' . $query . 'page=' . ($first_lists_page - 1) . '&amp;list=' . $previous_list . '" title="' . ($first_lists_page - 1) . '">&#8722;</a> ';
    }

    // Pages list
    for ($current_page = $first_lists_page; $current_page <= $last_lists_page && $current_page <= $num_pages; $current_page++)
    {
        if ($_GET['page'] == $current_page)
        {
            $list .= '<strong>' . $_GET['page'] . '</strong> ';
        }
        else
        {
            $list .= '<a href="' . $query . 'page=' . $current_page . '&amp;list=' . $current_list . '" title="' . $current_page . '">' . $current_page . '</a> ';
        }
    }

    // + link
    if ($current_list < $lists_limit)
    {
        $list .= '<a href="' . $query . 'page=' . ($last_lists_page + 1) . '&amp;list=' . $next_list . '" title="' . ($last_lists_page + 1) . '">&#43;</a> ';
    }

    if ($num_pages > 1 && ($_GET['page'] < $num_pages))
    {
        // > link
        if ($_GET['page'] == $last_lists_page)
        {
            $list .= '<a href="' . $query . 'page=' . $next_page . '&amp;list=' . $next_list . '" title="' . $GLOBALS['lang']['NEXT_PAGE'] . '">&#8827;</a> ';
        }
        else
        {
            $list .= '<a href="' . $query . 'page=' . $next_page . '&amp;list=' . $current_list . '" title="' . $GLOBALS['lang']['NEXT_PAGE'] . '">&#8827;</a> ';
        }

        // >> link
        $list .= '<a href="' . $query . 'page=' . $num_pages . '&amp;list=' . $lists_limit . '" title="' . $num_pages . '">&#8811;</a>';
    }
    return $list;
}

function get_phpversion()
{
    $version = phpversion();
    if (strpos($version, '-') !== false)
    {
        $version = substr($version, 0, strpos($version, '-'));
    }
    return $version;
}

function get_template()
{
    if ($GLOBALS['settings']['template_unique'])
    {
        $template = $GLOBALS['settings']['template'];
    }
    elseif (isset($GLOBALS['users']['user_template']))
    {
        $template = $GLOBALS['users']['user_template'];
    }
    elseif (isset($_COOKIE['gnew_template']))
    {
        $template = $_COOKIE['gnew_template'];
    }
    else
    {
        $template = $GLOBALS['settings']['template'];
    }
    return $template;
}

function get_templates_list()
{
    $dir = './../templates';
    $i = 0;
    $list = array();
    if (is_dir($dir))
    {
        if ($handle = opendir($dir))
        {
            while (($file = readdir($handle)) !== false)
            {
                if ($file != '.' && $file != '..')
                {
                    if (is_dir($dir . '/' . $file))
                    {
                        $list[$i] = $file;
                        $i++;
                    }
                }
            }
            closedir ($handle);
        }
    }
    sort($list);
    return $list;
}

function get_templates_tree()
{
    $elements = array();
    $tree = '';
    if (empty($_GET['dir']) || !preg_match('`^\./\.\./templates`', $_GET['dir']))
    {
        $dir = './../templates';
    }
    else
    {
        $dir = $_GET['dir'];
    }
    if (is_dir($dir))
    {
        if ($handle = opendir($dir))
        {
            $previous = substr($dir, 0, (strrpos(dirname($dir . '/.'), '/')));
            if ($dir != './../templates')
            {
                $tree .= '&#09;<a href="./../admin/templates.php?dir=' . $previous . '" title="../"><strong>../</strong></a><br />';
            }
            while (($file = readdir($handle)) !== false)
            {
                if ($file != '.' && $file != '..' && $file != 'images')
                {
                    if (is_dir($dir . '/' . $file) || preg_match('`\.(css|htpl|js)$`', $file))
                    {
                        $name = $dir . '/' . $file;
                        $elements[$file] = $name;
                    }
                }
            }
            asort($elements);
            $num_elements = count($elements);
            for ($i = 0; $i < $num_elements; $i++)
            {
                $pointer = each($elements);
                if (is_dir($dir . '/' . $pointer[0]))
                {
                    $tree .= substr(sprintf('%o', fileperms($dir . '/' . $pointer[0])), -4) . '&#09;<a href="./../admin/templates.php?dir=' . $dir . '/' . $pointer[0] . '" title="' . $pointer[0] . '/"><strong>' . $pointer[0] . '/</strong></a><br />';
                }
            }
            reset($elements);
            for ($j = 0; $j < $num_elements; $j++)
            {
                $pointer = each($elements);
                if (is_file($dir . '/' . $pointer[0]))
                {
                    $tree .= substr(sprintf('%o', fileperms($dir . '/' . $pointer[0])), -4) . '&#09;<a href="./../admin/templates.php?action=edit_template&amp;file=' . $dir . '/' . $pointer[0] . '" title="' . $pointer[0] . '">' . $pointer[0] . '</a><br />';
                }
            }
            closedir ($handle);
        }
    }
    return $tree;
}

function get_videos_list()
{
    $dir = './../medias/videos';
    $elements = array();
    $i = 0;
    if (is_dir($dir))
    {
        if ($handle = opendir($dir))
        {
            while (($file = readdir($handle)) !== false)
            {
                if ($file != '.' && $file != '..')
                {
                    if (is_dir($dir . '/' . $file) || preg_match('`\.(mp4|mp4v|mpg4|ogv|webm)$`i', $file))
                    {
                        $file_length = utf8_strlen($file);
                        $name = $dir . '/' . $file;
                        $elements[$i] = '<a href="' . $name . '" class="monospace" title="' . $file . '">' . (ceil($file_length / 2) > 10 ? utf8_substr($file, 0, 10) . '...' . utf8_substr($file, ($file_length - 10), $file_length) : $file) . '</a> <a href="./../admin/medias.php?action=delete_media&amp;file=' . $name . '"><img src="./../images/admin/delete.png" alt="' . $GLOBALS['lang']['DELETE'] . '" title="' . $GLOBALS['lang']['DELETE'] . '" /></a>';
                        $i++;
                    }
                }
            }
            closedir ($handle);
        }
    }
    sort($elements);

    $list = '';
    $num_elements = count($elements);
    for ($j = 0; $j < $num_elements; $j++)
    {
        $list .= $elements[$j] . '<br />';
    }
    return $list;
}

function make_articles_feed()
{
    $str = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
    $str .= '<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">' . "\n";
    $str .= '  <channel>' . "\n";
    $str .= '    <title>' . $GLOBALS['settings']['site_name'] . '</title>' . "\n";
    $str .= '    <link>' . $GLOBALS['settings']['site_url'] . '/index.php</link>' . "\n";
    $str .= '    <atom:link href="' . $GLOBALS['settings']['site_url'] . '/feeds/articles.xml" rel="self" type="application/rss+xml" />' . "\n";
    $str .= '    <description>' . $GLOBALS['lang']['LAST_ARTICLES'] . '</description>' . "\n";
    $GLOBALS['sql']->query('SELECT t1.article_id, t1.category_id, t1.article_subject, t1.article_creation, t2.category_name, t3.user_email, t3.user_name
                            FROM ' . TABLE_ARTICLES . ' AS t1
                            INNER JOIN ' . TABLE_CATEGORIES . ' AS t2
                                        ON (t2.category_id = t1.category_id)
                            INNER JOIN ' . TABLE_USERS . ' AS t3
                                        ON (t3.user_id = t1.user_id)
                            ORDER BY t1.article_creation DESC
                            LIMIT ' . $GLOBALS['settings']['headlines_per_feed']);
    while ($table_articles = $GLOBALS['sql']->fetch())
    {
        $article_creation = gmdate('D, d M Y H:i:s \G\M\T', $table_articles['article_creation']);
        $str .= '    <item>' . "\n";
        $str .= '      <title>' . $table_articles['article_subject'] . '</title>' . "\n";
        $str .= '      <link>' . $GLOBALS['settings']['site_url'] . '/articles/read.php?article_id=' . $table_articles['article_id'] . '</link>' . "\n";
        $str .= '      <author>' . $table_articles['user_email'] . ' (' . $table_articles['user_name'] . ')</author>' . "\n";
        $str .= '      <category domain="' . $GLOBALS['settings']['site_url'] . '/articles/index.php?category_id=' . $table_articles['category_id'] . '">' . $table_articles['category_name'] . '</category>' . "\n";
        $str .= '      <guid>' . $GLOBALS['settings']['site_url'] . '/articles/read.php?article_id=' . $table_articles['article_id'] . '</guid>' . "\n";
        $str .= '      <pubDate>' . $article_creation . '</pubDate>' . "\n";
        $str .= '    </item>' . "\n";
    }
    $str .= '  </channel>' . "\n";
    $str .= '</rss>';
    if ($fp = @fopen('./../feeds/articles.xml', 'wb'))
    {
        flock($fp, LOCK_EX);
        fwrite($fp, $str, strlen($str));
        flock($fp, LOCK_UN);
        fclose($fp);
    }
    else
    {
        printf($GLOBALS['lang']['ERROR_FEED_FILE_OPEN'], $GLOBALS['settings']['site_url'] . '/feeds/articles.xml');
        session_write_close();
        $GLOBALS['sql']->close();
        exit();
    }
}

function make_clickable($str)
{
    $str = preg_replace('`(^|[\n ])(\w+://[^ "\n\r\t\]<]+)\b`', '\\1<a href="\\2" title="\\2">\\2</a>', $str);
    $str = preg_replace('`(^|[\n ])([a-z0-9!#$%&\'*+\-/=?^_\`{|}~](\.?[a-z0-9!#$%&\'*+\-/=?^_\`{|}~])*@[a-z](-?[a-z0-9])*(\.[a-z](-?[a-z0-9])*)+)`i', '\\1<a href="mailto:\\2" title="\\2">\\2</a>', $str);
    return $str;
}

function make_comments_feed()
{
    $str = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
    $str .= '<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">' . "\n";
    $str .= '  <channel>' . "\n";
    $str .= '    <title>' . $GLOBALS['settings']['site_name'] . '</title>' . "\n";
    $str .= '    <link>' . $GLOBALS['settings']['site_url'] . '/index.php</link>' . "\n";
    $str .= '    <atom:link href="' . $GLOBALS['settings']['site_url'] . '/feeds/comments.xml" rel="self" type="application/rss+xml" />' . "\n";
    $str .= '    <description>' . $GLOBALS['lang']['LAST_COMMENTS'] . '</description>' . "\n";

    // Pages and lists are allocated to comments
    $num_comments = $table_lists = $table_pages = array();
    $GLOBALS['sql']->query('SELECT t2.comment_id, t2.story_id, COUNT(*) AS comments_per_story
                            FROM ' . TABLE_COMMENTS . ' AS t1
                            INNER JOIN (SELECT comment_id, story_id, comment_creation
                                        FROM ' . TABLE_COMMENTS . '
                                        GROUP BY story_id, comment_id, comment_creation
                                        ORDER BY comment_creation DESC
                                        LIMIT ' . $GLOBALS['settings']['headlines_per_feed'] . ') AS t2
                                        ON (t2.story_id = t1.story_id)
                            GROUP BY t2.story_id, t2.comment_id, t2.comment_creation
                            ORDER BY t2.comment_creation DESC');
    while ($table_comments = $GLOBALS['sql']->fetch())
    {
        if (array_key_exists($table_comments['story_id'], $table_pages))
        {
            $num_comments[$table_comments['story_id']]--;
        }
        else
        {
            $num_comments[$table_comments['story_id']] = $table_comments['comments_per_story'];
        }
        $table_pages[$table_comments['story_id']][$table_comments['comment_id']] = ceil($num_comments[$table_comments['story_id']] / $GLOBALS['settings']['comments_per_page']);
        $table_lists[$table_comments['story_id']][$table_comments['comment_id']] = ceil($table_pages[$table_comments['story_id']][$table_comments['comment_id']] / $GLOBALS['settings']['pages_limit']);
    }

    $GLOBALS['sql']->query('SELECT t1.comment_id, t1.story_id, t1.news_id, t1.comment_subject, t1.comment_creation, t2.news_subject, t3.user_email, t3.user_name
                            FROM ' . TABLE_COMMENTS . ' AS t1
                            INNER JOIN ' . TABLE_NEWS . ' AS t2
                                        ON (t2.news_id = t1.news_id)
                            INNER JOIN ' . TABLE_USERS . ' AS t3
                                        ON (t3.user_id = t1.user_id)
                            ORDER BY t1.comment_creation DESC
                            LIMIT ' . $GLOBALS['settings']['headlines_per_feed']);
    while ($table_comments = $GLOBALS['sql']->fetch())
    {
        $comment_creation = gmdate('D, d M Y H:i:s \G\M\T', $table_comments['comment_creation']);
        $str .= '    <item>' . "\n";
        $str .= '      <title>' . $table_comments['comment_subject'] . '</title>' . "\n";
        $str .= '      <link>' . $GLOBALS['settings']['site_url'] . '/comments/index.php?news_id=' . $table_comments['news_id'] . '&amp;story_id=' . $table_comments['story_id'] . '&amp;page=' . $table_pages[$table_comments['story_id']][$table_comments['comment_id']] . '&amp;list=' . $table_lists[$table_comments['story_id']][$table_comments['comment_id']] . '#c' . $table_comments['comment_id'] . '</link>' . "\n";
        $str .= '      <author>' . $table_comments['user_email'] . ' (' . $table_comments['user_name'] . ')</author>' . "\n";
        $str .= '      <category domain="' . $GLOBALS['settings']['site_url'] . '/comments/index.php?news_id=' . $table_comments['news_id'] . '">' . $table_comments['news_subject'] . '</category>' . "\n";
        $str .= '      <guid>' . $GLOBALS['settings']['site_url'] . '/comments/index.php?news_id=' . $table_comments['news_id'] . '&amp;story_id=' . $table_comments['story_id'] . '&amp;page=' . $table_pages[$table_comments['story_id']][$table_comments['comment_id']] . '&amp;list=' . $table_lists[$table_comments['story_id']][$table_comments['comment_id']] . '#c' . $table_comments['comment_id'] . '</guid>' . "\n";
        $str .= '      <pubDate>' . $comment_creation . '</pubDate>' . "\n";
        $str .= '    </item>' . "\n";
    }
    $str .= '  </channel>' . "\n";
    $str .= '</rss>';
    if ($fp = @fopen('./../feeds/comments.xml', 'wb'))
    {
        flock($fp, LOCK_EX);
        fwrite($fp, $str, strlen($str));
        flock($fp, LOCK_UN);
        fclose($fp);
    }
    else
    {
        printf($GLOBALS['lang']['ERROR_FEED_FILE_OPEN'], $GLOBALS['settings']['site_url'] . '/feeds/comments.xml');
        session_write_close();
        $GLOBALS['sql']->close();
        exit();
    }
}

function make_news_feed()
{
    $str = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
    $str .= '<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">' . "\n";
    $str .= '  <channel>' . "\n";
    $str .= '    <title>' . $GLOBALS['settings']['site_name'] . '</title>' . "\n";
    $str .= '    <link>' . $GLOBALS['settings']['site_url'] . '/index.php</link>' . "\n";
    $str .= '    <atom:link href="' . $GLOBALS['settings']['site_url'] . '/feeds/news.xml" rel="self" type="application/rss+xml" />' . "\n";
    $str .= '    <description>' . $GLOBALS['lang']['LAST_NEWS'] . '</description>' . "\n";
    $GLOBALS['sql']->query('SELECT t1.news_id, t1.category_id, t1.news_subject, t1.news_creation, t2.category_name, t3.user_email, t3.user_name
                            FROM ' . TABLE_NEWS . ' AS t1
                            INNER JOIN ' . TABLE_CATEGORIES . ' AS t2
                                        ON (t2.category_id = t1.category_id)
                            INNER JOIN ' . TABLE_USERS . ' AS t3
                                        ON (t3.user_id = t1.user_id)
                            WHERE t1.news_active = \'1\'
                            ORDER BY t1.news_creation DESC
                            LIMIT ' . $GLOBALS['settings']['headlines_per_feed']);
    while ($table_news = $GLOBALS['sql']->fetch())
    {
        $news_creation = gmdate('D, d M Y H:i:s \G\M\T', $table_news['news_creation']);
        $str .= '    <item>' . "\n";
        $str .= '      <title>' . $table_news['news_subject'] . '</title>' . "\n";
        $str .= '      <link>' . $GLOBALS['settings']['site_url'] . '/comments/index.php?news_id=' . $table_news['news_id'] . '</link>' . "\n";
        $str .= '      <author>' . $table_news['user_email'] . ' (' . $table_news['user_name'] . ')</author>' . "\n";
        $str .= '      <category domain="' . $GLOBALS['settings']['site_url'] . '/news/index.php?category_id=' . $table_news['category_id'] . '">' . $table_news['category_name'] . '</category>' . "\n";
        $str .= '      <guid>' . $GLOBALS['settings']['site_url'] . '/comments/index.php?news_id=' . $table_news['news_id'] . '</guid>' . "\n";
        $str .= '      <pubDate>' . $news_creation . '</pubDate>' . "\n";
        $str .= '    </item>' . "\n";
    }
    $str .= '  </channel>' . "\n";
    $str .= '</rss>';
    if ($fp = @fopen('./../feeds/news.xml', 'wb'))
    {
        flock($fp, LOCK_EX);
        fwrite($fp, $str, strlen($str));
        flock($fp, LOCK_UN);
        fclose($fp);
    }
    else
    {
        printf($GLOBALS['lang']['ERROR_FEED_FILE_OPEN'], $GLOBALS['settings']['site_url'] . '/feeds/news.xml');
        session_write_close();
        $GLOBALS['sql']->close();
        exit();
    }
}

function make_polls_feed()
{
    $str = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
    $str .= '<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">' . "\n";
    $str .= '  <channel>' . "\n";
    $str .= '    <title>' . $GLOBALS['settings']['site_name'] . '</title>' . "\n";
    $str .= '    <link>' . $GLOBALS['settings']['site_url'] . '/index.php</link>' . "\n";
    $str .= '    <atom:link href="' . $GLOBALS['settings']['site_url'] . '/feeds/polls.xml" rel="self" type="application/rss+xml" />' . "\n";
    $str .= '    <description>' . $GLOBALS['lang']['LAST_POLLS'] . '</description>' . "\n";
    $GLOBALS['sql']->query('SELECT t1.question_id, t1.question_text, t1.question_creation, t2.user_email, t2.user_name
                            FROM ' . TABLE_QUESTIONS . ' AS t1
                            INNER JOIN ' . TABLE_USERS . ' AS t2
                                        ON (t2.user_id = t1.user_id)
                            ORDER BY t1.question_creation DESC
                            LIMIT ' . $GLOBALS['settings']['headlines_per_feed']);
    while ($table_questions = $GLOBALS['sql']->fetch())
    {
        $question_creation = gmdate('D, d M Y H:i:s \G\M\T', $table_questions['question_creation']);
        $str .= '    <item>' . "\n";
        $str .= '      <title>' . $table_questions['question_text'] . '</title>' . "\n";
        $str .= '      <link>' . $GLOBALS['settings']['site_url'] . '/polls/vote.php?question_id=' . $table_questions['question_id'] . '</link>' . "\n";
        $str .= '      <author>' . $table_questions['user_email'] . ' (' . $table_questions['user_name'] . ')</author>' . "\n";
        $str .= '      <guid>' . $GLOBALS['settings']['site_url'] . '/polls/vote.php?question_id=' . $table_questions['question_id'] . '</guid>' . "\n";
        $str .= '      <pubDate>' . $question_creation . '</pubDate>' . "\n";
        $str .= '    </item>' . "\n";
    }
    $str .= '  </channel>' . "\n";
    $str .= '</rss>';
    if ($fp = @fopen('./../feeds/polls.xml', 'wb'))
    {
        flock($fp, LOCK_EX);
        fwrite($fp, $str, strlen($str));
        flock($fp, LOCK_UN);
        fclose($fp);
    }
    else
    {
        printf($GLOBALS['lang']['ERROR_FEED_FILE_OPEN'], $GLOBALS['settings']['site_url'] . '/feeds/polls.xml');
        session_write_close();
        $GLOBALS['sql']->close();
        exit();
    }
}

function make_posts_feed()
{
    $str = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
    $str .= '<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">' . "\n";
    $str .= '  <channel>' . "\n";
    $str .= '    <title>' . $GLOBALS['settings']['site_name'] . '</title>' . "\n";
    $str .= '    <link>' . $GLOBALS['settings']['site_url'] . '/index.php</link>' . "\n";
    $str .= '    <atom:link href="' . $GLOBALS['settings']['site_url'] . '/feeds/posts.xml" rel="self" type="application/rss+xml" />' . "\n";
    $str .= '    <description>' . $GLOBALS['lang']['LAST_POSTS'] . '</description>' . "\n";

    // Pages and lists are allocated to posts
    $num_posts = $table_lists = $table_pages = array();
    $GLOBALS['sql']->query('SELECT t2.post_id, t2.thread_id, COUNT(*) AS posts_per_thread
                            FROM ' . TABLE_POSTS . ' AS t1
                            INNER JOIN (SELECT t3.post_id, t3.thread_id, t3.post_creation
                                        FROM ' . TABLE_POSTS . ' AS t3
                                        INNER JOIN ' . TABLE_CATEGORIES . ' AS t4
                                                    ON (t4.category_id = t3.category_id AND t4.category_level IN (\'3\', \'4\'))
                                        GROUP BY t3.thread_id, t3.post_id, t3.post_creation
                                        ORDER BY t3.post_creation DESC
                                        LIMIT ' . $GLOBALS['settings']['headlines_per_feed'] . ') AS t2
                                        ON (t2.thread_id = t1.thread_id)
                            GROUP BY t2.thread_id, t2.post_id, t2.post_creation
                            ORDER BY t2.post_creation DESC');
    while ($table_posts = $GLOBALS['sql']->fetch())
    {
        if (array_key_exists($table_posts['thread_id'], $table_pages))
        {
            $num_posts[$table_posts['thread_id']]--;
        }
        else
        {
            $num_posts[$table_posts['thread_id']] = $table_posts['posts_per_thread'];
        }
        $table_pages[$table_posts['thread_id']][$table_posts['post_id']] = ceil($num_posts[$table_posts['thread_id']] / $GLOBALS['settings']['posts_per_page']);
        $table_lists[$table_posts['thread_id']][$table_posts['post_id']] = ceil($table_pages[$table_posts['thread_id']][$table_posts['post_id']] / $GLOBALS['settings']['pages_limit']);
    }

    $GLOBALS['sql']->query('SELECT t1.post_id, t1.thread_id, t1.category_id, t1.post_subject, t1.post_creation, t2.category_name, t3.user_email, t3.user_name
                            FROM ' . TABLE_POSTS . ' AS t1
                            INNER JOIN ' . TABLE_CATEGORIES . ' AS t2
                                        ON (t2.category_id = t1.category_id AND t2.category_level IN (\'3\', \'4\'))
                            INNER JOIN ' . TABLE_USERS . ' AS t3
                                        ON (t3.user_id = t1.user_id)
                            ORDER BY t1.post_creation DESC
                            LIMIT ' . $GLOBALS['settings']['headlines_per_feed']);
    while ($table_posts = $GLOBALS['sql']->fetch())
    {
        // First post
        if ($table_posts['post_id'] == $table_posts['thread_id'])
        {
            $post_subject = $table_posts['post_subject'];
        }
        else
        {
            $post_subject = $GLOBALS['lang']['RE'] . $table_posts['post_subject'];
        }
        $post_creation = gmdate('D, d M Y H:i:s \G\M\T', $table_posts['post_creation']);
        $str .= '    <item>' . "\n";
        $str .= '      <title>' . $post_subject . '</title>' . "\n";
        $str .= '      <link>' . $GLOBALS['settings']['site_url'] . '/posts/read.php?category_id=' . $table_posts['category_id'] . '&amp;thread_id=' . $table_posts['thread_id'] . '&amp;page=' . $table_pages[$table_posts['thread_id']][$table_posts['post_id']] . '&amp;list=' . $table_lists[$table_posts['thread_id']][$table_posts['post_id']] . '#p' . $table_posts['post_id'] . '</link>' . "\n";
        $str .= '      <author>' . $table_posts['user_email'] . ' (' . $table_posts['user_name'] . ')</author>' . "\n";
        $str .= '      <category domain="' . $GLOBALS['settings']['site_url'] . '/posts/list.php?category_id=' . $table_posts['category_id'] . '">' . $table_posts['category_name'] . '</category>' . "\n";
        $str .= '      <guid>' . $GLOBALS['settings']['site_url'] . '/posts/read.php?category_id=' . $table_posts['category_id'] . '&amp;thread_id=' . $table_posts['thread_id'] . '&amp;page=' . $table_pages[$table_posts['thread_id']][$table_posts['post_id']] . '&amp;list=' . $table_lists[$table_posts['thread_id']][$table_posts['post_id']] . '#p' . $table_posts['post_id'] . '</guid>' . "\n";
        $str .= '      <pubDate>' . $post_creation . '</pubDate>' . "\n";
        $str .= '    </item>' . "\n";
    }
    $str .= '  </channel>' . "\n";
    $str .= '</rss>';
    if ($fp = @fopen('./../feeds/posts.xml', 'wb'))
    {
        flock($fp, LOCK_EX);
        fwrite($fp, $str, strlen($str));
        flock($fp, LOCK_UN);
        fclose($fp);
    }
    else
    {
        printf($GLOBALS['lang']['ERROR_FEED_FILE_OPEN'], $GLOBALS['settings']['site_url'] . '/feeds/posts.xml');
        session_write_close();
        $GLOBALS['sql']->close();
        exit();
    }
}

function page_footer()
{
    $end_time = microtime(true);
    $total_time = number_format(($end_time - $GLOBALS['start_time']), 3, '.', '') . ' s';
    $GLOBALS['template']->set_file('footer', 'footer.htpl');
    $GLOBALS['template']->set_var(array('COPYRIGHT' => sprintf($GLOBALS['lang']['COPYRIGHT'], GNEW_VERSION),
                                        'ONLINE_USERS' => get_online_users(),
                                        'PAGE_GENERATED' => sprintf($GLOBALS['lang']['PAGE_GENERATED'], $total_time, $GLOBALS['sql']->num_queries())));
    $GLOBALS['template']->parse('footer');
    session_write_close();
    $GLOBALS['sql']->close();
}

function page_header($page_title)
{
    // User logged?
    if (isset($GLOBALS['users']['user_name']))
    {
        $log_link = sprintf($GLOBALS['lang']['LOGOUT_LINK'], $GLOBALS['users']['user_name']);
    }
    else
    {
        $log_link = $GLOBALS['lang']['LOGIN_LINK'];
    }
    $GLOBALS['template']->set_file('header', 'header.htpl');
    $GLOBALS['template']->set_var(array('LOG_LINK' => $log_link,
                                        'PAGE_TITLE' => $page_title,
                                        'SITE_NAME' => $GLOBALS['settings']['site_name'],
                                        'TEMPLATE' => get_template()));
    $GLOBALS['template']->parse('header', null, false, TABLE_SETTINGS);
}

function parse_feed($url, $bullet = '', $limit = null)
{
    $handle = @fopen($url, 'rb');
    if (!$handle)
    {
        $str = sprintf($GLOBALS['lang']['ERROR_FEED_FILE_OPEN'], $url);
    }
    else
    {
        $file = stream_get_contents($handle);
        fclose($handle);

        $str = '';
        preg_match_all('`<item>(.+)</item>`sU', $file, $items);
        $num_items = count($items[0]);
        if ($num_items > 0)
        {
            if (string_is_int($limit) && $limit < $num_items)
            {
                $num_elements = $limit;
            }
            else
            {
                $num_elements = $num_items;
            }
            for ($i = 0; $i < $num_elements; $i++)
            {
                if (array_key_exists($i, $items[1]))
                {
                    preg_match('`<title>([^<]+)</title>`', $items[1][$i], $titles);
                    preg_match('`<link>([^<]+)</link>`', $items[1][$i], $links);
                    preg_match('`<author>[^\s]+ \(([^<]+)\)</author>`', $items[1][$i], $authors);
                    preg_match('`<category(?: domain="([^"]+)")?>([^<]+)</category>`', $items[1][$i], $categories);
                    preg_match('`<pubDate>([^<]+)</pubDate>`', $items[1][$i], $pubDates);
                    if (array_key_exists(1, $titles) && array_key_exists(1, $links) && array_key_exists(1, $authors) && array_key_exists(1, $pubDates))
                    {
                        $time = strtotime($pubDates[1]);
                        $creation = format_date($time);
                        if (array_key_exists(1, $categories) && !empty($categories[1]))
                        {
                            $str .= $bullet . '<a href="' . $links[1] . '" title="' . $titles[1] . '">' . $titles[1] . '</a> ' . $GLOBALS['lang']['BY'] . ' ' . $authors[1] . ' ' . $GLOBALS['lang']['IN'] . ' <a href="' . $categories[1] . '" title="' . $categories[2] . '">' . $categories[2] . '</a> ' . $creation . '<br />';
                        }
                        elseif (array_key_exists(2, $categories))
                        {
                            $str .= $bullet . '<a href="' . $links[1] . '" title="' . $titles[1] . '">' . $titles[1] . '</a> ' . $GLOBALS['lang']['BY'] . ' ' . $authors[1] . ' ' . $GLOBALS['lang']['IN'] . ' ' . $categories[2] . ' ' . $creation . '<br />';
                        }
                        else
                        {
                            $str .= $bullet . '<a href="' . $links[1] . '" title="' . $titles[1] . '">' . $titles[1] . '</a> ' . $GLOBALS['lang']['BY'] . ' ' . $authors[1] . ' ' . $creation . '<br />';
                        }
                    }
                }
            }
        }
    }
    return $str;
}

function recursive_replies($reply_key)
{
    static $level = 0;
    if (array_key_exists($GLOBALS['table_comments_tmp'][$reply_key]['comment_id'], $GLOBALS['replies_per_comment']))
    {
        $level++;
        $sub_reply_key = array_search_column($GLOBALS['table_comments_tmp'][$reply_key]['comment_id'], $GLOBALS['table_comments_tmp'], 'reply_id');
        for ($i = 0; $i < $GLOBALS['replies_per_comment'][$GLOBALS['table_comments_tmp'][$reply_key]['comment_id']]; $i++)
        {
            $GLOBALS['table_comments'][($GLOBALS['key'] + $level + $GLOBALS['num_replies'])] = $GLOBALS['table_comments_tmp'][$sub_reply_key];
            $GLOBALS['articles_margins'][($GLOBALS['key'] + $level + $GLOBALS['num_replies'])] = $level + 1;
            $GLOBALS['replies_margins'][($GLOBALS['key'] + $level + $GLOBALS['num_replies'])] = str_repeat('&nbsp;&nbsp;', $level) . '<img src="./../images/comments/tree.png" alt="" />';
            recursive_replies($sub_reply_key);
            $sub_reply_key++;
            $GLOBALS['num_replies']++;
        }
        $level--;
    }
}

/* function remove_form_data()
{
    if ($_SERVER['REQUEST_METHOD'] == 'POST')
    {
        foreach ($_POST as $key => $value)
        {
            if ($key != 'user_id' && $key != 'user_captcha' && $key != 'check_version')
            {
                unset($_SESSION['_' . $key . '_']);
            }
        }
    }
    return true;
} */

function remove_slashes(&$data)
{
    if (is_array($data))
    {
        foreach ($data as $key => $value)
        {
            $data[$key] = (is_array($value)) ? remove_slashes($value) : stripslashes($value);
        }
    }
    return $data;
}

function return_bytes($str)
{
    $str = trim($str);
    $unit = strtolower($str{strlen($str) - 1});
    switch ($unit)
    {
        case 'k':
            return $str * 1024;
            break;
        case 'm':
            return $str * 1024 * 1024;
            break;
        case 'g':
            return $str * 1024 * 1024 * 1024;
            break;
        default:
            return $str;
    }
}

/* function store_form_data()
{
    if ($_SERVER['REQUEST_METHOD'] == 'POST')
    {
        foreach ($_POST as $key => $value)
        {
            if ($key != 'user_id' && $key != 'user_captcha' && $key != 'check_version')
            {
                $value = utf8_entities($value);
                $_SESSION['_' . $key . '_'] = $value;
            }
        }
    }
    return true;
} */

function string_is_int($str)
{
    return preg_match('`^[0-9]{1,10}$`', $str);
}

function success_template($str, $url)
{
    // remove_form_data();
    $GLOBALS['template']->set_file('success', 'success.htpl');
    $GLOBALS['template']->set_var(array('SUCCESS' => $str,
                                        'URL' => $url));
    $GLOBALS['template']->parse('success');
    header('Refresh: 3;URL=' . $url);
}

function undo_bbcodes($str)
{
    // Code
    preg_match_all('`<!-- GNEW_CODE_START -->.+<!-- GNEW_CODE_END -->`sU', $str, $matches, PREG_OFFSET_CAPTURE);
    $num_matches = count($matches[0]);
    for ($i = ($num_matches - 1); $i >= 0; $i--)
    {
        $code = $matches[0][$i][0];

        // Clean code
        $code = preg_replace('`<!-- GNEW_CODE_START --><span class="quoteHeader">Code:</span><span class="quoteCode">(.+)</span><!-- GNEW_CODE_END -->`sU', '[code]\\1[/code]', $code);
        $code = preg_replace('`<span class="codeLine">[^<]+`', '', $code);
        $code = preg_replace('`<span style="color:[^"]+">`', '', $code);
        $code = str_replace('</span>', '', $code);
        $code = str_replace('<br />', "\n", $code);

        // Rebuild string
        $start = substr($str, 0, $matches[0][$i][1]);
        $end = substr($str, ($matches[0][$i][1] + strlen($matches[0][$i][0])), strlen($str));
        $str = $start . $code . $end;
    }

    // Others
    preg_match_all('`<(?!/)[^>]+>`', $str, $opened_matches);
    preg_match_all('`</[^>]+>`', $str, $closed_matches);
    $num_opened_matches = count($opened_matches[0]);
    $num_closed_matches = count($closed_matches[0]);
    $opened = array('<ol>' => '[ol]',
                    '<ul>' => '[ul]',
                    '<li>' => '[*]');
    $closed = array('</ol>' => '[/ol]',
                    '</ul>' => '[/ul]',
                    '</li>' => '[/*]');
    for ($i = ($num_opened_matches - 1); $i >= 0; $i--)
    {
        $str = preg_replace('`<img src="((ht|f)tp://[^ "\n\r\t<]+)" alt="\\1" title="\\1" />`', '[image=\\1]', $str);
        if (array_key_exists($opened_matches[0][$i], $opened))
        {
            $str = str_replace($opened_matches[0][$i], $opened[$opened_matches[0][$i]], $str);
        }
    }
    for ($j = 0; $j < $num_closed_matches; $j++)
    {
        $str = preg_replace('`<span style="display: block; text-align: left;">([^<]+)' . $closed_matches[0][$j] . '`', '[left]\\1[/left]', $str);
        $str = preg_replace('`<span style="display: block; text-align: right;">([^<]+)' . $closed_matches[0][$j] . '`', '[right]\\1[/right]', $str);
        $str = preg_replace('`<span style="display: block; text-align: center;">([^<]+)' . $closed_matches[0][$j] . '`', '[center]\\1[/center]', $str);
        $str = preg_replace('`<span style="display: block; text-align: justify;">([^<]+)' . $closed_matches[0][$j] . '`', '[justify]\\1[/justify]', $str);
        $str = preg_replace('`<span style="font-weight: bold">([^<]+)' . $closed_matches[0][$j] . '`', '[b]\\1[/b]', $str);
        $str = preg_replace('`<span style="font-style: italic">([^<]+)' . $closed_matches[0][$j] . '`', '[i]\\1[/i]', $str);
        $str = preg_replace('`<span style="text-decoration: underline">([^<]+)' . $closed_matches[0][$j] . '`', '[u]\\1[/u]', $str);
        $str = preg_replace('`<span style="text-decoration: line-through">([^<]+)' . $closed_matches[0][$j] . '`', '[s]\\1[/s]', $str);
        $str = preg_replace('`<span style="color: (#[0-9a-f]{3,6}|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow)">([^<]+)' . $closed_matches[0][$j] . '`', '[color=\\1]\\2[/color]', $str);
        $str = preg_replace('`<span style="font-size: ([1-2]?[0-9](px|pt)|smaller|larger)">([^<]+)' . $closed_matches[0][$j] . '`', '[size=\\1]\\3[/size]', $str);
        $str = preg_replace('`<a id="([a-z0-9-_:.]+)">([^<]+)?' . $closed_matches[0][$j] . '`', '[url=#\\1]\\2[/url]', $str);
        $str = preg_replace('`<a href="(\w+://[^ "\n\r\t<]+)" title="\\1">([^<]+)' . $closed_matches[0][$j] . '`', '[url=\\1]\\2[/url]', $str);
        $str = preg_replace('`<a href="mailto:([a-z0-9!#$%&\'*+\-/=?^_\`{|}~](\.?[a-z0-9!#$%&\'*+\-/=?^_\`{|}~])*@[a-z](-?[a-z0-9])*(\.[a-z](-?[a-z0-9])*)+)" title="\\1">\\1' . $closed_matches[0][$j] . '`i', '[email=\\1]', $str);
        $str = preg_replace('`<span class="quoteHeader">([^<]+)' . $closed_matches[0][$j] . '<span class="quoteText">([^<]+)' . $closed_matches[0][$j] . '`', '[quote=\\1]\\2[/quote]', $str);
        $str = preg_replace('`<span class="quoteText">([^<]+)' . $closed_matches[0][$j] . '`', '[quote]\\1[/quote]', $str);
        $str = preg_replace('`<audio src="([^"]+)" controls="controls" preload="metadata">' . $GLOBALS['lang']['ERROR_UNSUPPORTED_MEDIA_TYPE'] . '</audio>`', '[audio=\\1]', $str);
        $str = preg_replace('`<video src="([^"]+)" controls="controls" preload="metadata">' . $GLOBALS['lang']['ERROR_UNSUPPORTED_MEDIA_TYPE'] . '</video>`', '[video=\\1]', $str);
        if (array_key_exists($closed_matches[0][$j], $closed))
        {
            $str = str_replace($closed_matches[0][$j], $closed[$closed_matches[0][$j]], $str);
        }
    }
    return $str;
}

function undo_emoticons($str)
{
    $GLOBALS['sql']->query('SELECT emoticon_code, emoticon_image
                            FROM ' . TABLE_EMOTICONS);
    while ($table_emoticons = $GLOBALS['sql']->fetch())
    {
        $str = str_replace('<img src="' . $table_emoticons['emoticon_image'] . '" alt="' . $table_emoticons['emoticon_code'] . '" title="' . $table_emoticons['emoticon_code'] . '" />', $table_emoticons['emoticon_code'], $str);
    }
    return $str;
}

function undo_escape_sequences($str)
{
    $str = str_replace("\n", '<br />', $str);
    $str = str_replace("\r", '', $str);
    $str = str_replace("\t", '&nbsp;&nbsp;&nbsp;&nbsp;', $str);
    return $str;
}

// UTF-8 functions
// http://www.unicode.org/versions/Unicode6.0.0/ch03.pdf#page=41

function utf8_chars($str)
{
    // HTML entities
    preg_match_all('`&#([^;\s]+);`', $str, $entities);
    $num_entities = count($entities[0]);
    for ($x = 0; $x < $num_entities; $x++)
    {
        $search = $entities[0][$x];
        // 1 byte character
        if ($entities[1][$x] < 128)
        {
            $replace = chr($entities[1][$x]);
        }
        // 2 bytes character
        if ($entities[1][$x] > 127 && $entities[1][$x] < 2048)
        {
            $replace = chr((($entities[1][$x] >> 6) & 31) + 192) .
                       chr(($entities[1][$x] & 63) + 128);
        }
        // 3 bytes character
        if ($entities[1][$x] > 2047 && $entities[1][$x] < 65536)
        {
            $replace = chr((($entities[1][$x] >> 12) & 15) + 224) .
                       chr((($entities[1][$x] >> 6) & 63) + 128) .
                       chr(($entities[1][$x] & 63) + 128);
        }
        // 4 bytes character
        if ($entities[1][$x] > 65535 && $entities[1][$x] < 2097152)
        {
            $replace = chr((($entities[1][$x] >> 18) & 7) + 240) .
                       chr((($entities[1][$x] >> 12) & 63) + 128) .
                       chr((($entities[1][$x] >> 6) & 63) + 128) .
                       chr(($entities[1][$x] & 63) + 128);
        }
        $str = str_replace($search, $replace, $str);
    }
    return $str;
}

function utf8_entities($str)
{
    // Replace chars with special significance in HTML, database queries and templates
    $search = array('&', '"', "'", '<', '>', '\\', '{', '}');
    $replace = array('&#38;', '&#34;', '&#39;', '&#60;', '&#62;', '&#92;', '&#123;', '&#125;');
    $str = str_replace($search, $replace, $str);

    $chars = '';
    $length = strlen($str);
    for ($i = 0; $i < $length; $i++)
    {
        $ascii1 = ord($str{$i});
        // 1 byte character
        if ($ascii1 < 128)
        {
            $chars .= $str{$i};
        }
        else
        {
            // 2 bytes character
            if ($ascii1 > 193 && $ascii1 < 224)
            {
                if (isset($str{$i + 1}))
                {
                    $ascii2 = ord($str{$i + 1});
                    if ($ascii2 > 127 && $ascii2 < 192)
                    {
                        $html = ($ascii1 & 31) << 6 | ($ascii2 & 63);
                        $chars .= '&#' . $html . ';';
                        $i++;
                    }
                }
            }
            // 3 bytes character
            if ($ascii1 > 223 && $ascii1 < 240)
            {
                if (isset($str{$i + 1}) && isset($str{$i + 2}))
                {
                    $ascii2 = ord($str{$i + 1});
                    $ascii3 = ord($str{$i + 2});
                    if (($ascii1 == 224 && ($ascii2 > 159 && $ascii2 < 192)) ||
                        ($ascii1 == 237 && ($ascii2 > 127 && $ascii2 < 160)) ||
                        ($ascii1 != 224 && $ascii1 != 237 && ($ascii2 > 127 && $ascii2 < 192)))
                    {
                        $html = ($ascii1 & 15) << 12 | ($ascii2 & 63) << 6 | ($ascii3 & 63);
                        $chars .= '&#' . $html . ';';
                        $i += 2;
                    }
                }
            }
            // 4 bytes character
            if ($ascii1 > 239 && $ascii1 < 245)
            {
                if (isset($str{$i + 1}) && isset($str{$i + 2}) && isset($str{$i + 3}))
                {
                    $ascii2 = ord($str{$i + 1});
                    $ascii3 = ord($str{$i + 2});
                    $ascii4 = ord($str{$i + 3});
                    if (($ascii1 == 240 && ($ascii2 > 143 && $ascii2 < 192)) ||
                        ($ascii1 == 244 && ($ascii2 > 127 && $ascii2 < 144)) ||
                        ($ascii1 != 240 && $ascii1 != 244 && ($ascii2 > 127 && $ascii2 < 192)))
                    {
                        $html = ($ascii1 & 7) << 18 | ($ascii2 & 63) << 12 | ($ascii3 & 63) << 6 | ($ascii4 & 63);
                        $chars .= '&#' . $html . ';';
                        $i += 3;
                    }
                }
            }
        }
    }
    return $chars;
}

function utf8_strlen($str)
{
    $length = 0;
    $str_length = strlen($str);
    for ($i = 0; $i < $str_length; $i++)
    {
        $ascii1 = ord($str{$i});
        // 1 byte character
        if ($ascii1 < 128)
        {
            $length++;
        }
        else
        {
            // 2 bytes character
            if ($ascii1 > 193 && $ascii1 < 224)
            {
                if (isset($str{$i + 1}))
                {
                    $ascii2 = ord($str{$i + 1});
                    if ($ascii2 > 127 && $ascii2 < 192)
                    {
                        $length++;
                    }
                }
            }
            // 3 bytes character
            if ($ascii1 > 223 && $ascii1 < 240)
            {
                if (isset($str{$i + 1}) && isset($str{$i + 2}))
                {
                    $ascii2 = ord($str{$i + 1});
                    $ascii3 = ord($str{$i + 2});
                    if (($ascii1 == 224 && ($ascii2 > 159 && $ascii2 < 192)) ||
                        ($ascii1 == 237 && ($ascii2 > 127 && $ascii2 < 160)) ||
                        ($ascii1 != 224 && $ascii1 != 237 && ($ascii2 > 127 && $ascii2 < 192)))
                    {
                        $length++;
                    }
                }
            }
            // 4 bytes character
            if ($ascii1 > 239 && $ascii1 < 245)
            {
                if (isset($str{$i + 1}) && isset($str{$i + 2}) && isset($str{$i + 3}))
                {
                    $ascii2 = ord($str{$i + 1});
                    $ascii3 = ord($str{$i + 2});
                    $ascii4 = ord($str{$i + 3});
                    if (($ascii1 == 240 && ($ascii2 > 143 && $ascii2 < 192)) ||
                        ($ascii1 == 244 && ($ascii2 > 127 && $ascii2 < 144)) ||
                        ($ascii1 != 240 && $ascii1 != 244 && ($ascii2 > 127 && $ascii2 < 192)))
                    {
                        $length++;
                    }
                }
            }
        }
    }
    return $length;
}

function utf8_substr($str, $start, $length)
{
    return preg_replace('`^(?:[\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|(?:\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|[\xEE-\xEF][\x80-\xBF]{2})|(?:\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})){0,' . $start . '}' . '((?:[\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|(?:\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|[\xEE-\xEF][\x80-\xBF]{2})|(?:\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})){0,' . $length . '}).*`s', '\\1', $str);
}

?>
Return current item: Gnew