2
$cvs_version_tracker[]="\$Id: forum.inc 12748 2007-05-26 17:00:01Z Rytis $"; //Generated automatically - do not edit
4
require_once('../inc/db.inc');
5
require_once('../inc/db_forum.inc');
6
require_once('../inc/time.inc');
7
require_once('../inc/forum_moderators.inc');
8
require_once('../inc/text_transform.inc');
9
require_once('../inc/util.inc');
10
require_once('../inc/forum_pm.inc');
3
require_once("../inc/forum_db.inc");
4
require_once("../inc/pm.inc");
5
require_once("../inc/team.inc");
6
require_once("../inc/text_transform.inc");
8
define('THREADS_PER_PAGE', 50);
11
define('MODIFIED_NEW', 1);
12
define('MODIFIED_OLD',2);
13
define('VIEWS_MOST',3);
14
define('REPLIES_MOST',4);
15
define('CREATE_TIME_NEW',5);
16
define('CREATE_TIME_OLD',6);
17
define('POST_SCORE',7);
19
// names for the above
20
$thread_sort_styles[CREATE_TIME_OLD] = "Oldest post first";
21
$thread_sort_styles[CREATE_TIME_NEW] = "Newest post first";
22
$thread_sort_styles[POST_SCORE] = "Highest rated posts first";
24
$forum_sort_styles[MODIFIED_NEW] = "Newest reply first";
25
//$forum_sort_styles[MODIFIED_OLD] = "Oldest reply first";
26
$forum_sort_styles[VIEWS_MOST] = "Most views first";
27
$forum_sort_styles[REPLIES_MOST] = "Most posts first";
28
$forum_sort_styles[CREATE_TIME_NEW] = "Newest first";
29
//$forum_sort_styles[CREATE_TIME_OLD] = "Oldest first";
31
// values for thread.status
32
define('THREAD_SOLVED', 1);
12
34
define('AVATAR_WIDTH', 100);
13
35
define('AVATAR_HEIGHT',100);
15
$special_user_bitfield[0]="Forum moderator";
16
$special_user_bitfield[1]="Project administrator";
17
$special_user_bitfield[2]="Project developer";
18
$special_user_bitfield[3]="Project tester";
19
$special_user_bitfield[4]="Volunteer developer";
20
$special_user_bitfield[5]="Volunteer tester";
21
$special_user_bitfield[6]="Project scientist";
23
37
define('ST_NEW_TIME', 1209600); //3600*24*14 - 14 days
24
38
define('ST_NEW', 'New member');
26
define('MAXIMUM_EDIT_TIME',3600); //Maximally allow edits of forums posts up till one hour after posting.
40
define('MAXIMUM_EDIT_TIME',3600);
41
// allow edits of forums posts up till one hour after posting.
28
define('FORUM_OPEN_LINK_IN_NEW_WINDOW',1);
29
43
define('MAX_FORUM_LOGGING_TIME', 2419200); //3600*24*28 - 28 days
30
44
define('NO_CONTROLS', 0);
31
45
define('FORUM_CONTROLS', 1);
58
72
define ('DEFAULT_LOW_RATING_THRESHOLD', -25);
59
73
define ('DEFAULT_HIGH_RATING_THRESHOLD', 5);
61
$thread_sort_styles['timestamp'] = "Newest first";
62
$thread_sort_styles['timestamp_asc'] = "Oldest first";
63
$thread_sort_styles['score'] = "Highest rated first";
65
$faq_sort_styles['create_time'] = "Most recent question first";
66
$faq_sort_styles['timestamp'] = "Most recent answer first";
67
$faq_sort_styles['activity'] = "Most frequently asked first";
69
$answer_sort_styles['score'] = "Highest score first";
70
$answer_sort_styles['timestamp'] = "Most recent first";
71
$answer_sort_styles['timestamp_asc'] = "Oldest first";
73
$thread_filter_styles['2'] = "\"Very helpful\"";
74
$thread_filter_styles['1'] = "At least \"helpful\"";
75
$thread_filter_styles['0'] = "At least \"neutral\"";
76
$thread_filter_styles['-1'] = "At least \"unhelpful\"";
77
$thread_filter_styles['-2'] = "All posts";
79
$post_ratings['2'] = "Very helpful (+2)";
80
$post_ratings['1'] = "Helpful (+1)";
81
$post_ratings['0'] = "Neutral";
82
$post_ratings['-1'] = "Not helpful (-1)";
83
$post_ratings['-2'] = "Off topic (-2)";
85
$config = get_config();
86
$no_forum_rating = parse_bool($config, "no_forum_rating");
89
* Process a user-supplied title to remove HTML stuff
75
// A list of what kind of special users exist
76
define('S_MODERATOR', 0);
79
define('S_TESTER', 3);
80
define('S_VOLUNTEER', 4);
81
define('S_VOLUNTEER_TESTER', 5);
82
define('S_SCIENTIST', 6);
84
$special_user_bitfield[S_MODERATOR]="Forum moderator";
85
$special_user_bitfield[S_ADMIN]="Project administrator";
86
$special_user_bitfield[S_DEV]="Project developer";
87
$special_user_bitfield[S_TESTER]="Project tester";
88
$special_user_bitfield[S_VOLUNTEER]="Volunteer developer";
89
$special_user_bitfield[S_VOLUNTEER_TESTER]="Volunteer tester";
90
$special_user_bitfield[S_SCIENTIST]="Project scientist";
92
// show a banner with search form on left and PM info on right
94
function show_forum_header($user) {
95
start_table_noborder();
99
echo "<td><form action=\"forum_search_action.php\" method=\"POST\">
100
<input type=\"hidden\" name=\"search_max_time\" value=\"30\">
101
<input type=\"hidden\" name=\"search_forum\" value=\"-1\">
102
<input type=\"hidden\" name=\"search_sort\" value=\"5\">
103
<input type=\"text\" name=\"search_keywords\">
104
<input class=\"btn\" title=\"".tra("Search for words in forum messages")."\" type=\"submit\" value=\"".tra("Search forums")."\"><br>
105
<span class=\"smalltext\"><a href=\"forum_search.php\">".tra("Advanced search")."</a></span>
111
echo "<td align=\"right\">\n";
112
echo "<p>".tra("Private messages").": ", pm_notification($user);
119
// Output the forum/thread title.
121
function show_forum_title($category, $forum, $thread, $link_thread=false) {
123
$is_helpdesk = $category->is_helpdesk;
125
$is_helpdesk = false;
127
$where = $is_helpdesk?tra("Questions and Answers"):tra("Message boards");
128
$top_url = $is_helpdesk?"forum_help_desk.php":"forum_index.php";
129
if (!$forum && !$thread) {
130
echo "<span class=\"title\">$where</span>";
132
} else if ($forum && !$thread) {
133
echo "<span class=title>";
134
echo "<a href=\"$top_url\">$where</a> : ";
137
} else if ($forum && $thread) {
138
echo "<span class=title>
139
<a href=\"$top_url\">$where</a> :
140
<a href=\"forum_forum.php?id=".$forum->id."\">", $forum->title, "</a> :
143
echo "<a href=forum_thread.php?id=$thread->id>";
145
echo cleanup_title($thread->title);
151
echo "Invalid input to show_forum_title<br>";
152
echo "threadid $thread->id";
153
// TODO: handle this condition gracefully
157
function show_team_forum_title($forum, $thread=null, $link_thread=false) {
158
$team = BoincTeam::lookup_id($forum->category);
159
echo "<span class=title>
160
<a href=\"forum_index.php\">".tra("Message boards")."</a> :
164
<a href=team_forum.php?teamid=$team->id>".tra("%1 message board", $team->name)."</a>
167
echo " : <a href=forum_thread.php?id=$thread->id>$thread->title</a>";
169
echo " : $thread->title";
172
echo tra("%1 message board", $team->name);
177
// Start the forum table, output the proper headings and such.
179
function start_forum_table($headings, $extra="width=\"100%\"") {
182
start_table($extra." cellspacing=\"0\"");
185
for ($i=0; $i<count($headings); $i++) {
186
if (is_array($headings[$i])){
187
$title = $headings[$i][0];
188
$class = $headings[$i][1]?$headings[$i][1]:"heading";
189
if (isset($headings[$i][2])) {
190
$span = " colspan=\"".$headings[$i][2]."\" ";
193
$title = $headings[$i];
197
echo "<th class=$class$span>$title</th>";
202
// return a string containing a paged navigation bar
203
// for the given forum. The default start place is 0.
205
function show_page_nav($forum, $start=0){
206
// How many pages to potentially show before and after this one:
207
$preshow = 5; $postshow = 10;
210
if ($forum->threads > THREADS_PER_PAGE) {
211
$total = ceil($forum->threads / THREADS_PER_PAGE);
212
$curpage = ceil($start / THREADS_PER_PAGE);
213
// If this is not the first page, display "previous"
215
$navbar = '<a href="forum_forum.php?id='.get_int("id").'&start='.(($curpage-1)*THREADS_PER_PAGE);
216
$sort = get_int("sort",true);
217
if ($sort) $navbar.='&sort='.$sort;
218
$navbar.= '"> <-- Previous</a> ';
221
// Display a list of pages surrounding this one
222
for ($i=$curpage-$preshow;$i<($curpage+$postshow);$i++){
224
if ($i>$total) break;
225
// If this is the current page, emphasize it.
226
if ($i == $curpage+1){
229
$navbar.='<a href="forum_forum.php?id='.get_int("id").'&start='.(($i-1)*THREADS_PER_PAGE);
230
$sort = get_int("sort",true);
231
if ($sort) $navbar.='&sort='.$sort;
232
$navbar.='">'.$i.' |</a> ';
233
if ($i == $curpage+1){$navbar.="</em>";}
236
// If there is a next page
237
if ($curpage+1 < $total){
238
$navbar.= '<a href="forum_forum.php?id='.get_int("id").'&start='.(($curpage+1)*THREADS_PER_PAGE);
239
$sort = get_int("sort",true);
240
if ($sort) $navbar.='&sort='.$sort;
241
$navbar.= '"> Next --></a>';
248
function thread_last_visit($user, $thread) {
249
if (!$user) return false;
250
$log = BoincForumLogging::lookup($user->id, $thread->id);
251
return $log->timestamp;
254
function thread_is_unread($user, $thread) {
255
if (!$user) return false;
256
if ($thread->timestamp < $user->prefs->mark_as_read_timestamp) return false;
257
$log = BoincForumLogging::lookup($user->id, $thread->id);
258
if ($log && ($thread->timestamp < $log->timestamp)) return false;
262
// Process a user-supplied title to remove HTML stuff
91
264
function cleanup_title($title) {
92
265
$x = trim(htmlspecialchars($title));
93
266
$x = stripslashes($x); // clean up funky old titles in DB
99
* Check if user has special user bit enabled
101
function isSpecialUser($user, $specialbit){
102
return (substr($user->special_user, $specialbit,1)==1);
106
* Check to see if a specific user has rated a specific post before
108
function getHasRated($user, $postid){
109
return (strstr($user->rated_posts,"|".$postid));
113
* Get the user's preferred sorting style.
115
function getSortStyle($user,$place){
117
list($forum,$thread,$faq,$answer)=explode("|",$user->sorting);
271
function can_reply($thread, $forum, $user) {
272
if ($thread->locked) {
273
if (!is_moderator($user, $forum)) return false;
278
function should_show_post(
279
$logged_in_user, $postcount, $postnumber, $post, $sort_style, $last_visit
281
$no_wraparound = get_str("nowrap",true);
283
// If no user logged in, display everything (useful for Google bots etc)
285
if (!$logged_in_user) return true;
287
// If the user hasn't enabled the feature to display only
288
// a certain amount of posts, simply display all of them.
290
if (!$logged_in_user->prefs->minimum_wrap_postcount) return true;
292
// If the user has asked to display all the posts just display them
294
if ($no_wraparound) return true;
296
// If it is enabled and we havent yet hit the limit, simply display all
297
if ($postcount < $logged_in_user->prefs->minimum_wrap_postcount) return true;
299
// display the post if it is the first post
301
if ($postnumber==1 || $postnumber==($postcount+1)) return true;
303
// if this post is unread, show it
305
if ($post->timestamp > $last_visit) return true;
307
// The user can choose to display the last X posts in a thread only,
308
// "last" here depends on sorting criteria:
310
if ($sort_style == CREATE_TIME_OLD){
311
if ($postnumber > $postcount+1-$logged_in_user->prefs->display_wrap_postcount) return true;
312
} else if ($sort_style == CREATE_TIME_NEW){
313
if ($postnumber <= $logged_in_user->prefs->display_wrap_postcount) return true;
119
list($forum,$thread,$faq,$answer)=explode("|",$_COOKIE['sorting']);
315
// For other sorting criteria we do not know how to define "last"
316
// so simply display it all
121
return $$place; // Huh?
321
// In all other cases we should not show this particular post
125
/*** display functions ***/
128
* Show the posts in a thread for a user.
131
function show_posts($thread, $sort_style, $filter, $logged_in_user, $show_controls=true) {
325
// Show the posts in a thread for a user.
328
$thread, $forum, $sort_style, $filter, $logged_in_user, $show_controls=true
331
$first_unread_post = null;
134
334
if ($show_controls) {
135
335
$controls = FORUM_CONTROLS;
140
340
// If logged in user is moderator,
141
341
// let him see all posts - including hidden ones
142
if ($logged_in_user && $logged_in_user->isSpecialUser(S_MODERATOR)){
143
$show_hidden_posts = true;
343
if (is_moderator($logged_in_user, $forum)) {
145
$show_hidden_posts = false;
346
$show_hidden = false;
147
$posts = $thread->getPosts($sort_style, $show_hidden_posts);
348
$posts = get_thread_posts($thread->id, $sort_style, $show_hidden);
148
349
$postcount = (sizeof($posts)-1);
149
if ($logged_in_user) $last_visit = $thread->getLastReadTimestamp($logged_in_user);
350
if ($logged_in_user) {
351
$last_visit = thread_last_visit($logged_in_user, $thread);
151
354
$postnumber=0; $previous_post=0;
152
355
$no_wraparound = get_str("nowrap",true);
153
foreach ($posts as $key => $post){
156
// There *HAS* to be a better way to do this. WOW.
157
if ((!$logged_in_user) // If the user isn't logged in
158
|| (!$logged_in_user->getMinimumWrapPostcount()) //or If the user hasn't enabled the feature to display only a certain amount of posts, simply display all of them.
159
|| ($postcount < $logged_in_user->getMinimumWrapPostcount()) //If it is enabled and we havent yet hit the limit, simply display all
160
|| ($no_wraparound) // If the user has asked to display all the posts just display them
163
($postcount >= $logged_in_user->getMinimumWrapPostcount()) //If it is enabled and we have hit the limit AND we have the minimum wraparound number of posts or more
166
($postnumber==1 || $postnumber==($postcount+1)) // Let's display the post only if it is the first post
169
(($postnumber > $postcount+1-$logged_in_user->getDisplayWrapPostcount()) //or it is one of the last wrap_display_postcount posts.
170
&& ($sort_style==CREATE_TIME_OLD))
172
(($postnumber <= $logged_in_user->getDisplayWrapPostcount()) //or it is one of the last wrap_display_postcount posts.
173
&& ($sort_style==CREATE_TIME_NEW))
174
|| ($sort_style!=CREATE_TIME_NEW && $sort_style!=CREATE_TIME_OLD)
176
|| ($post->getTimestamp() > $last_visit) //or if this post is unread
180
if ($postnumber!=$previous_post+1){
181
//A number of posts were hidden, display a way to unhide them:
182
echo "<tr class=\"postseperator\"><td></td><td colspan=\"2\">
183
Only the first post and the last ".($logged_in_user->getDisplayWrapPostcount())." posts
356
foreach ($posts as $post){
358
if (should_show_post(
359
$logged_in_user, $postcount, $postnumber, $post,
360
$sort_style, $last_visit)
363
if ($postnumber!=$previous_post+1){
364
// A number of posts were hidden, display a way to unhide them:
366
echo "<tr class=\"postseperator\"><td></td><td colspan=\"2\">
367
Only the first post and the last ".($logged_in_user->prefs->display_wrap_postcount)." posts
184
368
(of the ".($postcount+1)." posts in this thread) are displayed. <br />
185
<a href=\"?id=".$thread->getID()."&nowrap=true\">Click here to also display the remaining posts</a>.</td></tr>";
187
$previous_post=$postnumber;
188
show_post($post, $thread, $logged_in_user, $n, $controls, $filter);
189
// To allow users to start reading a thread even though our DB layer is super slow
192
if (($post->getTimestamp()>$last_visit) &&
193
((!$first_unread_post) || ($post->getTimestamp()<$first_unread_post->getTimestamp()))
195
$first_unread_post=$post;
369
<a href=\"?id=".$thread->id."&nowrap=true\">Click here to also display the remaining posts</a>.</td></tr>
372
$previous_post=$postnumber;
373
show_post($post, $thread, $forum, $logged_in_user, $last_visit, $n, $controls, $filter);
376
if (($post->timestamp>$last_visit) &&
377
((!$first_unread_post) || ($post->timestamp<$first_unread_post->timestamp))
379
$first_unread_post=$post;
200
if ($logged_in_user && $logged_in_user->hasJumpToUnread()){
384
if ($logged_in_user && $logged_in_user->prefs->jump_to_unread){
201
385
if ($first_unread_post){
202
echo "<script>function jumpToUnread(){location.href='#".$first_unread_post->getID()."';}</script>";
386
echo "<script>function jumpToUnread(){location.href='#".$first_unread_post->id."';}</script>";
204
388
echo "<script>function jumpToUnread(){};</script>";
208
if ($logged_in_user) $thread->setLastReadTimestamp($logged_in_user);
212
* Display an individual post, as though in a thread.
214
function show_post($post, $thread, $logged_in_user, $n, $controls=FORUM_CONTROLS, $filter=true) {
215
$user = $post->getOwner();
216
global $no_forum_rating;
219
392
if ($logged_in_user) {
220
$tokens = url_tokens($logged_in_user->getAuthenticator());
223
//If the user that made this post is on the list of people to ignore, change thresholds to be much more strict
393
BoincForumLogging::replace($logged_in_user->id, $thread->id, time());
397
function get_ignored_list($user) {
398
return explode("|", $user->prefs->ignorelist);
401
function add_ignored_user($user, $other_user) {
402
$list = explode("|", $user->prefs->ignorelist);
403
foreach ($list as $key=>$userid) {
404
if ($userid == $other_user->id) {
408
$list[] = $other_user->id;
409
$x = implode("|", array_values($list));
410
return $user->prefs->update("ignorelist='$x'");
413
function remove_ignored_user($user, $other_user) {
414
$list = explode("|", $user->prefs->ignorelist);
415
foreach ($list as $key=>$userid) {
416
if ($userid == $other_user->id) {
420
$x = implode("|", array_values($list));
421
return $user->prefs->update("ignorelist='$x'");
424
function is_ignoring($user, $other_user) {
425
$list = explode("|", $user->prefs->ignorelist);
426
return in_array($other_user->id, $list);
429
// Display an individual post
432
$post, $thread, $forum, $logged_in_user, $last_visit, $n, $controls=FORUM_CONTROLS, $filter=true
434
$user = BoincUser::lookup_id($post->user);
435
BoincForumPrefs::lookup($user);
436
if (is_banished($user) && !is_moderator($logged_in_user, $forum)) {
440
$config = get_config();
441
$no_forum_rating = parse_bool($config, "no_forum_rating");
444
$rated_below_threshold = false;
445
$rated_above_threshold = false;
446
$options = get_output_options($logged_in_user);
448
//If the user that made this post is on the list of people to ignore,
449
// change thresholds to be much more strict
224
451
if ($logged_in_user){
225
if (in_array($user->getID(),$logged_in_user->getIgnoreList())){
452
$tokens = url_tokens($logged_in_user->authenticator);
453
if (is_ignoring($logged_in_user, $user)){
226
454
$user_is_on_ignorelist=true;
227
$rated_below_threshold = ($logged_in_user->getHighRatingThreshold()>$post->getRating());
228
$rated_above_threshold = ($logged_in_user->getHighRatingThreshold()+abs($logged_in_user->getLowRatingThreshold())<($post->getRating()));
455
$rated_below_threshold = ($logged_in_user->prefs->high_rating_threshold>$post->rating());
456
$rated_above_threshold = ($logged_in_user->prefs->high_rating_threshold+abs($logged_in_user->prefs->low_rating_threshold)<($post->rating));
229
457
} else { //Use normal threshold values
230
$rated_below_threshold = ($logged_in_user->getLowRatingThreshold()>($post->getRating()));
231
$rated_above_threshold = ($logged_in_user->getHighRatingThreshold()<($post->getRating()));
458
$rated_below_threshold = ($logged_in_user->prefs->low_rating_threshold>($post->rating()));
459
$rated_above_threshold = ($logged_in_user->prefs->high_rating_threshold<($post->rating()));
234
463
// The creator can edit the post, but only in a specified amount of time
235
464
// (exception: a moderator can edit his/her posts at any time)
237
466
$can_edit = false;
238
467
if ($logged_in_user) {
239
if ($user->getID() == $logged_in_user->getID()) {
240
if ($logged_in_user->isSpecialUser(S_MODERATOR)) {
468
if ($user->id == $logged_in_user->id) {
469
if (is_moderator($logged_in_user, $forum)) {
241
470
$can_edit = true;
242
} else if (can_reply($thread, $logged_in_user)) {
243
$time_limit = $post->getTimestamp()+MAXIMUM_EDIT_TIME;
471
} else if (can_reply($thread, $forum, $logged_in_user)) {
472
$time_limit = $post->timestamp+MAXIMUM_EDIT_TIME;
244
473
$can_edit = time()<$time_limit;
246
475
$can_edit = false;
264
491
$keys = array_keys($special_user_bitfield);
265
492
for ($i=0; $i<sizeof($special_user_bitfield);$i++) {
266
if ($user->isSpecialUser($keys[$i])) {
493
if ($user->prefs->privilege($keys[$i])) {
267
494
$fstatus.=$special_user_bitfield[$keys[$i]]."<br>";
270
if ($user->create_time>time()-ST_NEW_TIME) $fstatus.=ST_NEW."<br>";
497
if ($user->create_time > time()-ST_NEW_TIME) $fstatus.=ST_NEW."<br>";
271
498
if ($fstatus) echo "<font size=\"-2\">$fstatus</font>";
273
500
echo "<span class=\"authorinfo\">";
274
501
if (!$filter || !$rated_below_threshold){
275
if ($user->hasAvatar() && (!$logged_in_user || ($logged_in_user->hasHideAvatars()==false))) {
276
echo "<img width=\"".AVATAR_WIDTH."\" height=\"".AVATAR_HEIGHT."\" src=\"".$user->getAvatar()."\" alt=\"Avatar\"><br>";
502
if ($user->prefs->avatar!="" && (!$logged_in_user || ($logged_in_user->prefs->hide_avatars==false))) {
503
echo "<img width=\"".AVATAR_WIDTH."\" height=\"".AVATAR_HEIGHT."\" src=\"".$user->prefs->avatar."\" alt=\"Avatar\"><br>";
280
echo "<a href=\"forum_pm.php?action=new&userid=".$user->getID()."\" class=\"smalltext\">private message</a><br>\n";
281
echo "Joined: ", gmdate('M j, Y', $user->getCreateTime()), "<br>";
507
$url = "pm.php?action=new&userid=".$user->id;
509
show_button($url, "Send message", "Send $name a private message");
510
echo "<br>Joined: ", gmdate('M j y', $user->create_time), "<br>";
512
if (!isset($user->nposts)) {
513
$user->nposts = BoincPost::count("user=$user->id");
283
516
if(function_exists('project_forum_user_info')){
284
517
project_forum_user_info($user);
285
518
} else { // default
286
519
// circumvent various forms of identity spoofing
287
520
// by displaying the user id of the poster.
288
// its cheap, easy, and doesn't require any additional database calls.
289
echo "Posts: ".$user->getPostCount()."<br>";
290
echo "ID: ".$user->getID()."<br>";
291
echo "Credit: ".number_format($user->getTotalCredit())."<br>";
292
echo "RAC: ".number_format($user->getExpavgCredit())."<br>";
522
echo "Posts: $user->nposts<br>";
523
echo "ID: ".$user->id."<br>";
524
echo "Credit: ".number_format($user->total_credit)."<br>";
525
echo "RAC: ".number_format($user->expavg_credit)."<br>";
294
527
echo "</span></div></td>";
296
529
if ($controls == FORUM_CONTROLS) {
297
echo "<form action=\"forum_rate.php?post=", $post->getID(), "\" method=\"post\">";
298
530
echo "<td colspan=\"2\" class=\"postheader\">";
531
echo "<form action=\"forum_rate.php?post=", $post->id, "\" method=\"post\">";
300
533
echo "<td class=\"postheader\">";
303
if ($logged_in_user && $post->getTimestamp()>$thread->getLastReadTimestamp($logged_in_user)){
304
echo "<img src=\"".NEW_IMAGE."\" alt=\"Unread post\" height=\"".NEW_IMAGE_HEIGHT."\">";
536
if ($logged_in_user && $post->timestamp>$last_visit){
537
show_image(NEW_IMAGE, "You haven't read this message yet", "Unread", NEW_IMAGE_HEIGHT);
306
539
if ($rated_above_threshold){
307
echo "<img src=\"".EMPHASIZE_IMAGE."\" alt=\"!\" height=\"".EMPHASIZE_IMAGE_HEIGHT."\">";
540
show_image(EMPHASIZE_IMAGE, "This message has a high average rating", "Highly rated", EMPHASIZE_IMAGE_HEIGHT);
310
echo " <a href=\"forum_thread.php?id=".$thread->getID()."&nowrap=true#$post->id\">Message ".$post->getID()."</a> - ";
311
if ($post->isHidden()) echo "<font color=red>[deleted] </font>";
543
echo " <a href=\"forum_thread.php?id=".$thread->id."&nowrap=true#$post->id\">Message ".$post->id."</a> - ";
544
if ($post->hidden) echo "<font color=red>[hidden] </font>";
313
Posted ", pretty_time_str($post->getTimestamp());
546
Posted ", pretty_time_str($post->timestamp);
316
if ($post->getParentPostID()) echo " - in response to <a href=\"forum_thread.php?id=".$thread->getID()."&nowrap=true#".$post->getParentPostID()."\">Message ID ".$post->getParentPostID()."</a>.";
317
if ($can_edit && $controls != NO_CONTROLS) echo " <a href=\"forum_edit.php?id=".$post->getID()."$tokens\">[Edit this post]</a>";
318
if ($logged_in_user && $logged_in_user->isSpecialUser(S_MODERATOR)) echo post_moderation_links($config,$logged_in_user,$post,$tokens); //If user is moderator, show links
319
if ($post->getModificationTimestamp()) echo "<br>Last modified: ", pretty_time_Str($post->getModificationTimestamp());
549
if ($post->parent_post) {
550
echo " - in response to <a href=\"forum_thread.php?id=".$thread->id."&nowrap=true#".$post->parent_post."\">Message ID ".$post->parent_post."</a>.";
553
if ($can_edit && $controls != NO_CONTROLS) {
554
show_button("forum_edit.php?id=".$post->id."$tokens", "Edit", "Edit this message");
556
if (is_moderator($logged_in_user, $forum)) {
557
show_post_moderation_links($config, $logged_in_user, $post, $forum, $tokens);
559
if ($post->modified) {
560
echo "<br>Last modified: ", pretty_time_Str($post->modified);
320
562
if ($rated_below_threshold && $filter){
321
if ($user_is_on_ignorelist) $andtext=" and the user is on your ignore list";
322
echo "<br>This post has been filtered (rating: ".($post->getRating()).")$andtext, press <a href=\"?id=".$thread->getID()."&filter=false#".$post->getID()."\">here</a> to view this thread without filtering";
563
if ($user_is_on_ignorelist) {
564
$andtext=" and the user is on your ignore list";
566
echo "<br>This post has been filtered (rating: ".($post->rating()).")$andtext, press <a href=\"?id=".$thread->id."&filter=false#".$post->id."\">here</a> to view this thread without filtering";
324
568
echo "</td></tr></form>";
325
569
echo "<tr class=\"row$n\"><td class=\"postbody\" colspan=\"2\">";
327
//If either filtering is turned off or this post is not below the threshold
328
571
if (!$filter || !$rated_below_threshold){
329
$posttext = $post->getContent();
572
$posttext = $post->content;
331
574
// If the creator of this post has a signature and
332
575
// wants it to be shown for this post AND the logged in
333
576
// user has signatures enabled: show it
335
if ($post->hasSignature() && (!$logged_in_user || !$logged_in_user->hasHideSignatures())){
336
$posttext.="\n____________\n".$user->getSignature();
578
if ($post->signature && (!$logged_in_user || !$logged_in_user->prefs->hide_signatures)){
579
$posttext.="\n____________\n".$user->prefs->signature;
339
if ($logged_in_user){
340
$options = $logged_in_user->getTextTransformSettings();
342
$options = new output_options;
344
$posttext = output_transform($posttext,$options);
582
$posttext = output_transform($posttext, $options);
346
584
echo "<p>", $posttext, "</p>";
347
585
echo "</td></tr><tr><td class=\"postfooter\">ID: <i>", $post->id;
348
586
if ($no_forum_rating != NULL) {
349
echo " | <a href=\"forum_report_post.php?post=".$post->getID()."\"><img src=\"".REPORT_POST_IMAGE."\" alt=\"Report this post as offensive\" height=\"".REPORT_POST_IMAGE_HEIGHT."\" border=0></a></td>";
587
echo " | <a href=\"forum_report_post.php?post=".$post->id."\">";
588
show_image(REPORT_POST_IMAGE, "Report this post as offensive", "Report as offensive", REPORT_POST_IMAGE_HEIGHT);
351
$rating = $post->getRating();
352
echo " | Rating: ", $rating, "</i> | rate: <a href=\"forum_rate.php?post=".$post->getID()."&choice=p$tokens\"><img src=\"".RATE_POSITIVE_IMAGE."\" alt=\"+\" height=\"".RATE_POSITIVE_IMAGE_HEIGHT."\" border=0></a> / <a href=\"forum_rate.php?post=".$post->getID()."&choice=n$tokens\"><img src=\"".RATE_NEGATIVE_IMAGE."\" alt=\"-\" height=\"".RATE_NEGATIVE_IMAGE_HEIGHT."\" border=0></a> - <a href=\"forum_report_post.php?post=".$post->getID()."\"><img src=\"".REPORT_POST_IMAGE."\" alt=\"Report this post as offensive\" height=\"".REPORT_POST_IMAGE_HEIGHT."\" border=0></a></td>";
591
$rating = $post->rating();
592
echo " | Rating: ", $rating, "</i> | rate:
593
<a href=\"forum_rate.php?post=".$post->id."&choice=p$tokens\">
595
show_image(RATE_POSITIVE_IMAGE, "Click if you like this message", "Rate +", RATE_POSITIVE_IMAGE_HEIGHT);
596
echo "</a> / <a href=\"forum_rate.php?post=".$post->id."&choice=n$tokens\">";
597
show_image(RATE_NEGATIVE_IMAGE, "Click if you don't like this message", "Rate -", RATE_NEGATIVE_IMAGE_HEIGHT);
598
echo "</a> <a href=\"forum_report_post.php?post=".$post->id."\">";
599
show_image(REPORT_POST_IMAGE, "Report this post as offensive", "Report as offensive", REPORT_POST_IMAGE_HEIGHT);
354
if (($controls == FORUM_CONTROLS) && (can_reply($thread, $logged_in_user))) {
355
echo "<td align=right class=\"postfooter\">[<a href=\"forum_reply.php?thread=" . $thread->getID() . "&post=" . $post->getID() . "#input\">Reply to this post</a>]</td>";
602
if (($controls == FORUM_CONTROLS) && (can_reply($thread, $forum, $logged_in_user))) {
603
echo "<td align=right class=\"postfooter\">";
604
$url = "forum_reply.php?thread=" . $thread->id . "&post=" . $post->id . "#input";
605
show_button($url, "Reply", "Post a reply to this message");
357
608
echo "<td class=\"postfooter\"></td>";
612
echo "</td></tr><tr><td class=\"postfooter\" colspan=\"2\">";
362
614
echo "<tr class=\"postseperator\"><td colspan=3></td></tr>";
365
/*** utility functions ***/
368
* Start the forum table, output the proper headings and such.
370
function start_forum_table($headings, $extra="width=100%") {
371
start_table($extra." cellspacing=0 cellpadding=2");
374
for ($i=0; $i<count($headings); $i++) {
375
if (is_array($headings[$i])){
376
$title = $headings[$i][0];
377
$class = $headings[$i][1]?$headings[$i][1]:"heading";
378
if ($headings[$i][2]) $span = " colspan=\"".$headings[$i][2]."\" ";
380
$title = $headings[$i];
384
echo "<th class=$class$span>$title</th>";
390
* End the forum table, currently just close the open table tag.
392
function end_forum_table() {
397
* Output the forum/thread title.
399
function show_forum_title($forum=NULL, $thread=NULL, $extended=true) {
401
start_table_noborder();
405
echo "<td><form action=\"forum_search_action.php\" method=\"POST\">
406
<input type=\"hidden\" name=\"search_max_time\" value=\"30\">
407
<input type=\"hidden\" name=\"search_forum\" value=\"-1\">
408
<input type=\"hidden\" name=\"search_sort\" value=\"5\">
409
<input type=\"text\" name=\"search_keywords\">
410
<input type=\"submit\" value=\"search\"><br>
411
<span class=\"smalltext\"><a href=\"forum_search.php\">advanced search</a></span>
416
$logged_in_user = get_logged_in_user(false);
417
// Custom stuff for logged in user
418
if ($logged_in_user) {
419
echo "<td align=\"right\">\n";
422
echo pm_notification($logged_in_user);
432
$category = $forum->getCategory();
433
$is_helpdesk = $category->getType();
435
$is_helpdesk = false;
437
$where = $is_helpdesk?tr(LINKS_QA):tr(FORUM_TITLE_SHORT);
438
$top_url = $is_helpdesk?"forum_help_desk.php":"forum_index.php";
439
if (!$forum && !$thread) {
440
echo "<p class=\"title\">";
443
} else if ($forum && !$thread) {
444
echo "<span class=title>";
445
echo "<a href=\"$top_url\">$where</a> : ";
446
echo $forum->getTitle();
448
} else if ($forum && $thread) {
449
echo "<span class=title>";
450
echo "<a href=\"$top_url\">$where</a> : ";
452
echo "<a href=\"forum_forum.php?id=".$forum->getID()."\">", $forum->getTitle(), "</a> : ";
453
echo cleanup_title($thread->getTitle());
456
echo "Invalid input to show_forum_title<br>"; // TODO: handle this condition gracefully
462
* show a thread with its context (e.g. for search results)
464
function show_thread($thread, $n) {
465
$forum = getForum($thread->forum);
466
$category = getCategory($forum->category);
467
$first_post = getFirstPost($thread->id);
468
$title = cleanup_title($thread->title);
469
$where = $category->is_helpdesk?"Questions and answers":"Message boards";
470
$top_url = $category->is_helpdesk?"forum_help_desk.php":"forum_index.php";
471
$excerpt = sub_sentence(stripslashes($first_post->content), ' ', EXCERPT_LENGTH, true);
472
$posted = time_diff_str($thread->create_time, time());
473
$last = time_diff_str($thread->timestamp, time());
477
<td><font size=\"-2\">
483
<a href=\"$top_url\">$where</a> : $category->name :
484
<a href=\"forum_forum.php?id=$forum->id\">$forum->title</a> :
485
<a href=\"forum_thread.php?id=$thread->id\">$title</a>
487
<font size=\"-2\">$excerpt</font>
494
* Show a post with its context (e.g. for search results)
496
function show_post2($post, $n) {
497
$thread = getThread($post->thread);
498
$forum = getForum($thread->forum);
499
$category = getCategory($forum->category);
500
$where = $category->is_helpdesk?"Questions and answers":"Message boards";
501
$top_url = $category->is_helpdesk?"forum_help_desk.php":"forum_index.php";
502
$content = output_transform($post->content);
617
// Show a post and its context (e.g. for search results, user posts)
619
function show_post_and_context($post, $thread, $forum, $options, $n) {
620
$thread = BoincThread::lookup_id($post->thread);
621
$forum = BoincForum::lookup_id($thread->forum);
623
$content = output_transform($post->content, $options);
503
624
$when = time_diff_str($post->timestamp, time());
504
625
$user = lookup_user_id($post->user);
505
626
$title = cleanup_title($thread->title);
508
//Todo: factor this array out, it is also used elsewhere
509
$deleted_text = array( "Obscene", "Flame/Hate", "Commercial Spam", "Flamebait", "Doublepost", "User Request", "Other");
510
$deleted = "<br><font color=red>[Deleted " .
512
//as " . $deleted_text[$post->hidden-1] .
629
$deleted = "<br><font color=red>[Hidden by a moderator]</font>";
520
$n) <a href=\"$top_url\">$where</a> : $category->name :
521
<a href=\"forum_forum.php?id=$forum->id\">$forum->title</a> :
522
<a href=\"forum_thread.php?id=$thread->id\">$title</a>
524
Posted $when by $user->name $deleted
638
switch ($forum->parent_type) {
640
$category = BoincCategory::lookup_id($forum->category);
641
show_forum_title($category, $forum, $thread);
644
show_team_forum_title($forum);
648
(<a href=\"forum_thread.php?id=".$thread->id."&nowrap=true#".$post->id."\">Message ".$post->id."</a>)
650
Posted $when by ".user_links($user)." $deleted
657
function is_banished($user) {
658
return ($user->prefs->banished_until > time());
661
function check_banished($user) {
662
if (is_banished($user)) {
664
"You may not post or rate messages until ".gmdate('M j, Y', $user->prefs->banished_until)
533
669
function post_rules() {
670
if (function_exists("project_forum_post_rules")) {
671
$project_rules=project_forum_post_rules();
536
677
<li> Posts must be 'kid friendly': they may not contain
563
function check_banished($user) {
564
$x = $user->getBanishedUntil();
567
"You may not post or rate messages until ".gmdate('M j, Y', $x)
572
function can_reply($thread, $user) {
573
if (!$thread->isLocked() || ($user && $user->isSpecialUser(S_MODERATOR))) {
580
function pm_notification($user) {
582
$pm = mysql_query("SELECT COUNT(*) AS unread FROM private_messages WHERE userid=".$user->id." AND opened=0");
583
$pm = mysql_fetch_object($pm);
584
if ($pm->unread > 1) {
585
$output .= "<strong><a href=\"forum_pm.php?action=inbox\">You have ".$pm->unread." unread private messages.</a> </strong>";
586
} elseif ($pm->unread == 1) {
587
$output .= "<strong><a href=\"forum_pm.php?action=inbox\">You have one unread private message.</a> </strong>";
589
$output .= "You have no unread private messages. ";
592
$output .= "| <a href=\"forum_pm.php?action=inbox\">Inbox</a>\n";
593
$output .= "| <a href=\"forum_pm.php?action=new\">Write</a>\n";
705
function notify_subscriber($thread, $user) {
706
BoincForumPrefs::lookup($user);
707
if ($user->prefs->pm_notification == 1) {
708
send_reply_notification_email($thread, $user);
711
$type = NOTIFY_SUBSCRIBED_POST;
712
BoincNotify::replace("userid=$user->id, create_time=$now, type=$type, opaque=$thread->id");
715
// Various functions for adding/hiding/unhiding stuff.
716
// These take care of counts and timestamps.
717
// Don't do these things directly - use these functions
719
function create_post($content, $parent_id, $user, $forum, $thread, $signature) {
720
$content = substr($content, 0, 64000);
721
$content = mysql_real_escape_string($content);
723
$sig = $signature?1:0;
724
$id = BoincPost::insert("(thread, user, timestamp, content, parent_post, signature) values ($thread->id, $user->id, $now, '$content', $parent_id, $sig)");
725
if (!$id) return null;
727
// notify subscribed users
729
$subs = BoincSubscription::enum("threadid=$thread->id");
730
foreach ($subs as $sub) {
731
if ($user->id == $sub->userid) continue;
732
$user2 = BoincUser::lookup_id($sub->userid);
733
notify_subscriber($thread, $user2);
735
$user->update("posts=posts+1");
736
$thread->update("replies=replies+1, timestamp=$now");
737
$forum->update("posts=posts+1, timestamp=$now");
740
function create_thread($title, $content, $user, $forum, $signature) {
741
$title = trim($title);
742
$title = strip_tags($title);
743
$title = mysql_real_escape_string($title);
745
$id = BoincThread::insert("(forum, owner, title, create_time, timestamp, replies) values ($forum->id, $user->id, '$title', $now, $now, -1)");
746
if (!$id) return null;
747
$thread = BoincThread::lookup_id($id);
748
create_post($content, 0, $user, $forum, $thread, $signature);
749
$forum->update("threads=threads+1");
753
function hide_post($post, $thread, $forum) {
754
$post->update("hidden=1");
755
$thread->update("replies=replies-1");
756
return $forum->update("posts=posts-1");
759
function unhide_post($post, $thread, $forum) {
761
$post->update("hidden=0");
762
$thread->update("replies=replies+1, timestamp=$now");
763
return $forum->update("posts=posts+1, timestamp=$now");
766
function delete_post($post, $thread, $forum) {
768
$thread->update("replies=replies-1");
769
$forum->update("posts=posts-1");
770
$count = BoincPost::count("thread=$thread->id");
772
$forum->update("threads=threads-1");
777
function move_post($post, $old_thread, $old_forum, $new_thread, $new_forum) {
779
$post->update("thread=$new_thread->id");
780
$old_thread->update("replies=replies-1");
781
$new_thread->update("replies=replies+1, timestamp=$now");
782
$old_forum->update("posts=posts-1");
783
return $new_forum->update("posts=posts+1, timestamp=$now");
786
function hide_thread($thread, $forum) {
787
$thread->update("hidden=1");
788
$forum->update("threads=threads-1");
789
return $forum->update("posts=posts-$thread->replies-1");
792
function unhide_thread($thread, $forum) {
794
$thread->update("hidden=0");
795
return $forum->update("threads=threads+1, posts=posts+$thread->replies+1, timestamp=$now");
798
function move_thread($thread, $old_forum, $new_forum) {
800
$old_forum->update("threads=threads-1, posts=posts-$thread->replies-1");
801
$new_forum->update("threads=threads+1, posts=posts+$thread->replies+1, timestamp=$now");
802
return $thread->update("forum=$new_forum->id");
805
// $show_hidden: 1 if it is a moderator reading
806
// Error page if this function returns NULL.
810
// $sort_style - string (checked by switch statement)
811
// $show_hidden - bool (not directly passed to SQL)
812
// $sticky - bool (not directly passed to SQL)
814
function get_forum_threads(
815
$forumID, $start=-1, $nRec=-1, $sort_style=MODIFIED_NEW,
816
$show_hidden = 0, $sticky = 1
818
//if (! (is_numeric($forumID) && is_numeric($min) && is_numeric($nRec))) {
819
// return NULL; // Something is wrong here.
822
$sql = 'forum = ' . $forumID ;
824
$stickysql = "sticky DESC, ";
827
$sql .= ' AND hidden = 0';
829
switch($sort_style) {
831
$sql .= ' ORDER BY '.$stickysql.'timestamp DESC';
834
$sql .= ' ORDER BY '.$stickysql.'timestamp ASC';
837
$sql .= ' ORDER BY '.$stickysql.'views DESC';
840
$sql .= ' ORDER BY '.$stickysql.'replies DESC';
842
case CREATE_TIME_NEW:
843
$sql .= ' ORDER by '.$stickysql.'create_time desc';
845
case CREATE_TIME_OLD:
846
$sql .= ' ORDER by '.$stickysql.'create_time asc';
849
$sql .= ' ORDER by '.$stickysql.'sufferers desc';
852
$sql .= ' ORDER by '.$stickysql.'activity desc';
855
$sql .= ' ORDER by '.$stickysql.'score desc';
858
$sql .= ' ORDER BY '.$stickysql.'timestamp DESC';
862
$sql .= ' LIMIT '.$start;
866
} else if ($nRec > -1) {
867
$sql .= ' LIMIT '.$nRec;
869
return BoincThread::enum($sql);
872
// $show_hidden = true when it is a moderator reading
873
// error_page if this function returns NULL.
874
// $sort_style - string (checked by switch statement)
875
// $show_hidden - bool (not directly passed to SQL)
877
function get_thread_posts($threadid, $sort_style, $show_hidden) {
878
$sql = "thread=$threadid";
880
$sql .= ' AND hidden = 0';
882
switch($sort_style) {
883
case CREATE_TIME_NEW:
884
$sql .= ' ORDER BY timestamp desc';
886
case CREATE_TIME_OLD:
887
$sql .= ' ORDER BY timestamp asc';
890
$sql .= ' ORDER BY score DESC';
893
$sql .= ' ORDER BY timestamp asc';
896
return BoincPost::enum($sql);
899
// Show the links for possible moderation actions related to a single post
901
function show_post_moderation_links(
902
$config, $logged_in_user, $post, $forum, $tokens
904
$moderators_allowed_to_ban = parse_bool($config, "moderators_allowed_to_ban");
905
$moderators_vote_to_ban = parse_bool($config, "moderators_vote_to_ban");
908
show_button("forum_moderate_post_action.php?action=unhide&id=".$post->id."$tokens", "Unhide", "Unhide this post");
910
show_button("forum_moderate_post.php?action=hide&id=".$post->id."$tokens", "Hide", "Hide this post");
914
"forum_moderate_post.php?action=move&id=".$post->id."$tokens",
915
"Move", "Move post to a different thread"
918
if ($forum->parent_type == 0) {
919
if ($logged_in_user->prefs->privilege(S_ADMIN) || ($logged_in_user->prefs->privilege(S_MODERATOR) && $moderators_allowed_to_ban)) {
920
show_button("forum_moderate_post.php?action=banish_user&id=".$post->id."&userid=".$post->user."$tokens", "Banish author", "Banish author");
922
if ($logged_in_user->prefs->privilege(S_MODERATOR) && $moderators_vote_to_ban) {
923
require_once("../inc/forum_banishment_vote.inc");
924
if (vote_is_in_progress($post->user)) {
925
show_button("forum_banishment_vote.php?action=yes&userid=".$post->user, "Vote to banish author", "Vote to banish author");
926
show_button("forum_banishment_vote.php?action=no&userid=".$post->user, "Vote not to banish author", "Vote not to banish author");
928
show_button("forum_banishment_vote.php?action=start&userid=".$post->user, "Start vote to banish author", "Start vote to banish author");
934
function check_create_thread_access($user, $forum) {
935
if ($forum->is_dev_blog){
937
(!$user->prefs->privilege(S_SCIENTIST)) &&
938
(!$user->prefs->privilege(S_DEV)) &&
939
(!$user->prefs->privilege(S_ADMIN))
941
error_page("This forum is marked as a development blog, only people directly working with the project may start a new thread here. <br/>However, you may post a reply to an existing thread.");
944
check_post_access($user, $forum);
947
function check_post_access($user, $forum) {
948
switch ($forum->parent_type) {
950
if ($user->prefs->privilege(S_MODERATOR)) return;
953
$team = BoincTeam::lookup_id($forum->category);
954
if (is_team_admin($user, $team)) return;
956
// non-team-members can't post
958
if ($user->teamid != $team->id) {
959
error_page("Only team members can post to the team message board");
964
// If user haven't got enough credit (according to forum regulations)
965
// We do not tell the (ab)user how much this is -
966
// no need to make it easy for them to break the system.
968
if ($user->total_credit<$forum->post_min_total_credit || $user->expavg_credit<$forum->post_min_expavg_credit) {
969
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));
972
// If the user is posting faster than forum regulations allow
973
// Tell the user to wait a while before creating any more posts
975
if (time()-$user->prefs->last_post <$forum->post_min_interval) {
976
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."));
980
function check_reply_access($user, $forum, $thread) {
981
if ($thread->locked && !is_moderator($user, $forum)) {
983
"This thread is locked. Only forum moderators and administrators are allowed to post there."
986
if ($thread->hidden) {
988
"Can't post to a hidden thread."
992
check_post_access($user, $forum);
995
function is_moderator($user, $forum) {
996
if (!$user) return false;
997
switch ($forum->parent_type) {
999
if ($user->prefs->privilege(S_MODERATOR)) return true;
1000
if ($user->prefs->privilege(S_ADMIN)) return true;
1001
if ($user->prefs->privilege(S_DEV)) return true;
1004
if ($user->prefs->privilege(S_ADMIN)) return true;
1005
$team = BoincTeam::lookup_id($forum->category);
1006
return is_team_admin($user, $team);
1012
function show_thread_and_context_header() {
1013
start_forum_table(array(tra("Thread"), tra("Posts"), tra("Author"), tra("Views"), "<nobr>".tra("Last post")."</nobr>"));
1016
// show a 1-line summary of thread and its forum.
1017
// Used for search results and subscription list
1019
function show_thread_and_context($thread, $user) {
1020
$thread_forum = BoincForum::lookup_id($thread->forum);
1021
if (!$thread_forum) return;
1022
if (!is_forum_visible_to_user($thread_forum, $user)) return;
1023
$owner = BoincUser::lookup_id($thread->owner);
1025
switch($thread_forum->parent_type) {
1027
$category = BoincCategory::lookup_id($thread_forum->category);
1028
show_forum_title($category, $thread_forum, $thread, true);
1031
show_team_forum_title($thread_forum, $thread);
1035
</td><td>'.($thread->replies+1).'</td>
1036
<td align="left"><div class="authorcol">'.user_links($owner).'</div></td>
1037
<td>'.$thread->views.'</td>
1038
<td style="text-align:right">'.time_diff_str($thread->timestamp, time()).'</td>
1043
// see if thread is in subscription list
1045
function is_subscribed($thread, $subs) {
1046
foreach ($subs as $sub) {
1047
if ($sub->threadid == $thread->id) return true;
1052
function is_forum_visible_to_user($forum, $user) {
1053
if ($forum->parent_type == 1) {
1054
if (parse_config(get_config(), "<team_forums_members_only>")) {
1055
if (!$user) return false;
1056
if ($user->teamid != $forum->category) return false;
1062
function subscribed_post_email_line($notify) {
1063
$thread = BoincThread::lookup_id($notify->opaque);
1064
return "There are new posts in the thread '$thread->title'";
1067
function subscribed_post_web_line($notify) {
1068
$thread = BoincThread::lookup_id($notify->opaque);
1069
return "New posts in the thread <a href=forum_thread.php?id=$thread->id>$thread->title</a>";
1072
function subscribe_rss($notify, &$title, &$msg, &$url) {
1073
$thread = BoincThread::lookup_id($notify->opaque);
1074
$title = "New posts in subscribed thread";
1075
$msg = "There are new posts in the thread '$thread->title'";
1076
$url = URL_BASE."forum_thread.php?id=$thread->id";
1079
function show_mark_as_read_button($user) {
1081
$return = urlencode(current_url());
1082
$tokens = url_tokens($user->authenticator);
1083
$url = "forum_index.php?read=1$tokens&return=$return";
1084
show_button($url, tra("Mark all threads as read"), tra("Mark all threads in all message boards as 'read'."));