comment.inc 13.4 KB
Newer Older
Dries's avatar
 
Dries committed
1
<?php
Dries's avatar
Dries committed
2

Dries's avatar
 
Dries committed
3 4
// Security check:
if (strstr($id, " ") || strstr($pid, " ") || strstr($lid, " ") || strstr($mode, " ") || strstr($order, " ") || strstr($threshold, " ")) {
Dries's avatar
 
Dries committed
5
  watchdog("error", "comment: attempt to provide malicious input through URI");
Dries's avatar
 
Dries committed
6 7 8 9
  exit();
}

$cmodes = array(1 => "List - min", 2 => "List - max", 3 => "Threaded - min", 4 => "Threaded - max");
Dries's avatar
 
Dries committed
10
$corder = array(1 => "Date - new", 2 => "Date - old", 3 => "Rate - high", 4 => "Rate - low");
Dries's avatar
 
Dries committed
11

Dries's avatar
Dries committed
12
class Comment {
Dries's avatar
 
Dries committed
13
  function Comment($userid, $subject, $comment, $timestamp, $url, $fake_email, $score, $votes, $cid, $lid) {
Dries's avatar
Dries committed
14 15 16 17 18 19 20 21 22
    $this->userid = $userid;
    $this->subject = $subject;
    $this->comment = $comment;
    $this->timestamp = $timestamp;
    $this->url = $url;
    $this->fake_email = $fake_email;
    $this->score = $score;
    $this->votes = $votes;
    $this->cid = $cid;
Dries's avatar
 
Dries committed
23
    $this->lid = $lid;
Dries's avatar
Dries committed
24 25 26
  }
}

Dries's avatar
 
Dries committed
27 28 29 30 31 32 33
function comment_moderate($moderate) {
  global $user, $comment_votes;

  if ($user->id && $moderate) {
    $none = $comment_votes[key($comment_votes)];

    foreach ($moderate as $id=>$vote) {
Dries's avatar
 
Dries committed
34
      if ($vote != $comment_votes[$none] && !user_get($user, "history", "c$id")) {
Dries's avatar
 
Dries committed
35
        // Update the comment's score:
Dries's avatar
 
Dries committed
36
        $result = db_query("UPDATE comments SET score = score ". check_input($vote) .", votes = votes + 1 WHERE cid = '". check_input($id) ."'");
Dries's avatar
 
Dries committed
37 38

        // Update the user's history:
Dries's avatar
 
Dries committed
39
        $user = user_set($user, "history", "c$id", $vote);
Dries's avatar
 
Dries committed
40 41 42 43 44 45 46
      }
    }
  }
}

function comment_settings($mode, $order, $threshold) {
  global $user;
Dries's avatar
 
Dries committed
47
  if ($user->id) $user = user_save($user, array("mode" => $mode, "sort" => $order, "threshold" => $threshold));
Dries's avatar
 
Dries committed
48 49 50
}

