<?php

$head = '<html><body>';
$foot = '</body></html>';
$a = "<BR style=left:expression(eval('document.location=\"http://www.ipa.go.jp/\";'))>";

echo $head . COM_applyFilter($a) . $foot;


// +---------------------------------------------------------------------------+
// | HTML WIDGETS                                                              |
// +---------------------------------------------------------------------------+

/**
* Return the file to use for a block template.
*
* This returns the template needed to build the HTML for a block.  This function
* allows designers to give a block it's own custom look and feel.  If no
* templates for the block are specified, the default blockheader.html and
* blockfooter.html will be used.
*
* @param        string      $blockname      corresponds to name field in block table
* @param        string      $which          can be either 'header' or 'footer' for corresponding template
* @see function COM_startBlock
* @see function COM_endBlock
* @see function COM_showBlocks
* @see function COM_showBlock
* @return   string  template name
*/
function COM_getBlockTemplate( $blockname, $which )
{
    global $_BLOCK_TEMPLATE, $_COM_VERBOSE;

    if( $_COM_VERBOSE )
    {
        COM_errorLog( "_BLOCK_TEMPLATE[$blockname] = " . $_BLOCK_TEMPLATE[$blockname], 1 );
    }

    if( !empty( $_BLOCK_TEMPLATE[$blockname] ))
    {
        $templates = explode( ',', $_BLOCK_TEMPLATE[$blockname] );
        if( $which == 'header' )
        {
            if( !empty( $templates[0] ))
            {
                $template = $templates[0];
            }
            else
            {
                $template = 'blockheader.thtml';
            }
        }
        else
        {
            if( !empty( $templates[1] ))
            {
                $template = $templates[1];
            }
            else
            {
                $template = 'blockfooter.thtml';
            }
        }
    }
    else
    {
        if( $which == 'header' )
        {
            $template = 'blockheader.thtml';
        }
        else
        {
            $template = 'blockfooter.thtml';
        }
    }

    if( $_COM_VERBOSE )
    {
        COM_errorLog( "Block template for the $which of $blockname is: $template", 1 );
    }

    return $template;
}

/**
* Gets all installed themes
*
* Returns a list of all the directory names in $_CONF['path_themes'], i.e.
* a list of all the theme names.
*
* @param    bool    $all    if true, return all themes even if users aren't allowed to change their default themes
* @return   array           All installed themes
*
*/
function COM_getThemes( $all = false )
{
    global $_CONF;

    $index = 1;

    $themes = array();

    $fd = opendir( $_CONF['path_themes'] );

    // If users aren't allowed to change their theme then only return the default theme

    if(( $_CONF['allow_user_themes'] == 0 ) && !$all )
    {
        $themes[$index] = $_CONF['theme'];
    }
    else
    {
        while(( $dir = @readdir( $fd )) == TRUE )
        {
            // Changed by Phize <----
            if ((!empty($_CONF['r_theme_admin'])) && (is_dir($_CONF['path_themes'] . $_CONF['r_theme_admin']) === true)) {
                $theme_admin = $_CONF['r_theme_admin'];
            } else {
                $theme_admin = 'Admin';
            }

            if( is_dir( $_CONF['path_themes'] . $dir) && $dir <> '.' && $dir <> '..' && $dir <> 'CVS' && substr( $dir, 0 , 1 ) <> '.'  && $dir <> $theme_admin)
            {
                clearstatcache();
                $themes[$index] = $dir;
                $index++;
            }
            // Changed by Phize ---->
        }
    }

    return $themes;
}

/**
* Create the menu, i.e. replace {menu_elements} in the site header with the
* actual menu entries.
*
* @param    Template    $header     reference to the header template
* @param    array       $plugin_menu    array of plugin menu entries, if any
*
*/
function COM_renderMenu( &$header, $plugin_menu )
{
    global $_CONF, $_USER, $LANG01, $topic;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_renderMenu';
    if( function_exists( $function ))
    {
        return $function( $header, $plugin_menu );
    }
    // Added by Phize ---->

    // Added by Phize <----
    $attr_class_first = ' class="first"';
    $attr_class_last = ' class="last"';
    $value_class_first = ' first';
    $value_class_last = ' last';
    // Added by Phize ---->

    if( empty( $_CONF['menu_elements'] ))
    {
        $_CONF['menu_elements'] = array( // default set of links
                'contribute', 'search', 'stats', 'directory', 'plugins' );
    }

    $anon = ( empty( $_USER['uid'] ) || ( $_USER['uid'] <= 1 )) ? true : false;
    $menuCounter = 0;
    $allowedCounter = 0;
    $counter = 0;

    $num_plugins = sizeof( $plugin_menu );
    if( ( $num_plugins == 0 ) && in_array( 'plugins', $_CONF['menu_elements'] ))
    {
        $key = array_search( 'plugins', $_CONF['menu_elements'] );
        unset( $_CONF['menu_elements'][$key] );
    }

    if( in_array( 'custom', $_CONF['menu_elements'] ))
    {
        $custom_entries = array();
        if( function_exists( 'CUSTOM_menuEntries' ))
        {
            $custom_entries = CUSTOM_menuEntries();
        }
        if( sizeof( $custom_entries ) == 0 )
        {
            $key = array_search( 'custom', $_CONF['menu_elements'] );
            unset( $_CONF['menu_elements'][$key] );
        }
    }

    $num_elements = sizeof( $_CONF['menu_elements'] );

    foreach( $_CONF['menu_elements'] as $item )
    {
        $counter++;
        $allowed = true;
        $last_entry = ( $counter == $num_elements ) ? true : false;

        switch( $item )
        {
            case 'contribute':
                if( empty( $topic ))
                {
                    $url = $_CONF['site_url'] . '/submit.php?type=story';
                    $header->set_var( 'current_topic', '' );
                }
                else
                {
                    $url = $_CONF['site_url']
                         . '/submit.php?type=story&amp;topic=' . $topic;
                    $header->set_var( 'current_topic', '&amp;topic=' . $topic );
                }
                $label = $LANG01[71];
                if( $anon && ( $_CONF['loginrequired'] ||
                        $_CONF['submitloginrequired'] ))
                {
                    $allowed = false;
                }
                break;

            case 'custom':
                $custom_count = 0;
                $custom_size = sizeof( $custom_entries );
                foreach( $custom_entries as $entry )
                {
                    $custom_count++;

                    if( empty( $entry['url'] ) || empty( $entry['label'] ))
                    {
                        continue;
                    }

                    $header->set_var( 'menuitem_url',  $entry['url'] );
                    $header->set_var( 'menuitem_text', $entry['label'] );

                    // Changed by Phize <----
                    if ( $menuCounter == 0 )
                    {
                        $header->set_var( 'attr_class', $attr_class_first );
                        $header->set_var( 'value_class', $value_class_first );
                        $header->parse( 'menu_elements', 'menuitem', true );
                    }
                    else if( $last_entry && ( $custom_count == $custom_size ))
                    {
                        $header->set_var( 'attr_class', $attr_class_last );
                        $header->set_var( 'value_class', $value_class_last );
                        $header->parse( 'menu_elements', 'menuitem_last', true );
                    }
                    else
                    {
                        $header->set_var( 'attr_class', '' );
                        $header->set_var( 'value_class', '' );
                        $header->parse( 'menu_elements', 'menuitem', true );
                    }
                    // Changed by Phize ---->

                    $menuCounter++;
                }
                $url = '';
                $label = '';
                break;

            case 'directory':
                $url = $_CONF['site_url'] . '/directory.php';
                if( !empty( $topic ))
                {
                    $url = COM_buildUrl( $url . '?topic='
                                         . urlencode( $topic ));
                }
                $label = $LANG01[117];
                if( $anon && ( $_CONF['loginrequired'] ||
                        $_CONF['directoryloginrequired'] ))
                {
                    $allowed = false;
                }
                break;

            case 'home':
                $url = $_CONF['site_url'] . '/';
                $label = $LANG01[90];
                break;

            case 'plugins':
                for( $i = 1; $i <= $num_plugins; $i++ )
                {
                    $header->set_var( 'menuitem_url', current( $plugin_menu ));
                    $header->set_var( 'menuitem_text', key( $plugin_menu ));

                    // Changed by Phize <----
                    if ( $menuCounter == 0 )
                    {
                        $header->set_var( 'attr_class', $attr_class_first );
                        $header->set_var( 'value_class', $value_class_first );
                        $header->parse( 'menu_elements', 'menuitem', true );
                    }
                    else if( $last_entry && ( $i == $num_plugins ))
                    {
                        $header->set_var( 'attr_class', $attr_class_last );
                        $header->set_var( 'value_class', $value_class_last );
                        $header->parse( 'menu_elements', 'menuitem_last', true );
                    }
                    else
                    {
                        $header->set_var( 'attr_class', '' );
                        $header->set_var( 'value_class', '' );
                        $header->parse( 'menu_elements', 'menuitem', true );
                    }
                    // Changed by Phize ---->
                    $menuCounter++;

                    next( $plugin_menu );
                }
                $url = '';
                $label = '';
                break;

            case 'prefs':
                $url = $_CONF['site_url'] . '/usersettings.php?mode=edit';
                $label = $LANG01[48];
                break;

            case 'search':
                $url = $_CONF['site_url'] . '/search.php';
                $label = $LANG01[75];
                if( $anon && ( $_CONF['loginrequired'] ||
                        $_CONF['searchloginrequired'] ))
                {
                    $allowed = false;
                }
                break;

            case 'stats':
                $url = $_CONF['site_url'] . '/stats.php';
                $label = $LANG01[76];
                if( $anon &&
                    ( $_CONF['loginrequired'] || $_CONF['statsloginrequired'] ))
                {
                    $allowed = false;
                }
                break;

            default: // unknown entry
                $url = '';
                $label = '';
                break;
        }

        if( !empty( $url ) && !empty( $label ))
        {
            $header->set_var( 'menuitem_url',  $url );
            $header->set_var( 'menuitem_text', $label );

            // Changed by Phize <----
            if ( $menuCounter == 0 )
            {
                $header->set_var( 'attr_class', $attr_class_first );
                $header->set_var( 'value_class', $value_class_first );
                $header->parse( 'menu_elements', 'menuitem', true );
            }
            else if( $last_entry )
            {
                $header->set_var( 'attr_class', $attr_class_last );
                $header->set_var( 'value_class', $value_class_last );
                $header->parse( 'menu_elements', 'menuitem_last', true );
            }
            else
            {
                $header->set_var( 'attr_class', '' );
                $header->set_var( 'value_class', '' );
                $header->parse( 'menu_elements', 'menuitem', true );
            }
            // Changed by Phize ---->

            $menuCounter++;

            if( $allowed )
            {
                // Changed by Phize <----
                if ( $menuCounter == 0 )
                {
                    $header->set_var( 'attr_class', $attr_class_first );
                    $header->set_var( 'value_class', $value_class_first );
                    $header->parse( 'allowed_menu_elements', 'menuitem', true );
                }
                else if( $last_entry )
                {
                    $header->set_var( 'attr_class', $attr_class_last );
                    $header->set_var( 'value_class', $value_class_last );
                    $header->parse( 'allowed_menu_elements', 'menuitem_last', true );
                }
                else
                {
                    $header->set_var( 'attr_class', '' );
                    $header->set_var( 'value_class', '' );
                    $header->parse( 'allowed_menu_elements', 'menuitem', true );
                }
                // Changed by Phize ---->

                $allowedCounter++;
            }
        }
    }

    // Changed by Phize <----
    //if( $menuCounter == 0 )
    //{
    //    $header->parse( 'menu_elements', 'menuitem_none', true );
    //}
    //if( $allowedCounter == 0 )
    //{
    //    $header->parse( 'allowed_menu_elements', 'menuitem_none', true );
    //}
    // Changed by Phize ---->
}

/**
* Returns the site header
*
* This loads the proper templates, does variable substitution and returns the
* HTML for the site header with or without blocks depending on the value of $what
*
* Programming Note:
*
* The two functions COM_siteHeader and COM_siteFooter provide the framework for
* page display in Geeklog.  COM_siteHeader controls the display of the Header
* and left blocks and COM_siteFooter controls the dsiplay of the right blocks
* and the footer.  You use them like a sandwich.  Thus the following code will
* display a Geeklog page with both right and left blocks displayed.
*
* -------------------------------------------------------------------------------------
* <?php
* require_once('lib-common.php');
* $display .= COM_siteHeader(); //Change to COM_siteHeader('none') to not display left blocks
* $display .= "Here is your html for display";
* $display .= COM_siteFooter(true);  // Change to COM_siteFooter() to not display right blocks
* echo $display;
* ? >
* ---------------------------------------------------------------------------------------
*
* Note that the default for the header is to display the left blocks and the
* default of the footer is to not display the right blocks.
*
* This sandwich produces code like this (greatly simplified)
*
* // COM_siteHeader
* <table><tr><td colspan="3">Header</td></tr>
* <tr><td>Left Blocks</td><td>
*
* // Your HTML goes here
* Here is your html for display
*
* // COM_siteFooter
* </td><td>Right Blocks</td></tr>
* <tr><td colspan="3">Footer</td></table>
*
* @param    string  $what       If 'none' then no left blocks are returned, if 'menu' (default) then right blocks are returned
* @param    string  $pagetitle  optional content for the page's <title>
* @param    string  $headercode optional code to go into the page's <head>
* @return   string              Formatted HTML containing the site header
* @see function COM_siteFooter
*
*/

function COM_siteHeader( $what = 'menu', $pagetitle = '', $headercode = '' )
{
    global $_CONF, $_TABLES, $_USER, $LANG01, $LANG_BUTTONS, $LANG_CHARSET,
           $LANG_DIRECTION, $_IMAGE_TYPE, $topic, $_COM_VERBOSE;

    // If the theme implemented this for us then call their version instead.

    $function = $_CONF['theme'] . '_siteHeader';

    if( function_exists( $function ))
    {
        return $function( $what, $pagetitle, $headercode );
    }

    // Added by Phize <----
    $attr_class_first = ' class="first"';
    $attr_class_last = ' class="last"';
    $value_class_first = ' first';
    $value_class_last = ' last';
    // Added by Phize ---->

    // send out the charset header

    if( empty( $LANG_CHARSET )) {
        $charset = $_CONF['default_charset'];
        if( empty( $charset )) {
            $charset = 'iso-8859-1';
        }
    } else {
        $charset = $LANG_CHARSET;
    }
    header ('Content-Type: text/html; charset=' . $charset);

    // If we reach here then either we have the default theme OR
    // the current theme only needs the default variable substitutions

    $header = new Template( $_CONF['path_layout'] );
    $header->set_file( array(
        'header'        => 'header.thtml',
        'menuitem'      => 'menuitem.thtml',

        // Changed by Phize <----
        'menuitem_last' => 'menuitem.thtml',
        'menuitem_none' => 'menuitem.thtml',
        'leftblocks'    => 'blocks_1.thtml'
        // Changed by Phize ---->
        ));

    // get topic if not on home page
    if( !isset( $_GET['topic'] ))
    {
        if( isset( $_GET['story'] ))
        {
            $sid = COM_applyFilter( $_GET['story'] );
        }
        elseif( isset( $_GET['sid'] ))
        {
            $sid = COM_applyFilter( $_GET['sid'] );
        }
        elseif( isset( $_POST['story'] ))
        {
            $sid = COM_applyFilter( $_POST['story'] );
        }
        if( empty( $sid ) && $_CONF['url_rewrite'] &&
                ( strpos( $_SERVER['PHP_SELF'], 'article.php' ) !== false ))
        {
            COM_setArgNames( array( 'story', 'mode' ));
            $sid = COM_applyFilter( COM_getArgument( 'story' ));
        }
        if( !empty( $sid ))
        {
            $topic = DB_getItem( $_TABLES['stories'], 'tid', "sid='$sid'" );
        }
    }
    else
    {
        $topic = COM_applyFilter( $_GET['topic'] );
    }

    $feed_url = array();
    if( $_CONF['backend'] == 1 ) // add feed-link to header if applicable
    {
        $baseurl = SYND_getFeedUrl();

        $sql = 'SELECT format, filename, title, language FROM '
             . $_TABLES['syndication'] . " WHERE (header_tid = 'all')";
        if( !empty( $topic ))
        {
            $sql .= " OR (header_tid = '" . addslashes( $topic ) . "')";
        }
        $result = DB_query( $sql );
        $numRows = DB_numRows( $result );
        for( $i = 0; $i < $numRows; $i++ )
        {
            $A = DB_fetchArray( $result );
            if ( !empty( $A['filename'] ))
            {
                $format = explode( '-', $A['format'] );
                $format_type = strtolower( $format[0] );
                $format_name = ucwords( $format[0] );

                $feed_url[] = '<link rel="alternate" type="application/'
                          . $format_type . '+xml" hreflang="' . $A['language']
                          . '" href="' . $baseurl . $A['filename'] . '" title="'
                          . $format_name . ' Feed: ' . $A['title'] . '">';
            }
        }
    }
    $header->set_var( 'feed_url', implode( LB, $feed_url ));

    $relLinks = array();
    if( !COM_onFrontpage() )
    {
        $relLinks['home'] = '<link rel="home" href="' . $_CONF['site_url']
                          . '/" title="' . $LANG01[90] . '">';
    }
    $loggedInUser = ( isset( $_USER['uid'] ) && ( $_USER['uid'] > 1 ));
    if( $loggedInUser || (( $_CONF['loginrequired'] == 0 ) &&
                ( $_CONF['searchloginrequired'] == 0 )))
    {
        if(( substr( $_SERVER['PHP_SELF'], -strlen( '/search.php' ))
                != '/search.php' ) || isset( $_GET['mode'] ))
        {
            $relLinks['search'] = '<link rel="search" href="'
                                . $_CONF['site_url'] . '/search.php" title="'
                                . $LANG01[75] . '">';
        }
    }
    if( $loggedInUser || (( $_CONF['loginrequired'] == 0 ) &&
                ( $_CONF['directoryloginrequired'] == 0 )))
    {
        if( strpos( $_SERVER['PHP_SELF'], '/article.php' ) !== false ) {
            $relLinks['contents'] = '<link rel="contents" href="'
                        . $_CONF['site_url'] . '/directory.php" title="'
                        . $LANG01[117] . '">';
        }
    }
    // TBD: add a plugin API and a lib-custom.php function
    $header->set_var( 'rel_links', implode( LB, $relLinks ));

    if( empty( $pagetitle ) && isset( $_CONF['pagetitle'] ))
    {
        $pagetitle = $_CONF['pagetitle'];
    }
    if( empty( $pagetitle ))
    {
        if( empty( $topic ))
        {
            $pagetitle = $_CONF['site_slogan'];
        }
        else
        {
            $pagetitle = stripslashes( DB_getItem( $_TABLES['topics'], 'topic',
                                                   "tid = '$topic'" ));
        }
    }
    if( !empty( $pagetitle ))
    {
        $pagetitle = ' - ' . $pagetitle;
    }
    $header->set_var( 'page_title', $_CONF['site_name'] . $pagetitle );

    if( isset( $_CONF['advanced_editor'] ) && ( $_CONF['advanced_editor'] == 1 )
            && file_exists( $_CONF['path_layout']
                            . 'advanced_editor_header.thtml' ))
    {
        $header->set_file( 'editor'  , 'advanced_editor_header.thtml');
        $header->parse( 'advanced_editor', 'editor' );

    }
    else
    {
         $header->set_var( 'advanced_editor', '' );
    }

    $langAttr = '';
    if( isset( $_CONF['languages'] ) && isset( $_CONF['language_files'] ))
    {
        $langId = COM_getLanguageId();
    }
    else
    {
        // try to derive the language id from the locale
        $l = explode( '.', $_CONF['locale'] );
        $langId = $l[0];
    }
    if( !empty( $langId ))
    {
        $l = explode( '-', str_replace( '_', '-', $langId ));
        if(( count( $l ) == 1 ) && ( strlen( $langId ) == 2 ))
        {
            $langAttr = 'lang="' . $langId . '"';
        }
        else if( count( $l ) == 2 )
        {
            if(( $l[0] == 'i' ) || ( $l[0] == 'x' ))
            {
                $langId = implode( '-', $l );
                $langAttr = 'lang="' . $langId . '"';
            }
            else if( strlen( $l[0] ) == 2 )
            {
                $langId = implode( '-', $l );
                $langAttr = 'lang="' . $langId . '"';
            }
            else
            {
                $langId = $l[0];
            }
        }
    }
    $header->set_var( 'lang_id', $langId );
    $header->set_var( 'lang_attribute', $langAttr );

    $header->set_var( 'background_image', $_CONF['layout_url']
                                          . '/images/bg.' . $_IMAGE_TYPE );
    $header->set_var( 'site_url', $_CONF['site_url'] );
    $header->set_var( 'layout_url', $_CONF['layout_url'] );
    $header->set_var( 'site_mail', "mailto:{$_CONF['site_mail']}" );
    $header->set_var( 'site_name', $_CONF['site_name'] );
    $header->set_var( 'site_slogan', $_CONF['site_slogan'] );
    $rdf = substr_replace( $_CONF['rdf_file'], $_CONF['site_url'], 0,
                           strlen( $_CONF['path_html'] ) - 1 );
    $header->set_var( 'rdf_file', $rdf );
    $header->set_var( 'rss_url', $rdf );

    $msg = $LANG01[67] . ' ' . $_CONF['site_name'];

    if( !empty( $_USER['username'] ))
    {
        $msg .= ', ' . COM_getDisplayName( $_USER['uid'], $_USER['username'],
                                           $_USER['fullname'] );
    }

    $curtime =  COM_getUserDateTimeFormat();

    $header->set_var( 'welcome_msg', $msg );
    $header->set_var( 'datetime', $curtime[0] );
    $header->set_var( 'site_logo', $_CONF['layout_url']
                                   . '/images/logo.' . $_IMAGE_TYPE );
    $header->set_var( 'css_url', $_CONF['layout_url'] . '/style.css' );
    $header->set_var( 'theme', $_CONF['theme'] );

    if( empty( $LANG_CHARSET ))
    {
        $charset = $_CONF['default_charset'];

        if( empty( $charset ))
        {
            $charset = 'iso-8859-1';
        }
    }
    else
    {
        $charset = $LANG_CHARSET;
    }

    $header->set_var( 'charset', $charset );
    if( empty( $LANG_DIRECTION ))
    {
        // default to left-to-right
        $header->set_var( 'direction', 'ltr' );
    }
    else
    {
        $header->set_var( 'direction', $LANG_DIRECTION );
    }

    // Now add variables for buttons like e.g. those used by the Yahoo theme
    $header->set_var( 'button_home', $LANG_BUTTONS[1] );
    $header->set_var( 'button_contact', $LANG_BUTTONS[2] );
    $header->set_var( 'button_contribute', $LANG_BUTTONS[3] );
    $header->set_var( 'button_sitestats', $LANG_BUTTONS[7] );
    $header->set_var( 'button_personalize', $LANG_BUTTONS[8] );
    $header->set_var( 'button_search', $LANG_BUTTONS[9] );
    $header->set_var( 'button_advsearch', $LANG_BUTTONS[10] );
    $header->set_var( 'button_directory', $LANG_BUTTONS[11] );

    // Get plugin menu options
    $plugin_menu = PLG_getMenuItems();

    if( $_COM_VERBOSE )
    {
        COM_errorLog( 'num plugin menu items in header = ' . count( $plugin_menu ), 1 );
    }

    // Now add nested template for menu items
    COM_renderMenu( $header, $plugin_menu );

    if( count( $plugin_menu ) == 0 )
    {
        $header->parse( 'plg_menu_elements', 'menuitem_none', true );
    }
    else
    {
        for( $i = 1; $i <= count( $plugin_menu ); $i++ )
        {
            $header->set_var( 'menuitem_url', current( $plugin_menu ));
            $header->set_var( 'menuitem_text', key( $plugin_menu ));

            // Changed by Phize <----
            if( $i == 1)
            {
                $header->set_var( 'attr_class', $attr_class_first );
                $header->set_var( 'value_class', $value_class_first );
                $header->parse( 'plg_menu_elements', 'menuitem', true );
            }
            else if( $i == count( $plugin_menu ))
            {
                $header->set_var( 'attr_class', $attr_class_last );
                $header->set_var( 'value_class', $value_class_last );
                $header->parse( 'plg_menu_elements', 'menuitem', true );
            }
            else
            {
                $header->set_var( 'attr_class', '' );
                $header->set_var( 'value_class', '' );
                $header->parse( 'plg_menu_elements', 'menuitem', true );
            }
            // Changed by Phize ---->

            next( $plugin_menu );
        }
    }

    if( $_CONF['left_blocks_in_footer'] == 1 )
    {
        $header->set_var( 'geeklog_blocks', '' );
        $header->set_var( 'left_blocks', '' );
    }
    else
    {
        $lblocks = '';

        /* Check if an array has been passed that includes the name of a plugin
         * function or custom function
         * This can be used to take control over what blocks are then displayed
         */
        if( is_array( $what ))
        {
            $function = $what[0];
            if( function_exists( $function ))
            {
                $lblocks = $function( $what[1], 'left' );
            }
            else
            {
                $lblocks = COM_showBlocks( 'left', $topic );
            }
        }
        else if( $what <> 'none' )
        {
            // Now show any blocks -- need to get the topic if not on home page
            $lblocks = COM_showBlocks( 'left', $topic );
        }

        if( empty( $lblocks ))
        {
            $header->set_var( 'geeklog_blocks', '' );
            $header->set_var( 'left_blocks', '' );
        }
        else
        {
            $header->set_var( 'geeklog_blocks', $lblocks );
            $header->parse( 'left_blocks', 'leftblocks', true );
        }
    }

    // Call any plugin that may want to include extra Meta tags
    // or Javascript functions
    $header->set_var( 'plg_headercode', $headercode . PLG_getHeaderCode() );

    // Call to plugins to set template variables in the header
    PLG_templateSetVars( 'header', $header );

    // The following lines allow users to embed PHP in their templates.  This
    // is almost a contradition to the reasons for using templates but this may
    // prove useful at times ...
    // Don't use PHP in templates if you can live without it!

    $tmp = $header->parse( 'index_header', 'header' );

    ob_start();
    eval( '?>' . $tmp );
    $retval = ob_get_contents();
    ob_end_clean();

    return $retval;
}


