comment.inc 12.4 KB
Newer Older
Dries's avatar
   
Dries committed
1
<?php
2
// $Id$
Dries's avatar
Dries committed
3

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

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

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

Dries's avatar
   
Dries committed
26
function comment_moderate($moderate) {
Dries's avatar
   
Dries committed
27
  global $user;
Dries's avatar
   
Dries committed
28

Dries's avatar
   
Dries committed
29
  if ($user->uid && $moderate) {
Dries's avatar
   
Dries committed
30
31
32
33
34
35
36
    foreach ($moderate as $cid => $score) {
      if ($score > 0 && $score < 6) {
        if (db_fetch_object(db_query("SELECT * FROM moderate WHERE uid = '". check_query($user->uid) ."' AND cid = '". check_query($cid) ."'"))) {
          db_query("UPDATE moderate SET score = '". check_query($score) ."' WHERE uid = '". check_query($user->uid) ."' AND cid = '". check_query($cid) ."'");
        }
        else {
          db_query("INSERT INTO moderate (uid, cid, score, timestamp) VALUES ('". check_query($user->uid) ."', '". check_query($cid) ."', '". check_query($score) ."', '". time() ."')");
Dries's avatar
   
Dries committed
37
        }
Dries's avatar
   
Dries committed
38
39
40
41
42
43
44
      }
    }
  }
}

function comment_settings($mode, $order, $threshold) {
  global $user;
Dries's avatar
   
Dries committed
45
46
47
48

  if ($user->uid) {
    $user = user_save($user, array("mode" => $mode, "sort" => $order, "threshold" => $threshold));
  }
Dries's avatar
   
Dries committed
49
50
}

natrak's avatar
Changes    
natrak committed
51
function comment_form($edit) {
Dries's avatar
   
Dries committed
52
  global $user;
natrak's avatar
Changes    
natrak committed
53

Dries's avatar
   
Dries committed
54
  // name field:
Dries's avatar
   
Dries committed
55
  $form .= form_item(t("Your name"), format_name($user));
natrak's avatar
Changes    
natrak committed
56

Dries's avatar
   
Dries committed
57
  // subject field:
Dries's avatar
   
Dries committed
58
  $form .= form_textfield(t("Subject"), "subject", $edit[subject], 50, 64);
natrak's avatar
Changes    
natrak committed
59

Dries's avatar
   
Dries committed
60
  // comment field:
Dries's avatar
   
Dries committed
61
  $form .= form_textarea(t("Comment"), "comment", $edit[comment] ? $edit[comment] : $user->signature, 70, 10, t("Allowed HTML tags") .": ". htmlspecialchars(variable_get("allowed_html", "")));
natrak's avatar
Changes    
natrak committed
62

Dries's avatar
   
Dries committed
63
  // preview button:
Dries's avatar
   
Dries committed
64
65
  $form .= form_hidden("pid", $edit[pid]);
  $form .= form_hidden("id", $edit[id]);
natrak's avatar
Changes    
natrak committed
66

Dries's avatar
   
Dries committed
67
  if (!$edit[comment]) {
natrak's avatar
Changes    
natrak committed
68
69
70
71
72
73
    $form .= form_submit(t("Preview comment"));
  }
  else {
    $form .= form_submit(t("Preview comment"));
    $form .= form_submit(t("Post comment"));
  }
Dries's avatar
   
Dries committed
74

Dries's avatar
   
Dries committed
75
  return form($form);
natrak's avatar
Changes    
natrak committed
76
77
}

Dries's avatar
   