function comment_reply($pid, $id) {
Dries's avatar
 
Dries committed
51
  global $allowed_html, $REQUEST_URI, $theme, $user;
Dries's avatar
 
Dries committed
52 53

  if ($pid) {
Dries's avatar
 
Dries committed
54
    $item = db_fetch_object(db_query("SELECT comments.*, users.userid FROM comments LEFT JOIN users ON comments.author = users.id WHERE comments.cid = '$pid'"));
Dries's avatar
 
Dries committed
55
    comment_view(new Comment($item->userid, $item->subject, $item->comment, $item->timestamp, $item->url, $item->fake_email, comment_score($comment), $comment->votes, $item->cid, $item->lid), t("reply to this comment"));
Dries's avatar
 
Dries committed
56
  }
Dries's avatar
 
Dries committed
57
  else $pid = 0;
Dries's avatar
 
Dries committed
58 59

  // Build reply form:
60
  $output .= "<FORM ACTION=\"$REQUEST_URI\" METHOD=\"post\">\n";
Dries's avatar
 
Dries committed
61 62

  // Name field:
Dries's avatar
 
Dries committed
63 64
  $output .= "<B>". t("Your name") .":</B><BR>\n";
  $output .= format_username($user->userid) ."<P>\n";
Dries's avatar
 
Dries committed
65 66

  // Subject field:
Dries's avatar
 
Dries committed
67 68
  $output .= "<B>". t("Subject") .":</B><BR>\n";
  $output .= "<INPUT TYPE=\"text\" NAME=\"subject\" SIZE=\"50\" MAXLENGTH=\"60\"><P>\n";
Dries's avatar
 
Dries committed
69 70

  // Comment field:
Dries's avatar
 
Dries committed
71 72 73
  $output .= "<B>".t("Comment") .":</B><BR>\n";
  $output .= "<TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"10\" NAME=\"comment\">". check_textarea($user->signature) ."</TEXTAREA><BR>\n";
  $output .= "<SMALL><I>". t("Allowed HTML tags") .": ". htmlspecialchars($allowed_html) .".</I></SMALL><P>\n";
Dries's avatar
 
Dries committed
74

Dries's avatar
 
Dries committed
75
  // Preview button:
Dries's avatar
 
Dries committed
76 77 78 79
  $output .= "<SMALL><I>". t("You must preview at least once before you can submit") .":</I></SMALL><BR>\n";
  $output .= "<INPUT TYPE=\"hidden\" NAME=\"pid\" VALUE=\"$pid\">\n";
  $output .= "<INPUT TYPE=\"hidden\" NAME=\"id\" VALUE=\"$id\">\n";
  $output .= "<INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"". t("Preview comment") ."\"><BR>\n";
Dries's avatar
 
Dries committed
80 81 82

  $output .= "</FORM>\n";

Dries's avatar
 
Dries committed
83
  $theme->box(t("Reply"), $output);
Dries's avatar
 
Dries committed
84 85 86
}

function comment_preview($pid, $id, $subject, $comment) {
Dries's avatar
 
Dries committed
87
  global $allowed_html, $REQUEST_URI, $theme, $user;
Dries's avatar
 
Dries committed
88 89

  // Preview comment:
Dries's avatar
 
Dries committed
90
  comment_view(new Comment($user->userid, $subject, $comment, time(), $user->url, $user->fake_email, 0, 0, 0, 0), t("reply to this comment"));
Dries's avatar
 
Dries committed
91 92

  // Build reply form:
93
  $output .= "<FORM ACTION=\"$REQUEST_URI\" METHOD=\"post\">\n";
Dries's avatar
 
Dries committed
94 95

  // Name field:
Dries's avatar
 
Dries committed
96 97
  $output .= "<B>". t("Your name") .":</B><BR>\n";
  $output .= format_username($user->userid) ."<P>\n";
Dries's avatar
 
Dries committed
98 99

  // Subject field:
Dries's avatar
 
Dries committed
100 101
  $output .= "<B>". t("Subject") .":</B><BR>\n";
  $output .= "<INPUT TYPE=\"text\" NAME=\"subject\" SIZE=\"50\" MAXLENGTH=\"60\" VALUE=\"". check_textfield($subject) ."\"><P>\n";
Dries's avatar
 
Dries committed
102 103

  // Comment field:
Dries's avatar
 
Dries committed
104 105 106
  $output .= "<B>". t("Comment") .":</B><BR>\n";
  $output .= "<TEXTAREA WRAP=\"virtual\" COLS=\"50\" ROWS=\"10\" NAME=\"comment\">". check_textarea($comment) ."</TEXTAREA><BR>\n";
  $output .= "<SMALL><I>". t("Allowed HTML tags") .": ". htmlspecialchars($allowed_html) .".</I></SMALL><P>\n";
Dries's avatar
 
Dries committed
107

Dries's avatar
 
Dries committed
108 109 110 111 112
  // Hidden fields:
  $output .= "<INPUT TYPE=\"hidden\" NAME=\"pid\" VALUE=\"$pid\">\n";
  $output .= "<INPUT TYPE=\"hidden\" NAME=\"id\" VALUE=\"$id\">\n";

  if (empty($subject)) {
Dries's avatar
 
Dries committed
113
    $output .= "<FONT COLOR=\"red\">". t("Warning: you did not supply a subject.") ."</FONT><P>\n";
Dries's avatar
 
Dries committed
114 115 116
  }

  // Preview and submit button:
Dries's avatar
 
Dries committed
117 118 119
  $output .= "<INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"". t("Preview comment") ."\">\n";
  $output .= "<INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"". t("Post comment") ."\">\n";
  $output .= "</FORM>\n";
Dries's avatar
 
Dries committed
120

Dries's avatar
 
Dries committed
121
  $theme->box(t("Reply"), $output);
Dries's avatar
 
Dries committed
122 123 124
}