/**
* Returns the site footer
*
* This loads the proper templates, does variable substitution and returns the
* HTML for the site footer.
*
* @param   boolean     $rightblock     Whether or not to show blocks on right hand side default is no
* @param   array       $custom         An array defining custom function to be used to format Rightblocks
* @see function COM_siteHeader
* @return   string  Formated HTML containing site footer and optionally right blocks
*
*/
function COM_siteFooter( $rightblock = -1, $custom = '' )
{
    global $_CONF, $_TABLES, $LANG01, $_PAGE_TIMER, $topic;


    if( $rightblock < 0 )
    {
        if( isset( $_CONF['show_right_blocks'] ))
        {
            $rightblock = $_CONF['show_right_blocks'];
        }
        else
        {
            $rightblock = false;
        }
    }

    // If the theme implemented this for us then call their version instead.

    $function = $_CONF['theme'] . '_siteFooter';

    if( function_exists( $function ))
    {
        return $function( $rightblock, $custom );
    }

    // Set template directory
    $footer = new Template( $_CONF['path_layout'] );

    // Set template file
    $footer->set_file( array(
            'footer'      => 'footer.thtml',
            // Changed by Phize <----
            'rightblocks' => 'blocks_2.thtml',
            'leftblocks'  => 'blocks_1.thtml'
            // Changed by Phize ---->
            ));

    // Do variable assignments
    DB_change( $_TABLES['vars'], 'value', 'value + 1', 'name', 'totalhits', '', true );

    $footer->set_var( 'site_url', $_CONF['site_url']);
    $footer->set_var( 'layout_url',$_CONF['layout_url']);
    $footer->set_var( 'site_mail', "mailto:{$_CONF['site_mail']}" );
    $footer->set_var( 'site_name', $_CONF['site_name'] );
    $footer->set_var( 'site_slogan', $_CONF['site_slogan'] );
    $rdf = substr_replace( $_CONF['rdf_file'], $_CONF['site_url'], 0,
                           strlen( $_CONF['path_html'] ) - 1 );
    $footer->set_var( 'rdf_file', $rdf );
    $footer->set_var( 'rss_url', $rdf );

    $year = date( 'Y' );
    $copyrightyear = $year;
    if( !empty( $_CONF['copyrightyear'] ))
    {
        $copyrightyear = $_CONF['copyrightyear'];
    }
    $footer->set_var( 'copyright_notice', '&nbsp;' . $LANG01[93] . ' &copy; '
            . $copyrightyear . ' ' . $_CONF['site_name'] . '<br>&nbsp;'
            . $LANG01[94] );
    $footer->set_var( 'copyright_msg', $LANG01[93] . ' &copy; '
            . $copyrightyear . ' ' . $_CONF['site_name'] );
    $footer->set_var( 'current_year', $year );
    $footer->set_var( 'lang_copyright', $LANG01[93] );
    $footer->set_var( 'trademark_msg', $LANG01[94] );
    $footer->set_var( 'powered_by', $LANG01[95] );
    $footer->set_var( 'geeklog_url', 'http://www.geeklog.net/' );
    $footer->set_var( 'geeklog_version', VERSION );

    /* Check if an array has been passed that includes the name of a plugin
     * function or custom function.
     * This can be used to take control over what blocks are then displayed
     */
    if( is_array( $custom ))
    {
        $function = $custom['0'];
        if( function_exists( $function ))
        {
            $rblocks = $function( $custom['1'], 'right' );
        }
    }
    elseif( $rightblock )
    {
        $rblocks = COM_showBlocks( 'right', $topic );
    }
    if( $rightblock && !empty( $rblocks ))
    {
        $footer->set_var( 'geeklog_blocks', $rblocks );
        $footer->parse( 'right_blocks', 'rightblocks', true );
    }
    else
    {
        $footer->set_var( 'geeklog_blocks', '' );
        $footer->set_var( 'right_blocks', '' );
    }

    if( $_CONF['left_blocks_in_footer'] == 1 )
    {
        $lblocks = '';

        /* Check if an array has been passed that includes the name of a plugin
         * function or custom function
         * This can be used to take control over what blocks are then displayed
         */
        if( is_array( $custom ))
        {
            $function = $custom[0];
            if( function_exists( $function ))
            {
                $lblocks = $function( $custom[1], 'left' );
            }
        }
        else
        {
            $lblocks = COM_showBlocks( 'left', $topic );
        }

        if( empty( $lblocks ))
        {
            $footer->set_var( 'geeklog_blocks', '' );
            $footer->set_var( 'left_blocks', '' );
        }
        else
        {
            $footer->set_var( 'geeklog_blocks', $lblocks );
            $footer->parse( 'left_blocks', 'leftblocks', true );
        }
    }

    // Global centerspan variable set in index.php
    if( isset( $GLOBALS['centerspan'] ))
    {
        $footer->set_var( 'centerblockfooter-span', '</td></tr></table>' );
    }

    $exectime = $_PAGE_TIMER->stopTimer();
    $exectext = $LANG01[91] . ' ' . $exectime . ' ' . $LANG01[92];

    $footer->set_var( 'execution_time', $exectime );
    $footer->set_var( 'execution_textandtime', $exectext );

    // Call to plugins to set template variables in the footer
    PLG_templateSetVars( 'footer', $footer );

    // Actually parse the template and make variable substitutions
    $footer->parse( 'index_footer', 'footer' );

    // Return resulting HTML
    return $footer->finish( $footer->get_var( 'index_footer' ));
}

/**
* Prints out standard block header
*
* Prints out standard block header but pulling header HTML formatting from
* the database.
*
* Programming Note:  The two functions COM_startBlock and COM_endBlock are used
* to sandwich your block content.  These functions are not used only for blocks
* but anything that uses that format, e.g. Stats page.  They are used like
* COM_siteHeader and COM_siteFooter but for internal page elements.
*
*
* @param        string      $title      Value to set block title to
* @param        string      $helpfile   Help file, if one exists
* @param        string      $template   HTML template file to use to format the block
* @see COM_endBlock
* @see COM_siteHeader  For similiar construct
* @return   string  Formatted HTML containing block header
*
*/

function COM_startBlock( $title='', $helpfile='', $template='blockheader.thtml' )
{
    global $_CONF, $LANG01, $_IMAGE_TYPE;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_startBlock';
    if( function_exists( $function ))
    {
        return $function( $title, $helpfile, $template );
    }
    // Added by Phize ---->

    // Added by Phize <----
    $value_class_help = 'icon help icon-help';
    // Added by Phize ---->

    $block = new Template( $_CONF['path_layout'] );
    $block->set_file( 'block', $template );
    $block->set_var( 'site_url', $_CONF['site_url'] );
    $block->set_var( 'layout_url', $_CONF['layout_url'] );
    $block->set_var( 'block_title', stripslashes( $title ));

    if( !empty( $helpfile ))
    {
        // Added by Phize <----
        $img_help = $_CONF['layout_url'] . '/images/button_help.' . $_IMAGE_TYPE;
        $img_size = getimagesize($img_help);
        // Added by Phize ---->

        if( !stristr( $helpfile, 'http://' ))
        {
            // Changed by Phize <----
            $help = '<a class="blocktitle" href="' . $_CONF['site_url'] . '/help/' . $helpfile
                . '"><img src="' . $img_help
                . '" ' . $img_size[3] . ' alt="?" class="' . $value_class_help . '"></a>';
            // Changed by Phize ---->
        }
        else
        {
            // Changed by Phize <----
            $help = '<a class="blocktitle" href="' . $helpfile
                . '"><img src="' . $img_help
                . '" ' . $img_size[3] . ' alt="?" class="' . $value_class_help . '"></a>';
            // Changed by Phize ---->
        }

        $block->set_var( 'block_help', $help );
    }

    // Changed by Phize <----
    // Return resulting HTML
    return $block->finish( $block->parse( 'startHTML', 'block' ) );
    // Changed by Phize ---->
}

/**
* Closes out COM_startBlock
*
* @param        string      $template       HTML template file used to format block footer
* @return   string  Formatted HTML to close block
* @see function COM_startBlock
*
*/
function COM_endBlock( $template='blockfooter.thtml' )
{
    global $_CONF;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_endBlock';
    if( function_exists( $function ))
    {
        return $function( $template );
    }
    // Added by Phize ---->

    $block = new Template( $_CONF['path_layout'] );
    $block->set_file( 'block', $template );

    $block->set_var( 'site_url', $_CONF['site_url'] );
    $block->set_var( 'layout_url', $_CONF['layout_url'] );
    $block->parse( 'endHTML', 'block' );

    return $block->finish( $block->get_var( 'endHTML' ));
}


/**
* Creates a <option> list from a database list for use in forms
*
* Creates option list form field using given arguments
*
* @param        string      $table      Database Table to get data from
* @param        string      $selection  Comma delimited string of fields to pull The first field is the value of the option and the second is the label to be displayed.  This is used in a SQL statement and can include DISTINCT to start.
* @param        string/array      $selected   Value (from $selection) to set to SELECTED or default
* @param        int         $sortcol    Which field to sort option list by 0 (value) or 1 (label)
* @param        string      $where      Optional WHERE clause to use in the SQL Selection
* @see function COM_checkList
* @return   string  Formated HTML of option values
*
*/
function COM_optionList( $table, $selection, $selected='', $sortcol=1, $where='' )
{
    global $_DB_table_prefix;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_optionList';
    if( function_exists( $function ))
    {
        return $function( $table, $selection, $selected, $sortcol, $where );
    }
    // Added by Phize ---->

    $retval = '';

    $LangTableName = '';
    if( substr( $table, 0, strlen( $_DB_table_prefix )) == $_DB_table_prefix )
    {
        $LangTableName = 'LANG_' . substr( $table, strlen( $_DB_table_prefix ));
    }
    else
    {
        $LangTableName = 'LANG_' . $table;
    }

    global $$LangTableName;

    if( isset( $$LangTableName ))
    {
        $LangTable = $$LangTableName;
    }
    else
    {
        $LangTable = array();
    }

    $tmp = str_replace( 'DISTINCT ', '', $selection );
    $select_set = explode( ',', $tmp );

    $sql = "SELECT $selection FROM $table";
    if( $where != '' )
    {
        $sql .= " WHERE $where";
    }
    $sql .= " ORDER BY {$select_set[$sortcol]}";
    $result = DB_query( $sql );
    $nrows = DB_numRows( $result );

    for( $i = 0; $i < $nrows; $i++ )
    {
        $A = DB_fetchArray( $result, true );
        $retval .= '<option value="' . $A[0] . '"';

        if( is_array( $selected ) AND count( $selected ) > 0 )
        {
            foreach( $selected as $selected_item )
            {
                if( $A[0] == $selected_item )
                {
                    $retval .= ' selected="selected"';
                }
            }
        }
        elseif( !is_array( $selected ) AND $A[0] == $selected )
        {
            $retval .= ' selected="selected"';
        }

        $retval .= '>';
        if( empty( $LangTable[$A[0]] ))
        {
            $retval .= $A[1];
        }
        else
        {
            $retval .= $LangTable[$A[0]];
        }
        $retval .= '</option>' . LB;
    }

    return $retval;
}

/**
* Create and return a dropdown-list of available topics
*
* This is a variation of COM_optionList() from lib-common.php. It will add
* only those topics to the option list which are accessible by the current
* user.
*
* @param        string      $selection  Comma delimited string of fields to pull The first field is the value of the option and the second is the label to be displayed.  This is used in a SQL statement and can include DISTINCT to start.
* @param        string      $selected   Value (from $selection) to set to SELECTED or default
* @param        int         $sortcol    Which field to sort option list by 0 (value) or 1 (label)
* @see function COM_optionList
* @return   string  Formated HTML of option values
*
*/

function COM_topicList( $selection, $selected = '', $sortcol = 1, $ignorelang = false )
{
    global $_TABLES;

    // Added by Phize <----
    global $_CONF;
    // Added by Phize ---->

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_topicList';
    if( function_exists( $function ))
    {
        return $function( $selection, $selected, $sortcol, $ignorelang );
    }
    // Added by Phize ---->

    $retval = '';

    $tmp = str_replace( 'DISTINCT ', '', $selection );
    $select_set = explode( ',', $tmp );

    $sql = "SELECT $selection FROM {$_TABLES['topics']}";
    if( $ignorelang )
    {
        $sql .= COM_getPermSQL();
    }
    else
    {
        $permsql = COM_getPermSQL();
        if( empty( $permsql ))
        {
            $sql .= COM_getLangSQL( 'tid' );
        }
        else
        {
            $sql .= $permsql . COM_getLangSQL( 'tid', 'AND' );
        }
    }
    $sql .=  " ORDER BY $select_set[$sortcol]";

    $result = DB_query( $sql );
    $nrows = DB_numRows( $result );

    for( $i = 0; $i < $nrows; $i++ )
    {
        $A = DB_fetchArray( $result, true );
        $retval .= '<option value="' . $A[0] . '"';

        if( $A[0] == $selected )
        {
            $retval .= ' selected="selected"';
        }

        $retval .= '>' . stripslashes( $A[1] ) . '</option>' . LB;
    }

    return $retval;
}

/**
* Creates a <input> checklist from a database list for use in forms
*
* Creates a group of checkbox form fields with given arguments
*
* @param        string      $table      DB Table to pull data from
* @param        string      $selection  Comma delimited list of fields to pull from table
* @param        string      $where      Where clause of SQL statement
* @param        string      $selected   Value to set to CHECKED
* @see function COM_optionList
* @return   string  HTML with Checkbox code
*
*/

function COM_checkList( $table, $selection, $where='', $selected='' )
{
    global $_TABLES, $_COM_VERBOSE;

    // Added by Phize <----
    global $_CONF;
    // Added by Phize ---->

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_checkList';
    if( function_exists( $function ))
    {
        return $function( $table, $selection, $where, $selected );
    }
    // Added by Phize ---->

    // Added by Phize <----
    $value_class_checkbox = 'checkbox';
    // Added by Phize ---->

    $retval = '';

    $sql = "SELECT $selection FROM $table";

    if( !empty( $where ))
    {
        $sql .= " WHERE $where";
    }

    $result = DB_query( $sql );
    $nrows = DB_numRows( $result );

    if( !empty( $selected ))
    {
        if( $_COM_VERBOSE )
        {
            COM_errorLog( "exploding selected array: $selected in COM_checkList", 1 );
        }

        $S = explode( ' ', $selected );
    }
    else
    {
        if( $_COM_VERBOSE)
        {
            COM_errorLog( 'selected string was empty COM_checkList', 1 );
        }

        $S = array();
    }

    for( $i = 0; $i < $nrows; $i++ )
    {
        $access = true;
        $A = DB_fetchArray( $result, true );

        if( $table == $_TABLES['topics'] AND SEC_hasTopicAccess( $A['tid'] ) == 0 )
        {
            $access = false;
        }

        if( $access )
        {
            $id = $table . '_' . ($i + 1);
            $retval .= '<input type="checkbox" name="' . $table . '[]" value="' . $A[0] . '" id="' . $id . '"';

            for( $x = 0; $x < sizeof( $S ); $x++ )
            {
                if( $A[0] == $S[$x] )
                {
                    $retval .= ' checked="checked"';
                }
            }

            if(( $table == $_TABLES['blocks'] ) && isset( $A[2] ) && ( $A[2] == 'gldefault' ))
            {
                // Changed by Phize <----
                $retval .= ' class="' . $value_class_checkbox . '"><label for="' . $id . '"><strong>' . stripslashes( $A[1] ) . '</strong></label>' . LB;
                // Changed by Phize ---->
            }
            else
            {
                // Changed by Phize <----
                $retval .= ' class="' . $value_class_checkbox . '"><label for="' . $id . '">' . stripslashes( $A[1] ) . '</label>' . LB;
                // Changed by Phize ---->
            }
        }
    }

    return $retval;
}

/**
* Prints out an associative array for debugging
*
* The core of this code has been lifted from phpweblog which is licenced
* under the GPL.  This is not used very much in the code but you can use it
* if you see fit
*
* @param        array       $A      Array to loop through and print values for
* @return   string  Formated HTML List
*
*/

function COM_debug( $A )
{
    if( !empty( $A ))
    {
        $retval .= LB . '<pre><p>---- DEBUG ----</p>';

        for( reset( $A ); $k = key( $A ); next( $A ))
        {
            $retval .= sprintf( "<li>%13s [%s]</li>\n", $k, $A[$k] );
        }

        $retval .= '<p>---------------</p></pre>' . LB;
    }

    return $retval;
}

/**
*
* Checks to see if RDF file needs updating and updates it if so.
* Checks to see if we need to update the RDF as a result
* of an article with a future publish date reaching it's
* publish time and if so updates the RDF file.
*
* @param    string  $updated_type   (optional) feed type to update
* @param    string  $updated_topic  (optional) feed topic to update
* @param    string  $updated_id     (optional) feed id to update
*
* @note When called without parameters, this will only check for new entries to
*       include in the feeds. Pass the $updated_XXX parameters when the content
*       of an existing entry has changed.
*
* @see file lib-syndication.php
*
*/
function COM_rdfUpToDateCheck( $updated_type = '', $updated_topic = '', $updated_id = '' )
{
    global $_CONF, $_TABLES;

    if( $_CONF['backend'] > 0 )
    {
        if( !empty( $updated_type ) && ( $updated_type != 'geeklog' ))
        {
            // when a plugin's feed is to be updated, skip Geeklog's own feeds
            $sql = "SELECT fid,type,topic,limits,update_info FROM {$_TABLES['syndication']} WHERE (is_enabled = 1) AND (type <> 'geeklog')";
        }
        else
        {
            $sql = "SELECT fid,type,topic,limits,update_info FROM {$_TABLES['syndication']} WHERE is_enabled = 1";
        }
        $result = DB_query( $sql );
        $num = DB_numRows( $result );
        for( $i = 0; $i < $num; $i++)
        {
            $A = DB_fetchArray( $result );

            $is_current = true;
            if( $A['type'] == 'geeklog' )
            {
                $is_current = SYND_feedUpdateCheck( $A['topic'],
                                $A['update_info'], $A['limits'],
                                $updated_topic, $updated_id );
            }
            else
            {
                $is_current = PLG_feedUpdateCheck( $A['type'], $A['fid'],
                                $A['topic'], $A['update_info'], $A['limits'],
                                $updated_type, $updated_topic, $updated_id );
            }
            if( !$is_current )
            {
                SYND_updateFeed( $A['fid'] );
            }
        }
    }
}

/**
* Checks and Updates the featured status of all articles.
*
* Checks to see if any articles that were published for the future have been
* published and, if so, will see if they are featured.  If they are featured,
* this will set old featured article (if there is one) to normal
*
*/

function COM_featuredCheck()
{
    global $_TABLES;

    $curdate = date( "Y-m-d H:i:s", time() );

    if( DB_getItem( $_TABLES['stories'], 'count(*)', "featured = 1 AND draft_flag = 0 AND date <= '$curdate'" ) > 1 )
    {
        // OK, we have two featured stories, fix that

        $sid = DB_getItem( $_TABLES['stories'], 'sid', "featured = 1 AND draft_flag = 0 ORDER BY date LIMIT 1" );
        DB_query( "UPDATE {$_TABLES['stories']} SET featured = 0 WHERE sid = '$sid'" );
    }
}

/**
*
* Logs messages to error.log or the web page or both
*
* Prints a well formatted message to either the web page, error log
* or both.
*
* @param        string      $logentry       Text to log to error log
* @param        int         $actionid       1 = write to log file, 2 = write to screen (default) both
* @see function COM_accessLog
* @return   string  If $actionid = 2 or '' then HTML formatted string (wrapped in block) else nothing
*
*/

function COM_errorLog( $logentry, $actionid = '' )
{
    global $_CONF, $LANG01;

    $retval = '';

    if( !empty( $logentry ))
    {
        $logentry = str_replace( array( '<?', '?>' ), array( '(@', '@)' ),
                                 $logentry );

        $timestamp = strftime( '%c' );

        switch( $actionid )
        {
            case 1:
                $logfile = $_CONF['path_log'] . 'error.log';

                if( !$file = fopen( $logfile, 'a' ))
                {
                    $retval .= $LANG01[33] . ' ' . $logfile . ' (' . $timestamp . ')<br>' . LB;
                }
                else
                {
                    fputs( $file, "$timestamp - $logentry \n" );
                }
                break;

           case 2:
                $retval .= COM_startBlock( $LANG01[55] . ' ' . $timestamp, '',
                               COM_getBlockTemplate( '_msg_block', 'header' ))

                        // Changed by Phize <----
                        . '<p>' . nl2br( $logentry ) . '</p>'
                        // Changed by Phize ---->

                        . COM_endBlock( COM_getBlockTemplate( '_msg_block',
                                                              'footer' ));
                break;

            default:
                $logfile = $_CONF['path_log'] . 'error.log';

                if( !$file = fopen( $logfile, 'a' ))
                {
                    $retval .= $LANG01[33] . ' ' . $logfile . ' (' . $timestamp . ')<br>' . LB;
                }
                else
                {
                    fputs( $file, "$timestamp - $logentry \n" );
                    $retval .= COM_startBlock( $LANG01[34] . ' - ' . $timestamp,
                                   '', COM_getBlockTemplate( '_msg_block',
                                   'header' ))

                            // Changed by Phize <----
                            . '<p>' . nl2br( $logentry ) . '</p>'
                            // Changed by Phize ---->

                            . COM_endBlock( COM_getBlockTemplate( '_msg_block',
                                                                  'footer' ));
                }
                break;
        }
    }

    return $retval;
}

/**
* Logs message to access.log
*
* This will print a message to the Geeklog access log
*
* @param        string      $string         Message to write to access log
* @see COM_errorLog
*
*/

function COM_accessLog( $logentry )
{
    global $_CONF, $_USER, $LANG01;

    $retval = '';

    if( !empty( $logentry ))
    {
        $logentry = str_replace( array( '<?', '?>' ), array( '(@', '@)' ),
                                 $logentry );

        $timestamp = strftime( '%c' );
        $logfile = $_CONF['path_log'] . 'access.log';

        if( !$file = fopen( $logfile, 'a' ))
        {
            return $LANG01[33] . $logfile . ' (' . $timestamp . ')<br>' . LB;
        }

        if( isset( $_USER['uid'] ))
        {
            $byuser = $_USER['uid'] . '@' . $_SERVER['REMOTE_ADDR'];
        }
        else
        {
            $byuser = 'anon@' . $_SERVER['REMOTE_ADDR'];
        }

        fputs( $file, "$timestamp ($byuser) - $logentry\n" );
    }

    return $retval;
}

