\n"; // Search echo "

Advanced search
"; echo "\n"; if ($user) { echo "\n"; echo "

Private messages: ", pm_notification($user); echo "\n"; } echo "\n"; end_table(); } // Output the forum/thread title. // function show_forum_title($category, $forum, $thread) { if ($category) { $is_helpdesk = $category->is_helpdesk; } else { $is_helpdesk = false; } $where = $is_helpdesk?tra("Questions and Answers"):tra("Message boards"); $top_url = $is_helpdesk?"forum_help_desk.php":"forum_index.php"; if (!$forum && !$thread) { echo "$where"; } else if ($forum && !$thread) { echo ""; echo "$where : "; echo $forum->title; echo ""; } else if ($forum && $thread) { echo ""; echo "$where : "; echo "id."\">", $forum->title, " : "; echo cleanup_title($thread->title); echo ""; } else { echo "Invalid input to show_forum_title
"; echo "threadid $thread->id"; // TODO: handle this condition gracefully } } function show_team_forum_title($forum, $thread=null) { $team = BoincTeam::lookup_id($forum->category); echo "id>$team->name message board "; if ($thread) { echo " : id>$thread->title"; } } // Start the forum table, output the proper headings and such. // function start_forum_table($headings, $extra="width=\"100%\"") { $span = null; start_table($extra." cellspacing=\"0\""); echo ""; for ($i=0; $i$title"; } echo "\n"; } // return a string containing a paged navigation bar // for the given forum. The default start place is 0. // function show_page_nav($forum, $start=0){ // How many pages to potentially show before and after this one: $preshow = 5; $postshow = 10; $navbar = ""; if ($forum->threads > THREADS_PER_PAGE) { $total = ceil($forum->threads / THREADS_PER_PAGE); $curpage = ceil($start / THREADS_PER_PAGE); // If this is not the first page, display "previous" if ($curpage > 0){ $navbar = ' <-- Previous '; } // Display a list of pages surrounding this one for ($i=$curpage-$preshow;$i<($curpage+$postshow);$i++){ if ($i<1) continue; if ($i>$total) break; // If this is the current page, emphasize it. if ($i == $curpage+1){ $navbar.=""; } $navbar.=''.$i.' | '; if ($i == $curpage+1){$navbar.="";} } // If there is a next page if ($curpage+1 < $total){ $navbar.= ' Next -->'; } } return $navbar; } function thread_last_visit($user, $thread) { if (!$user) return false; $log = BoincForumLogging::lookup($user->id, $thread->id); return $log->timestamp; } function thread_is_unread($user, $thread) { if (!$user) return false; $log = BoincForumLogging::lookup($user->id, $thread->id); if ($thread->timestamp < $log->timestamp) return false; if ($thread->timestamp < $user->prefs->mark_as_read_timestamp) return false; return true; } // Process a user-supplied title to remove HTML stuff // function cleanup_title($title) { $x = trim(htmlspecialchars($title)); $x = stripslashes($x); // clean up funky old titles in DB if (strlen($x)==0) return "(no title)"; else return $x; } function can_reply($thread, $forum, $user) { if ($thread->locked) { if (!is_moderator($user, $forum)) return false; } return true; } function should_show_post( $logged_in_user, $postcount, $postnumber, $post, $sort_style, $last_visit ){ $no_wraparound = get_str("nowrap",true); // If no user logged in, display everything (useful for Google bots etc) // if (!$logged_in_user) return true; // If the user hasn't enabled the feature to display only // a certain amount of posts, simply display all of them. // if (!$logged_in_user->prefs->minimum_wrap_postcount) return true; // If the user has asked to display all the posts just display them // if ($no_wraparound) return true; // If it is enabled and we havent yet hit the limit, simply display all if ($postcount < $logged_in_user->prefs->minimum_wrap_postcount) return true; // display the post if it is the first post // if ($postnumber==1 || $postnumber==($postcount+1)) return true; // if this post is unread, show it // if ($post->timestamp > $last_visit) return true; // The user can choose to display the last X posts in a thread only, // "last" here depends on sorting criteria: // if ($sort_style==CREATE_TIME_OLD){ if ($postnumber > $postcount+1-$logged_in_user->prefs->display_wrap_postcount) return true; } else if (CREATE_TIME_NEW){ if ($postnumber <= $logged_in_user->prefs->display_wrap_postcount) return true; } else { // For other sorting criteria we do not know how to define "last" // so simply display it all // return true; } // In all other cases we should not show this particular post return false; } // Show the posts in a thread for a user. // function show_posts( $thread, $forum, $sort_style, $filter, $logged_in_user, $show_controls=true ) { $n = 1; $first_unread_post = null; $last_visit = 0; if ($show_controls) { $controls = FORUM_CONTROLS; } else { $controls = NO_CONTROLS; } // If logged in user is moderator, // let him see all posts - including hidden ones // if (is_moderator($logged_in_user, $forum)) { $show_hidden = true; } else { $show_hidden = false; } $posts = get_thread_posts($thread->id, $sort_style, $show_hidden); $postcount = (sizeof($posts)-1); if ($logged_in_user) { $last_visit = thread_last_visit($logged_in_user, $thread); } $postnumber=0; $previous_post=0; $no_wraparound = get_str("nowrap",true); foreach ($posts as $post){ $postnumber++; if (should_show_post( $logged_in_user, $postcount, $postnumber, $post, $sort_style, $last_visit) ) { if ($postnumber!=$previous_post+1){ // A number of posts were hidden, display a way to unhide them: // echo " Only the first post and the last ".($logged_in_user->prefs->display_wrap_postcount)." posts (of the ".($postcount+1)." posts in this thread) are displayed.
id."&nowrap=true\">Click here to also display the remaining posts. "; } $previous_post=$postnumber; show_post($post, $thread, $forum, $logged_in_user, $last_visit, $n, $controls, $filter); $n = ($n+1)%2; if (($post->timestamp>$last_visit) && ((!$first_unread_post) || ($post->timestamp<$first_unread_post->timestamp)) ){ $first_unread_post=$post; } } } if ($logged_in_user && $logged_in_user->prefs->jump_to_unread){ if ($first_unread_post){ echo ""; } else { echo ""; } } if ($logged_in_user) { BoincForumLogging::replace($logged_in_user->id, $thread->id, time()); } } function get_ignored_list($user) { return explode("|", $user->prefs->ignorelist); } function add_ignored_user($user, $other_user) { $list = explode("|", $user->prefs->ignorelist); foreach ($list as $key=>$userid) { if ($userid == $other_user->id) { return true; } } $list[] = $other_user->id; $x = implode("|", array_values($list)); return $user->prefs->update("ignorelist='$x'"); } function remove_ignored_user($user, $other_user) { $list = explode("|", $user->prefs->ignorelist); foreach ($list as $key=>$userid) { if ($userid == $other_user->id) { unset($list[$key]); } } $x = implode("|", array_values($list)); return $user->prefs->update("ignorelist='$x'"); } function is_ignoring($user, $other_user) { $list = explode("|", $user->prefs->ignorelist); return in_array($other_user->id, $list); } function get_output_options($user) { if (!$user) return null; $options = new output_options(); if ($user->prefs->images_as_links) $options->images_as_links = 1; if ($user->prefs->link_popup) $options->link_popup = 1; return $options; } // Display an individual post // function show_post( $post, $thread, $forum, $logged_in_user, $last_visit, $n, $controls=FORUM_CONTROLS, $filter=true ) { $user = BoincUser::lookup_id($post->user); BoincForumPrefs::lookup($user); $config = get_config(); $no_forum_rating = parse_bool($config, "no_forum_rating"); $tokens = ""; $rated_below_threshold = false; $rated_above_threshold = false; $options = get_output_options($logged_in_user); //If the user that made this post is on the list of people to ignore, // change thresholds to be much more strict // if ($logged_in_user){ $tokens = url_tokens($logged_in_user->authenticator); if (is_ignoring($logged_in_user, $user)){ $user_is_on_ignorelist=true; $rated_below_threshold = ($logged_in_user->prefs->high_rating_threshold>$post->rating()); $rated_above_threshold = ($logged_in_user->prefs->high_rating_threshold+abs($logged_in_user->prefs->low_rating_threshold)<($post->rating)); } else { //Use normal threshold values $rated_below_threshold = ($logged_in_user->prefs->low_rating_threshold>($post->rating())); $rated_above_threshold = ($logged_in_user->prefs->high_rating_threshold<($post->rating)); } } // The creator can edit the post, but only in a specified amount of time // (exception: a moderator can edit his/her posts at any time) // $can_edit = false; if ($logged_in_user) { if ($user->id == $logged_in_user->id) { if (is_moderator($logged_in_user, $forum)) { $can_edit = true; } else if (can_reply($thread, $forum, $logged_in_user)) { $time_limit = $post->timestamp+MAXIMUM_EDIT_TIME; $can_edit = time()<$time_limit; } else { $can_edit = false; } } } echo " id."\">