Dries committed
78
function comment_reply($pid, $id) {
natrak's avatar
Changes    
natrak committed
79
  global $theme;
Dries's avatar
   
Dries committed
80
81

  if ($pid) {
Dries's avatar
   
Dries committed
82
    $item = db_fetch_object(db_query("SELECT c.*, u.uid, u.name FROM comments c LEFT JOIN users u ON c.uid = u.uid WHERE c.cid = '$pid'"));
Dries's avatar
   
Dries committed
83
    comment_view(new Comment($item->uid, $item->name, $item->subject, $item->comment, $item->timestamp, $item->url, $item->cid, $item->lid), t("reply to this comment"));
Dries's avatar
   
Dries committed
84
  }
Dries's avatar
   
Dries committed
85
  else {
Dries's avatar
   
Dries committed
86
    node_view(node_load(array("nid" => $id)));
Dries's avatar
   
Dries committed
87
88
    $pid = 0;
  }
Dries's avatar
   
Dries committed
89

Dries's avatar
   
Dries committed
90
  if (user_access("post comments")) {
Dries's avatar
   
Dries committed
91
92
93
94
95
    $theme->box(t("Reply"), comment_form(array(pid=>$pid, id=>$id)));
  }
  else {
    $theme->box(t("Reply"), t("You are not authorized to post comments."));
  }
Dries's avatar
   
Dries committed
96
97
}

natrak's avatar
Changes    
natrak committed
98
function comment_preview($edit) {
Dries's avatar
   
Dries committed
99
  global $theme, $user;
Dries's avatar
   
Dries committed
100
101

  // Preview comment:
Dries's avatar
   
Dries committed
102
  comment_view(new Comment($user->uid, $user->name, check_preview($edit[subject]), check_preview($edit[comment]), time(), check_preview($user->homepage), 0, 0, 0, 0), t("reply to this comment"));
Dries's avatar
   
Dries committed
103

natrak's avatar
Changes    
natrak committed
104
  $theme->box(t("Reply"), comment_form($edit));
Dries's avatar
   
Dries committed
105
106
}

natrak's avatar
Changes    
natrak committed
107
function comment_post($edit) {
Dries's avatar
   
Dries committed
108
  global $theme, $user;
Dries's avatar
   
Dries committed
109

Dries's avatar
   
Dries committed
110
  if (user_access("post comments")) {
Dries's avatar
   
Dries committed
111
112
    // check comment submission rate:
    throttle("post comment", variable_get(max_comment_rate, 60));
Dries's avatar
   
Dries committed
113

Dries's avatar
   
Dries committed
114
115
    // check for duplicate comments:
    $duplicate = db_result(db_query("SELECT COUNT(cid) FROM comments WHERE pid = '". check_input($edit[pid]) ."' AND lid = '". check_input($edit[id]) ."' AND subject = '". check_input($edit[subject]) ."' AND comment = '". check_input($edit[comment]) ."'"), 0);
Dries's avatar
   
Dries committed
116

Dries's avatar
   
Dries committed
117
    if ($duplicate != 0) {
Dries's avatar
   
Dries committed
118
      watchdog("warning", "comment: duplicate '$edit[subject]'");
Dries's avatar
   
Dries committed
119
120
121
    }
    else {
      // validate subject:
Dries's avatar
   
Dries committed
122
      $edit[subject] = $edit[subject] ? $edit[subject] : substr($edit[comment], 0, 29);
Dries's avatar
   
Dries committed
123

Dries's avatar
   
Dries committed
124
      // add watchdog entry:
Dries's avatar
   
Dries committed
125
      watchdog("special", "comment: added '$edit[subject]'");
Dries's avatar
   
Dries committed
126

Dries's avatar
   
Dries committed
127
      // add comment to database:
Dries's avatar
   
Dries committed
128
      db_query("INSERT INTO comments (lid, pid, uid, subject, comment, hostname, timestamp) VALUES ('". check_input($edit[id]) ."', '". check_input($edit[pid]) ."', '$user->uid', '". check_input($edit[subject]) ."', '". check_input($edit[comment]) ."', '". getenv("REMOTE_ADDR") ."', '". time() ."')");
Dries's avatar
   
Dries committed
129
130
131

      // clear cache:
      cache_clear();
Dries's avatar
   
Dries committed
132
    }
Dries's avatar
   
Dries committed
133
134
135
136
  }
}

function comment_num_replies($id, $count = 0) {
Dries's avatar
   
Dries committed
137

Dries's avatar
   
Dries committed
138
  $result = db_query("SELECT COUNT(cid) FROM comments WHERE pid = '$id'");
Dries's avatar
   
Dries committed
139
  return ($result) ? db_result($result, 0) : 0;
Dries's avatar
   
Dries committed
140

Dries's avatar
   
Dries committed
141
}
Dries's avatar
   