/**
* Shows all available topics
*
* Show the topics in the system the user has access to and prints them in HTML.
* This function is used to show the topics in the topics block.
*
* @param    string    $topic      ID of currently selected topic
* @return   string                HTML formatted topic list
*
*/

function COM_showTopics( $topic='' )
{
    global $_CONF, $_TABLES, $_USER, $LANG01, $_BLOCK_TEMPLATE, $page;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_showTopics';
    if( function_exists( $function ))
    {
        return $function( $topic );
    }
    // Added by Phize ---->

    // Added by Phize <----
    $attr_class_list = 'option topic option-topic';
    $attr_class_inactive = ' class="inactive"';
    $value_class_inactive = ' inactive';
    // Added by Phize ---->

    $langsql = COM_getLangSQL( 'tid' );
    if( empty( $langsql ))
    {
        $op = 'WHERE';
    }
    else
    {
        $op = 'AND';
    }

    $sql = "SELECT tid,topic,imageurl FROM {$_TABLES['topics']}" . $langsql;
    if( !empty( $_USER['uid'] ) && ( $_USER['uid'] > 1 ))
    {
        $tids = DB_getItem( $_TABLES['userindex'], 'tids',
                            "uid = '{$_USER['uid']}'" );
        if( !empty( $tids ))
        {
            $sql .= " $op (tid NOT IN ('" . str_replace( ' ', "','", $tids )
                 . "'))" . COM_getPermSQL( 'AND' );
        }
        else
        {
            $sql .= COM_getPermSQL( $op );
        }
    }
    else
    {
        $sql .= COM_getPermSQL( $op );
    }
    if( $_CONF['sortmethod'] == 'alpha' )
    {
        $sql .= ' ORDER BY topic ASC';
    }
    else
    {
        $sql .= ' ORDER BY sortnum';
    }
    $result = DB_query( $sql );

    $retval = '';
    $sections = new Template( $_CONF['path_layout'] );
    if( isset( $_BLOCK_TEMPLATE['topicoption'] ))
    {
        $templates = explode( ',', $_BLOCK_TEMPLATE['topicoption'] );
        $sections->set_file( array( 'option'  => $templates[0],
                                    'current' => $templates[1] ));
    }
    else
    {
        // Changed by Phize <----
        $sections->set_file( array( 'option'   => 'option.thtml',
                                    'inactive' => 'option.thtml' ));
        // Changed by Phize ---->
    }
    $sections->set_var( 'site_url', $_CONF['site_url'] );
    $sections->set_var( 'layout_url', $_CONF['layout_url'] );
    $sections->set_var( 'block_name', str_replace( '_', '-', 'section_block' ));

    // Added by Phize <----
    $sections->set_var( 'if_admin', '<!-- if_admin -->' );
    $sections->set_var( 'endif_admin', '<!-- endif_admin -->' );
    $sections->set_var( 'if_topic', '<!-- if_topic -->' );
    $sections->set_var( 'endif_topic', '<!-- endif_topic -->' );
    $sections->set_var( 'if_user', '<!-- if_user -->' );
    $sections->set_var( 'endif_user', '<!-- endif_user -->' );
    // Added by Phize ---->

    if( $_CONF['hide_home_link'] == 0 )
    {
        // Give a link to the homepage here since a lot of people use this for
        // navigating the site

        if( COM_onFrontpage() )
        {
            $sections->set_var( 'option_url', '' );
            $sections->set_var( 'option_label', $LANG01[90] );
            $sections->set_var( 'option_count', '' );
            $sections->set_var( 'topic_image', '' );

            // Added by Phize <----
            $sections->set_var( 'attr_class', $attr_class_inactive );
            $sections->set_var( 'value_class', $value_class_inactive );
            // Added by Phize ---->

            $retval .= $sections->parse( 'item', 'inactive' );
        }
        else
        {
            $sections->set_var( 'option_url',
                                $_CONF['site_url'] . '/index.php' );
            $sections->set_var( 'option_label', $LANG01[90] );
            $sections->set_var( 'option_count', '' );
            $sections->set_var( 'topic_image', '' );

            // Added by Phize <----
            $sections->set_var( 'attr_class', '' );
            $sections->set_var( 'value_class', '' );
            // Added by Phize ---->

            $retval .= $sections->parse( 'item', 'option' );
        }
    }

    if( $_CONF['showstorycount'] )
    {
        $sql = "SELECT tid, COUNT(*) AS count FROM {$_TABLES['stories']} "
             . 'WHERE (draft_flag = 0) AND (date <= NOW()) '
             . COM_getPermSQL( 'AND' )
             . ' GROUP BY tid';
        $rcount = DB_query( $sql );
        while( $C = DB_fetchArray( $rcount ))
        {
            $storycount[$C['tid']] = $C['count'];
        }
    }

    if( $_CONF['showsubmissioncount'] )
    {
        $sql = "SELECT tid, COUNT(*) AS count FROM {$_TABLES['storysubmission']} "
             . ' GROUP BY tid';
        $rcount = DB_query( $sql );
        while( $C = DB_fetchArray( $rcount ))
        {
            $submissioncount[$C['tid']] = $C['count'];
        }
    }

    while( $A = DB_fetchArray( $result ) )
    {
        $topicname = stripslashes( $A['topic'] );
        $sections->set_var( 'option_url', $_CONF['site_url']
                            . '/index.php?topic=' . $A['tid'] );
        $sections->set_var( 'option_label', $topicname );

        $countstring = '';
        if( $_CONF['showstorycount'] || $_CONF['showsubmissioncount'] )
        {
            $countstring .= '(';

            if( $_CONF['showstorycount'] )
            {
                if( empty( $storycount[$A['tid']] ))
                {
                    $countstring .= 0;
                }
                else
                {
                    $countstring .= COM_numberFormat( $storycount[$A['tid']] );
                }
            }

            if( $_CONF['showsubmissioncount'] )
            {
                if( $_CONF['showstorycount'] )
                {
                    $countstring .= '/';
                }
                if( empty( $submissioncount[$A['tid']] ))
                {
                    $countstring .= 0;
                }
                else
                {
                    $countstring .= COM_numberFormat( $submissioncount[$A['tid']] );
                }
            }

            $countstring .= ')';
        }
        $sections->set_var( 'option_count', $countstring );

        $topicimage = '';
        if( !empty( $A['imageurl'] ))
        {
            $imageurl = COM_getTopicImageUrl( $A['imageurl'] );
            $topicimage = '<img src="' . $imageurl . '" alt="' . $topicname
                        . '" title="' . $topicname . '" border="0">';
        }
        $sections->set_var( 'topic_image', $topicimage );

        // Added by Phize <----
        $sections->set_var( 'if_admin', '<!-- if_admin -->' );
        $sections->set_var( 'endif_admin', '<!-- endif_admin -->' );
        $sections->set_var( 'if_topic', '<!-- if_topic -->' );
        $sections->set_var( 'endif_topic', '<!-- endif_topic -->' );
        $sections->set_var( 'if_user', '<!-- if_user -->' );
        $sections->set_var( 'endif_user', '<!-- endif_user -->' );
        // Added by Phize ---->

        if(( $A['tid'] == $topic ) && ( $page == 1 ))
        {
            // Added by Phize <----
            $sections->set_var( 'attr_class', $attr_class_inactive );
            $sections->set_var( 'value_class', $value_class_inactive );
            // Added by Phize ---->

            $retval .= $sections->parse( 'item', 'inactive' );
        }
        else
        {
            // Added by Phize <----
            $sections->set_var( 'attr_class', '' );
            $sections->set_var( 'value_class', '' );
            // Added by Phize ---->

            $retval .= $sections->parse( 'item', 'option' );
        }
    }

    $retval = '<ul class="' . $attr_class_list . '">' . "\n" . $retval . '</ul>' . "\n";

    // Added by Phize <----
    $retval = preg_replace('/<!-- if_admin -->.*?<!-- endif_admin -->/', '', $retval);
    $retval = preg_replace('/<!-- if_topic -->(.*?)<!-- endif_topic -->/', '\1', $retval);
    $retval = preg_replace('/<!-- if_user -->.*?<!-- endif_user -->/', '', $retval);
    // Added by Phize ---->

    return $retval;
}

/**
* Shows the user their menu options
*
* This shows the average joe use their menu options. This is the user block on right side
*
* @param        string      $help       Help file to show
* @param        string      $title      Title of Menu
* @see function COM_adminMenu
*
*/

function COM_userMenu( $help='', $title='' )
{
    global $_TABLES, $_USER, $_CONF, $LANG01, $LANG04, $_BLOCK_TEMPLATE;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_userMenu';
    if( function_exists( $function ))
    {
        return $function( $help, $title );
    }
    // Added by Phize ---->

    // Added by Phize <----
    $attr_class_list = 'option user option-user';
    $attr_class_current = ' class="current"';
    $value_class_current = ' current';
    // Added by Phize ---->

    $retval = '';

    if( !empty( $_USER['uid'] ) && ( $_USER['uid'] > 1 ))
    {
        $usermenu = new Template( $_CONF['path_layout'] );
        if( isset( $_BLOCK_TEMPLATE['useroption'] ))
        {
            $templates = explode( ',', $_BLOCK_TEMPLATE['useroption'] );
            $usermenu->set_file( array( 'option' => $templates[0],
                                        'current' => $templates[1] ));
        }
        else
        {
           // Changed by Phize <----
           $usermenu->set_file( array( 'option' => 'option.thtml',
                                       'current' => 'option.thtml' ));
           // Changed by Phize ---->
        }
        $usermenu->set_var( 'site_url', $_CONF['site_url'] );
        $usermenu->set_var( 'layout_url', $_CONF['layout_url'] );
        $usermenu->set_var( 'block_name', str_replace( '_', '-', 'user_block' ));

        if( empty( $title ))
        {
            $title = DB_getItem( $_TABLES['blocks'], 'title',
                                 "name='user_block'" );
        }

        // what's our current URL?
        $thisUrl = COM_getCurrentURL();

        $retval .= COM_startBlock( $title, $help,
                           COM_getBlockTemplate( 'user_block', 'header' ));

        // This function will show the user options for all installed plugins
        // (if any)

        $plugin_options = PLG_getUserOptions();
        $nrows = count( $plugin_options );

        // Added by Phize <----
        $retval = $retval . "\n" . '<ul class="' . $attr_class_list . '">' . "\n";
        // Added by Phize ---->

        for( $i = 0; $i < $nrows; $i++ )
        {
            $plg = current( $plugin_options );
            $usermenu->set_var( 'option_label', $plg->adminlabel );

            if( !empty( $plg->numsubmissions ))
            {
                $usermenu->set_var( 'option_count', '(' . $plg->numsubmissions . ')' );
            }
            else
            {
                $usermenu->set_var( 'option_count', '' );
            }

            $usermenu->set_var( 'option_url', $plg->adminurl );

            // Added by Phize <----
            $usermenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $usermenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $usermenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $usermenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $usermenu->set_var( 'if_user', '<!-- if_user -->' );
            $usermenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            if( $thisUrl == $plg->adminurl )
            {
                // Added by Phize <----
                $usermenu->set_var( 'attr_class', $attr_class_current );
                $usermenu->set_var( 'value_class', $value_class_current );
                // Added by Phize ---->

                $retval .= $usermenu->parse( 'item', 'current' );
            }
            else
            {
                // Added by Phize <----
                $usermenu->set_var( 'attr_class', '' );
                $usermenu->set_var( 'value_class', '' );
                // Added by Phize ---->

                $retval .= $usermenu->parse( 'item', 'option' );
            }
            next( $plugin_options );
        }

        $url = $_CONF['site_url'] . '/usersettings.php?mode=edit';
        $usermenu->set_var( 'option_label', $LANG01[48] );
        $usermenu->set_var( 'option_count', '' );
        $usermenu->set_var( 'option_url', $url );

        // Added by Phize <----
        $usermenu->set_var( 'if_admin', '<!-- if_admin -->' );
        $usermenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
        $usermenu->set_var( 'if_topic', '<!-- if_topic -->' );
        $usermenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
        $usermenu->set_var( 'if_user', '<!-- if_user -->' );
        $usermenu->set_var( 'endif_user', '<!-- endif_user -->' );
        // Added by Phize ---->

        if( $thisUrl == $url )
        {
            // Added by Phize <----
            $usermenu->set_var( 'attr_class', $attr_class_current );
            $usermenu->set_var( 'value_class', $value_class_current );
            // Added by Phize ---->

            $retval .= $usermenu->parse( 'item', 'current' );
        }
        else
        {
            // Added by Phize <----
            $usermenu->set_var( 'attr_class', '' );
            $usermenu->set_var( 'value_class', '' );
            // Added by Phize ---->

            $retval .= $usermenu->parse( 'item', 'option' );
        }

        $url = $_CONF['site_url'] . '/users.php?mode=logout';
        $usermenu->set_var( 'option_label', $LANG01[19] );
        $usermenu->set_var( 'option_count', '' );
        $usermenu->set_var( 'option_url', $url );

        // Added by Phize <----
        $usermenu->set_var( 'attr_class', '' );
        $usermenu->set_var( 'value_class', '' );
        // Added by Phize ---->

        $retval .= $usermenu->parse( 'item', 'option' );

        // Added by Phize <----
        $retval = $retval . "\n" . '</ul>' . "\n";
        // Added by Phize ---->

        $retval .=  COM_endBlock( COM_getBlockTemplate( 'user_block', 'footer' ));
    }
    else
    {
        $retval .= COM_startBlock( $LANG01[47], $help,
                           COM_getBlockTemplate( 'user_block', 'header' ));

        $login = new Template( $_CONF['path_layout'] );
        $login->set_file( 'form', 'loginform.thtml' );
        $login->set_var( 'site_url', $_CONF['site_url'] );
        $login->set_var( 'layout_url', $_CONF['layout_url'] );
        $login->set_var( 'lang_username', $LANG01[21] );
        $login->set_var( 'lang_password', $LANG01[57] );
        $login->set_var( 'lang_forgetpassword', $LANG01[119] );
        $login->set_var( 'lang_login', $LANG01[58] );
        if( $_CONF['disable_new_user_registration'] == 1 )
        {
            $login->set_var( 'lang_signup', '' );
        }
        else
        {
            $login->set_var( 'lang_signup', $LANG01[59] );
        }
        if( $_CONF['remoteauthentication'] && !$_CONF['usersubmission'] )
        {
            // Build select
            // Changed by Phize <----
            $select = '<select name="service" id="Service"><option value="">' .
                            $_CONF['site_name'] . '</option>';
            // Changed by Phize ---->

            if( is_dir( $_CONF['path_system'] . 'classes/authentication/' ))
            {
                $folder = opendir( $_CONF['path_system']
                                   . 'classes/authentication/' );
                while(( $filename = @readdir( $folder )) !== false )
                {
                    $strpos = strpos( $filename, '.auth.class.php' );
                    if( $strpos )
                    {
                        $service = substr( $filename, 0, $strpos );
                        $select .= '<option value="' . $service . '">'
                                . $service . '</option>';
                    }
                }
            }
            $select .= '</select>';
            $login->set_file( 'services', 'blockservices.thtml' );
            $login->set_var( 'lang_service', $LANG04[121] );
            $login->set_var( 'select_service', $select );
            $login->parse( 'output', 'services' );
            $login->set_var( 'services',
                             $login->finish( $login->get_var( 'output' )));
        }
        else
        {
            $login->set_var( 'services', '' );
        }
        $retval .= $login->parse( 'output', 'form' );

        $retval .= COM_endBlock( COM_getBlockTemplate( 'user_block', 'footer' ));
    }

    // Added by Phize <----
    $retval = preg_replace('/<!-- if_admin -->.*?<!-- endif_admin -->/', '', $retval);
    $retval = preg_replace('/<!-- if_topic -->.*?<!-- endif_topic -->/', '', $retval);
    $retval = preg_replace('/<!-- if_user -->(.*?)<!-- endif_user -->/', '\1', $retval);
    // Added by Phize ---->

    return $retval;
}

/**
* Prints administration menu
*
* This will return the administration menu items that the user has
* sufficient rights to -- Admin Block on right side.
*
* @param        string      $help       Help file to show
* @param        string      $title      Menu Title
* @see function COM_userMenu
*
*/