function comment_post($pid, $id, $subject, $comment) {
Dries's avatar
 
Dries committed
125
  global $theme, $user;
Dries's avatar
 
Dries committed
126 127

  // Check for duplicate comments:
Dries's avatar
 
Dries committed
128
  $duplicate = db_result(db_query("SELECT COUNT(cid) FROM comments WHERE pid = '$pid' AND lid = '$id' AND subject = '$subject' AND comment = '$comment'"), 0);
Dries's avatar
 
Dries committed
129 130

  if ($duplicate != 0) {
Dries's avatar
 
Dries committed
131
    watchdog("warning", "comment: duplicate '$subject'");
Dries's avatar
 
Dries committed
132
  }
Dries's avatar
 
Dries committed
133
  else {
Dries's avatar
 
Dries committed
134 135 136 137
    // Validate subject:
    $subject = ($subject) ? $subject : substr($comment, 0, 29);

    // Add watchdog entry:
Dries's avatar
 
Dries committed
138
    watchdog("comment", "comment: added '$subject'");
Dries's avatar
 
Dries committed
139 140

    // Add comment to database:
Dries's avatar
 
Dries committed
141
    db_query("INSERT INTO comments (lid, pid, author, subject, comment, hostname, timestamp, score) VALUES ('$id', '$pid', '$user->id', '$subject', '$comment', '". getenv("REMOTE_ADDR") ."', '". time() ."', '". ($user->userid ? 1 : 0) ."')");
Dries's avatar
 
Dries committed
142 143 144 145 146 147 148 149 150
  }
}

function comment_score($comment) {
  $value = ($comment->votes) ? ($comment->score / $comment->votes) : (($comment->score) ? $comment->score : 0);
  return ((strpos($value, ".")) ? substr($value ."00", 0, 4) : $value .".00");
}

function comment_num_replies($id, $count = 0) {
Dries's avatar
 
Dries committed
151
  $result = db_query("SELECT COUNT(cid) FROM comments WHERE pid = '$id'");
Dries's avatar
 
Dries committed
152 153
  return ($result) ? db_result($result, 0) : 0;
}
Dries's avatar
 
Dries committed
154

Dries's avatar
 
Dries committed
155 156 157 158 159 160
function comment_num_filtered($lid, $pid) {
  global $user;

  $threshold = ($user->id) ? $user->threshold  : "0";
  $pid = ($pid) ? $pid : 0;

Dries's avatar
 
Dries committed
161
  $result = db_query("SELECT COUNT(cid) FROM comments WHERE lid = '$lid' AND pid = '$pid' AND ((votes = 0 AND score < $threshold) OR (score / votes < $threshold))");
Dries's avatar
 
Dries committed
162 163 164 165 166 167 168
  return ($result) ? db_result($result, 0) : 0;
}