Dries committed
142

Dries's avatar
   
Dries committed
143
function comment_moderation($comment) {
Dries's avatar
   
Dries committed
144
  global $user;
Dries's avatar
   
Dries committed
145

Dries's avatar
   
Dries committed
146
147
148
149
150
151
  $values = array("--", 1, 2, 3, 4, 5);

  $moderate = db_fetch_object(db_query("SELECT * FROM moderate WHERE cid = '$comment->cid' AND uid = '$user->uid'"));

  foreach ($values as $key => $value) {
    $options .= " <option value=\"$key\"". ($moderate->score == $key ? " selected=\"selected\"" : "") .">$value</option>\n";
Dries's avatar
   
Dries committed
152
153
  }

Dries's avatar
   
Dries committed
154
 $output .= "<select name=\"moderate[comment][$comment->cid]\">$options</select><br />". ($comment->score ? $comment->score : "--") ." / $comment->votes";
Dries's avatar
   
Dries committed
155

Dries's avatar
   
Dries committed
156
157
158
159
  return $output;
}

function comment_threshold($threshold) {
Dries's avatar
   
Dries committed
160
161
  for ($i = 0; $i < 6; $i++) $options .= " <option value=\"$i\"". ($threshold == $i ? " SELECTED" : "") .">". t("Visibility") ." - $i</option>";
  return "<select name=\"threshold\">$options</select>\n";
Dries's avatar
   
Dries committed
162
163
164
165
}

function comment_mode($mode) {
  global $cmodes;
Dries's avatar
   
Dries committed
166
167
168

  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
169
170
171
172
}

function comment_order($order) {
  global $corder;
Dries's avatar
   
Dries committed
173
174
175

  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
176
177
}

Dries's avatar
   
Dries committed
178
function comment_query($lid, $order, $pid = -1) {
Dries's avatar
   
Dries committed
179

Dries's avatar
   
Dries committed
180
  $query .= "SELECT c.cid, c.pid, c.lid, c.subject, c.comment, c.timestamp, u.uid, u.name, AVG(m.score) AS score, COUNT(m.cid) AS votes FROM comments c LEFT JOIN users u ON c.uid = u.uid LEFT JOIN moderate m ON c.cid = m.cid WHERE c.lid = '$lid'";
Dries's avatar
   
Dries committed
181
182
183
184
185

  if ($pid >= 0) {
    $query .= " AND pid = '$pid'";
  }

Dries's avatar
   
Dries committed
186
  $query .= " GROUP BY c.cid, c.pid, c.lid, c.subject, c.comment, c.timestamp, u.uid, u.name";
Dries's avatar
   
Dries committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200

  if ($order == 1) {
    $query .= " ORDER BY c.timestamp DESC";
  }
  else if ($order == 2) {
    $query .= " ORDER BY c.timestamp";
  }
  else if ($order == 3) {
    $query .= " ORDER BY score DESC";
  }
  else if ($order == 4) {
    $query .= " ORDER BY score";
  }

Dries's avatar
   
Dries committed
201
202
203
204
  return db_query($query);

}

Dries's avatar
   
Dries committed
205
206
207
208
209
210
211
function comment_visible($comment, $threshold = 0) {
  if ($comment->votes == 0 || $comment->score >= $threshold) {
    return 1;
  }
  else {
    return 0;
  }
Dries's avatar
   
Dries committed
212
213
}

Dries's avatar
   
Dries committed
214
function comment_links($comment, $return = 1) {
Dries's avatar
   
Dries committed
215
  global $theme;
Dries's avatar
   
Dries committed
216
217
218
219
220
221
222

  if ($return) {
    return "<a href=\"node.php?id=$comment->lid#$comment->cid\"><font color=\"$theme->type\">". t("return") ."</font></a> | <a href=\"node.php?op=reply&id=$comment->lid&pid=$comment->cid\"><font color=\"$theme->type\">". t("reply to this comment") ."</font></a>";
  }
  else {
    return "<a href=\"node.php?op=reply&id=$comment->lid&pid=$comment->cid\"><font color=\"$theme->type\">". t("reply to this comment") ."</font></a>";
  }
Dries's avatar
   
Dries committed
223
224
}