function COM_adminMenu( $help = '', $title = '' )
{
    global $_TABLES, $_USER, $_CONF, $LANG01, $_BLOCK_TEMPLATE, $LANG_PDF,
           $_DB_dbms;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_adminMenu';
    if( function_exists( $function ))
    {
        return $function( $help, $title );
    }
    // Added by Phize ---->

    // Added by Phize <----
    $attr_class_list = 'option admin option-admin';
    $attr_class_current = ' class="current"';
    $value_class_current = ' current';
    // Added by Phize ---->

    $retval = '';

    if( empty( $_USER['username'] ))
    {
        return $retval;
    }

    $plugin_options = PLG_getAdminOptions();
    $num_plugins = count( $plugin_options );

    if( SEC_isModerator() OR SEC_hasRights( 'story.edit,block.edit,topic.edit,user.edit,plugin.edit,user.mail,syndication.edit', 'OR' ) OR ( $num_plugins > 0 ))
    {
        // what's our current URL?
        $thisUrl = COM_getCurrentURL();

        $adminmenu = new Template( $_CONF['path_layout'] );
        if( isset( $_BLOCK_TEMPLATE['adminoption'] ))
        {
            $templates = explode( ',', $_BLOCK_TEMPLATE['adminoption'] );
            $adminmenu->set_file( array( 'option' => $templates[0],
                                         'current' => $templates[1] ));
        }
        else
        {
            // Changed by Phize <----
            $adminmenu->set_file( array( 'option' => 'option.thtml',
                                         'current' => 'option.thtml' ));
            // Changed by Phize ---->
        }
        $adminmenu->set_var( 'site_url', $_CONF['site_url'] );
        $adminmenu->set_var( 'layout_url', $_CONF['layout_url'] );
        $adminmenu->set_var( 'block_name', str_replace( '_', '-', 'admin_block' ));

        if( empty( $title ))
        {
            $title = DB_getItem( $_TABLES['blocks'], 'title',
                                 "name = 'admin_block'" );
        }

        $retval .= COM_startBlock( $title, $help,
                           COM_getBlockTemplate( 'admin_block', 'header' ));

        // Added by Phize <----
        $retval = $retval . "\n" . '<ul class="' . $attr_class_list . '">' . "\n";
        // Added by Phize ---->

        $topicsql = '';
        if( SEC_isModerator() || SEC_hasRights( 'story.edit' ))
        {
            $tresult = DB_query( "SELECT tid FROM {$_TABLES['topics']}"
                                 . COM_getPermSQL() );
            $trows = DB_numRows( $tresult );
            if( $trows > 0 )
            {
                $tids = array();
                for( $i = 0; $i < $trows; $i++ )
                {
                    $T = DB_fetchArray( $tresult );
                    $tids[] = $T['tid'];
                }
                if( sizeof( $tids ) > 0 )
                {
                    $topicsql = " (tid IN ('" . implode( "','", $tids ) . "'))";
                }
            }
        }

        $modnum = 0;
        if( SEC_hasRights( 'story.edit,story.moderate', 'OR' ) || (( $_CONF['usersubmission'] == 1 ) && SEC_hasRights( 'user.edit,user.delete' )))
        {

            if( SEC_hasRights( 'story.moderate' ))
            {
                if( empty( $topicsql ))
                {
                    $modnum += DB_count( $_TABLES['storysubmission'] );
                }
                else
                {
                    $sresult = DB_query( "SELECT COUNT(*) AS count FROM {$_TABLES['storysubmission']} WHERE" . $topicsql );
                    $S = DB_fetchArray( $sresult );
                    $modnum += $S['count'];
                }
            }

            if(( $_CONF['listdraftstories'] == 1 ) && SEC_hasRights( 'story.edit' ))
            {
                $sql = "SELECT COUNT(*) AS count FROM {$_TABLES['stories']} WHERE (draft_flag = 1)";
                if( !empty( $topicsql ))
                {
                    $sql .= ' AND' . $topicsql;
                }
                $result = DB_query( $sql . COM_getPermSQL( 'AND', 0, 3 ));
                $A = DB_fetchArray( $result );
                $modnum += $A['count'];
            }

            if( $_CONF['usersubmission'] == 1 )
            {
                if( SEC_hasRights( 'user.edit' ) && SEC_hasRights( 'user.delete' ))
                {
                    $modnum += DB_count( $_TABLES['users'], 'status', '2' );
                }
            }
        }

        // now handle submissions for plugins
        $modnum += PLG_getSubmissionCount();

        if( SEC_hasRights( 'story.edit' ))
        {
            $url = $_CONF['site_admin_url'] . '/story.php';
            $adminmenu->set_var( 'option_url', $url );
            $adminmenu->set_var( 'option_label', $LANG01[11] );
            if( empty( $topicsql ))
            {
                $numstories = DB_count( $_TABLES['stories'] );
            }
            else
            {
                $nresult = DB_query( "SELECT COUNT(*) AS count from {$_TABLES['stories']} WHERE" . $topicsql . COM_getPermSql( 'AND' ));
                $N = DB_fetchArray( $nresult );
                $numstories = $N['count'];
            }

            // Changed by Phize <----
            $adminmenu->set_var( 'option_count', '(' . COM_numberFormat( $numstories ) . ')' );
            // Changed by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Changed by Phize <----
            if( $thisUrl == $url ) {
                $adminmenu->set_var( 'attr_class', $attr_class_current );
                $adminmenu->set_var( 'value_class', $value_class_current );
                $menu_item = $adminmenu->parse( 'item', 'current' );
            }
            else
            {
                $adminmenu->set_var( 'attr_class', '' );
                $adminmenu->set_var( 'value_class', '' );
                $menu_item = $adminmenu->parse( 'item', 'option' );
            }
            // Changed by Phize ---->

            $link_array[$LANG01[11]] = $menu_item;
        }

        if( SEC_hasRights( 'block.edit' ))
        {
            $result = DB_query( "SELECT COUNT(*) AS count FROM {$_TABLES['blocks']}" . COM_getPermSql());
            list( $count ) = DB_fetchArray( $result );

            $url = $_CONF['site_admin_url'] . '/block.php';
            $adminmenu->set_var( 'option_url', $url );
            $adminmenu->set_var( 'option_label', $LANG01[12] );

            // Changed by Phize <----
            $adminmenu->set_var( 'option_count', '(' . COM_numberFormat( $count ) . ')' );
            // Changed by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Changed by Phize <----
            if( $thisUrl == $url ) {
                $adminmenu->set_var( 'attr_class', $attr_class_current );
                $adminmenu->set_var( 'value_class', $value_class_current );
                $menu_item = $adminmenu->parse( 'item', 'current' );
            }
            else
            {
                $adminmenu->set_var( 'attr_class', '' );
                $adminmenu->set_var( 'value_class', '' );
                $menu_item = $adminmenu->parse( 'item', 'option' );
            }
            // Changed by Phize ---->

            $link_array[$LANG01[12]] = $menu_item;
        }

        if( SEC_hasRights( 'topic.edit' ))
        {
            $result = DB_query( "SELECT COUNT(*) AS count FROM {$_TABLES['topics']}" . COM_getPermSql());
            list( $count ) = DB_fetchArray( $result );

            $url = $_CONF['site_admin_url'] . '/topic.php';
            $adminmenu->set_var( 'option_url', $url );
            $adminmenu->set_var( 'option_label', $LANG01[13] );

            // Changed by Phize <----
            $adminmenu->set_var( 'option_count', '(' . COM_numberFormat( $count ) . ')' );
            // Changed by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Changed by Phize <----
            if( $thisUrl == $url ) {
                $adminmenu->set_var( 'attr_class', $attr_class_current );
                $adminmenu->set_var( 'value_class', $value_class_current );
                $menu_item = $adminmenu->parse( 'item', 'current' );
            }
            else
            {
                $adminmenu->set_var( 'attr_class', '' );
                $adminmenu->set_var( 'value_class', '' );
                $menu_item = $adminmenu->parse( 'item', 'option' );
            }
            // Changed by Phize ---->

            $link_array[$LANG01[13]] = $menu_item;
        }

        if( SEC_hasRights( 'user.edit' ))
        {
            $url = $_CONF['site_admin_url'] . '/user.php';
            $adminmenu->set_var( 'option_url', $url );
            $adminmenu->set_var( 'option_label', $LANG01[17] );

            // Changed by Phize <----
            $adminmenu->set_var( 'option_count', '(' . COM_numberFormat( DB_count( $_TABLES['users'] ) -1 ) . ')' );
            // Changed by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Changed by Phize <----
            if( $thisUrl == $url ) {
                $adminmenu->set_var( 'attr_class', $attr_class_current );
                $adminmenu->set_var( 'value_class', $value_class_current );
                $menu_item = $adminmenu->parse( 'item', 'current' );
            }
            else
            {
                $adminmenu->set_var( 'attr_class', '' );
                $adminmenu->set_var( 'value_class', '' );
                $menu_item = $adminmenu->parse( 'item', 'option' );
            }
            // Changed by Phize ---->

            $link_array[$LANG01[17]] = $menu_item;
        }

        if( SEC_hasRights( 'group.edit' ))
        {
            if (SEC_inGroup('Root')) {
                $grpFilter = '';
            } else {
                $thisUsersGroups = SEC_getUserGroups ();
                $grpFilter = 'WHERE (grp_id IN (' . implode (',', $thisUsersGroups) . '))';
            }
            $result = DB_query( "SELECT COUNT(*) AS count FROM {$_TABLES['groups']} $grpFilter;" );
            $A = DB_fetchArray( $result );

            $url = $_CONF['site_admin_url'] . '/group.php';
            $adminmenu->set_var( 'option_url', $url );
            $adminmenu->set_var( 'option_label', $LANG01[96] );

            // Changed by Phize <----
            $adminmenu->set_var( 'option_count', '(' . COM_numberFormat( $A['count'] ) . ')' );
            // Changed by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Changed by Phize <----
            if( $thisUrl == $url ) {
                $adminmenu->set_var( 'attr_class', $attr_class_current );
                $adminmenu->set_var( 'value_class', $value_class_current );
                $menu_item = $adminmenu->parse( 'item', 'current' );
            }
            else
            {
                $adminmenu->set_var( 'attr_class', '' );
                $adminmenu->set_var( 'value_class', '' );
                $menu_item = $adminmenu->parse( 'item', 'option' );
            }
            // Changed by Phize ---->

            $link_array[$LANG01[96]] = $menu_item;
        }

        if( SEC_hasRights( 'user.mail' ))
        {
            $url = $_CONF['site_admin_url'] . '/mail.php';
            $adminmenu->set_var( 'option_url', $url );
            $adminmenu->set_var( 'option_label', $LANG01[105] );

            // Changed by Phize <----
            $adminmenu->set_var( 'option_count', '(N/A)' );
            // Changed by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Changed by Phize <----
            if( $thisUrl == $url ) {
                $adminmenu->set_var( 'attr_class', $attr_class_current );
                $adminmenu->set_var( 'value_class', $value_class_current );
                $menu_item = $adminmenu->parse( 'item', 'current' );
            }
            else
            {
                $adminmenu->set_var( 'attr_class', '' );
                $adminmenu->set_var( 'value_class', '' );
                $menu_item = $adminmenu->parse( 'item', 'option' );
            }
            // Changed by Phize ---->

            $link_array[$LANG01[105]] = $menu_item;
        }

        if(( $_CONF['backend'] == 1 ) && SEC_hasRights( 'syndication.edit' ))
        {
            $url = $_CONF['site_admin_url'] . '/syndication.php';
            $adminmenu->set_var( 'option_url', $url );
            $adminmenu->set_var( 'option_label', $LANG01[38] );
            $count = COM_numberFormat( DB_count( $_TABLES['syndication'] ));

            // Changed by Phize <----
            $adminmenu->set_var( 'option_count', '(' . $count . ')' );
            // Changed by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Changed by Phize <----
            if( $thisUrl == $url ) {
                $adminmenu->set_var( 'attr_class', $attr_class_current );
                $adminmenu->set_var( 'value_class', $value_class_current );
                $menu_item = $adminmenu->parse( 'item', 'current' );
            }
            else
            {
                $adminmenu->set_var( 'attr_class', '' );
                $adminmenu->set_var( 'value_class', '' );
                $menu_item = $adminmenu->parse( 'item', 'option' );
            }
            // Changed by Phize ---->

            $link_array[$LANG01[38]] = $menu_item;
        }

        if(( $_CONF['trackback_enabled'] || $_CONF['pingback_enabled'] ||
                $_CONF['ping_enabled'] ) && SEC_hasRights( 'story.ping' ))
        {
            $url = $_CONF['site_admin_url'] . '/trackback.php';
            $adminmenu->set_var( 'option_url', $url );
            $adminmenu->set_var( 'option_label', $LANG01[116] );
            if( $_CONF['ping_enabled'] )
            {
                $count = COM_numberFormat( DB_count( $_TABLES['pingservice'] ));

                // Changed by Phize <----
                $adminmenu->set_var( 'option_count', '(' . $count . ')' );
                // Changed by Phize ---->
            }
            else
            {
                // Changed by Phize <----
                $adminmenu->set_var( 'option_count', '(N/A)' );
                // Changed by Phize ---->
            }

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Changed by Phize <----
            if( $thisUrl == $url ) {
                $adminmenu->set_var( 'attr_class', $attr_class_current );
                $adminmenu->set_var( 'value_class', $value_class_current );
                $menu_item = $adminmenu->parse( 'item', 'current' );
            }
            else
            {
                $adminmenu->set_var( 'attr_class', '' );
                $adminmenu->set_var( 'value_class', '' );
                $menu_item = $adminmenu->parse( 'item', 'option' );
            }
            // Changed by Phize ---->

            $link_array[$LANG01[116]] = $menu_item;
        }

        if( SEC_hasRights( 'plugin.edit' ))
        {
            $url = $_CONF['site_admin_url'] . '/plugins.php';
            $adminmenu->set_var( 'option_url', $url );
            $adminmenu->set_var( 'option_label', $LANG01[77] );

            // Changed by Phize <----
            $adminmenu->set_var( 'option_count', '(' . COM_numberFormat( DB_count( $_TABLES['plugins'] )) . ')' );
            // Changed by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Changed by Phize <----
            if( $thisUrl == $url ) {
                $adminmenu->set_var( 'attr_class', $attr_class_current );
                $adminmenu->set_var( 'value_class', $value_class_current );
                $menu_item = $adminmenu->parse( 'item', 'current' );
            }
            else
            {
                $adminmenu->set_var( 'attr_class', '' );
                $adminmenu->set_var( 'value_class', '' );
                $menu_item = $adminmenu->parse( 'item', 'option' );
            }
            // Changed by Phize ---->

            $link_array[$LANG01[77]] = $menu_item;
        }

        // This will show the admin options for all installed plugins (if any)

        for( $i = 0; $i < $num_plugins; $i++ )
        {
            $plg = current( $plugin_options );

            $adminmenu->set_var( 'option_url', $plg->adminurl );
            $adminmenu->set_var( 'option_label', $plg->adminlabel );

            if( empty( $plg->numsubmissions ))
            {
                // Changed by Phize <----
                $adminmenu->set_var( 'option_count', '(N/A)' );
                // Changed by Phize ---->
            }
            else
            {
                // Changed by Phize <----
                $adminmenu->set_var( 'option_count', '(' . COM_numberFormat( $plg->numsubmissions ) . ')' );
                // Changed by Phize ---->
            }

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Changed by Phize <----
            if( $thisUrl == $plg->adminurl ) {
                $adminmenu->set_var( 'attr_class', $attr_class_current );
                $adminmenu->set_var( 'value_class', $value_class_current );
                $menu_item = $adminmenu->parse( 'item', 'current', true );
            }
            else
            {
                $adminmenu->set_var( 'attr_class', '' );
                $adminmenu->set_var( 'value_class', '' );
                $menu_item = $adminmenu->parse( 'item', 'option', true );
            }
            // Changed by Phize ---->

            $link_array[$plg->adminlabel] = $menu_item;

            next( $plugin_options );
        }

        if(( $_CONF['allow_mysqldump'] == 1 ) AND ( $_DB_dbms == 'mysql' ) AND
                SEC_inGroup( 'Root' ))
        {
            $url = $_CONF['site_admin_url'] . '/database.php';
            $adminmenu->set_var( 'option_url', $url );
            $adminmenu->set_var( 'option_label', $LANG01[103] );

            // Changed by Phize <----
            $adminmenu->set_var( 'option_count', '(N/A)' );
            // Changed by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Changed by Phize <----
            if( $thisUrl == $url ) {
                $adminmenu->set_var( 'attr_class', $attr_class_current );
                $adminmenu->set_var( 'value_class', $value_class_current );
                $menu_item = $adminmenu->parse( 'item', 'current' );
            }
            else
            {
                $adminmenu->set_var( 'attr_class', '' );
                $adminmenu->set_var( 'value_class', '' );
                $menu_item = $adminmenu->parse( 'item', 'option' );
            }
            // Changed by Phize ---->

            $link_array[$LANG01[103]] = $menu_item;
        }

        // Add PDF Generator Link if the feature is enabled
        if(( $_CONF['pdf_enabled'] == 1 ) AND SEC_inGroup( 'Root' ))
        {
            $url = $_CONF['site_url'] . '/pdfgenerator.php';
            $adminmenu->set_var( 'option_url', $url );
            $adminmenu->set_var( 'option_label', $LANG_PDF[9] );

            // Changed by Phize <----
            $adminmenu->set_var( 'option_count', '(N/A)' );
            // Changed by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Changed by Phize <----
            if( $thisUrl == $url ) {
                $adminmenu->set_var( 'attr_class', $attr_class_current );
                $adminmenu->set_var( 'value_class', $value_class_current );
                $menu_item = $adminmenu->parse( 'item', 'current' );
            }
            else
            {
                $adminmenu->set_var( 'attr_class', '' );
                $adminmenu->set_var( 'value_class', '' );
                $menu_item = $adminmenu->parse( 'item', 'option' );
            }
            // Changed by Phize ---->

            $link_array[$LANG_PDF[9]] = $menu_item;
        }

        if( $_CONF['link_documentation'] == 1 )
        {
            $adminmenu->set_var( 'option_url',
                                 $_CONF['site_url'] . '/docs/index.html' );
            $adminmenu->set_var( 'option_label', $LANG01[113] );

            // Changed by Phize <----
            $adminmenu->set_var( 'option_count', '(N/A)' );
            // Changed by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'attr_class', '' );
            $adminmenu->set_var( 'value_class', '' );
            // Added by Phize ---->

            $menu_item = $adminmenu->parse( 'item', 'option' );
            $link_array[$LANG01[113]] = $menu_item;
        }

        if( SEC_inGroup( 'Root' ))
        {
            $adminmenu->set_var( 'option_url',
               'http://www.geeklog.net/versionchecker.php?version=' . VERSION );
            $adminmenu->set_var( 'option_label', $LANG01[107] );

            // Changed by Phize <----
            $adminmenu->set_var( 'option_count', '(' . VERSION . ')' );
            // Changed by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
            $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
            $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
            $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
            $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
            $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
            // Added by Phize ---->

            // Added by Phize <----
            $adminmenu->set_var( 'attr_class', '' );
            $adminmenu->set_var( 'value_class', '' );
            // Added by Phize ---->

            $menu_item = $adminmenu->parse( 'item', 'option' );
            $link_array[$LANG01[107]] = $menu_item;
        }

        if( $_CONF['sort_admin'] )
        {
            uksort( $link_array, 'strcasecmp' );
        }

        $url = $_CONF['site_admin_url'] . '/moderation.php';
        $adminmenu->set_var( 'option_url', $url );
        $adminmenu->set_var( 'option_label', $LANG01[10] );

        // Changed by Phize <----
        $adminmenu->set_var( 'option_count', '(' . COM_numberFormat( $modnum ) . ')' );
        // Changed by Phize ---->

        // Added by Phize <----
        $adminmenu->set_var( 'if_admin', '<!-- if_admin -->' );
        $adminmenu->set_var( 'endif_admin', '<!-- endif_admin -->' );
        $adminmenu->set_var( 'if_topic', '<!-- if_topic -->' );
        $adminmenu->set_var( 'endif_topic', '<!-- endif_topic -->' );
        $adminmenu->set_var( 'if_user', '<!-- if_user -->' );
        $adminmenu->set_var( 'endif_user', '<!-- endif_user -->' );
        // Added by Phize ---->

        // Changed by Phize <----
        if( $thisUrl == $url ) {
            $adminmenu->set_var( 'attr_class', $attr_class_current );
            $adminmenu->set_var( 'value_class', $value_class_current );
            $menu_item = $adminmenu->parse( 'item', 'current' );
        }
        else
        {
            $adminmenu->set_var( 'attr_class', '' );
            $adminmenu->set_var( 'value_class', '' );
            $menu_item = $adminmenu->parse( 'item', 'option' );
        }
        // Changed by Phize ---->

        $link_array = array( $menu_item ) + $link_array;

        foreach( $link_array as $link )
        {
            $retval .= $link;
        }

        // Added by Phize <----
        $retval = $retval . "\n" . '</ul>' . "\n";
        // Added by Phize ---->

        $retval .= COM_endBlock( COM_getBlockTemplate( 'admin_block', 'footer' ));
    }

    // Added by Phize <----
    $retval = preg_replace('/<!-- if_admin -->(.*?)<!-- endif_admin -->/', '\1', $retval);
    $retval = preg_replace('/<!-- if_topic -->.*?<!-- endif_topic -->/', '', $retval);
    $retval = preg_replace('/<!-- if_user -->.*?<!-- endif_user -->/', '', $retval);
    // Added by Phize ---->

    return $retval;
}

/**
* Redirects user to a given URL
*
* This function COM_passes a meta tag to COM_refresh after a form is sent.  This is
* necessary because for some reason Nutscrape and PHP4 don't play well with
* the header() function COM_100% of the time.
*
* @param        string      $url        URL to send user to
*
*/

// this file can't be used on its own - redirect to index.php
function COM_refresh( $url )
{
    //@@@@@20070115update---->
    //return "<html><head><meta http-equiv=\"refresh\" content=\"0; URL=$url\"></head></html>\n";
    if( function_exists( 'CUSTOM_refresh' )) {
        return CUSTOM_refresh( $url );
    } else {
        return "<html><head><meta http-equiv=\"refresh\" content=\"0; URL=$url\"></head></html>\n";
    }
    //@@@@@20070115update<----
}
/**
 * DEPRECIATED -- see CMT_userComments in lib-comment.php
 */
function COM_userComments( $sid, $title, $type='article', $order='', $mode='', $pid = 0, $page = 1, $cid = false, $delete_option = false ) {
    global $_CONF;

    require_once $_CONF['path_system'] . 'lib-comment.php';
    return CMT_userComments( $sid, $title, $type, $order, $mode, $pid, $page, $cid, $delete_option );
}

/**
* This censors inappropriate content
*
* This will replace 'bad words' with something more appropriate
*
* @param        string      $Message        String to check
* @see function COM_checkHTML
* @return   string  Edited $Message
*
*/

function COM_checkWords( $Message )
{
    global $_CONF;

    $EditedMessage = $Message;

    if( $_CONF['censormode'] != 0 )
    {
        if( is_array( $_CONF['censorlist'] ))
        {
            $Replacement = $_CONF['censorreplace'];

            switch( $_CONF['censormode'])
            {
                case 1: # Exact match
                    $RegExPrefix = '(\s*)';
                    $RegExSuffix = '(\W*)';
                    break;

                case 2: # Word beginning
                    $RegExPrefix = '(\s*)';
                    $RegExSuffix = '(\w*)';
                    break;

                case 3: # Word fragment
                    $RegExPrefix   = '(\w*)';
                    $RegExSuffix   = '(\w*)';
                    break;
            }

            for( $i = 0; $i < count( $_CONF['censorlist']); $i++ )
            {
                $EditedMessage = MBYTE_eregi_replace( $RegExPrefix . $_CONF['censorlist'][$i] . $RegExSuffix, "\\1$Replacement\\2", $EditedMessage );
            }
        }
    }

    return $EditedMessage;
}

/**
*  Takes some amount of text and replaces all javascript events on*= with in
*
*  This script takes some amount of text and matches all javascript events, on*= (onBlur= onMouseClick=)
*  and replaces them with in*=
*  Essentially this will cause onBlur to become inBlur, onFocus to be inFocus
*  These are not valid javascript events and the browser will ignore them.
* @param    string  $Message    Text to filter
* @return   string  $Message with javascript filtered
* @see  COM_checkWords
* @see  COM_checkHTML
*
*/

function COM_killJS( $Message )
{
    return( preg_replace( '/(\s)+[oO][nN](\w*) ?=/', '\1in\2=', $Message ));
}

/**
* Handles the part within a [code] ... [/code] section, i.e. escapes all
* special characters.
*
* @param   string  $str  the code section to encode
* @return  string  $str with the special characters encoded
* @see     COM_checkHTML
*
*/
function COM_handleCode( $str )
{
    $search  = array( '&',     '\\',    '<',    '>',    '[',     ']'     );
    $replace = array( '&amp;', '&#92;', '&lt;', '&gt;', '&#91;', '&#93;' );

    $str = str_replace( $search, $replace, $str );

    return( $str );
}

/**
* This function checks html tags.
*
* Checks to see that the HTML tags are on the approved list and
* removes them if not.
*
* @param    string  $str            HTML to check
* @param    string  $permissions    comma-separated list of rights which identify the current user as an "Admin"
* @return   string                  Filtered HTML
*
*/
function COM_checkHTML( $str, $permissions = 'story.edit' )
{
    global $_CONF;

    // replace any \ with &#092; (HTML equiv)
    $str = str_replace('\\', '&#092;', COM_stripslashes($str) );

    // Get rid of any newline characters
    $str = preg_replace( "/\n/", '', $str );

    // Replace any $ with &#36; (HTML equiv)
    $str = str_replace( '$', '&#36;', $str );
    // handle [code] ... [/code]
    do
    {
        $start_pos = MBYTE_strpos( MBYTE_strtolower( $str ), '[code]' );
        if( $start_pos !== false )
        {
            $end_pos = MBYTE_strpos( MBYTE_strtolower( $str ), '[/code]' );
            if( $end_pos !== false )
            {
                $encoded = COM_handleCode( MBYTE_substr( $str, $start_pos + 6,
                        $end_pos - ( $start_pos + 6 )));
                $encoded = '<pre><code>' . $encoded . '</code></pre>';
                $str = MBYTE_substr( $str, 0, $start_pos ) . $encoded
                     . MBYTE_substr( $str, $end_pos + 7 );
            }
            else // missing [/code]
            {
                // Treat the rest of the text as code (so as not to lose any
                // special characters). However, the calling entity should
                // better be checking for missing [/code] before calling this
                // function ...
                $encoded = COM_handleCode( MBYTE_substr( $str, $start_pos + 6 ));
                $encoded = '<pre><code>' . $encoded . '</code></pre>';
                $str = MBYTE_substr( $str, 0, $start_pos ) . $encoded;
            }
        }
    }
    while( $start_pos !== false );

    if( isset( $_CONF['skip_html_filter_for_root'] ) &&
             ( $_CONF['skip_html_filter_for_root'] == 1 ) &&
            SEC_inGroup( 'Root' ))
    {
        return $str;
    }

    // strip_tags() gets confused by HTML comments ...
    $str = preg_replace( '/<!--.+?-->/', '', $str );

    $filter = new kses4;
    if( isset( $_CONF['allowed_protocols'] ) && is_array( $_CONF['allowed_protocols'] ) && ( sizeof( $_CONF['allowed_protocols'] ) > 0 ))
    {
        $filter->SetProtocols( $_CONF['allowed_protocols'] );
    }
    else
    {
        $filter->SetProtocols( array( 'http:', 'https:', 'ftp:' ));
    }

    if( empty( $permissions) || !SEC_hasRights( $permissions ) ||
            empty( $_CONF['admin_html'] ))
    {
        $html = $_CONF['user_html'];
    }
    else
    {
        $html = array_merge_recursive( $_CONF['user_html'],
                                       $_CONF['admin_html'] );
    }

    foreach( $html as $tag => $attr )
    {
        $filter->AddHTML( $tag, $attr );
    }

    return $filter->Parse( $str );
}

/**
* undo function for htmlspecialchars()
*
* This function translates HTML entities created by htmlspecialchars() back
* into their ASCII equivalents. Also handles the entities for $, {, and }.
*
* @param    string   $string   The string to convert.
* @return   string   The converted string.
*
*/
function COM_undoSpecialChars( $string )
{
    $string = str_replace( '&#36;',  '$', $string );
    $string = str_replace( '&#123;', '{', $string );
    $string = str_replace( '&#125;', '}', $string );
    $string = str_replace( '&gt;',   '>', $string );
    $string = str_replace( '&lt;',   '<', $string );
    $string = str_replace( '&quot;', '"', $string );
    $string = str_replace( '&nbsp;', ' ', $string );
    $string = str_replace( '&amp;',  '&', $string );

    return( $string );
}

/**
* Makes an ID based on current date/time
*
* This function creates a 17 digit sid for stories based on the 14 digit date
* and a 3 digit random number that was seeded with the number of microseconds
* (.000001th of a second) since the last full second.
* NOTE: this is now used for more than just stories!
*
* @return   string  $sid  Story ID
*
*/

function COM_makesid()
{
    $sid = date( 'YmdHis' );
    srand(( double ) microtime() * 1000000 );
    $sid .= rand( 0, 999 );

    return $sid;
}

/**
* Checks to see if email address is valid.
*
* This function checks to see if an email address is in the correct from.
*
* @param    string    $email   Email address to verify
* @return   boolean            True if valid otherwise false
*
*/
function COM_isEmail( $email )
{
    require_once( 'Mail/RFC822.php' );

    $rfc822 = new Mail_RFC822;

    return( $rfc822->isValidInetAddress( $email ) ? true : false );
}


/**
* Encode a string such that it can be used in an email header
*
* @param    string  $string     the text to be encoded
* @return   string              encoded text
*
*/
function COM_emailEscape( $string )
{
    global $_CONF, $LANG_CHARSET;

    if( empty( $LANG_CHARSET ))
    {
        $charset = $_CONF['default_charset'];
        if( empty( $charset ))
        {
            $charset = 'iso-8859-1';
        }
    }
    else
    {
        $charset = $LANG_CHARSET;
    }

    if(( $charset == 'utf-8' ) && ( $string != utf8_decode( $string )))
    {
        if( function_exists( 'iconv_mime_encode' ))
        {
            $mime_parameters = array( 'input-charset'  => 'utf-8',
                                      'output-charset' => 'utf-8',
                                      // 'Q' encoding is more readable than 'B'
                                      'scheme'         => 'Q'
                                    );
            $string = substr( iconv_mime_encode( '', $string,
                                                 $mime_parameters ), 2 );
        }
        else
        {
            $string = '=?' . $charset . '?B?' . base64_encode( $string ) . '?=';
        }
    }
    else if( preg_match( '/[^0-9a-z\-\.,:;\?! ]/i', $string ))
    {
        $string = '=?' . $charset . '?B?' . base64_encode( $string ) . '?=';
    }

    return $string;
}

/**
* Takes a name and an email address and returns a string that vaguely
* resembles an email address specification conforming to RFC(2)822 ...
*
* @param    string  $name       name, e.g. John Doe
* @param    string  $address    email address only, e.g. john.doe@example.com
* @return   string              formatted email address
*
*/
function COM_formatEmailAddress( $name, $address )
{
    $formatted_name = COM_emailEscape( $name );

    // if the name comes back unchanged, it's not UTF-8, so preg_match is fine
    if(( $formatted_name == $name ) && preg_match( '/[^0-9a-z ]/i', $name ))
    {
        $formatted_name = str_replace( '"', '\\"', $formatted_name );
        $formatted_name = '"' . $formatted_name . '"';
    }

    return $formatted_name . ' <' . $address . '>';
}