function comment_moderation($comment) {
  global $comment_votes, $op, $user;

  if ($op == "reply") {
Dries's avatar
 
Dries committed
169
    // preview comment:
Dries's avatar
 
Dries committed
170 171
    $output .= "&nbsp;";
  }
Dries's avatar
 
Dries committed
172
  else if ($user->id && $user->userid != $comment->userid && !user_get($user, "history", "c$comment->cid")) {
Dries's avatar
 
Dries committed
173 174 175
    // comment hasn't been moderated yet:
    foreach ($comment_votes as $key=>$value) $options .= " <OPTION VALUE=\"$value\">$key</OPTION>\n";
    $output .= "<SELECT NAME=\"moderate[$comment->cid]\">$options</SELECT>\n";
Dries's avatar
 
Dries committed
176 177
  }
  else {
Dries's avatar
 
Dries committed
178
    // comment has already been moderated:
Dries's avatar
 
Dries committed
179
    $output .= "<TABLE BORDER=\"0\" CELLSPACING=\"1\" CELLPADDING=\"1\"><TR><TD ALIGN=\"right\">". t("score") .":</TD><TD>". check_output($comment->score) ."</TD></TR><TR><TD ALIGN=\"right\">". t("votes") .":</TD><TD>". check_output($comment->votes) ."</TR></TABLE>\n";
Dries's avatar
 
Dries committed
180 181 182 183 184
  }

  return $output;
}

Dries's avatar
 
Dries committed
185 186
function comment_controls($threshold = 1, $mode = 3, $order = 1) {
  global $REQUEST_URI, $user;
Dries's avatar
 
Dries committed
187 188
  $output .= "<FONT SIZE=\"2\">\n";
  $output .= "<FORM METHOD=\"post\" ACTION=\"$REQUEST_URI\">\n";
Dries's avatar
 
Dries committed
189 190 191
  $output .= comment_mode(($user->id ? $user->mode : $mode));
  $output .= comment_order(($user->id ? $user->sort : $order));
  $output .= comment_threshold(($user->id ? $user->threshold : $threshold));
Dries's avatar
 
Dries committed
192
  $output .= "<INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"". t("Update settings") ."\">\n";
Dries's avatar
 
Dries committed
193 194 195 196 197 198
  $output .= "</FORM>\n";
  $output .= "</FONT>\n";
  return $output;
}

function comment_threshold($threshold) {
Dries's avatar
 
Dries committed
199 200
  for ($i = -1; $i < 6; $i++) $options .= " <OPTION VALUE=\"$i\"". ($threshold == $i ? " SELECTED" : "") .">". t("Filter") ." - $i</OPTION>";
  return "<SELECT NAME=\"threshold\">$options</SELECT>\n";
Dries's avatar
 
Dries committed
201 202 203 204
}

function comment_mode($mode) {
  global $cmodes;
Dries's avatar
 
Dries committed
205 206
  foreach ($cmodes as $key=>$value) $options .= " <OPTION VALUE=\"$key\"". ($mode == $key ? " SELECTED" : "") .">$value</OPTION>\n";
  return "<SELECT NAME=\"mode\">$options</SELECT>\n";
Dries's avatar
 
Dries committed
207 208 209 210
}

function comment_order($order) {
  global $corder;
Dries's avatar
 
Dries committed
211 212
  foreach ($corder as $key=>$value) $options .= " <OPTION VALUE=\"$key\"". ($order == $key ? " SELECTED" : "") .">$value</OPTION>\n";
  return "<SELECT NAME=\"order\">$options</SELECT>\n";
Dries's avatar
 
Dries committed
213 214
}

Dries's avatar
 
Dries committed
215 216
function comment_query($lid, $order, $pid = -1) {
  $query .= "SELECT c.*, u.* FROM comments c LEFT JOIN users u ON c.author = u.id WHERE c.lid = '$lid'";
Dries's avatar
 
Dries committed
217
  if ($pid >= 0) $query .= " AND pid = '$pid'";
Dries's avatar
 
Dries committed
218
  if ($order == 1) $query .= " ORDER BY c.timestamp DESC";
Dries's avatar
 
Dries committed
219 220 221
  else if ($order == 2) $query .= " ORDER BY c.timestamp";
  else if ($order == 3) $query .= " ORDER BY c.score DESC";
  else if ($order == 4) $query .= " ORDER BY c.score";
Dries's avatar
 
Dries committed
222 223 224 225 226 227 228 229 230 231
  return db_query($query);
}

