1

(15 replies, posted in General discussion)

Bad Behaviour is pretty easy to integrate into PunBB, and probably will become a plugin in 1.3 (if I have anything to say about it wink). I have some code for it sitting around somewhere, and that provides a decent level of protection.

2

(5 replies, posted in Feature requests)

mesnews wrote:

I want to read the group with a newsreader, like OE [Editor note: what is OE?], MesNews, XNews, etc.... Not a rss.

I don't know that there is really any sort of plugin which would make the forum readable by a newsreader (I presume you mean a USENET reader, like that included with most e-mail clients, for instance Thunderbird). That would require running a separate daemon on your server, and you'd need not only root access but also some significant programming skills to make the forum work in the NNTP protocol.

3

(0 replies, posted in Feature requests)

It seems like it would be a very helpful feature to use PHP's built in timezone system for calculating local times for users on the forum. I put this together on my own forum, and it works remarkably well. It would unfortunately require setting all users' timezones to UTC on an upgrade, but afterwords, I think the benifits would outweigh the initial investment: it automatically handles Daylight Saving Time no matter whether you're in the Northern or Southern hemisphere so long as you select the right timezone.

It would require ALTERing the structure of the user table to change the timezone field from a float to a TEXT or a VARCHAR, and would also require the replacement of the timezone boxes, but other than that, it's quite simple. Most of my code follows, except for the list of timezones because it would make this post REALLY REALLY LONG. It was mostly generated from the appendix to the PHP Manual listing all the timezones they support, removing some of the extra/legacy cruft.

<?php

/**
 * Helper function for timezone_select().
 * $tzlist: The list of timezones, with a nested array indicating a new header.
 * $prefix: What should be printed before the value, for instance "Europe/"
 * $disppre: What should be printed before the option text (spaces used as
 *           padding in this case, since we can't use nested <optgroup>s :(
 * $current: The currently selected index.
 */
function tzselect($tzlist, $prefix, $disppre, $current) {
    if(! is_array($tzlist)) return false ;
    foreach($tzlist as $id => $value) {
        $newprefix = $prefix ;
        $newdisppre = $disppre ;
        if(is_array($value)) {
            $newprefix .= "$id/" ;
            $id = htmlspecialchars($id) ;
            $timestring .= "<option disabled='disabled' class='grouphead'>$disppre$id:</option>\n" ;
            $newdisppre = $newdisppre.'  ' ;
            $timestring .= tzselect($value, $newprefix, $newdisppre, $current) ;
        } else {
            $optvalue = $newprefix.$value ;
            $optvalue = htmlspecialchars($optvalue);
            $value = htmlspecialchars($value) ;
            $attr = selectifactive($optvalue, $current) ;
            $timestring .= "<option $attr>$disppre$value</option>\n" ;
        }
    }
    return $timestring ;
}

/**
 * Returns a timezone box.
 * $name: the name of the <select> in the form.
 * $id: the id of the <select>. If left blank, no ID will be used.
 * $current: The currently selected timezone. Used to put selected="selected" in
 *           the right zone.
 */
function timezone_select($name, $id='', $current='') {
    // Just enough to tell what the structure is; if anybody wants to put my entire filtered list, I will
    $timezones =
        Array(
            'Africa' => Array (
                'Abidjan',
                'Accra',
                'Addis_Ababa',
                'Algiers',
                'Asmera',
                'Bamako'
            ) ,
            'Indian' => Array (
                'Antananarivo',
                'Chagos',
                'Christmas'
            )
        ) ;
    $idp = ($id == '' ? '' : "id='$id'") ;
    $timestr = "<select name='$name' $idp>\n" ;
    if('' == $current) {
        $sel1 = 'selected="selected"' ;
    }
    $timestr .= '<option value="UTC" '.$sel1.'>Select a timezone</option>'."\n" ;
    $timestr .= '<option '.selectifactive('UTC', $current).'>UTC</option>'."\n" ;
    $timestr .= tzselect($timezones, '', '', $current) ;
    $timestr .='</select>'."\n" ;
    return $timestr ;
}