"; // Print the user links echo user_links($user, URL_BASE); echo "
"; // Print the special user lines, if any global $special_user_bitfield; $fstatus=""; $keys = array_keys($special_user_bitfield); for ($i=0; $iprefs->privilege($keys[$i])) { $fstatus.=$special_user_bitfield[$keys[$i]]."
"; } } if ($user->create_time > time()-ST_NEW_TIME) $fstatus.=ST_NEW."
"; if ($fstatus) echo "$fstatus"; echo ""; if (!$filter || !$rated_below_threshold){ if ($user->prefs->avatar!="" && (!$logged_in_user || ($logged_in_user->prefs->hide_avatars==false))) { echo "prefs->avatar."\" alt=\"Avatar\">
"; } } $url = "pm.php?action=new&userid=".$user->id; $name = $user->name; show_button($url, "Send message", "Send $name a private message"); echo "
Joined: ", gmdate('M j y', $user->create_time), "
"; if (!isset($user->nposts)) { $user->nposts = BoincPost::count("user=$user->id"); } if(function_exists('project_forum_user_info')){ project_forum_user_info($user); } else { // default // circumvent various forms of identity spoofing // by displaying the user id of the poster. // echo "Posts: $user->nposts
"; echo "ID: ".$user->id."
"; echo "Credit: ".number_format($user->total_credit)."
"; echo "RAC: ".number_format($user->expavg_credit)."
"; } echo "
"; if ($controls == FORUM_CONTROLS) { echo ""; echo "
id, "\" method=\"post\">"; } else { echo ""; } if ($logged_in_user && $post->timestamp>$last_visit){ show_image(NEW_IMAGE, "You haven't read this message yet", NEW_IMAGE_HEIGHT); } if ($rated_above_threshold){ show_image(EMPHASIZE_IMAGE, "This message has a high average rating", EMPHASIZE_IMAGE_HEIGHT); } echo " id."&nowrap=true#$post->id\">Message ".$post->id." - "; if ($post->hidden) echo "[hidden] "; echo " Posted ", pretty_time_str($post->timestamp); ; if ($post->parent_post) { echo " - in response to id."&nowrap=true#".$post->parent_post."\">Message ID ".$post->parent_post."."; } echo " "; if ($can_edit && $controls != NO_CONTROLS) { show_button("forum_edit.php?id=".$post->id."$tokens", "Edit", "Edit this message"); } if (is_moderator($logged_in_user, $forum)) { show_post_moderation_links($config, $logged_in_user, $post, $forum, $tokens); } if ($post->modified) { echo "
Last modified: ", pretty_time_Str($post->modified); } if ($rated_below_threshold && $filter){ if ($user_is_on_ignorelist) { $andtext=" and the user is on your ignore list"; } echo "
This post has been filtered (rating: ".($post->rating()).")$andtext, press id."&filter=false#".$post->id."\">here to view this thread without filtering"; } echo "
"; echo ""; if (!$filter || !$rated_below_threshold){ $posttext = $post->content; // If the creator of this post has a signature and // wants it to be shown for this post AND the logged in // user has signatures enabled: show it // if ($post->signature && (!$logged_in_user || !$logged_in_user->prefs->hide_signatures)){ $posttext.="\n____________\n".$user->prefs->signature; } $posttext = output_transform($posttext, $options); echo "