function comment_visible($comment, $threshold = 0) {
  if ($comment->votes == 0 && $comment->score >= $threshold) return 1;
  else if ($comment->votes > 0 && $comment->score / $comment->votes >= $threshold) return 1;
  else return 0;
}

function comment_uri($args = 0) {
Dries's avatar
 
Dries committed
232 233 234
  global $mod;
  if ($args) return ($mod) ? "module.php?mod=$mod;$args" : "node.php?$args";
  else return ($mod) ? "module.php?mod=$mod" : "node.php";
Dries's avatar
 
Dries committed
235 236 237
}

function comment_link($comment, $return = 1) {
Dries's avatar
 
Dries committed
238 239 240
  global $theme;
  if ($return) return "<A HREF=\"". comment_uri("id=$comment->lid#$comment->cid") ."\"><FONT COLOR=\"$theme->type\">". t("return") ."</FONT></A> | <A HREF=\"". comment_uri("op=reply&id=$comment->lid&pid=$comment->cid") ."\"><FONT COLOR=\"$theme->type\">". t("reply to this comment") ."</FONT></A>";
  else return "<A HREF=\"". comment_uri("op=reply&id=$comment->lid&pid=$comment->cid") ."\"><FONT COLOR=\"$theme->type\">". t("reply to this comment") ."</FONT></A>";
Dries's avatar
 
Dries committed
241 242
}

Dries's avatar
 
Dries committed
243
function comment_view($comment, $folded = 0) {
Dries's avatar
 
Dries committed
244
  global $theme;
Dries's avatar
 
Dries committed
245 246 247 248 249

  // calculate comment's score:
  $comment->score = comment_score($comment);

  // display comment:
Dries's avatar
 
Dries committed
250
  if ($folded) $theme->comment($comment, $folded);
Dries's avatar
 
Dries committed
251
  else print "<A HREF=\"". comment_uri("id=$comment->lid&cid=$comment->cid#$comment->cid") ."\">". check_output($comment->subject) ."</A> by ". format_username($comment->userid) ." <SMALL>($comment->score)</SMALL><P>";
Dries's avatar
 
Dries committed
252 253 254
}

function comment_thread_min($cid, $threshold) {
Dries's avatar
 
Dries committed
255
  global $user;
Dries's avatar
 
Dries committed
256

Dries's avatar
 
Dries committed
257
  $result = db_query("SELECT c.*, u.* FROM comments c LEFT JOIN users u ON c.author = u.id WHERE c.pid = '$cid' ORDER BY c.timestamp, c.cid");
Dries's avatar
 
Dries committed
258 259 260

  print "<UL>";
  while ($comment = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
261
    comment_view($comment);
Dries's avatar
 
Dries committed
262 263 264 265 266 267
    comment_thread_min($comment->cid, $threshold);
  }
  print "</UL>";
}

function comment_thread_max($cid, $mode, $threshold, $level = 0, $dummy = 0) {
Dries's avatar
 
Dries committed
268
  global $user;
Dries's avatar
 
Dries committed
269

Dries's avatar
 
Dries committed
270
  $result = db_query("SELECT c.*, u.* FROM comments c LEFT JOIN users u ON c.author = u.id WHERE c.pid = '$cid' ORDER BY c.timestamp, c.cid");
Dries's avatar
 
Dries committed
271 272 273

  print "<UL>";
  while ($comment = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
274
    comment_view($comment, (comment_visible($comment, $threshold) ? comment_link($comment, 0) : 0));
Dries's avatar
 
Dries committed
275 276 277 278 279 280
    comment_thread_max($comment->cid, $mode, $threshold, $level + 1, $dummy + 1);
  }
  print "</UL>";
}