/**
* Send an email.
*
* All emails sent by Geeklog are sent through this function now.
*
* @param    string      $to         recipients name and email address
* @param    string      $subject    subject of the email
* @param    string      $message    the text of the email
* @param    string      $from       (optional) sender of the the email
* @param    boolean     $html       (optional) true if to be sent as HTML email
* @param    int         $priority   (optional) add X-Priority header, if > 0
* @param    string      $cc         (optional) other recipients (name + email)
* @return   boolean                 true if successful,  otherwise false
*
* @note Please note that using the $cc parameter will expose the email addresses
*       of all recipients. Use with care.
*
*/
function COM_mail( $to, $subject, $message, $from = '', $html = false, $priority = 0, $cc = '' )
{
    global $_CONF, $LANG_CHARSET;

    static $mailobj;

    //@@@@@20070312del---->
    //if( empty( $from ))
    //{
    //    $from = COM_formatEmailAddress( $_CONF['site_name'], $_CONF['site_mail']);
    //}
    //@@@@@20070312del<-----

    //@@@@@20051026,20070102 add kaigyo sisugiru ----->
    $message=str_replace("\r\n","\n",$message);
    //@@@@@20051026,20070102 add kaigyo sisugiru <-----

    $to = substr( $to, 0, strcspn( $to, "\r\n" ));
    $cc = substr( $cc, 0, strcspn( $cc, "\r\n" ));
    $from = substr( $from, 0, strcspn( $from, "\r\n" ));
    $subject = substr( $subject, 0, strcspn( $subject, "\r\n" ));
    //$subject = COM_emailEscape( $subject );//@@@@@20070301del

    if( function_exists( 'CUSTOM_mail' ))
    {
        return CUSTOM_mail( $to, $subject, $message, $from, $html, $priority, $cc );
    }

    //@@@@@20070312add---->
    if( empty( $from ))
    {
        $from = COM_formatEmailAddress( $_CONF['site_name'], $_CONF['site_mail']);
    }
    //@@@@@20070312add<-----

    $subject = COM_emailEscape( $subject );//@@@@@20070301addl

    include_once( 'Mail.php' );
    include_once( 'Mail/RFC822.php' );

    $method = $_CONF['mail_settings']['backend'];

    if( !isset( $mailobj ))
    {
        if(( $method == 'sendmail' ) || ( $method == 'smtp' ))
        {
            $mailobj =& Mail::factory( $method, $_CONF['mail_settings'] );
        }
        else
        {
            $method = 'mail';
            $mailobj =& Mail::factory( $method );
        }
    }

    if( empty( $LANG_CHARSET ))
    {
        $charset = $_CONF['default_charset'];
        if( empty( $charset ))
        {
            $charset = 'iso-8859-1';
        }
    }
    else
    {
        $charset = $LANG_CHARSET;
    }

    $headers = array();

    $headers['From'] = $from;
    if( $method != 'mail' )
    {
        $headers['To'] = $to;
    }
    if( !empty( $cc ))
    {
        $headers['Cc'] = $cc;
    }
    $headers['Date'] = date( 'r' ); // RFC822 formatted date
    if( $method == 'smtp' )
    {
        list( $usec, $sec ) = explode( ' ', microtime());
        $m = substr( $usec, 2, 5 );
        $headers['Message-Id'] = '<' .  date( 'YmdHis' ) . '.' . $m
                               . '@' . $_CONF['mail_settings']['host'] . '>';
    }
    if( $html )
    {
        $headers['Content-Type'] = 'text/html; charset=' . $charset;
        $headers['Content-Transfer-Encoding'] = '8bit';
    }
    else
    {
        $headers['Content-Type'] = 'text/plain; charset=' . $charset;
    }
    $headers['Subject'] = $subject;
    if( $priority > 0 )
    {
        $headers['X-Priority'] = $priority;
    }
    $headers['X-Mailer'] = 'GeekLog ' . VERSION;

    $retval = $mailobj->send( $to, $headers, $message );
    if( $retval !== true )
    {
        COM_errorLog( $retval->toString(), 1 );
    }

    return( $retval === true ? true : false );
}


/**
* Creates older stuff block
*
* Creates the olderstuff block for display.
* Actually updates the olderstuff record in the gl_blocks database.
* @return   void
*/

function COM_olderStuff()
{
    global $_TABLES, $_CONF;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_olderStuff';
    if( function_exists( $function ))
    {
        return $function();
    }
    // Added by Phize ---->

    $sql = "SELECT sid,tid,title,comments,UNIX_TIMESTAMP(date) AS day FROM {$_TABLES['stories']} WHERE (perm_anon = 2) AND (frontpage = 1) AND (date <= NOW()) AND (draft_flag = 0)" . COM_getTopicSQL( 'AND', 1 ) . " ORDER BY featured DESC, date DESC LIMIT {$_CONF['limitnews']}, {$_CONF['limitnews']}";
    $result = DB_query( $sql );
    $nrows = DB_numRows( $result );

    if( $nrows > 0 )
    {
        $dateonly = $_CONF['dateonly'];
        if( empty( $dateonly ))
        {
            $dateonly = '%d-%b'; // fallback: day - abbrev. month name
        }

        $day = 'noday';
        $string = '';

        for( $i = 0; $i < $nrows; $i++ )
        {
            $A = DB_fetchArray( $result );

            $daycheck = strftime( '%A', $A['day'] );
            if( $day != $daycheck )
            {
                if( $day != 'noday' )
                {
                    // Changed by Phize <----
                    $daylist = '<dd>' . COM_makeList( $oldnews, '' ) . '</dd>';
                    // Changed by Phize ---->

                    $daylist = preg_replace( "/(\015\012)|(\015)|(\012)/",
                                             '', $daylist );

                    // Changed by Phize <----
                    $string .= $daylist;
                    // Changed by Phize ---->
                }

                $day2 = strftime( $dateonly, $A['day'] );

                // Changed by Phize <----
                $string .= '<dt>' . $daycheck . $day2
                        . '</dt>' . LB;
                // Changed by Phize ---->

                $oldnews = array();
                $day = $daycheck;
            }

            $oldnews[] = '<a href="' . COM_buildUrl( $_CONF['site_url']
                . '/article.php?story=' . $A['sid'] ) . '">' . $A['title']
                . '</a> (' . COM_numberFormat( $A['comments'] ) . ')';
        }

        if( !empty( $oldnews ))
        {
            // Changed by Phize <----
            $daylist = '<dd>' . COM_makeList( $oldnews, '' ) . '</dd>';
            // Changed by Phize ---->

            $daylist = preg_replace( "/(\015\012)|(\015)|(\012)/", '', $daylist );
            $string .= $daylist;

            // Added by Phize <----
            $string = '<dl>' . $string . '</dl>';
            // Added by Phize ---->

            $string = addslashes( $string );

            DB_query( "UPDATE {$_TABLES['blocks']} SET content = '$string' WHERE name = 'older_stories'" );
        }
    }
}

/**
* Shows a single Geeklog block
*
* This shows a single block and is typically called from
* COM_showBlocks OR from plugin code
*
* @param        string      $name       Logical name of block (not same as title) -- 'user_block', 'admin_block', 'section_block', 'whats_new_block'.
* @param        string      $help       Help file location
* @param        string      $title      Title shown in block header
* @see function COM_showBlocks
* @return   string  HTML Formated block
*
*/

function COM_showBlock( $name, $help='', $title='' )
{
    global $_CONF, $topic, $_TABLES, $_USER;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_showBlock';
    if( function_exists( $function ))
    {
        return $function( $name, $help, $title );
    }
    // Added by Phize ---->

    $retval = '';

    if( !isset( $_USER['noboxes'] ))
    {
        if( !empty( $_USER['uid'] ))
        {
            $_USER['noboxes'] = DB_getItem( $_TABLES['userindex'], 'noboxes',
                                            "uid = {$_USER['uid']}" );
        }
        else
        {
            $_USER['noboxes'] = 0;
        }
    }

    switch( $name )
    {
        case 'user_block':
            $retval .= COM_userMenu( $help,$title );
            break;

        case 'admin_block':
            $retval .= COM_adminMenu( $help,$title );
            break;

        case 'section_block':
            $retval .= COM_startBlock( $title, $help,
                               COM_getBlockTemplate( $name, 'header' ))
                . COM_showTopics( $topic )
                . COM_endBlock( COM_getBlockTemplate( $name, 'footer' ));
            break;

        case 'whats_new_block':
            if( !$_USER['noboxes'] )
            {
                $retval .= COM_whatsNewBlock( $help, $title );
            }
            break;
    }

    return $retval;
}


/**
* Shows Geeklog blocks
*
* Returns HTML for blocks on a given side and, potentially, for
* a given topic. Currentlly only used by static pages.
*
* @param        string      $side       Side to get blocks for (right or left for now)
* @param        string      $topic      Only get blocks for this topic
* @param        string      $name       Block name (not used)
* @see function COM_showBlock
* @return   string  HTML Formated blocks
*
*/

function COM_showBlocks( $side, $topic='', $name='all' )
{
    global $_CONF, $_TABLES, $_USER, $LANG21, $topic, $page;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_showBlocks';
    if( function_exists( $function ))
    {
        return $function( $side, $topic, $name );
    }
    // Added by Phize ---->

    $retval = '';

    // Get user preferences on blocks
    if( !isset( $_USER['noboxes'] ) || !isset( $_USER['boxes'] ))
    {
        if( !empty( $_USER['uid'] ))
        {
            $result = DB_query( "SELECT boxes,noboxes FROM {$_TABLES['userindex']} "
                               ."WHERE uid = '{$_USER['uid']}'" );
            list($_USER['boxes'], $_USER['noboxes']) = DB_fetchArray( $result );
        }
        else
        {
            $_USER['boxes'] = '';
            $_USER['noboxes'] = 0;
        }
    }

    $sql = "SELECT *,UNIX_TIMESTAMP(rdfupdated) AS date "
         . "FROM {$_TABLES['blocks']} WHERE is_enabled = 1";

    if( $side == 'left' )
    {
        $sql .= " AND onleft = 1";
    }
    else
    {
        $sql .= " AND onleft = 0";
    }

    if( !empty( $topic ))
    {
        $sql .= " AND (tid = '$topic' OR tid = 'all')";
    }
    else
    {
        if( COM_onFrontpage() )
        {
            $sql .= " AND (tid = 'homeonly' OR tid = 'all')";
        }
        else
        {
            $sql .= " AND (tid = 'all')";
        }
    }

    if( !empty( $_USER['boxes'] ))
    {
        $BOXES = str_replace( ' ', ',', $_USER['boxes'] );

        $sql .= " AND (bid NOT IN ($BOXES) OR bid = '-1')";
    }

    $sql .= ' ORDER BY blockorder,title asc';

    $result = DB_query( $sql );
    $nrows = DB_numRows( $result );

    // convert result set to an array of associated arrays
    $blocks = array();
    for( $i = 0; $i < $nrows; $i++ )
    {
        $blocks[] = DB_fetchArray( $result );
    }

    // Check and see if any plugins have blocks to show
    $pluginBlocks = PLG_getBlocks( $side, $topic, $name );
    $blocks = array_merge( $blocks, $pluginBlocks );

    // sort the resulting array by block order
    $column = 'blockorder';
    $sortedBlocks = $blocks;
    for( $i = 0; $i < sizeof( $sortedBlocks ) - 1; $i++ )
    {
        for( $j = 0; $j < sizeof( $sortedBlocks ) - 1 - $i; $j++ )
        {
            if( $sortedBlocks[$j][$column] > $sortedBlocks[$j+1][$column] )
            {
                $tmp = $sortedBlocks[$j];
                $sortedBlocks[$j] = $sortedBlocks[$j + 1];
                $sortedBlocks[$j + 1] = $tmp;
            }
        }
    }
    $blocks = $sortedBlocks;

    // Loop though resulting sorted array and pass associative arrays
    // to COM_formatBlock
    foreach( $blocks as $A )
    {
        if( $A['type'] == 'dynamic' or SEC_hasAccess( $A['owner_id'], $A['group_id'], $A['perm_owner'], $A['perm_group'], $A['perm_members'], $A['perm_anon'] ) > 0 )
        {
           $retval .= COM_formatBlock( $A, $_USER['noboxes'] );
        }
    }

    return $retval;
}

/**
* Formats a Geeklog block
*
* This shows a single block and is typically called from
* COM_showBlocks OR from plugin code
*
* @param        array     $A          Block Record
* @param        bool      $noboxes    Set to true if userpref is no blocks
* @return       string    HTML Formated block
*
*/
function COM_formatBlock( $A, $noboxes = false )
{
    global $_CONF, $_TABLES, $_USER, $LANG21;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_formatBlock';
    if( function_exists( $function ))
    {
        return $function( $A, $noboxes );
    }
    // Added by Phize ---->

    $retval = '';
    if( $A['type'] == 'portal' )
    {
        if( COM_rdfCheck( $A['bid'], $A['rdfurl'], $A['date'], $A['rdflimit'] ))
        {
            $A['content'] = DB_getItem( $_TABLES['blocks'], 'content',
                                        "bid = '{$A['bid']}'");
        }
    }

    if( $A['type'] == 'gldefault' )
    {
        $retval .= COM_showBlock( $A['name'], $A['help'], $A['title'] );
    }

    if( $A['type'] == 'phpblock' && !$noboxes )
    {
        if( !( $A['name'] == 'whosonline_block' AND DB_getItem( $_TABLES['blocks'], 'is_enabled', "name='whosonline_block'" ) == 0 ))
        {
            $function = $A['phpblockfn'];
            $blkheader = COM_startBlock( $A['title'], $A['help'],
                    COM_getBlockTemplate( $A['name'], 'header' ));
            $blkfooter = COM_endBlock( COM_getBlockTemplate( $A['name'],
                    'footer' ));

            if( function_exists( $function ))
            {
                $fretval = $function();
                if( !empty( $fretval ))
                {
                    $retval .= $blkheader;
                    $retval .= $fretval;
                    $retval .= $blkfooter;
                }
            }
            else
            {
                // show error message
                $retval .= $blkheader;
                $retval .= sprintf( $LANG21[31], $function );
                $retval .= $blkfooter;
            }
        }
    }

    if( !empty( $A['content'] ) && ( trim( $A['content'] ) != '' ) && !$noboxes )
    {
        $blockcontent = stripslashes( $A['content'] );

        // Hack: If the block content starts with a '<' assume it
        // contains HTML and do not call nl2br() which would only add
        // unwanted <br> tags.

        if( substr( $blockcontent, 0, 1 ) != '<' )
        {
            $blockcontent = nl2br( $blockcontent );
        }

        if ($A['allow_autotags'] == 1) {
            $blockcontent = PLG_replaceTags( $blockcontent );
        }
        $blockcontent = str_replace( array( '<?', '?>' ), '', $blockcontent );

        $retval .= COM_startBlock( $A['title'], $A['help'],
                       COM_getBlockTemplate( $A['name'], 'header' ))
                . $blockcontent . LB
                . COM_endBlock( COM_getBlockTemplate( $A['name'], 'footer' ));
    }

    return $retval;
}


/**
* Checks to see if it's time to import and RDF/RSS block again
*
* Updates RDF/RSS block if needed
*
* @param    string  $bid            Block ID
* @param    string  $rdfurl         URL to get headlines from
* @param    string  $date           Last time the headlines were imported
* @param    string  $maxheadlines   max. number of headlines to import
* @return   void
* @see function COM_rdfImport
*
*/
function COM_rdfCheck( $bid, $rdfurl, $date, $maxheadlines = 0 )
{
    $retval = false;
    $nextupdate = $date + 3600;

    if( $nextupdate < time() )
    {
        COM_rdfImport( $bid, $rdfurl, $maxheadlines );
        $retval = true;
    }

    return $retval;
}

/**
* Syndication import function. Imports headline data to a portal block.
*
* Rewritten December 19th 2004 by Michael Jervis (mike@fuckingbrit.com). Now
* utilises a Factory Pattern to open a URL and automaticaly retreive a feed
* object populated with feed data. Then import it into the portal block.
*
* @param    string  $bid            Block ID
* @param    string  $rdfurl         URL to get content from
* @param    int     $maxheadlines   Maximum number of headlines to display
* @return   void
* @see function COM_rdfCheck
*
*/
function COM_rdfImport( $bid, $rdfurl, $maxheadlines = 0 )
{
    global $_CONF, $_TABLES, $LANG21, $LANG_CHARSET;

    // Import the feed handling classes:
    require_once( $_CONF['path_system']
                  . '/classes/syndication/parserfactory.class.php' );
    require_once( $_CONF['path_system']
                  . '/classes/syndication/feedparserbase.class.php' );

    // Load the actual feed handlers:
    $factory = new FeedParserFactory( $_CONF['path_system']
                                      . '/classes/syndication/' );
    $factory->userAgent = 'GeekLog/' . VERSION;
    //$feed = $factory->reader( $rdfurl, $_CONF['default_charset'] );
    $feed = $factory->reader( $rdfurl, $charset );

    // Aquire a reader:
    if( $feed )
    {
        /* We have located a reader, and populated it with the information from
         * the syndication file. Now we will sort out our display, and update
         * the block.
         */
        if( $maxheadlines == 0 )
        {
            if( !empty( $_CONF['syndication_max_headlines'] ))
            {
                $maxheadlines = $_CONF['syndication_max_headlines'];
            }
            else
            {
                $maxheadlines = count( $feed->articles );
            }
        }

        $update = date( 'Y-m-d H:i:s' );
        $result = DB_change( $_TABLES['blocks'], 'rdfupdated', $update,
                                                 'bid', $bid );

        if( empty( $LANG_CHARSET ))
        {
            $charset = $_CONF['default_charset'];
            if( empty( $charset ))
            {
                $charset = 'iso-8859-1';
            }
        }
        else
        {
            $charset = $LANG_CHARSET;
        }

        // format articles for display
        $readmax = min( $maxheadlines, count( $feed->articles ));
        for( $i = 0; $i < $readmax; $i++ )
        {
            if( empty( $feed->articles[$i]['title'] ))
            {
                $feed->articles[$i]['title'] = $LANG21[61];
            }

            //@@@@@update 20070118 mojibake----->
            //if( $charset == 'utf-8' )
            //{
            //    $title = $feed->articles[$i]['title'];
            //}
            //else
            //{
            //    $title = utf8_decode( $feed->articles[$i]['title'] );
            //}

            //if ( (PHP_VERSION >= 5) and ($charset == 'utf-8')) {
            //    $title = $feed->articles[$i]['title'];
            //} else {
                $title = mb_convert_encoding(
                    $feed->articles[$i]['title'], $charset,
                    mb_detect_encoding( $feed->articles[$i]['title'],
                    "UTF-8,EUC-JP,JIS,SJIS" ) ); 
            //}
            //@@@@@update 20070118 <-----

            $content = '<a href="' . $feed->articles[$i]['link'] . '">'
                     . $title . '</a>';
            $articles[] = $content;
        }

        // build a list
        $content = COM_makeList( $articles, 'list-feed' );
        $content = preg_replace( "/(\015\012)|(\015)|(\012)/", '', $content );

        // Standard theme based function to put it in the block
        $result = DB_change( $_TABLES['blocks'], 'content',
                             addslashes( $content ), 'bid', $bid );
    }
    else
    {
        // failed to aquire info, 0 out the block and log an error
        COM_errorLog( "Unable to aquire feed reader for $rdfurl", 1 );
        COM_errorLog( $factory->errorStatus[0] . ' ' .
                                    $factory->errorStatus[1] . ' ' .
                                    $factory->errorStatus[2] );
        $result = DB_change( $_TABLES['blocks'], 'content',
                             addslashes( $LANG21[4] ), 'bid', $bid );
    }
}


/**
* Returns what HTML is allowed in content
*
* Returns what HTML tags the system allows to be used inside content.
* You can modify this by changing $_CONF['user_html'] in config.php
* (for admins, see also $_CONF['admin_html']).
*
* @param    string  $permissions    comma-separated list of rights which identify the current user as an "Admin"
* @param    boolean $list_only      true = return only the list of HTML tags
* @return   string  HTML <span> enclosed string
* @see function COM_checkHTML
*/
function COM_allowedHTML( $permissions = 'story.edit', $list_only = false )
{
    global $_CONF, $LANG01;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_allowedHTML';
    if( function_exists( $function ))
    {
        return $function( $permissions, $list_only );
    }
    // Added by Phize ---->

    $retval = '';

    if( isset( $_CONF['skip_html_filter_for_root'] ) &&
             ( $_CONF['skip_html_filter_for_root'] == 1 ) &&
            SEC_inGroup( 'Root' ))
    {
        if( !$list_only )
        {
            $retval .= '<span class="warningsmall">' . $LANG01[123] . '</span>';
        }

        return $retval;
    }

    if( !$list_only )
    {
        $retval .= '<span class="warningsmall">' . $LANG01[31] . ' ';
    }

    $allow_page_break = false;
    if( empty( $permissions ) || !SEC_hasRights( $permissions ) ||
            empty( $_CONF['admin_html'] ))
    {
        $html = $_CONF['user_html'];
    }
    else
    {
        $html = array_merge_recursive( $_CONF['user_html'],
                                       $_CONF['admin_html'] );
        if( $_CONF['allow_page_breaks'] == 1 )
        {
            $perms = explode( ',', $permissions );
            foreach( $perms as $p )
            {
                if( substr( $p, 0, 6 ) == 'story.' )
                {
                    $allow_page_break = true;
                    break;
                }
            }
        }
    }

    foreach( $html as $tag => $attr )
    {
        $retval .= '&lt;' . $tag . '&gt;, ';
    }

    $retval .= '[code]';

    if( $allow_page_break )
    {
        $retval .= ', [page_break]';
    }

    // list autolink tags
    $autotags = PLG_collectTags();
    foreach( $autotags as $tag => $module )
    {
        $retval .= ', [' . $tag . ':]';
    }

    if( !$list_only )
    {
        $retval .= '</span>';
    }

    return $retval;
}

/**
* Return the password for the given username
*
* Fetches a password for the given user
*
* @param    string  $loginname  username to get password for
* @return   string              Password or ''
*
*/

function COM_getPassword( $loginname )
{
    global $_TABLES, $LANG01;

    $result = DB_query( "SELECT passwd FROM {$_TABLES['users']} WHERE username='$loginname'" );
    $tmp = DB_error();
    $nrows = DB_numRows( $result );

    if(( $tmp == 0 ) && ( $nrows == 1 ))
    {
        $U = DB_fetchArray( $result );
        return $U['passwd'];
    }
    else
    {
        $tmp = $LANG01[32] . ": '" . $loginname . "'";
        COM_errorLog( $tmp, 1 );
    }

    return '';
}


/**
* Return the username or fullname for the passed member id (uid)
*
* Allows the siteAdmin to determine if loginname (username) or fullname
* should be displayed.
*
* @param    int  $uid  site member id
* @param    string  $username   Username, if this is set no lookup is done.
* @param    string  $fullname   Users full name.
* @param    string  $service    Remote login service.
* @return   string  Username, fullname or username@Service
*
*/
function COM_getDisplayName( $uid = '', $username='', $fullname='', $remoteusername='', $remoteservice='' )
{
    global $_CONF, $_TABLES, $_USER;

    if ($uid == '')
    {
        if( empty( $_USER['uid'] ) || ( $_USER['uid'] <= 1 ))
        {
            $uid = 1;
        }
        else
        {
            $uid = $_USER['uid'];
        }
    }

    if( empty( $username ))
    {
        $query = DB_query( "SELECT username, fullname, remoteusername, remoteservice FROM {$_TABLES['users']} WHERE uid='$uid'" );
        list( $username, $fullname, $remoteusername, $remoteservice ) = DB_fetchArray( $query );
    }

    if( !empty( $fullname ) && ($_CONF['show_fullname'] == 1 ))
    {
        return $fullname;
    }
    else if( $_CONF['remoteauthentication'] && $_CONF['show_servicename'] &&
                    !empty( $remoteusername ))
    {
        return "$remoteusername@$remoteservice";
    }

    return $username;
}


/**
* Adds a hit to the system
*
* This function is called in the footer of every page and is used to
* track the number of hits to the Geeklog system.  This information is
* shown on stats.php
*
*/

function COM_hit()
{
    global $_TABLES;

    DB_query( "UPDATE {$_TABLES['vars']} SET value = value + 1 WHERE name = 'totalhits'" );
}

/**
* This will email new stories in the topics that the user is interested in
*
* In account information the user can specify which topics for which they
* will receive any new article for in a daily digest.
*
* @return   void
*/