/**
 * Gives pretty much all the parameters for an option.
 * $value: the value= of the option.
 * $active: the one you want selected.
 */
function selectifactive($value, $active) {
    $sel = "value='$value'" ;
    if($value == $active) {
        $sel .= ' selected="selected"' ;
    }
    return $sel ;
}

/**
 * Format a time string according to $time_format and timezones
 */
function format_time($timestamp, $date_only = false)
{
    global $pun_config, $lang_common, $pun_user;

    if ($timestamp == '')
        return $lang_common['Never'];

    $timezone = $pun_user['timezone'];
    $now = time();

    $date = date($pun_config['o_date_format'], $timestamp);
    $today = date($pun_config['o_date_format'], $now);
    $yesterday = date($pun_config['o_date_format'], strtotime('-1 day'));

    if ($date == $today)
        $date = $lang_common['Today'];
    else if ($date == $yesterday)
        $date = $lang_common['Yesterday'];

    if (!$date_only)
        return $date.' '.date($pun_config['o_time_format'], $timestamp);
    else
        return $date;
}


/**
 * Sets up the timezone system. $timezone is the timezone. In PunBB, this is
 * called by setup_dates($pun_user['timezone']) in common.php.
 */
function setup_dates($timezone) {
    if(function_exists('date_default_timezone_set')) {
        date_default_timezone_set($timezone) ;
    } else {
        putenv('TZ='.$timezone) ;
    }
}

?>

After doing a little searching, I see that one of the major reasons for doing the little <meta http-equiv?> redirect thing is for the user to get a sense of "it actually happened", but perhaps more importantly, to convert a POST request to the redirecting page to a GET request of the page to which they're redirected. Unfortunately, if you set the delay to 0, that's not what's supposed to happen when PHP sends its usual 302 error code for a "Location: ?" header. So this is really two bugs: The Location header must be an absolute URL, and the 302 response really ought to be be a 303.

So if you go into functions.php, in the neighbourhood of line 825 or so, replace the distributed redirect code with the following:

        header('HTTP/1.1 303 See Other') ;
        header('Location: '.$pun_config['o_base_url'].'/'.str_replace('&', '&', $destination_url));

Additionally, since we really "SHOULD provide a short hypertext note" and the new <meta> would be redundant, just get rid of the "exit;", introduce an if statement, and some curly braces around the <meta>:

    if ($pun_config['o_redirect_delay'] != '0') {
?>
<meta http-equiv="refresh" content="<?php echo $pun_config['o_redirect_delay'] ?>;URL=<?php echo str_replace(array('<', '>', '"'), array('<', '>', '"'), $destination_url) ?>" />
 } ?>

Unfortunately, this has a side effect of breaking logins. So to fix that, I went into login.php and replaced that one huge long line near around 200 that assigns $redirect_url with the following:

//decide where to return to
$redirect_url = '' ;
if(isset($_SERVER['HTTP_REFERER'])) {
    $inforum = false ;
    $phpfile = null ;
    $inforum = preg_match('#^'.preg_quote($pun_config['o_base_url']).'/(.*?\.php(?:\?.*)?)$#i', $_SERVER['HTTP_REFERER'], $phpfile ) ; // if we match, $inforum will be true, and $phpfile will grab the URL
    $redirect_url = $inforum ? $phpfile[1] : '' ; // if we're inforum, then use that URL we got, else just use nothing
}

It is tested and works properly.

Note that I can't give exact line numbers since I'm working off of a rather modified version of PunBB.

5

(8 replies, posted in PunBB 1.2 bug reports)

What would probably be better is if the system handled the form and re-presented it to the user with the errors displayed and the appropriate fields highlighted. That way, the user would be able to just change it right then and there.