", $posttext, "

"; echo "ID: ", $post->id; if ($no_forum_rating != NULL) { echo " | id."\">"; show_image(REPORT_POST_IMAGE, "Report this post as offensive", REPORT_POST_IMAGE_HEIGHT); echo ""; } else { $rating = $post->rating(); echo " | Rating: ", $rating, " | rate: id."&choice=p$tokens\"> "; show_image(RATE_POSITIVE_IMAGE, "Click if you like this message", RATE_POSITIVE_IMAGE_HEIGHT); echo " / id."&choice=n$tokens\">"; show_image(RATE_NEGATIVE_IMAGE, "Click if you don't like this message", RATE_NEGATIVE_IMAGE_HEIGHT); echo " id."\">"; show_image(REPORT_POST_IMAGE, "Report this post as offensive", REPORT_POST_IMAGE_HEIGHT); echo " "; } if (($controls == FORUM_CONTROLS) && (can_reply($thread, $forum, $logged_in_user))) { echo ""; $url = "forum_reply.php?thread=" . $thread->id . "&post=" . $post->id . "#input"; show_button($url, "Reply", "Post a reply to this message"); echo ""; } else { echo ""; } echo ""; } else { echo ""; } echo ""; } // Show a post and its context (e.g. for search results, user posts) // function show_post_and_context($post, $thread, $forum, $options, $n) { $thread = BoincThread::lookup_id($post->thread); $forum = BoincForum::lookup_id($thread->forum); $content = output_transform($post->content, $options); $when = time_diff_str($post->timestamp, time()); $user = lookup_user_id($post->user); $title = cleanup_title($thread->title); $m = $n%2; if ($post->hidden) { $deleted = "
[Hidden by a moderator]"; } else { $deleted = ""; } echo " $n) "; switch ($forum->parent_type) { case 0: $category = BoincCategory::lookup_id($forum->category); show_forum_title($category, $forum, $thread); break; case 1: show_team_forum_title($forum); break; } echo " (id."&nowrap=true#".$post->id."\">Message ".$post->id.")
Posted $when by ".user_links($user)." $deleted
$content "; } function check_banished($user) { $x = $user->prefs->banished_until; if ($x>time()) { error_page( "You may not post or rate messages until ".gmdate('M j, Y', $x) ); } } function post_rules() { return " "; } function post_warning() { return "

Rules: ".post_rules()." More info
"; } // Various functions for adding/hiding/unhiding stuff. // These take care of counts and timestamps. // Don't do these things directly - use these functions // function create_post($content, $parent_id, $user, $forum, $thread, $signature) { $content = substr($content, 0, 64000); $content = mysql_real_escape_string($content); $now = time(); $sig = $signature?1:0; $id = BoincPost::insert("(thread, user, timestamp, content, parent_post, signature) values ($thread->id, $user->id, $now, '$content', $parent_id, $sig)"); if (!$id) return null; // send emails to subscribed users // $subs = BoincSubscription::enum("threadid=$thread->id"); foreach ($subs as $sub) { if ($user->id == $sub->userid) continue; $user2 = BoincUser::lookup_id($sub->userid); $visit_time = thread_last_visit($user2, $thread); if ($visit_time > $sub->notified_time) { send_reply_notification_email($thread, $user2); } } $user->update("posts=posts+1"); $thread->update("replies=replies+1, timestamp=$now"); $forum->update("posts=posts+1, timestamp=$now"); } function create_thread($title, $content, $user, $forum, $signature) { $title = trim($title); $title = strip_tags($title); $title = mysql_real_escape_string($title); $now = time(); $id = BoincThread::insert("(forum, owner, title, create_time, timestamp, replies) values ($forum->id, $user->id, '$title', $now, $now, -1)"); if (!$id) return null; $thread = BoincThread::lookup_id($id); create_post($content, 0, $user, $forum, $thread, $signature); $forum->update("threads=threads+1"); return $thread; } function hide_post($post, $thread, $forum) { $post->update("hidden=1"); $thread->update("replies=replies-1"); return $forum->update("posts=posts-1"); } function unhide_post($post, $thread, $forum) { $now = time(); $post->update("hidden=0"); $thread->update("replies=replies+1, timestamp=$now"); return $forum->update("posts=posts+1, timestamp=$now"); } function move_post($post, $old_thread, $old_forum, $new_thread, $new_forum) { $now = time(); $post->update("thread=$new_thread->id"); $old_thread->update("replies=replies-1"); $new_thread->update("replies=replies+1, timestamp=$now"); $old_forum->update("posts=posts-1"); return $new_forum->update("posts=posts+1, timestamp=$now"); } function hide_thread($thread, $forum) { $thread->update("hidden=1"); $forum->update("threads=threads-1"); return $forum->update("posts=posts-$thread->replies-1"); } function unhide_thread($thread, $forum) { $now = time(); $thread->update("hidden=0"); return $forum->update("threads=threads+1, posts=posts+$thread->replies+1, timestamp=$now"); } function move_thread($thread, $old_forum, $new_forum) { $now = time(); $old_forum->update("threads=threads-1, posts=posts-$thread->replies-1"); $new_forum->update("threads=threads+1, posts=posts+$thread->replies+1, timestamp=$now"); return $thread->update("forum=$new_forum->id"); } // $show_hidden: 1 if it is a moderator reading // Error page if this function returns NULL. // $forumID - int // $min - int // $nRec - int // $sort_style - string (checked by switch statement) // $show_hidden - bool (not directly passed to SQL) // $sticky - bool (not directly passed to SQL) // function get_forum_threads( $forumID, $start=-1, $nRec=-1, $sort_style=MODIFIED_NEW, $show_hidden = 0, $sticky = 1 ) { //if (! (is_numeric($forumID) && is_numeric($min) && is_numeric($nRec))) { // return NULL; // Something is wrong here. //} $sql = 'forum = ' . $forumID ; if ($sticky){ $stickysql = "sticky DESC, "; } if (!$show_hidden) { $sql .= ' AND hidden = 0'; } switch($sort_style) { case MODIFIED_NEW: $sql .= ' ORDER BY '.$stickysql.'timestamp DESC'; break; case MODIFIED_OLD: $sql .= ' ORDER BY '.$stickysql.'timestamp ASC'; break; case VIEWS_MOST: $sql .= ' ORDER BY '.$stickysql.'views DESC'; break; case REPLIES_MOST: $sql .= ' ORDER BY '.$stickysql.'replies DESC'; break; case CREATE_TIME_NEW: $sql .= ' ORDER by '.$stickysql.'create_time desc'; break; case CREATE_TIME_OLD: $sql .= ' ORDER by '.$stickysql.'create_time asc'; break; case 'sufferers': $sql .= ' ORDER by '.$stickysql.'sufferers desc'; break; case 'activity': $sql .= ' ORDER by '.$stickysql.'activity desc'; break; case 'score': $sql .= ' ORDER by '.$stickysql.'score desc'; break; default: $sql .= ' ORDER BY '.$stickysql.'timestamp DESC'; break; } if ($start > -1) { $sql .= ' LIMIT '.$start; if ($nRec > -1) { $sql .= ', '.$nRec; } } else if ($nRec > -1) { $sql .= ' LIMIT '.$nRec; } return BoincThread::enum($sql); } // $show_hidden = true when it is a moderator reading // error_page if this function returns NULL. // $sort_style - string (checked by switch statement) // $show_hidden - bool (not directly passed to SQL) // function get_thread_posts($threadid, $sort_style, $show_hidden) { $sql = "thread=$threadid"; if (!$show_hidden) { $sql .= ' AND hidden = 0'; } switch($sort_style) { case CREATE_TIME_NEW: $sql .= ' ORDER BY timestamp desc'; break; case CREATE_TIME_OLD: $sql .= ' ORDER BY timestamp asc'; break; case POST_SCORE: $sql .= ' ORDER BY score DESC'; break; default: $sql .= ' ORDER BY timestamp asc'; break; } return BoincPost::enum($sql); } // Show the links for possible moderation actions related to a single post // function show_post_moderation_links( $config, $logged_in_user, $post, $forum, $tokens ){ $moderators_allowed_to_ban = parse_bool($config, "moderators_allowed_to_ban"); $moderators_vote_to_ban = parse_bool($config, "moderators_vote_to_ban"); if ($post->hidden) { show_button("forum_moderate_post_action.php?action=unhide&id=".$post->id."$tokens", "Unhide", "Unhide this post"); } else { show_button("forum_moderate_post.php?action=hide&id=".$post->id."$tokens", "Hide", "Hide this post"); } show_button( "forum_moderate_post.php?action=move&id=".$post->id."$tokens", "Move", "Move post to a different thread" ); if ($forum->parent_type == 0) { if ($logged_in_user->prefs->privilege(S_ADMIN) || ($logged_in_user->prefs->privilege(S_MODERATOR) && $moderators_allowed_to_ban)) { show_button("forum_moderate_post.php?action=banish_user&id=".$post->id."&userid=".$post->user."$tokens", "Banish author", "Banish author"); } if ($logged_in_user->prefs->privilege(S_MODERATOR) && $moderators_vote_to_ban) { require_once("../inc/forum_banishment_vote.inc"); if (vote_is_in_progress($post->user)) { show_button("forum_banishment_vote.php?action=yes&userid=".$post->user, "Vote to banish author", "Vote to banish author"); show_button("forum_banishment_vote.php?action=no&userid=".$post->user, "Vote not to banish author", "Vote not to banish author"); } else { show_button("forum_banishment_vote.php?action=start&userid=".$post->user, "Start vote to banish author", "Start vote to banish author"); } } } } function check_create_thread_access($user, $forum) { if ($forum->is_dev_blog){ if ( (!$user->prefs->privilege(S_SCIENTIST)) && (!$user->prefs->privilege(S_DEV)) && (!$user->prefs->privilege(S_ADMIN)) ) { error_page("This forum is marked as a development blog, only people directly working with the project may start a new thread here.
However, you may post a reply to an existing thread."); } } check_post_access($user, $forum); } function check_post_access($user, $forum) { switch ($forum->parent_type) { case 0: if ($user->prefs->privilege(S_MODERATOR)) return; break; case 1: $team = BoincTeam::lookup_id($forum->category); if (is_team_admin($user, $team)) return; // non-team-members can't post // if ($user->teamid != $team->id) { error_page("Only team members can post to the team message board"); } break; } // If user haven't got enough credit (according to forum regulations) // We do not tell the (ab)user how much this is - // no need to make it easy for them to break the system. // if ($user->total_credit<$forum->post_min_total_credit || $user->expavg_credit<$forum->post_min_expavg_credit) { error_page(tra("In order to create a new thread in %1 you must have a certain amount of credit. This is to prevent and protect against abuse of the system.", $forum->title)); } // If the user is posting faster than forum regulations allow // Tell the user to wait a while before creating any more posts // if (time()-$user->last_post <$forum->min_post_interval) { error_page(tra("You cannot create any more threads right now. Please wait a while before trying again. This delay has been enforced to protect against abuse of the system.")); } } function check_reply_access($user, $forum, $thread) { if ($thread->locked && !is_moderator($user, $forum)) { error_page( "This thread is locked. Only forum moderators and administrators are allowed to post there." ); } if ($thread->hidden) { error_page( "Can't post to a hidden thread." ); } check_post_access($user, $forum); } function is_moderator($user, $forum) { if (!$user) return false; switch ($forum->parent_type) { case 0: if ($user->prefs->privilege(S_MODERATOR)) return true; if ($user->prefs->privilege(S_ADMIN)) return true; if ($user->prefs->privilege(S_DEV)) return true; break; case 1: if ($user->prefs->privilege(S_ADMIN)) return true; $team = BoincTeam::lookup_id($forum->category); return is_team_admin($user, $team); break; } return false; } ?>