function COM_emailUserTopics()
{
    global $_CONF, $_TABLES, $LANG08, $LANG24;

    $subject = strip_tags( $_CONF['site_name'] . $LANG08[30] . strftime( '%Y-%m-%d', time() ));

    $authors = array();

    // Get users who want stories emailed to them
    $usersql = "SELECT username,email,etids,{$_TABLES['users']}.uid AS uuid "
        . "FROM {$_TABLES['users']}, {$_TABLES['userindex']} "
        . "WHERE {$_TABLES['users']}.uid > 1 AND {$_TABLES['userindex']}.uid = {$_TABLES['users']}.uid AND (etids <> '-' OR etids IS NULL) ORDER BY {$_TABLES['users']}.uid";

    $users = DB_query( $usersql );
    $nrows = DB_numRows( $users );

    $lastrun = DB_getItem( $_TABLES['vars'], 'value', "name = 'lastemailedstories'" );

    // For each user, pull the stories they want and email it to them
    for( $x = 1; $x <= $nrows; $x++ )
    {
        $U = DB_fetchArray( $users );

        $storysql = array();
        $storysql['mysql'] = "SELECT sid,uid,date AS day,title,introtext,bodytext";

        $storysql['mssql'] = "SELECT sid,uid,date AS day,title,CAST(introtext AS text) AS introtext,CAST(bodytext AS text) AS introtext";

        $commonsql = " FROM {$_TABLES['stories']} WHERE draft_flag = 0 AND date <= NOW() AND date >= '{$lastrun}'";

        $topicsql = "SELECT tid FROM {$_TABLES['topics']}"
                  . COM_getPermSQL( 'WHERE', $U['uuid'] );
        $tresult = DB_query( $topicsql );
        $trows = DB_numRows( $tresult );

        if( $trows == 0 )
        {
            // this user doesn't seem to have access to any topics ...
            continue;
        }

        $TIDS = array();
        for( $i = 1; $i <= $trows; $i++ )
        {
            $T = DB_fetchArray( $tresult );
            $TIDS[] = $T['tid'];
        }

        if( !empty( $U['etids'] ))
        {
            $ETIDS = explode( ' ', $U['etids'] );
            $TIDS = array_intersect( $TIDS, $ETIDS );
        }

        if( sizeof( $TIDS ) > 0)
        {
            $commonsql .= " AND (tid IN ('" . implode( "','", $TIDS ) . "'))";
        }

        $commonsql .= COM_getPermSQL( 'AND', $U['uuid'] );
        $commonsql .= ' ORDER BY featured DESC, date DESC';

        $storysql['mysql'] .= $commonsql;
        $storysql['mssql'] .= $commonsql;

        $stories = DB_query( $storysql );
        $nsrows = DB_numRows( $stories );

        if( $nsrows == 0 )
        {
            // If no new stories where pulled for this user, continue with next
            continue;
        }

        $mailtext = $LANG08[29] . strftime( $_CONF['shortdate'], time() ) . "\n";

        for( $y = 0; $y < $nsrows; $y++ )
        {
            // Loop through stories building the requested email message
            $S = DB_fetchArray( $stories );

            $mailtext .= "\n------------------------------\n\n";
            $mailtext .= "$LANG08[31]: "
                . COM_undoSpecialChars( stripslashes( $S['title'] )) . "\n";
            if( $_CONF['contributedbyline'] == 1 )
            {
                if( empty( $authors[$S['uid']] ))
                {
                    $storyauthor = COM_getDisplayName ($S['uid']);
                    $authors[$S['uid']] = $storyauthor;
                }
                else
                {
                    $storyauthor = $authors[$S['uid']];
                }
                $mailtext .= "$LANG24[7]: " . $storyauthor . "\n";
            }

            $mailtext .= "$LANG08[32]: " . strftime( $_CONF['date'], strtotime( $S['day' ])) . "\n\n";

            if( $_CONF['emailstorieslength'] > 0 )
            {
                $storytext = COM_undoSpecialChars( strip_tags( PLG_replaceTags( stripslashes( $S['introtext'] ))));

                if( $_CONF['emailstorieslength'] > 1 )
                {
                    $storytext = COM_truncate( $storytext,
                                    $_CONF['emailstorieslength'], '...' );
                }

                $mailtext .= $storytext . "\n\n";
            }

            $mailtext .= $LANG08[33] . ' ' . COM_buildUrl( $_CONF['site_url']
                      . '/article.php?story=' . $S['sid'] ) . "\n";
        }

        $mailtext .= "\n------------------------------\n";
        $mailtext .= "\n$LANG08[34]\n";
        $mailtext .= "\n------------------------------\n";

        $mailto = $U['username'] . ' <' . $U['email'] . '>';

        COM_mail( $mailto, $subject, $mailtext );
    }

    DB_query( "UPDATE {$_TABLES['vars']} SET value = NOW() WHERE name = 'lastemailedstories'" );
}

/**
* Shows any new information in a block
*
* Return the HTML that shows any new stories, comments, etc
*
* @param    string  $help   Help file for block
* @param    string  $title  Title used in block header
* @return   string  Return the HTML that shows any new stories, comments, etc
*
*/

function COM_whatsNewBlock( $help = '', $title = '' )
{
    global $_CONF, $_TABLES, $_USER, $LANG01, $LANG_WHATSNEW, $page, $newstories;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_whatsNewBlock';
    if( function_exists( $function ))
    {
        return $function( $help, $title );
    }
    // Added by Phize ---->

    $retval = COM_startBlock( $title, $help,
                       COM_getBlockTemplate( 'whats_new_block', 'header' ));

    $topicsql = '';
    if(( $_CONF['hidenewstories'] == 0 ) || ( $_CONF['hidenewcomments'] == 0 )
            || ( $_CONF['trackback_enabled']
            && ( $_CONF['hidenewtrackbacks'] == 0 )))
    {
        $topicsql = COM_getTopicSql ('AND', 0, $_TABLES['stories']);
    }

    if( $_CONF['hidenewstories'] == 0 )
    {
        $archsql = '';
        $archivetid = DB_getItem( $_TABLES['topics'], 'tid', "archive_flag=1" );
        if( !empty( $archivetid ))
        {
            $archsql = " AND (tid <> '" . addslashes( $archivetid ) . "')";
        }

        // Find the newest stories
        $sql = "SELECT COUNT(*) AS count FROM {$_TABLES['stories']} WHERE (date >= (date_sub(NOW(), INTERVAL {$_CONF['newstoriesinterval']} SECOND))) AND (date <= NOW()) AND (draft_flag = 0)" . $archsql . COM_getPermSQL( 'AND' ) . $topicsql . COM_getLangSQL( 'sid', 'AND' );
        $result = DB_query( $sql );
        $A = DB_fetchArray( $result );
        $nrows = $A['count'];

        if( empty( $title ))
        {
            $title = DB_getItem( $_TABLES['blocks'], 'title', "name='whats_new_block'" );
        }

        // Any late breaking news stories?
        $retval .= '<h3>' . $LANG01[99] . '</h3>';

        if( $nrows > 0 )
        {
            $newmsg = COM_formatTimeString( $LANG_WHATSNEW['new_string'],
                        $_CONF['newstoriesinterval'], $LANG01[11], $nrows);

            if( $newstories && ( $page < 2 ))
            {
                $retval .= $newmsg . '<br>';
            }
            else
            {
                $retval .= '<a href="' . $_CONF['site_url']
                    . '/index.php?display=new">' . $newmsg . '</a><br>';
            }
        }
        else
        {
            $retval .= $LANG01[100] . '<br>';
        }

        if(( $_CONF['hidenewcomments'] == 0 ) || ( $_CONF['trackback_enabled']
                && ( $_CONF['hidenewtrackbacks'] == 0 ))
                || ( $_CONF['hidenewplugins'] == 0 ))
        {
            $retval .= '<br>';
        }
    }

    if( $_CONF['hidenewcomments'] == 0 )
    {
        // Go get the newest comments
        $retval .= '<h3>' . $LANG01[83] . ' <small>'
                . COM_formatTimeString( $LANG_WHATSNEW['new_last'],
                                        $_CONF['newcommentsinterval'] )
                . '</small></h3>';

        $stwhere = '';

        if( !empty( $_USER['uid'] ))
        {
            $stwhere .= "({$_TABLES['stories']}.owner_id IS NOT NULL AND {$_TABLES['stories']}.perm_owner IS NOT NULL) OR ";
            $stwhere .= "({$_TABLES['stories']}.group_id IS NOT NULL AND {$_TABLES['stories']}.perm_group IS NOT NULL) OR ";
            $stwhere .= "({$_TABLES['stories']}.perm_members IS NOT NULL)";
        }
        else
        {
            $stwhere .= "({$_TABLES['stories']}.perm_anon IS NOT NULL)";
        }
        $sql = "SELECT DISTINCT COUNT(*) AS dups, type, {$_TABLES['stories']}.title, {$_TABLES['stories']}.sid, max({$_TABLES['comments']}.date) AS lastdate FROM {$_TABLES['comments']} LEFT JOIN {$_TABLES['stories']} ON (({$_TABLES['stories']}.sid = {$_TABLES['comments']}.sid)" . COM_getPermSQL( 'AND', 0, 2, $_TABLES['stories'] ) . " AND ({$_TABLES['stories']}.draft_flag = 0) AND ({$_TABLES['stories']}.commentcode = 0)" . $topicsql . COM_getLangSQL( 'sid', 'AND', $_TABLES['stories'] ) . ") WHERE ({$_TABLES['comments']}.date >= (DATE_SUB(NOW(), INTERVAL {$_CONF['newcommentsinterval']} SECOND))) AND ((({$stwhere}))) GROUP BY {$_TABLES['comments']}.sid,type, {$_TABLES['stories']}.title, {$_TABLES['stories']}.title, {$_TABLES['stories']}.sid ORDER BY 5 DESC LIMIT 15";

        $result = DB_query( $sql );

        $nrows = DB_numRows( $result );

        if( $nrows > 0 )
        {
            $newcomments = array();

            for( $x = 0; $x < $nrows; $x++ )
            {
                $A = DB_fetchArray( $result );

                if(( $A['type'] == 'article' ) || empty( $A['type'] ))
                {
                    $urlstart = '<a href="' . COM_buildUrl( $_CONF['site_url']
                        . '/article.php?story=' . $A['sid'] ) . '#comments' . '"';
                }

                $title = COM_undoSpecialChars( stripslashes( $A['title'] ));
                $titletouse = COM_truncate( $title, $_CONF['title_trim_length'],
                                            '...' );

                if( $title != $titletouse )
                {
                    $urlstart .= ' title="' . htmlspecialchars( $title ) . '">';
                }
                else
                {
                    $urlstart .= '>';
                }

                $acomment = str_replace( '$', '&#36;', $titletouse );
                $acomment = str_replace( ' ', '&nbsp;', $acomment );

                if( $A['dups'] > 1 )
                {
                    $acomment .= ' [+' . $A['dups'] . ']';
                }

                $newcomments[] = $urlstart . $acomment . '</a>';
            }

            $retval .= COM_makeList( $newcomments, 'list-new-comments' );
        }
        else
        {
            $retval .= $LANG01[86] . '<br>' . LB;
        }
        if(( $_CONF['hidenewplugins'] == 0 )
                || ( $_CONF['trackback_enabled']
                && ( $_CONF['hidenewtrackbacks'] == 0 )))
        {
            $retval .= '<br>';
        }
    }

    if( $_CONF['trackback_enabled'] && ( $_CONF['hidenewtrackbacks'] == 0 ))
    {
        $retval .= '<h3>' . $LANG01[114] . ' <small>'
                . COM_formatTimeString( $LANG_WHATSNEW['new_last'],
                                        $_CONF['newtrackbackinterval'] )
                . '</small></h3>';

        $sql = "SELECT DISTINCT COUNT(*) AS count,{$_TABLES['stories']}.title,t.sid,max(t.date) AS lastdate FROM {$_TABLES['trackback']} AS t,{$_TABLES['stories']} WHERE (t.type = 'article') AND (t.sid = {$_TABLES['stories']}.sid) AND (t.date >= (DATE_SUB(NOW(), INTERVAL {$_CONF['newtrackbackinterval']} SECOND)))" . COM_getPermSQL( 'AND', 0, 2, $_TABLES['stories'] ) . " AND ({$_TABLES['stories']}.draft_flag = 0) AND ({$_TABLES['stories']}.trackbackcode = 0)" . $topicsql . COM_getLangSQL( 'sid', 'AND', $_TABLES['stories'] ) . " GROUP BY t.sid, {$_TABLES['stories']}.title ORDER BY lastdate DESC LIMIT 15";
        $result = DB_query( $sql );

        $nrows = DB_numRows( $result );
        if( $nrows > 0 )
        {
            $newcomments = array();

            for( $i = 0; $i < $nrows; $i++ )
            {
                $A = DB_fetchArray( $result );

                $urlstart = '<a href="' . COM_buildUrl( $_CONF['site_url']
                    . '/article.php?story=' . $A['sid'] ) . '#trackback' . '"';

                $title = COM_undoSpecialChars( stripslashes( $A['title'] ));
                $titletouse = COM_truncate( $title, $_CONF['title_trim_length'],
                                            '...' );

                if( $title != $titletouse )
                {
                    $urlstart .= ' title="' . htmlspecialchars( $title ) . '">';
                }
                else
                {
                    $urlstart .= '>';
                }

                $acomment = str_replace( '$', '&#36;', $titletouse );
                $acomment = str_replace( ' ', '&nbsp;', $acomment );

                if( $A['count'] > 1 )
                {
                    $acomment .= ' [+' . $A['count'] . ']';
                }

                $newcomments[] = $urlstart . $acomment . '</a>';
            }

            $retval .= COM_makeList( $newcomments, 'list-new-trackbacks' );
        }
        else
        {
            $retval .= $LANG01[115] . '<br>' . LB;
        }
        if( $_CONF['hidenewplugins'] == 0 )
        {
            $retval .= '<br>';
        }
    }

    if( $_CONF['hidenewplugins'] == 0 )
    {
        list( $headlines, $smallheadlines, $content ) = PLG_getWhatsNew();
        $plugins = sizeof( $headlines );
        if( $plugins > 0 )
        {
            for( $i = 0; $i < $plugins; $i++ )
            {
                $retval .= '<h3>' . $headlines[$i] . ' <small>'
                        . $smallheadlines[$i] . '</small></h3>';
                if( is_array( $content[$i] ))
                {
                    $retval .= COM_makeList( $content[$i], 'list-new-plugins' );
                }
                else
                {
                    $retval .= $content[$i];
                }

                if( $i + 1 < $plugins )
                {
                    $retval .= '<br>';
                }
            }
        }
    }

    $retval .= COM_endBlock( COM_getBlockTemplate( 'whats_new_block', 'footer' ));

    return $retval;
}

/**
* Creates the string that indicates the timespan in which new items were found
*
* @param    string  $time_string    template string
* @param    int     $time           number of seconds in which results are found
* @param    string  $type           type (translated string) of new item
* @param    int     $amount         amount of things that have been found.
*/
function COM_formatTimeString( $time_string, $time, $type = '', $amount = 0 )
{
    global $LANG_WHATSNEW;

    $retval = $time_string;

    // This is the amount you have to divide the previous by to get the
    // different time intervals: hour, day, week, months
    $time_divider = array( 60, 60, 24, 7, 30 );

    // These are the respective strings to the numbers above. They have to match
    // the strings in $LANG_WHATSNEW (i.e. these are the keys for the array -
    // the actual text strings are taken from the language file).
    $time_description  = array( 'minute',  'hour',  'day',  'week',  'month'  );
    $times_description = array( 'minutes', 'hours', 'days', 'weeks', 'months' );

    for( $s = 0; $s < count( $time_divider ); $s++ )
    {
        $time = $time / $time_divider[$s];
        if( $time < $time_divider[$s + 1] )
        {
            if( $time == 1 )
            {
                if( $s == 0 )
                {
                    $time_str = $time_description[$s];
                }
                else // go back to the previous unit, e.g. 1 day -> 24 hours
                {
                    $time_str = $times_description[$s - 1];
                    $time *= $time_divider[$s];
                }
            }
            else
            {
                $time_str = $times_description[$s];
            }
            $fields = array( '%n', '%i', '%t', '%s' );
            $values = array( $amount, $type, $time, $LANG_WHATSNEW[$time_str] );
            $retval = str_replace( $fields, $values, $retval );
            break;
        }
    }

    return $retval;
}


/**
* Displays a message on the webpage
*
* Pulls $msg off the URL string and gets the corresponding message and returns
* it for display on the calling page
*
* @param      int     $msg        ID of message to show
* @param      string  $plugin     Optional Name of plugin to lookup plugin defined message
* @return     string  HTML block with message
*/

function COM_showMessage( $msg, $plugin='' )
{
    global $_CONF, $MESSAGE, $_IMAGE_TYPE;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_showMessage';
    if( function_exists( $function ))
    {
        return $function( $msg, $plugin );
    }
    // Added by Phize ---->

    $retval = '';

    if( $msg > 0 )
    {
        if( !empty( $plugin ))
        {
            $var = 'PLG_' . $plugin . '_MESSAGE' . $msg;
            global $$var;
            if( isset( $$var ))
            {
                $message = $$var;
            }
            else
            {
                $message = sprintf( $MESSAGE[61], $plugin );
                COM_errorLog ($MESSAGE[61]. ": " . $var,1);
            }
        }
        else
        {
            $message = $MESSAGE[$msg];
        }

        $timestamp = strftime( $_CONF['daytime'] );
        $retval .= COM_startBlock( $MESSAGE[40] . ' - ' . $timestamp, '',
                           COM_getBlockTemplate( '_msg_block', 'header' ))

            // Changed by Phize <----
            . '<p>' . $message . '</p>'
            // Changed by Phize ---->

            . COM_endBlock( COM_getBlockTemplate( '_msg_block', 'footer' ));
    }

    return $retval;
}


/**
* Prints Google(tm)-like paging navigation
*
* @param        string      $base_url       base url to use for all generated links
* @param        int         $curpage        current page we are on
* @param        int         $num_pages      Total number of pages
* @param        string      $page_str       page-variable name AND '='
* @param        bool        $do_rewrite     if true, url-rewriting is respected
* @param        string      $msg            to be displayed with the navigation
* @param        string      $open_ended     replace next/last links with this
* @return   string   HTML formatted widget
*/
function COM_printPageNavigation( $base_url, $curpage, $num_pages,
                                  $page_str='page=', $do_rewrite=false, $msg='',
                                  $open_ended = '')
{
    global $LANG05;

    // Added by Phize <----
    global $_CONF;
    // Added by Phize ---->

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_printPageNavigation';
    if( function_exists( $function ))
    {
        return $function( $base_url, $curpage, $num_pages, $page_str, $do_rewrite, $msg, $open_ended );
    }
    // Added by Phize ---->

    // Added by Phize <----
    $value_class = 'navigation page navigation-page';
    $value_class_first = 'first';
    $value_class_last = 'last';
    // Added by Phize ---->

    $retval = '';

    if( $num_pages < 2 )
    {
        return;
    }

    if( !$do_rewrite )
    {
        $hasargs = strstr( $base_url, '?' );
        if( $hasargs )
        {
            $sep = '&amp;';
        }
        else
        {
            $sep = '?';
        }
    }
    else
    {
        $sep = '/';
        $page_str = '';
    }

    if( $curpage > 1 )
    {
        // Changed by Phize <----
        $retval .= '<li class="' . $value_class_first . '"><a href="' . $base_url . '">' . $LANG05[7] . '</a></li>';
        // Changed by Phize ---->

        $pg = '';
        if( ( $curpage - 1 ) > 1 )
        {
            $pg = $sep . $page_str . ( $curpage - 1 );
        }

        // Changed by Phize <----
        $retval .= '<li><a href="' . $base_url . $pg . '">' . $LANG05[6]
                . '</a></li>';
        // Changed by Phize ---->
    }
    else
    {
        // Changed by Phize <----
        $retval .= '<li class="' . $value_class_first . '">' . $LANG05[7] . '</li>' ;
        $retval .= '<li>' . $LANG05[6] . '</li>' ;
        // Changed by Phize ---->
    }

    for( $pgcount = ( $curpage - 10 ); ( $pgcount <= ( $curpage + 9 )) AND ( $pgcount <= $num_pages ); $pgcount++ )
    {
        if( $pgcount <= 0 )
        {
            $pgcount = 1;
        }

        if( $pgcount == $curpage )
        {
            // Changed by Phize <----
            $retval .= '<li class="current"><strong>' . $pgcount . '</strong></li>';
            // Changed by Phize ---->
        }
        else
        {
            $pg = '';
            if( $pgcount > 1 )
            {
                $pg = $sep . $page_str . $pgcount;
            }

            // Changed by Phize <----
            $retval .= '<li><a href="' . $base_url . $pg . '">' . $pgcount
                    . '</a></li>';
            // Changed by Phize ---->
        }
    }

    if( !empty( $open_ended ))
    {
        // Changed by Phize <----
        $retval .= '<li class="' . $value_class_last . '">' . $open_ended . '</li>';
        // Changed by Phize ---->
    }
    else if( $curpage == $num_pages )
    {
        // Changed by Phize <----
        $retval .= '<li>' . $LANG05[5] . '</li>';
        $retval .= '<li class="' . $value_class_last . '">' . $LANG05[8] . '</li>';
        // Changed by Phize ---->
    }
    else
    {
        // Changed by Phize <----
        $retval .= '<li><a href="' . $base_url . $sep . $page_str
                . ( $curpage + 1 ) . '">' . $LANG05[5] . '</a></li>';
        $retval .= '<li class="' . $value_class_last . '"><a href="' . $base_url . $sep . $page_str . $num_pages
                . '">' . $LANG05[8] . '</a></li>';
        // Changed by Phize ---->
    }

    if( !empty( $retval ))
    {
        if( !empty( $msg ))
        {
            $msg .=  ' ';
        }
        // Changed by Phize <----
        $retval = '<ul class="' . $value_class . '">' . $msg . $retval . '</ul>';
        // Changed by Phize ---->
    }

    return $retval;
}

/**
* Returns formatted date/time for user
*
* This function COM_takes a date in either unixtimestamp or in english and
* formats it to the users preference.  If the user didn't specify a format
* the format in the config file is used.  This returns an array where array[0]
* is the formatted date and array[1] is the unixtimestamp
*
* @param        string      $date       date to format, otherwise we format current date/time
* @return   array   array[0] is the formatted date and array[1] is the unixtimestamp.
*/

function COM_getUserDateTimeFormat( $date='' )
{
    global $_TABLES, $_USER, $_CONF;

    // Get display format for time

    if( !empty( $_USER['uid'] ) && ( $_USER['uid'] > 1 ))
    {
        if( empty( $_USER['format'] ))
        {
            $dateformat = $_CONF['date'];
        }
        else
        {
            $dateformat = $_USER['format'];
        }
    }
    else
    {
        $dateformat = $_CONF['date'];
    }

    if( empty( $date ))
    {
        // Date is empty, get current date/time
        $stamp = time();
    }
    else if( is_numeric( $date ))
    {
        // This is a timestamp
        $stamp = $date;
    }
    else
    {
        // This is a string representation of a date/time
        $stamp = strtotime( $date );
    }

    // Format the date

    $date = strftime( $dateformat, $stamp );

    return array( $date, $stamp );
}

/**
* Returns user-defined cookie timeout
*
* In account preferences users can specify when their long-term cookie expires.
* This function returns that value.
*
* @return   int Cookie time out value in seconds
*/

function COM_getUserCookieTimeout()
{
    global $_TABLES, $_USER, $_CONF;

    if( empty( $_USER ))
    {
        return;
    }

    $timeoutvalue = DB_getItem( $_TABLES['users'], 'cookietimeout', "uid = {$_USER['uid']}" );

    if( empty( $timeoutvalue ))
    {
        $timeoutvalue = 0;
    }

    return $timeoutvalue;
}

/**
* Shows who is online in slick little block
* @return   string  HTML string of online users seperated by line breaks.
*/