Dries's avatar
   
Dries committed
225
function comment_view($comment, $folded = 0) {
Dries's avatar
   
Dries committed
226
  global $theme;
Dries's avatar
   
Dries committed
227

Dries's avatar
   
Dries committed
228
229
230
231
232
233
  if ($folded) {
    $theme->comment($comment, $folded);
  }
  else {
    print "<a href=\"node.php?id=$comment->lid&cid=$comment->cid#$comment->cid\">". check_output($comment->subject) ."</a> by ". format_name($comment) ." <small>(". ($comment->score ? $comment->score : "--") ." / $comment->votes)</small><p />";
  }
Dries's avatar
   
Dries committed
234
235
236
}

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

Dries's avatar
   
Dries committed
239
  $result = db_query("SELECT c.cid, c.pid, c.lid, c.subject, c.comment, c.timestamp, u.uid, u.name, AVG(m.score) AS score, COUNT(m.cid) AS votes FROM comments c LEFT JOIN users u ON c.uid = u.uid LEFT JOIN moderate m ON c.cid = m.cid WHERE c.pid = '$cid' GROUP BY c.cid, c.pid, c.lid, c.subject, c.comment, c.timestamp, u.uid, u.name ORDER BY c.timestamp");
Dries's avatar
   
Dries committed
240
241

  while ($comment = db_fetch_object($result)) {
natrak's avatar
natrak committed
242
    print "<ul>";
Dries's avatar
   
Dries committed
243
    print comment_view($comment);
Dries's avatar
   
Dries committed
244
    comment_thread_min($comment->cid, $threshold);
natrak's avatar
natrak committed
245
    print "</ul>";
Dries's avatar
   
Dries committed
246
247
248
249
  }
}

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

Dries's avatar
   
Dries committed
252
  /*
Dries's avatar
   
Dries committed
253
254
255
256
257
258
  ** We had quite a few browser specific issues: expanded comments below
  ** the top level got truncated on the right hand side.  A range of
  ** solutions have been proposed and tried but either the right margins of
  ** the comments didn't line up well, or the heavily nested tables made
  ** for slow rendering and cluttered HTML.  This is the best work-around
  ** in terms of speed and size.
Dries's avatar
   
Dries committed
259
260
  */

Dries's avatar
   
Dries committed
261
  $result = db_query("SELECT c.cid, c.pid, c.lid, c.subject, c.comment, c.timestamp, u.uid, u.name, AVG(m.score) AS score, COUNT(m.cid) AS votes FROM comments c LEFT JOIN users u ON c.uid = u.uid LEFT JOIN moderate m ON c.cid = m.cid WHERE c.pid = '$cid' GROUP BY c.cid, c.pid, c.lid, c.subject, c.comment, c.timestamp, u.uid, u.name ORDER BY c.timestamp");
Dries's avatar
   
Dries committed
262
263

  while ($comment = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
264
    print "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td width=\"". ($level * 25) ."\">&nbsp;</td><td>\n";
Dries's avatar
   
Dries committed
265
    comment_view($comment, (comment_visible($comment, $threshold) ? comment_links($comment, 0) : 0));
Dries's avatar
   
Dries committed
266
    print "</td></tr></table>\n";
Dries's avatar
   
Dries committed
267
268

    comment_thread_max($comment->cid, $mode, $threshold, $level + 1, $dummy + 1);
Dries's avatar
   
Dries committed
269
270
  }

Dries's avatar
   
Dries committed
271
272
273
}