function comment_render($lid, $cid) {
Dries's avatar
 
Dries committed
281
  global $theme, $REQUEST_URI, $user;
Dries's avatar
 
Dries committed
282 283

  // Pre-process variables:
Dries's avatar
 
Dries committed
284
  $lid = empty($lid) ? 0 : $lid;
Dries's avatar
 
Dries committed
285 286 287 288 289 290
  $cid = empty($cid) ? 0 : $cid;
  $mode  = ($user->id) ? $user->mode : 4;
  $order = ($user->id) ? $user->sort : 1;
  $threshold = ($user->id) ? $user->threshold : 3;

  if ($user->id) {
Dries's avatar
 
Dries committed
291 292 293
    // Comment control:
    $theme->controls($threshold, $mode, $order);

Dries's avatar
 
Dries committed
294 295 296 297 298
    // Print moderation form:
    print "<FORM METHOD=\"post\" ACTION=\"$REQUEST_URI\">\n";
  }

  if ($cid > 0) {
Dries's avatar
 
Dries committed
299
    $result = db_query("SELECT c.*, u.* FROM comments c LEFT JOIN users u ON c.author = u.id WHERE cid = '$cid'");
Dries's avatar
 
Dries committed
300
    if ($comment = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
301
      comment_view($comment, comment_link($comment));
Dries's avatar
 
Dries committed
302 303 304 305
    }
  }
  else {
    if ($mode == 1) {
Dries's avatar
 
Dries committed
306
      $result = comment_query($lid, $order);
Dries's avatar
 
Dries committed
307 308 309 310
      print "<TABLE BORDER=\"0\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
      print " <TR><TH>Subject</TH><TH>Author</TH><TH>Date</TH><TH>Score</TH></TR>\n";
      while ($comment = db_fetch_object($result)) {
        if (comment_visible($comment, $threshold)) {
Dries's avatar
 
Dries committed
311
          print " <TR><TD><A HREF=\"". comment_uri("id=$comment->lid;cid=$comment->cid#$comment->cid") ."\">". check_output($comment->subject) ."</A></TD><TD>". format_username($comment->userid) ."</TD><TD>". format_date($comment->timestamp, "small") ."</TD><TD>". comment_score($comment) ."</TD></TR>\n";
Dries's avatar
 
Dries committed
312 313 314 315 316
        }
      }
      print "</TABLE>\n";
    }
    else if ($mode == 2) {
Dries's avatar
 
Dries committed
317
      $result = comment_query($lid, $order);
Dries's avatar
 
Dries committed
318
      while ($comment = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
319
        comment_view($comment, (comment_visible($comment, $threshold) ? comment_link($comment, 0) : 0));
Dries's avatar
 
Dries committed
320 321 322
      }
    }
    else if ($mode == 3) {
Dries's avatar
 
Dries committed
323
      $result = comment_query($lid, $order, 0);
Dries's avatar
 
Dries committed
324
      while ($comment = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
325
        comment_view($comment);
Dries's avatar
 
Dries committed
326 327 328 329
        comment_thread_min($comment->cid, $threshold);
      }
    }
    else {
Dries's avatar
 
Dries committed
330
      $result = comment_query($lid, $order, 0);
Dries's avatar
 
Dries committed
331
      while ($comment = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
332
        comment_view($comment, (comment_visible($comment, $threshold) ? comment_link($comment, 0) : 0));
Dries's avatar
 
Dries committed
333 334 335 336
        comment_thread_max($comment->cid, $mode, $threshold, $level + 1);
      }
    }
  }
Dries's avatar
 
Dries committed
337

Dries's avatar
 
Dries committed
338 339
  if ($user->id) {
    // Print moderation form:
Dries's avatar
 
Dries committed
340 341
    print "  <INPUT TYPE=\"hidden\" NAME=\"id\" VALUE=\"$lid\">\n";
    print "  <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"". t("Moderate comments") ."\">\n";
Dries's avatar
 
Dries committed
342 343 344 345 346
    print "</FORM>\n";
  }
}

?>