function phpblock_whosonline()
{
    global $_CONF, $_TABLES, $_USER, $LANG01, $_IMAGE_TYPE;

    // Added by Phize <----
    $value_class_photo = 'icon photo icon-photo';
    // Added by Phize ---->

    $retval = '';

    $expire_time = time() - $_CONF['whosonline_threshold'];

    $byname = 'username';
    if( $_CONF['show_fullname'] == 1 )
    {
        $byname .= ',fullname';
    }
    if( $_CONF['remoteauthentication'] )
    {
        $byname .= ',remoteusername,remoteservice';
    }

    $result = DB_query( "SELECT DISTINCT {$_TABLES['sessions']}.uid,{$byname},photo,showonline FROM {$_TABLES['sessions']},{$_TABLES['users']},{$_TABLES['userprefs']} WHERE {$_TABLES['users']}.uid = {$_TABLES['sessions']}.uid AND {$_TABLES['users']}.uid = {$_TABLES['userprefs']}.uid AND start_time >= $expire_time AND {$_TABLES['sessions']}.uid <> 1 ORDER BY {$byname}" );
    $nrows = DB_numRows( $result );

    $num_anon = 0;
    $num_reg  = 0;

    for( $i = 0; $i < $nrows; $i++ )
    {
        $A = DB_fetchArray( $result );

        if( $A['showonline'] == 1 )
        {
            $fullname = '';
            if( $_CONF['show_fullname'] == 1 )
            {
                $fullname = $A['fullname'];
            }
            if( $_CONF['remoteauthentication'] )
            {
                $username = COM_getDisplayName( $A['uid'], $A['username'],
                        $fullname, $A['remoteusername'], $A['remoteservice'] );
            }
            else
            {
                $username = COM_getDisplayName( $A['uid'], $A['username'],
                                                $fullname );
            }

            // Changed by Phize <----
            $retval .= '<li><a href="' . $_CONF['site_url']
                    . '/users.php?mode=profile&amp;uid=' . $A['uid'] . '">'
                    . $username . '</a>';
            // Changed by Phize ---->

            //$retval .= '<a href="' . $_CONF['site_url']
            //        . '/users.php?mode=profile&amp;uid=' . $A['uid'] . '">'
            //        . $username . '</a>';

            // Changed by Phize <----
            if( !empty( $A['photo'] ) AND $_CONF['allow_user_photo'] == 1)
            {
                // Added by Phize <----
                $img_camera = $_CONF['layout_url'] . '/images/smallcamera.' . $_IMAGE_TYPE;
                $img_size = getimagesize($img_camera);
                // Added by Phize ---->

                $retval .= '<a href="' . $_CONF['site_url']
                        . '/users.php?mode=profile&amp;uid=' . $A['uid']
                        . '"><img src="' . $img_camera
                        . '"' . $img_size[3] . '" alt="" class="' . $value_class_photo . '"></a>';
            }
            //$retval .= '<br>';
            // Changed by Phize ---->

            // Changed by Phize <----
            $retval .= '</li>';
            // Changed by Phize ---->

            $num_reg++;
        }
        else
        {
            // this user does not want to show up in Who's Online
            $num_anon++; // count as anonymous
        }
    }

    $result = DB_query( "SELECT DISTINCT uid,remote_ip FROM {$_TABLES['sessions']} WHERE uid = 1" );
    $num_anon += DB_numRows( $result );

    if(( $_CONF['whosonline_anonymous'] == 1 ) &&
            ( empty( $_USER['uid'] ) || ( $_USER['uid'] == 1 )))
    {
        // note that we're overwriting the contents of $retval here
        if( $num_reg > 0 )
        {
            // Changed by Phize <----
            $retval = '<li>' . $LANG01[112] . ': ' . $num_reg . '</li>';
            // Changed by Phize ---->
        }
        else
        {
            $retval = '';
        }
    }

    if( $num_anon > 0 )
    {
        // Changed by Phize <----
        $retval .= '<li>' . $LANG01[41] . ': ' . $num_anon . '</li>';
        // Changed by Phize ---->
    }

    // Added by Phize <----
    if( !empty( $retval ))
    {
        $retval = '<ul>' . $retval . '</ul>';
    }
    // Added by Phize ---->

    return $retval;
}

/**
* Gets the <option> values for calendar months
*
* @param        string      $selected       Selected month
* @see function COM_getDayFormOptions
* @see function COM_getYearFormOptions
* @see function COM_getHourFormOptions
* @see function COM_getMinuteFormOptions
* @return   string  HTML Months as option values
*/

function COM_getMonthFormOptions( $selected = '' )
{
    global $LANG_MONTH;

    // Added by Phize <----
    global $_CONF;
    // Added by Phize ---->

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_getMonthFormOptions';
    if( function_exists( $function ))
    {
        return $function( $selected );
    }
    // Added by Phize ---->

    $month_options = '';

    for( $i = 1; $i <= 12; $i++ )
    {
        $mval = $i;
        $month_options .= '<option value="' . $mval . '"';

        if( $i == $selected )
        {
            $month_options .= ' selected="selected"';
        }

        $month_options .= '>' . $LANG_MONTH[$mval] . '</option>';
    }

    return $month_options;
}

/**
* Gets the <option> values for calendar days
*
* @param        string      $selected       Selected day
* @see function COM_getMonthFormOptions
* @see function COM_getYearFormOptions
* @see function COM_getHourFormOptions
* @see function COM_getMinuteFormOptions
* @return string HTML days as option values
*/

function COM_getDayFormOptions( $selected = '' )
{
    // Added by Phize <----
    global $_CONF;
    // Added by Phize ---->

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_getDayFormOptions';
    if( function_exists( $function ))
    {
        return $function( $selected );
    }
    // Added by Phize ---->

    $day_options = '';

    for( $i = 1; $i <= 31; $i++ )
    {
        if( $i < 10 )
        {
            $dval = '0' . $i;
        }
        else
        {
            $dval = $i;
        }

        $day_options .= '<option value="' . $dval . '"';

        if( $i == $selected )
        {
            $day_options .= ' selected="selected"';
        }

        $day_options .= '>' . $dval . '</option>';
    }

    return $day_options;
}

/**
* Gets the <option> values for calendar years
*
* Returns Option list Containing 5 years starting with current
* unless @selected is < current year then starts with @selected
*
* @param        string      $selected       Selected year
* @see function COM_getMonthFormOptions
* @see function COM_getDayFormOptions
* @see function COM_getHourFormOptions
* @see function COM_getMinuteFormOptions
* @return string  HTML years as option values
*/

function COM_getYearFormOptions( $selected = '' )
{
    // Added by Phize <----
    global $_CONF;
    // Added by Phize ---->

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_getYearFormOptions';
    if( function_exists( $function ))
    {
        return $function( $selected );
    }
    // Added by Phize ---->

    $year_options = '';
    $cur_year = date( 'Y', time() );
    $start_year = $cur_year;

    if( !empty( $selected ))
    {
        if( $selected < $cur_year )
        {
            $start_year = $selected;
        }
    }

    for( $i = $start_year - 1; $i <= $cur_year + 5; $i++ )
    {
        $year_options .= '<option value="' . $i . '"';

        if( $i == $selected )
        {
            $year_options .= ' selected="selected"';
        }

        $year_options .= '>' . $i . '</option>';
    }

    return $year_options;
}

/**
* Gets the <option> values for clock hours
*
* @param    string  $selected   Selected hour
* @param    int     $mode       12 or 24 hour mode
* @return   string              HTML string of options
* @see function COM_getMonthFormOptions
* @see function COM_getDayFormOptions
* @see function COM_getYearFormOptions
* @see function COM_getMinuteFormOptions
*/

function COM_getHourFormOptions( $selected = '', $mode = 12 )
{
    // Added by Phize <----
    global $_CONF;
    // Added by Phize ---->

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_getHourFormOptions';
    if( function_exists( $function ))
    {
        return $function( $selected = '', $mode );
    }
    // Added by Phize ---->

    $hour_options = '';

    if( $mode == 12 )
    {
        for( $i = 1; $i <= 11; $i++ )
        {
            if( $i < 10 )
            {
                $hval = '0' . $i;
            }
            else
            {
                $hval = $i;
            }

            // Changed by Phize <----
            //if( $i == 1 )
            //{
            //    $hour_options .= '<option value="12"';

            //    if( $selected == 12 )
            //    {
            //        $hour_options .= ' selected="selected"';
            //    }

            //    $hour_options .= '>12</option>';
            //}
            // Changed by Phize ---->

            $hour_options .= '<option value="' . $hval . '"';

            if( $selected == $i )
            {
                $hour_options .= ' selected="selected"';
            }

            $hour_options .= '>' . $i . '</option>';

            // Added by Phize <----
            if( $i == 11 )
            {
                $hour_options .= '<option value="12"';

                if( $selected == 12 )
                {
                    $hour_options .= ' selected="selected"';
                }

                $hour_options .= '>12</option>';
            }
            // Added by Phize ---->
        }
    }
    else // if( $mode == 24 )
    {
        for( $i = 0; $i < 24; $i++ )
        {
            if( $i < 10 )
            {
                $hval = '0' . $i;
            }
            else
            {
                $hval = $i;
            }

            $hour_options .= '<option value="' . $hval . '"';

            if( $selected == $i )
            {
                $hour_options .= ' selected="selected"';
            }

            $hour_options .= '>' . $i . '</option>';
        }
    }

    return $hour_options;
}

/**
* Gets the <option> values for clock minutes
*
* @param    string      $selected   Selected minutes
* @param    integer     $step       number of minutes between options, e.g. 15
* @see function COM_getMonthFormOptions
* @see function COM_getDayFormOptions
* @see function COM_getHourFormOptions
* @see function COM_getYearFormOptions
* @return string  HTML of option minutes
*/

function COM_getMinuteFormOptions( $selected = '', $step = 1 )
{
    // Added by Phize <----
    global $_CONF;
    // Added by Phize ---->

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_getMinuteFormOptions';
    if( function_exists( $function ))
    {
        return $function( $selected, $step );
    }
    // Added by Phize ---->

    $minute_options = '';

    if(( $step < 1 ) || ( $step > 30 ))
    {
        $step = 1;
    }

    for( $i = 0; $i <= 59; $i += $step )
    {
        if( $i < 10 )
        {
            $mval = '0' . $i;
        }
        else
        {
            $mval = $i;
        }

        $minute_options .= '<option value="' . $mval . '"';

        if( $selected == $i )
        {
            $minute_options .= ' selected="selected"';
        }

        $minute_options .= '>' . $mval . '</option>';
    }

    return $minute_options;
}

/**
* for backward compatibility only
* - this function should always have been called COM_getMinuteFormOptions
*
*/
function COM_getMinuteOptions( $selected = '', $step = 1 )
{
    return COM_getMinuteFormOptions( $selected, $step );
}

/**
* Create an am/pm selector dropdown menu
*
* @param    string  $name       name of the <select>
* @param    string  $selected   preselection: 'am' or 'pm'
* @return   string  HTML for the dropdown; empty string in 24 hour mode
*
*/
function COM_getAmPmFormSelection( $name, $selected = '' )
{
    global $_CONF;

    // Added by Phize <----
    // If the theme implemented this for us then call their version instead.
    $function = $_CONF['theme'] . '_getAmPmFormSelection';
    if( function_exists( $function ))
    {
        return $function( $name, $selected );
    }
    // Added by Phize ---->

    $retval = '';

    if( isset( $_CONF['hour_mode'] ) && ( $_CONF['hour_mode'] == 24 ))
    {
        $retval = '';
    }
    else
    {
        if( empty( $selected ))
        {
            $selected = date( 'a' );
        }

        $retval .= '<select name="' . $name . '">' . LB;
        $retval .= '<option value="am"';
        if( $selected == 'am' )
        {
            $retval .= ' selected="selected"';
        }
        $retval .= '>am</option>' . LB . '<option value="pm"';
        if( $selected == 'pm' )
        {
            $retval .= ' selected="selected"';
        }
        $retval .= '>pm</option>' . LB . '</select>' . LB;
    }

    return $retval;
}

/**
* Creates an HTML unordered list from the given array.
* It formats one list item per array element, using the list.thtml
* and listitem.thtml templates.
*
* @param        array       $listofitems        Items to list out
* @return   string  HTML unordered list of array items
*/

function COM_makeList( $listofitems, $classname = '' )
{
    global $_CONF;

    $list = new Template( $_CONF['path_layout'] );
    $list->set_file( array( 'list'     => 'list.thtml',
                            'listitem' => 'listitem.thtml' ));
    $list->set_var( 'site_url', $_CONF['site_url'] );
    $list->set_var( 'layout_url', $_CONF['layout_url'] );
    if( empty( $classname ))
    {
        $list->set_var( 'list_class', '' );
        $list->set_var( 'list_class_name', '' );
    }
    else
    {
        $list->set_var( 'list_class', 'class="' . $classname . '"' );
        $list->set_var( 'list_class_name', $classname );
    }

    foreach( $listofitems as $oneitem )
    {
        $list->set_var( 'list_item', $oneitem );
        $list->parse( 'list_items', 'listitem', true );
    }

    $list->parse( 'newlist', 'list', true );

    return $list->finish( $list->get_var( 'newlist' ));
}

/**
* Check if speed limit applies for current IP address.
*
* @param type   string   type of speed limit to check, e.g. 'submit', 'comment'
* @param max    int      max number of allowed tries within speed limit
* @return       int      0 = does not apply, else: seconds since last post
*/
function COM_checkSpeedlimit( $type = 'submit', $max = 1 )
{
    global $_TABLES;

    $last = 0;

    $res  = DB_query( "SELECT date FROM {$_TABLES['speedlimit']} WHERE (type = '$type') AND (ipaddress = '{$_SERVER['REMOTE_ADDR']}') ORDER BY date ASC" );

    // If the number of allowed tries has not been reached,
    // return 0 (didn't hit limit)
    if( DB_numRows( $res ) < $max )
    {
        return $last;
    }

    list( $date ) = DB_fetchArray( $res );

    if( !empty( $date ))
    {
        $last = time() - $date;
        if( $last == 0 )
        {
            // just in case someone manages to submit something in < 1 sec.
            $last = 1;
        }
    }

    return $last;
}

/**
* Store post info for current IP address.
*
* @param type   string   type of speed limit, e.g. 'submit', 'comment'
*
*/
function COM_updateSpeedlimit( $type = 'submit' )
{
    global $_TABLES;

    DB_save( $_TABLES['speedlimit'], 'ipaddress,date,type',
             "'{$_SERVER['REMOTE_ADDR']}',unix_timestamp(),'$type'" );
}

/**
* Clear out expired speed limits, i.e. entries older than 'x' seconds
*
* @param speedlimit   int      number of seconds
* @param type         string   type of speed limit, e.g. 'submit', 'comment'
*
*/
function COM_clearSpeedlimit( $speedlimit = 60, $type = '' )
{
    global $_TABLES;

    $sql = "DELETE FROM {$_TABLES['speedlimit']} WHERE ";
    if( !empty( $type ))
    {
        $sql .= "(type = '$type') AND ";
    }
    $sql .= "(date < unix_timestamp() - $speedlimit)";
    DB_query( $sql );
}

/**
* Wrapper function for URL class so as to not confuse people as this will
* eventually get used all over the place
*
* This function returns a crawler friendly URL (if possible)
*
* @param        string      $url        URL to try to build crawler friendly URL for
* @return   string      Rewritten URL
*/

function COM_buildURL( $url )
{
    global $_URL;

    return $_URL->buildURL( $url );
}

/**
* Wrapper function for URL class so as to not confuse people
*
* This function sets the name of the arguments found in url
*
* @param    array   $names  Names of arguments in query string to assign to values
* @return   boolean         True if successful
*/

function COM_setArgNames( $names )
{
    global $_URL;

    return $_URL->setArgNames( $names );
}

/**
* Wrapper function for URL class
*
* returns value for specified argument
*
* @param        string      $name       argument to get value for
* @return   string     Argument value
*/

function COM_getArgument( $name )
{
    global $_URL;

    return $_URL->getArgument( $name );
}

/**
* Occurences / time
*
* This will take a number of occurrences, and number of seconds for the time span and return
* the smallest #/time interval
*
* @param    int     $occurrences        how many occurrences during time interval
* @param    int     $timespan           time interval in seconds
* @return   int Seconds per interval
*/

function COM_getRate( $occurrences, $timespan )
{
    // want to define some common time words (yes, dirk, i need to put this in LANG)
    // time words and their value in seconds
    // week is 7 * day, month is 30 * day, year is 365.25 * day

    $common_time = array(
        "second" => 1,
        "minute" => 60,
        "hour"   => 3600,
        "day"    => 86400,
        "week"   => 604800,
        "month"  => 2592000,
        "year"   => 31557600
        );

    if( $occurrences != 0 )
    {
        $rate = ( int )( $timespan / $occurrences );
        $adjustedRate = $occurrences + 1;
        $time_unit = 'second';

        $found_one = false;

        foreach( $common_time as $unit=>$seconds )
        {
            if( $rate > $seconds )
            {
                $foo = ( int )(( $rate / $seconds ) + .5 );

                if(( $foo < $occurrences ) && ( $foo > 0 ))
                {
                    $adjustedRate = $foo;
                    $time_unit = $unit;
                }
            }
        }

        $singular = '1 shout every ' . $adjustedRate . ' ' . $time_unit;

        if( $adjustedRate > 1 )
        {
            $singular .= 's';
        }
    }
    else
    {
        $singular = 'No events';
    }

    return $singular;
}

/**
* Return SQL expression to check for permissions.
*
* Creates part of an SQL expression that can be used to request items with the
* standard set of Geeklog permissions.
*
* @param        string      $type     part of the SQL expr. e.g. 'WHERE', 'AND'
* @param        int         $u_id     user id or 0 = current user
* @param        int         $access   access to check for (2=read, 3=r&write)
* @param        string      $table    table name if ambiguous (e.g. in JOINs)
* @return       string      SQL expression string (may be empty)
*
*/
function COM_getPermSQL( $type = 'WHERE', $u_id = 0, $access = 2, $table = '' )
{
    global $_USER, $_GROUPS;

    if( !empty( $table ))
    {
        $table .= '.';
    }
    if( $u_id <= 0)
    {
        if( empty( $_USER['uid'] ))
        {
            $uid = 1;
        }
        else
        {
            $uid = $_USER['uid'];
        }
    }
    else
    {
        $uid = $u_id;
    }

    $UserGroups = array();
    if(( empty( $_USER['uid'] ) && ( $uid == 1 )) || ( $uid == $_USER['uid'] ))
    {
        if( empty( $_GROUPS ))
        {
            $_GROUPS = SEC_getUserGroups( $uid );
        }
        $UserGroups = $_GROUPS;
    }
    else
    {
        $UserGroups = SEC_getUserGroups( $uid );
    }

    if( empty( $UserGroups ))
    {
        // this shouldn't really happen, but if it does, handle user
        // like an anonymous user
        $uid = 1;
    }

    if( SEC_inGroup( 'Root', $uid ))
    {
        return '';
    }

    $sql = ' ' . $type . ' (';

    if( $uid > 1 )
    {
        $sql .= "(({$table}owner_id = '{$uid}') AND ({$table}perm_owner >= $access)) OR ";

        $sql .= "(({$table}group_id IN (" . implode( ',', $UserGroups )
             . ")) AND ({$table}perm_group >= $access)) OR ";
        $sql .= "({$table}perm_members >= $access)";
    }
    else
    {
        $sql .= "{$table}perm_anon >= $access";
    }

    $sql .= ')';

    return $sql;
}

/**
* Return SQL expression to check for allowed topics.
*
* Creates part of an SQL expression that can be used to only request stories
* from topics to which the user has access to.
*
* Note that this function does an SQL request, so you should cache
* the resulting SQL expression if you need it more than once.
*
* @param    string  $type   part of the SQL expr. e.g. 'WHERE', 'AND'
* @param    int     $u_id   user id or 0 = current user
* @param    string  $table  table name if ambiguous (e.g. in JOINs)
* @return   string          SQL expression string (may be empty)
*
*/
function COM_getTopicSQL( $type = 'WHERE', $u_id = 0, $table = '' )
{
    global $_TABLES, $_USER, $_GROUPS;

    $topicsql = ' ' . $type . ' ';

    if( !empty( $table ))
    {
        $table .= '.';
    }

    $UserGroups = array();
    if(( $u_id <= 0 ) || ( $u_id == $_USER['uid'] ))
    {
        if( isset( $_USER['uid'] ))
        {
            $uid = $_USER['uid'];
        }
        else
        {
            $uid = 1;
        }
        $UserGroups = $_GROUPS;
    }
    else
    {
        $uid = $u_id;
        $UserGroups = SEC_getUserGroups( $uid );
    }

    if( empty( $UserGroups ))
    {
        // this shouldn't really happen, but if it does, handle user
        // like an anonymous user
        $uid = 1;
    }

    if( SEC_inGroup( 'Root', $uid ))
    {
        return '';
    }

    $result = DB_query( "SELECT tid FROM {$_TABLES['topics']}"
                        . COM_getPermSQL( 'WHERE', $uid ));
    $tids = array();
    while( $T = DB_fetchArray( $result ))
    {
        $tids[] = $T['tid'];
    }

    if( sizeof( $tids ) > 0 )
    {
        $topicsql .= "({$table}tid IN ('" . implode( "','", $tids ) . "'))";
    }
    else
    {
        $topicsql .= '0';
    }

    return $topicsql;
}

/**
* Strip slashes from a string only when magic_quotes_gpc = on.
*
* @param   string  $text  The text
* @return  string  The text, possibly without slashes.
*/
function COM_stripslashes( $text )
{
    if( get_magic_quotes_gpc() == 1 )
    {
        return( stripslashes( $text ));
    }

    return( $text );
}

/**
* Filter parameters passed per GET (URL) or POST.
*
* @param    string    $parameter   the parameter to test
* @param    boolean   $isnumeric   true if $parameter is supposed to be numeric
* @return   string    the filtered parameter (may now be empty or 0)
*
*/
function COM_applyFilter( $parameter, $isnumeric = false )
{
    $log_manipulation = false; // set to true to log when the filter applied

    $p = COM_stripslashes( $parameter );
    $p = strip_tags( $p );
    $p = COM_killJS( $p ); // doesn't help a lot right now, but still ...

    if( $isnumeric )
    {
        // Note: PHP's is_numeric() accepts values like 4e4 as numeric
        if( !is_numeric( $p ) || ( preg_match( '/^-?\d+$/', $p ) == 0 ))
        {
            $p = 0;
        }
    }
    else
    {
        $p = preg_replace( '/\/\*.*/', '', $p );
        $pa = explode( "'", $p );
        $pa = explode( '"', $pa[0] );
        $pa = explode( '`', $pa[0] );
        $pa = explode( ';', $pa[0] );
        $pa = explode( ',', $pa[0] );
        $pa = explode( '\\', $pa[0] );
        $p = $pa[0];
    }

    if( $log_manipulation )
    {
        if( strcmp( $p, $parameter ) != 0 )
        {
            COM_errorLog( "Filter applied: >> $parameter << filtered to $p [IP {$_SERVER['REMOTE_ADDR']}]", 1);
        }
    }

    return $p;
}

/**
* Sanitize a URL
*
* @param    string  $url                URL to sanitized
* @param    array   $allowed_protocols  array of allowed protocols
* @param    string  $default_protocol   replacement protocol (default: http)
* @return   string                      sanitized URL
*
*/
function COM_sanitizeUrl( $url, $allowed_protocols = '', $default_protocol = '' )
{
    global $_CONF;

    if( empty( $allowed_protocols ))
    {
        $allowed_protocols = $_CONF['allowed_protocols'];
    }
    else if( !is_array( $allowed_protocols ))
    {
        $allowed_protocols = array( $allowed_protocols );
    }

    if( empty( $default_protocol ))
    {
        $default_protocol = 'http:';
    }
    else if( substr( $default_protocol, -1 ) != ':' )
    {
        $default_protocol .= ':';
    }

    $url = strip_tags( $url );
    if( !empty( $url ))
    {
        $pos = MBYTE_strpos( $url, ':' );
        if( $pos === false )
        {
            $url = $default_protocol . '//' . $url;
        }
        else
        {
            $protocol = MBYTE_substr( $url, 0, $pos + 1 );
            $found_it = false;
            foreach( $allowed_protocols as $allowed )
            {
                if( substr( $allowed, -1 ) != ':' )
                {
                    $allowed .= ':';
                }
                if( $protocol == $allowed )
                {
                    $found_it = true;
                    break;
                }
            }
            if( !$found_it )
            {
                $url = $default_protocol . MBYTE_substr( $url, $pos + 1 );
            }
        }
    }

    return $url;
}