function comment_render($lid, $cid) {
Dries's avatar
   
Dries committed
274
  global $user, $theme, $mode, $order, $threshold, $REQUEST_URI;
Dries's avatar
   
Dries committed
275

Dries's avatar
   
Dries committed
276
  if (user_access("access comments")) {
Dries's avatar
   
Dries committed
277

Dries's avatar
   
Dries committed
278
    /*
Dries's avatar
   
Dries committed
279
    ** Pre-process variables:
Dries's avatar
   
Dries committed
280
    */
Dries's avatar
   
Dries committed
281

Dries's avatar
   
Dries committed
282
283
284
285
286
    if (empty($lid)) {
      $lid = 0;
    }

    if (empty($cid)) {
Dries's avatar
   
Dries committed
287
      $cid = 0;
Dries's avatar
   
Dries committed
288
289
290
291
292
    }

    if (empty($mode)) {
      $mode = $user->uid ? $user->mode : variable_get(default_comment_mode, 4);
    }
Dries's avatar
   
Dries committed
293

Dries's avatar
   
Dries committed
294
295
296
297
298
299
300
301
    if (empty($order)) {
      $order = $user->uid ? $user->sort : variable_get(default_comment_order, 1);
    }

    if (empty($threshold)) {
      $threshold = $user->uid ? $user->threshold : variable_get(default_comment_threshold, 3);
    }

Dries's avatar
   
Dries committed
302
303
    print "<form method=\"post\" action=\"$REQUEST_URI\">\n";

Dries's avatar
   
Dries committed
304
    /*
Dries's avatar
   
Dries committed
305
    ** Render control panel:
Dries's avatar
   
Dries committed
306
307
    */

Dries's avatar
   
Dries committed
308
    $theme->box(t("Control panel"), $theme->comment_controls($threshold, $mode, $order));
Dries's avatar
   
Dries committed
309
310

    if ($cid > 0) {
Dries's avatar
   
Dries committed
311
      $result = db_query("SELECT c.cid, c.pid, c.lid, c.subject, c.comment, c.timestamp, u.uid, u.name, AVG(m.score) AS score, COUNT(m.cid) AS votes  FROM comments c LEFT JOIN users u ON c.uid = u.uid LEFT JOIN moderate m ON c.cid = m.cid WHERE c.cid = '$cid' GROUP BY c.cid, c.pid, c.lid, c.subject, c.comment, c.timestamp, u.uid, u.name");
Dries's avatar
   
Dries committed
312
      if ($comment = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
313
        comment_view($comment, comment_links($comment));
Dries's avatar
   
Dries committed
314
315
      }
    }
Dries's avatar
   
Dries committed
316
317
318
    else {
      if ($mode == 1) {
        $result = comment_query($lid, $order);
Dries's avatar
   
Dries committed
319
320
        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";
Dries's avatar
   
Dries committed
321
322
        while ($comment = db_fetch_object($result)) {
          if (comment_visible($comment, $threshold)) {
Dries's avatar
   
Dries committed
323
            print " <tr><td><a href=\"node.php?id=$comment->lid&cid=$comment->cid#$comment->cid\">". check_output($comment->subject) ."</a></td><td>". format_name($comment) ."</td><td>". format_date($comment->timestamp, "small") ."</td><td>$comment->score</td></tr>\n";
Dries's avatar
   
Dries committed
324
325
          }
        }
Dries's avatar
   
Dries committed
326
        print "</table>\n";
Dries's avatar
   
Dries committed
327
      }
Dries's avatar
   
Dries committed
328
329
330
      else if ($mode == 2) {
        $result = comment_query($lid, $order);
        while ($comment = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
331
          comment_view($comment, (comment_visible($comment, $threshold) ? comment_links($comment, 0) : 0));
Dries's avatar
   
Dries committed
332
        }
Dries's avatar
   
Dries committed
333
      }
Dries's avatar
   
Dries committed
334
335
336
337
338
339
340
341
342
343
      else if ($mode == 3) {
        $result = comment_query($lid, $order, 0);
        while ($comment = db_fetch_object($result)) {
          comment_view($comment);
          comment_thread_min($comment->cid, $threshold);
        }
      }
      else {
        $result = comment_query($lid, $order, 0);
        while ($comment = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
344
          comment_view($comment, (comment_visible($comment, $threshold) ? comment_links($comment, 0) : 0));
Dries's avatar
   
Dries committed
345
346
          comment_thread_max($comment->cid, $mode, $threshold, $level + 1);
        }
Dries's avatar
   
Dries committed
347
348
      }
    }
Dries's avatar
   
Dries committed
349

Dries's avatar
   
Dries committed
350
351
    print "</form>";

Dries's avatar
   
Dries committed
352
353
  }
}
Dries's avatar
   
Dries committed
354

Dries's avatar
   
Dries committed
355
?>