/**
* Detect links in a plain-ascii text and turn them into clickable links.
* Will detect links starting with "http:", "https:", "ftp:", and "www.".
*
* Derived from a newsgroup posting by Andreas Schwarz in
* news:de.comp.lang.php <aieq4p$12jn2i$3@ID-16486.news.dfncis.de>
*
* @param    string    $text     the (plain-ascii) text string
* @return   string    the same string, with links enclosed in <a>...</a> tags
*
*/
function COM_makeClickableLinks( $text )
{
    $text = preg_replace( '/([^"]?)((((ht|f)tps?):(\/\/)|www\.)[a-z0-9%&_\-\+,;=:@~#\/.\?\[\]]+(\/|[+0-9a-z]))/is', '\\1<a href="\\2">\\2</a>', $text );
    $text = str_replace( '<a href="www', '<a href="http://www', $text );

    return $text;
}

/**
* Undo the conversion of URLs to clickable links (in plain text posts),
* e.g. so that we can present the user with the post as they entered them.
*
* @param    string  $txt    story text
* @param    string          story text without links
*
*/
function COM_undoClickableLinks( $text )
{
    $text = preg_replace( '/<a href="[^"]*">([^<]*)<\/a>/', '\1', $text );

    return $text;
}

/**
* Highlight the words from a search query in a given text string.
*
* @param    string  $text   the text
* @param    string  $query  the search query
* @return   string          the text with highlighted search words
*
*/
function COM_highlightQuery( $text, $query )
{
    $query = str_replace( '+', ' ', $query );

    // escape all the other PCRE special characters
    $query = preg_quote( $query );

    // ugly workaround:
    // Using the /e modifier in preg_replace will cause all double quotes to
    // be returned as \" - so we replace all \" in the result with unescaped
    // double quotes. Any actual \" in the original text therefore have to be
    // turned into \\" first ...
    $text = str_replace( '\\"', '\\\\"', $text );

    $mywords = explode( ' ', $query );
    foreach( $mywords as $searchword )
    {
        if( !empty( $searchword ))
        {
            $searchword = preg_quote( str_replace( "'", "\'", $searchword ));
            $text = preg_replace( '/(\>(((?>[^><]+)|(?R))*)\<)/ie', "preg_replace('/(?>$searchword+)/i','<span class=\"highlight\">$searchword</span>','\\0')", '<!-- x -->' . $text . '<!-- x -->' );
        }
    }

    // ugly workaround, part 2
    $text = str_replace( '\\"', '"', $text );

    return $text;
}

/**
* Determines the difference between two dates.
*
* This will takes either unixtimestamps or English dates as input and will
* automatically do the date diff on the more recent of the two dates (e.g. the
* order of the two dates given doesn't matter).
*
* @author Tony Bibbs <tony.bibbs@iowa.gov
* @access public
* @param string $interval Can be:
* y = year
* m = month
* w = week
* h = hours
* i = minutes
* s = seconds
* @param string|int $date1 English date (e.g. 10 Dec 2004) or unixtimestamp
* @param string|int $date2 English date (e.g. 10 Dec 2004) or unixtimestamp
* @return int Difference of the two dates in the unit of time indicated by the interval
*
*/
function COM_dateDiff( $interval, $date1, $date2 )
{
    // Convert dates to timestamps, if needed.
    if( !is_numeric( $date1 ))
    {
        $date1 = strtotime( $date1 );
    }

    if( !is_numeric( $date2 ))
    {
        $date2 = strtotime( $date2 );
    }

    // Function roughly equivalent to the ASP "DateDiff" function
    if( $date2 > $date1 )
    {
        $seconds = $date2 - $date1;
    }
    else
    {
        $seconds = $date1 - $date2;
    }

    switch( $interval )
    {
        case "y":
            list($year1, $month1, $day1) = split('-', date('Y-m-d', $date1));
            list($year2, $month2, $day2) = split('-', date('Y-m-d', $date2));
            $time1 = (date('H',$date1)*3600) + (date('i',$date1)*60) + (date('s',$date1));
            $time2 = (date('H',$date2)*3600) + (date('i',$date2)*60) + (date('s',$date2));
            $diff = $year2 - $year1;
            if($month1 > $month2) {
                $diff -= 1;
            } elseif($month1 == $month2) {
                if($day1 > $day2) {
                    $diff -= 1;
                } elseif($day1 == $day2) {
                    if($time1 > $time2) {
                        $diff -= 1;
                    }
                }
            }
            break;
        case "m":
            list($year1, $month1, $day1) = split('-', date('Y-m-d', $date1));
            list($year2, $month2, $day2) = split('-', date('Y-m-d', $date2));
            $time1 = (date('H',$date1)*3600) + (date('i',$date1)*60) + (date('s',$date1));
            $time2 = (date('H',$date2)*3600) + (date('i',$date2)*60) + (date('s',$date2));
            $diff = ($year2 * 12 + $month2) - ($year1 * 12 + $month1);
            if($day1 > $day2) {
                $diff -= 1;
            } elseif($day1 == $day2) {
                if($time1 > $time2) {
                    $diff -= 1;
                }
            }
            break;
        case "w":
            // Only simple seconds calculation needed from here on
            $diff = floor($seconds / 604800);
            break;
         case "d":
            $diff = floor($seconds / 86400);
            break;
        case "h":
            $diff = floor($seconds / 3600);
            break;
        case "i":
            $diff = floor($seconds / 60);
            break;
        case "s":
            $diff = $seconds;
            break;
    }

    return $diff;
}

/**
* Try to figure out our current URL, including all parameters.
*
* This is an ugly hack since there's no single variable that returns what
* we want and the variables used here may not be available on all servers
* and / or setups.
*
* Seems to work on Apache (1.3.x and 2.x), IIS, and Zeus ...
*
* @return   string  complete URL, e.g. 'http://www.example.com/blah.php?foo=bar'
*
*/
function COM_getCurrentURL()
{
    global $_CONF;

    $thisUrl = '';

    if( empty( $_SERVER['SCRIPT_URI'] ))
    {
        if( !empty( $_SERVER['DOCUMENT_URI'] ))
        {
            $thisUrl = $_SERVER['DOCUMENT_URI'];
        }
    }
    else
    {
        $thisUrl = $_SERVER['SCRIPT_URI'];
    }
    if( !empty( $thisUrl ) && !empty( $_SERVER['QUERY_STRING'] ))
    {
        $thisUrl .= '?' . $_SERVER['QUERY_STRING'];
    }
    if( empty( $thisUrl ))
    {
        $requestUri = $_SERVER['REQUEST_URI'];
        if( empty( $_SERVER['REQUEST_URI'] ))
        {
            // on a Zeus webserver, prefer PATH_INFO over SCRIPT_NAME
            if( empty( $_SERVER['PATH_INFO'] ))
            {
                $requestUri = $_SERVER['SCRIPT_NAME'];
            }
            else
            {
                $requestUri = $_SERVER['PATH_INFO'];
            }
            if( !empty( $_SERVER['QUERY_STRING'] ))
            {
                $requestUri .= '?' . $_SERVER['QUERY_STRING'];
            }
        }

        $firstslash = strpos( $_CONF['site_url'], '/' );
        if( $firstslash === false )
        {
            // special case - assume it's okay
            $thisUrl = $_CONF['site_url'] . $requestUri;
        }
        else if( $firstslash + 1 == strrpos( $_CONF['site_url'], '/' ))
        {
            // site is in the document root
            $thisUrl = $_CONF['site_url'] . $requestUri;
        }
        else
        {
            // extract server name first
            $pos = strpos( $_CONF['site_url'], '/', $firstslash + 2 );
            $thisUrl = substr( $_CONF['site_url'], 0, $pos ) . $requestUri;
        }
    }

    return $thisUrl;
}

/**
* Check if we're on Geeklog's index page.
*
* See if we're on the main index page (first page, no topics selected).
*
* @return   bool    true = we're on the frontpage, false = we're not
*
*/
function COM_onFrontpage()
{
    global $_CONF, $topic, $page, $newstories;

    // Note: We can't use $PHP_SELF here since the site may not be in the
    // DocumentRoot
    $onFrontpage = false;

    // on a Zeus webserver, prefer PATH_INFO over SCRIPT_NAME
    if( empty( $_SERVER['PATH_INFO'] ))
    {
        $scriptName = $_SERVER['SCRIPT_NAME'];
    }
    else
    {
        $scriptName = $_SERVER['PATH_INFO'];
    }

    preg_match( '/\/\/[^\/]*(.*)/', $_CONF['site_url'], $pathonly );
    if(( $scriptName == $pathonly[1] . '/index.php' ) &&
            empty( $topic ) && ( $page == 1 ) && !$newstories )
    {
        $onFrontpage = true;
    }

    return $onFrontpage;
}

/**
* Check if we're on Geeklog's index page [deprecated]
*
* Note that this function returns FALSE when we're on the index page. Due to
* the inverted return values, it has been deprecated and is only provided for
* backward compatibility - use COM_onFrontpage() instead.
*
* @see COM_onFrontpage
*
*/
function COM_isFrontpage()
{
    return !COM_onFrontpage();
}

/**
* Ensure an ID contains only alphanumeric characters, dots, dashes, or underscores
*
* @param    string  $id     the ID to sanitize
* @param    boolean $new_id true = create a new ID in case we end up with an empty string
* @return   string          the sanitized ID
*/
function COM_sanitizeID( $id, $new_id = true )
{
    $id = str_replace( ' ', '', $id );
    $id = str_replace( array( '/', '\\', ':', '+' ), '-', $id );
    $id = preg_replace( '/[^a-zA-Z0-9\-_\.]/', '', $id );
    if( empty( $id ) && $new_id )
    {
        $id = COM_makesid();
    }

    return $id;
}

/** Converts a number for output into a formatted number with thousands-
*         separator, comma-separator and fixed decimals if necessary
*
*        @param        float        $number        Number that will be formatted
*        @return        string                        formatted number
*/
function COM_numberFormat( $number )
{
    global $_CONF;

    if( $number - abs( $number ) > 0 ) // number has decimals
    {
        $dc = $_CONF['decimal_count'];
    }
    else
    {
        $dc = 0;
    }
    $ts = $_CONF['thousand_separator'];
    $ds = $_CONF['decimal_separator'];

    return number_format( $number, $dc, $ds, $ts );
}

/**
* Convert a text based date YYYY-MM-DD to a unix timestamp integer value
*
* @param    string  $date   Date in the format YYYY-MM-DD
* @param    string  $time   Option time in the format HH:MM::SS
* @return   int             UNIX Timestamp
*/
function COM_convertDate2Timestamp( $date, $time = '' )
{
    $atoks = array();
    $btoks = array();

    // Breakup the string using either a space, fwd slash, dash, bkwd slash or
    // colon as a delimiter
    $atok = strtok( $date, ' /-\\:' );
    while( $atok !== FALSE )
    {
        $atoks[] = $atok;
        $atok = strtok( ' /-\\:' );  // get the next token
    }

    for( $i = 0; $i < 3; $i++ )
    {
        if( !isset( $atoks[$i] ) || !is_numeric( $atoks[$i] ))
        {
            $atoks[$i] = 0;
        }
    }

    if( $time == '' )
    {
        $timestamp = mktime( 0, 0, 0, $atoks[1], $atoks[2], $atoks[0] );
    }
    else
    {
        $btok = strtok( $time, ' /-\\:' );
        while( $btok !== FALSE )
        {
            $btoks[] = $btok;
            $btok = strtok( ' /-\\:' );
        }

        for( $i = 0; $i < 3; $i++ )
        {
            if( !isset( $btoks[$i] ) || !is_numeric( $btoks[$i] ))
            {
                $btoks[$i] = 0;
            }
        }

        $timestamp = mktime( $btoks[0], $btoks[1], $btoks[2],
                             $atoks[1], $atoks[2], $atoks[0] );
    }

    return $timestamp;
}

/**
* Get the HTML for an image with height & width
*
* @param    string  $file   full path to the file
* @return   string          html that will be included in the img-tag
*/
function COM_getImgSizeAttributes( $file )
{
    $sizeattributes = '';

    if( file_exists( $file ))
    {
        $dimensions = getimagesize( $file );
        if( !empty( $dimensions[0] ) AND !empty( $dimensions[1] ))
        {
            $sizeattributes = 'width="' . $dimensions[0]
                            . '" height="' . $dimensions[1] . '" ';
        }
    }

    return $sizeattributes;
}

/**
* Display a message and abort
*
* @param    int     $msg            message number
* @param    string  $plugin         plugin name, if applicable
* @param    int     $http_status    HTTP status code to send with the message
* @param    string  $http_text      Textual version of the HTTP status code
*
* @note Displays the message and aborts the script.
*
*/
function COM_displayMessageAndAbort( $msg, $plugin = '', $http_status = 200, $http_text = 'OK')
{
    $display = COM_siteHeader( 'menu' )
             . COM_showMessage( $msg, $plugin )
             . COM_siteFooter( true );

    if( $http_status != 200 )
    {
        header( "HTTP/1.1 $http_status $http_text" );
        header( "Status: $http_status $http_text" );
    }
    echo $display;
    exit;
}

/**
* Return full URL of a topic icon
*
* @param    string  $imageurl   (relative) topic icon URL
* @return   string              Full URL
*
*/
function COM_getTopicImageUrl( $imageurl )
{
    global $_CONF, $_THEME_URL;

    $iconurl = '';

    if( !empty( $imageurl ))
    {
        if( isset( $_THEME_URL ))
        {
            $iconurl = $_THEME_URL . $imageurl;
        }
        else
        {
            $stdImageLoc = true;
            if( !strstr( $_CONF['path_images'], $_CONF['path_html'] ))
            {
                $stdImageLoc = false;
            }

            if( $stdImageLoc )
            {
                $iconurl = $_CONF['site_url'] . $imageurl;
            }
            else
            {
                $t = explode( '/', $imageurl );
                $topicicon = $t[count( $t ) - 1];
                $iconurl = $_CONF['site_url']
                         . '/getimage.php?mode=topics&amp;image=' . $topicicon;
            }
        }
    }

    return $iconurl;
}

/**
* Try to determine the user's preferred language by looking at the
* "Accept-Language" header sent by their browser (assuming they bothered
* to select a preferred language there).
*
* @return   string  name of the language file to use or an empty string
*
* Bugs: Does not take the quantity ('q') parameter into account, but only
*       looks at the order of language codes.
*
* Sample header: Accept-Language: en-us,en;q=0.7,de-de;q=0.3
*
*/
function COM_getLanguageFromBrowser()
{
    global $_CONF;

    $retval = '';

    if( isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ))
    {
        $accept = explode( ',', $_SERVER['HTTP_ACCEPT_LANGUAGE'] );
        foreach( $accept as $l )
        {
            $l = explode( ';', trim( $l ));
            $l = $l[0];
            if( array_key_exists( $l, $_CONF['language_files'] ))
            {
                $retval = $_CONF['language_files'][$l];
                break;
            }
            else
            {
                $l = explode( '-', $l );
                $l = $l[0];
                if( array_key_exists( $l, $_CONF['language_files'] ))
                {
                    $retval = $_CONF['language_files'][$l];
                    break;
                }
            }
        }

    }

    return $retval;
}

/**
* Determine current language
*
* @return   string  name of the language file (minus the '.php' extension)
*
*/
function COM_getLanguage()
{
    global $_CONF, $_USER;

    $langfile = '';

    if( !empty( $_USER['language'] ))
    {
        $langfile = $_USER['language'];
    }
    else if( !empty( $_COOKIE[$_CONF['cookie_language']] ))
    {
        $langfile = $_COOKIE[$_CONF['cookie_language']];
    }
    else
    {
        $langfile = COM_getLanguageFromBrowser();
    }

    $langfile = preg_replace( '/[^a-z0-9\-_]/', '', $langfile );
    if( !empty( $langfile ))
    {
        if( is_file( $_CONF['path_language'] . $langfile . '.php' ))
        {
            return $langfile;
        }
    }

    // if all else fails, return the default language
    return $_CONF['language'];
}

/**
* Determine the ID to use for the current language
*
* The $_CONF['language_files'] array maps language IDs to language file names.
* This function returns the language ID for a certain language file, to be
* used in language-dependent URLs.
*
* @param    string  $language   current language file name (optional)
* @return   string              language ID, e.g 'en'; empty string on error
*
*/
function COM_getLanguageId( $language = '' )
{
    global $_CONF;

    if( empty( $language ))
    {
        $language = COM_getLanguage();
    }

    $lang_id = array_search( $language, $_CONF['language_files'] );
    if( $lang_id === false)
    {
        // that looks like a misconfigured $_CONF['language_files'] array ...
        COM_errorLog( 'Language "' . $language . '" not found in $_CONF[\'language_files\'] array!' );

        $lang_id = ''; // not much we can do here ...
    }

    return $lang_id;
}

/**
* Return SQL expression to request language-specific content
*
* Creates part of an SQL expression that can be used to request items in the
* current language only.
*
* @param    string  $field  name of the "id" field, e.g. 'sid' for stories
* @param    string  $type   part of the SQL expression, e.g. 'WHERE', 'AND'
* @param    string  $table  table name if ambiguous, e.g. in JOINs
* @return   string          SQL expression string (may be empty)
*
*/
function COM_getLangSQL( $field, $type = 'WHERE', $table = '' )
{
    global $_CONF;

    $sql = '';

    if( isset( $_CONF['languages'] ) && isset( $_CONF['language_files'] ))
    {
        if( !empty( $table ))
        {
            $table .= '.';
        }

        $lang_id = COM_getLanguageId();

        if( !empty( $lang_id ))
        {
            //@@@@@20070108update----->
            //$sql = ' ' . $type . " ({$table}$field LIKE '%_$lang_id')";
            $sql = ' ' . $type . " ({$table}$field LIKE '%\\_$lang_id')";
            //@@@@@20070108update----->
        }
    }

    return $sql;
}

/**
* Provides a drop-down menu (or simple link, if you only have two languages)
* to switch languages. This can be used as a PHP block or called from within
* your theme's header.thtml: <?php print phpblock_switch_language(); ?>
*
* @return   string  HTML for drop-down or link to switch languages
*
*/
function phpblock_switch_language()
{
    global $_CONF;

    $retval = '';

    if( !isset( $_CONF['languages'] ) || !isset( $_CONF['language_files'] ) ||
          ( count( $_CONF['languages'] ) != count( $_CONF['language_files'] )))
    {
        return $retval;
    }

    $lang = COM_getLanguage();
    $langId = COM_getLanguageId( $lang );

    if( count( $_CONF['languages'] ) == 2 )
    {
        foreach( $_CONF['languages'] as $key => $value )
        {
            if( $key != $langId )
            {
                $newLang = $value;
                $newLangId = $key;
                break;
            }
        }

        $switchUrl = COM_buildUrl( $_CONF['site_url'] . '/switchlang.php?lang='
                                   . $newLangId );
        $retval .= '<a href="' . $switchUrl . '">' . $newLang . '</a>';
    }
    else
    {
        $retval .= '<form name="change" action="'. $_CONF['site_url']
                . '/switchlang.php" method="GET">' . LB;
        $retval .= '<input type="hidden" name="oldlang" value="' . $langId
                . '">' . LB;

        $retval .= '<select onchange="change.submit()" name="lang">';
        foreach( $_CONF['languages'] as $key => $value )
        {
            if( $lang == $_CONF['language_files'][$key] )
            {
                $selected = ' selected="selected"';
            }
            else
            {
                $selected = '';
            }
            $retval .= '<option value="' . $key . '"' . $selected . '>'
                    . $value . '</option>' . LB;
        }
        $retval .= '</select>' . LB;
        $retval .= '</form>' . LB;
    }

    return $retval;
}

/**
* Switch locale settings
*
* When multi-language support is enabled, allow overwriting the default locale
* settings with language-specific settings (date format, etc.). So in addition
* to $_CONF['date'] you can have a $_CONF['date_en'], $_CONF['date_de'], etc.
*
*/
function COM_switchLocaleSettings()
{
    global $_CONF;

    if( isset( $_CONF['languages'] ) && isset( $_CONF['language_files'] ))
    {
        $overridables = array
        (
          'locale',
          'date', 'daytime', 'shortdate', 'dateonly', 'timeonly',
          'week_start', 'hour_mode',
          'thousand_separator', 'decimal_separator'
        );

        $langId = COM_getLanguageId();
        foreach( $overridables as $option )
        {
            if( isset( $_CONF[$option . '_' . $langId] ))
            {
                $_CONF[$option] = $_CONF[$option . '_' . $langId];
            }
        }
    }
}

/**
* Truncate a string
*
* Truncates a string to a max. length and optionally adds a filler string,
* e.g. '...', to indicate the truncation.
* This function is multi-byte string aware, based on a patch by Yusuke Sakata.
*
* @param    string  $text   the text string to truncate
* @param    int     $maxlen max. number of characters in the truncated string
* @param    string  $filler optional filler string, e.g. '...'
* @return   string          truncated string
*
* @note The truncated string may be shorter but will never be longer than
*       $maxlen characters, i.e. the $filler string is taken into account.
*
*/
function COM_truncate( $text, $maxlen, $filler = '' )
{
    $newlen = $maxlen - MBYTE_strlen( $filler );
    $len = MBYTE_strlen( $text );
    if( $len > $maxlen )
    {
        $text = MBYTE_substr( $text, 0, $newlen ) . $filler;
    }

    return $text;
}

/**
  * Handle errors.
  *
  * This function will handle all PHP errors thrown at it, without exposing
  * paths, and hopefully, providing much more information to Root Users than
  * the default white error page.
  *
  * This function will call out to CUSTOM_handleError if it exists, but, be
  * advised, only override this function with a very, very stable function. I'd
  * suggest one that outputs some static, basic HTML.
  *
  * The PHP feature that allows us to do so is documented here:
  * http://uk2.php.net/manual/en/function.set-error-handler.php
  *
  * @param  int     $errno      Error Number.
  * @param  string  $errstr     Error Message.
  * @param  string  $errfile    The file the error was raised in.
  * @param  int     $errline    The line of the file that the error was raised at.
  * @param  array   $errcontext An array that points to the active symbol table at the point the error occurred.
  */
function COM_handleError($errno, $errstr, $errfile='', $errline=0, $errcontext='')
{
    global $_CONF, $_USER;

    // Handle @ operator
    if( error_reporting() == 0 )
    {
        return;
    }

    /* If in PHP4, then respect error_reporting */
    if( (PHP_VERSION < 5) && (($errno & error_reporting()) == 0) ) return;

    /*
     * If we have a root user, then output detailed error message:
     */
    if( ( is_array($_USER) && function_exists('SEC_inGroup') ) || $_CONF['rootdebug'] )
    {
        if($_CONF['rootdebug'] || SEC_inGroup('Root'))
        {
            echo("
                An error has occurred:<br/>
                $errno - $errstr @ $errfile line $errline<br/>
            <pre>");
            ob_start();
            var_dump($errcontext);
            $errcontext = htmlspecialchars(ob_get_contents());
            ob_end_clean();
            echo("$errcontext</pre>
            (This text is only displayed to users in the group 'Root')
            ");
            exit;
        }
    }

    /* If there is a custom error handler, fail over to that, but only
     * if the error wasn't in lib-custom.php
     */
    if( is_array($_CONF) && !(strstr($errfile, 'lib-custom.php')))
    {
        if( array_key_exists('path_system', $_CONF) )
        {
            require_once($_CONF['path_system'].'lib-custom.php');
            if( function_exists('CUSTOM_handleError') )
            {
                CUSTOM_handleError($errno, $errstr, $errfile, $errline, $errcontext);
                exit;
            }
        }
    }

    /* Does the theme implement an error message html file? */
    if(file_exists($_CONF['path_layout'].'errormessage.html'))
    {
        // NOTE: NOT A TEMPLATE! JUST HTML!
        include($_CONF['path_layout'].'errormessage.html');
    } else {
        /* Otherwise, display simple error message */
        echo("
        <html>
            <head>
                <title>{$_CONF['site_name']} - An Error Occurred</title>
            </head>
            <body>
            <div style=\"width: 100%; text-align: center;\">
            Unfortunately, an error has occurred rendering this page. Please try
            again later.
            </div>
            </body>
        </html>
        ");
    }

    exit;
}

?>
