source: trunk/include/functions_comment.inc.php @ 28913

Last change on this file since 28913 was 28893, checked in by mistic100, 10 years ago

feature 3095 : block comment if website_url is not empty when field is disabled

  • Property svn:eol-style set to LF
File size: 14.6 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2014 Piwigo Team                  http://piwigo.org |
6// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
7// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
8// +-----------------------------------------------------------------------+
9// | This program is free software; you can redistribute it and/or modify  |
10// | it under the terms of the GNU General Public License as published by  |
11// | the Free Software Foundation                                          |
12// |                                                                       |
13// | This program is distributed in the hope that it will be useful, but   |
14// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
15// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
16// | General Public License for more details.                              |
17// |                                                                       |
18// | You should have received a copy of the GNU General Public License     |
19// | along with this program; if not, write to the Free Software           |
20// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
21// | USA.                                                                  |
22// +-----------------------------------------------------------------------+
23
24/**
25 * @package functions\comment
26 */
27
28
29add_event_handler('user_comment_check', 'user_comment_check');
30
31/**
32 * Does basic check on comment and returns action to perform.
33 * This method is called by a trigger_change()
34 *
35 * @param string $action before check
36 * @param array $comment
37 * @return string validate, moderate, reject
38 */
39function user_comment_check($action, $comment)
40{
41  global $conf,$user;
42
43  if ($action=='reject')
44    return $action;
45
46  $my_action = $conf['comment_spam_reject'] ? 'reject':'moderate';
47
48  if ($action==$my_action)
49    return $action;
50
51  // we do here only BASIC spam check (plugins can do more)
52  if ( !is_a_guest() )
53    return $action;
54
55  $link_count = preg_match_all( '/https?:\/\//',
56    $comment['content'], $matches);
57
58  if ( strpos($comment['author'], 'http://')!==false )
59  {
60    $link_count++;
61  }
62
63  if ( $link_count>$conf['comment_spam_max_links'] )
64  {
65    $_POST['cr'][] = 'links';
66    return $my_action;
67  }
68  return $action;
69}
70
71/**
72 * Tries to insert a user comment and returns action to perform.
73 *
74 * @param array &$comm
75 * @param string $key secret key sent back to the browser
76 * @param array &$infos output array of error messages
77 * @return string validate, moderate, reject
78 */
79function insert_user_comment(&$comm, $key, &$infos)
80{
81  global $conf, $user;
82
83  $comm = array_merge( $comm,
84    array(
85      'ip' => $_SERVER['REMOTE_ADDR'],
86      'agent' => $_SERVER['HTTP_USER_AGENT']
87    )
88   );
89
90  $infos = array();
91  if (!$conf['comments_validation'] or is_admin())
92  {
93    $comment_action='validate'; //one of validate, moderate, reject
94  }
95  else
96  {
97    $comment_action='moderate'; //one of validate, moderate, reject
98  }
99
100  // display author field if the user status is guest or generic
101  if (!is_classic_user())
102  {
103    if ( empty($comm['author']) )
104    {
105      if ($conf['comments_author_mandatory'])
106      {
107        $infos[] = l10n('Username is mandatory');
108        $comment_action='reject';
109      }
110      $comm['author'] = 'guest';
111    }
112    $comm['author_id'] = $conf['guest_id'];
113    // if a guest try to use the name of an already existing user, he must be
114    // rejected
115    if ( $comm['author'] != 'guest' )
116    {
117      $query = '
118SELECT COUNT(*) AS user_exists
119  FROM '.USERS_TABLE.'
120  WHERE '.$conf['user_fields']['username']." = '".addslashes($comm['author'])."'";
121      $row = pwg_db_fetch_assoc( pwg_query( $query ) );
122      if ( $row['user_exists'] == 1 )
123      {
124        $infos[] = l10n('This login is already used by another user');
125        $comment_action='reject';
126      }
127    }
128  }
129  else
130  {
131    $comm['author'] = addslashes($user['username']);
132    $comm['author_id'] = $user['id'];
133  }
134
135  if ( empty($comm['content']) )
136  { // empty comment content
137    $comment_action='reject';
138  }
139
140  if ( !verify_ephemeral_key(@$key, $comm['image_id']) )
141  {
142    $comment_action='reject';
143    $_POST['cr'][] = 'key'; // rvelices: I use this outside to see how spam robots work
144  }
145
146  // website
147  if (!empty($comm['website_url']))
148  {
149    if (!$conf['comments_enable_website'])
150    { // honeypot: if the field is disabled, it should be empty !
151      $comment_action='reject';
152      $_POST['cr'][] = 'website_url';
153    }
154    else
155    {
156      $comm['website_url'] = strip_tags($comm['website_url']);
157      if (!preg_match('/^https?/i', $comm['website_url']))
158      {
159        $comm['website_url'] = 'http://'.$comm['website_url'];
160      }
161      if (!url_check_format($comm['website_url']))
162      {
163        $infos[] = l10n('Your website URL is invalid');
164        $comment_action='reject';
165      }
166    }
167  }
168
169  // email
170  if (empty($comm['email']))
171  {
172    if (!empty($user['email']))
173    {
174      $comm['email'] = $user['email'];
175    }
176    else if ($conf['comments_email_mandatory'])
177    {
178      $infos[] = l10n('Email address is missing. Please specify an email address.');
179      $comment_action='reject';
180    }
181  }
182  else if (!email_check_format($comm['email']))
183  {
184    $infos[] = l10n('mail address must be like xxx@yyy.eee (example : jack@altern.org)');
185    $comment_action='reject';
186  }
187
188  // anonymous id = ip address
189  $ip_components = explode('.', $comm['ip']);
190  if (count($ip_components) > 3)
191  {
192    array_pop($ip_components);
193  }
194  $comm['anonymous_id'] = implode('.', $ip_components);
195
196  if ($comment_action!='reject' and $conf['anti-flood_time']>0 and !is_admin())
197  { // anti-flood system
198    $reference_date = pwg_db_get_flood_period_expression($conf['anti-flood_time']);
199
200    $query = '
201SELECT count(1) FROM '.COMMENTS_TABLE.'
202  WHERE date > '.$reference_date.'
203    AND author_id = '.$comm['author_id'];
204    if (!is_classic_user())
205    {
206      $query.= '
207      AND anonymous_id = "'.$comm['anonymous_id'].'"';
208    }
209    $query.= '
210;';
211
212    list($counter) = pwg_db_fetch_row(pwg_query($query));
213    if ( $counter > 0 )
214    {
215      $infos[] = l10n('Anti-flood system : please wait for a moment before trying to post another comment');
216      $comment_action='reject';
217      $_POST['cr'][] = 'flood_time';
218    }
219  }
220
221  // perform more spam check
222  $comment_action = trigger_change('user_comment_check',
223      $comment_action, $comm
224    );
225
226  if ( $comment_action!='reject' )
227  {
228    $query = '
229INSERT INTO '.COMMENTS_TABLE.'
230  (author, author_id, anonymous_id, content, date, validated, validation_date, image_id, website_url, email)
231  VALUES (
232    \''.$comm['author'].'\',
233    '.$comm['author_id'].',
234    \''.$comm['anonymous_id'].'\',
235    \''.$comm['content'].'\',
236    NOW(),
237    \''.($comment_action=='validate' ? 'true':'false').'\',
238    '.($comment_action=='validate' ? 'NOW()':'NULL').',
239    '.$comm['image_id'].',
240    '.(!empty($comm['website_url']) ? '\''.$comm['website_url'].'\'' : 'NULL').',
241    '.(!empty($comm['email']) ? '\''.$comm['email'].'\'' : 'NULL').'
242  )
243';
244    pwg_query($query);
245    $comm['id'] = pwg_db_insert_id(COMMENTS_TABLE);
246
247    invalidate_user_cache_nb_comments();
248
249    if ( ($conf['email_admin_on_comment'] && 'validate' == $comment_action)
250        or ($conf['email_admin_on_comment_validation'] and 'moderate' == $comment_action))
251    {
252      include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
253
254      $comment_url = get_absolute_root_url().'comments.php?comment_id='.$comm['id'];
255
256      $keyargs_content = array(
257        get_l10n_args('Author: %s', stripslashes($comm['author']) ),
258        get_l10n_args('Email: %s', stripslashes($comm['email']) ),
259        get_l10n_args('Comment: %s', stripslashes($comm['content']) ),
260        get_l10n_args(''),
261        get_l10n_args('Manage this user comment: %s', $comment_url),
262      );
263
264      if ('moderate' == $comment_action)
265      {
266        $keyargs_content[] = get_l10n_args('(!) This comment requires validation');
267      }
268
269      pwg_mail_notification_admins(
270        get_l10n_args('Comment by %s', stripslashes($comm['author']) ),
271        $keyargs_content
272      );
273    }
274  }
275
276  return $comment_action;
277}
278
279/**
280 * Tries to delete a (or more) user comment.
281 *    only admin can delete all comments
282 *    other users can delete their own comments
283 *
284 * @param int|int[] $comment_id
285 * @return bool false if nothing deleted
286 */
287function delete_user_comment($comment_id)
288{
289  $user_where_clause = '';
290  if (!is_admin())
291  {
292    $user_where_clause = '   AND author_id = \''.$GLOBALS['user']['id'].'\'';
293  }
294
295  if (is_array($comment_id))
296    $where_clause = 'id IN('.implode(',', $comment_id).')';
297  else
298    $where_clause = 'id = '.$comment_id;
299
300  $query = '
301DELETE FROM '.COMMENTS_TABLE.'
302  WHERE '.$where_clause.
303$user_where_clause.'
304;';
305
306  if ( pwg_db_changes(pwg_query($query)) )
307  {
308    invalidate_user_cache_nb_comments();
309
310    email_admin('delete',
311                array('author' => $GLOBALS['user']['username'],
312                      'comment_id' => $comment_id
313                  ));
314    trigger_notify('user_comment_deletion', $comment_id);
315
316    return true;
317  }
318
319  return false;
320}
321
322/**
323 * Tries to update a user comment
324 *    only admin can update all comments
325 *    users can edit their own comments if admin allow them
326 *
327 * @param array $comment
328 * @param string $post_key secret key sent back to the browser
329 * @return string validate, moderate, reject
330 */
331
332function update_user_comment($comment, $post_key)
333{
334  global $conf, $page;
335
336  $comment_action = 'validate';
337
338  if ( !verify_ephemeral_key($post_key, $comment['image_id']) )
339  {
340    $comment_action='reject';
341  }
342  elseif (!$conf['comments_validation'] or is_admin()) // should the updated comment must be validated
343  {
344    $comment_action='validate'; //one of validate, moderate, reject
345  }
346  else
347  {
348    $comment_action='moderate'; //one of validate, moderate, reject
349  }
350
351  // perform more spam check
352  $comment_action =
353    trigger_change('user_comment_check',
354                  $comment_action,
355                  array_merge($comment,
356                              array('author' => $GLOBALS['user']['username'])
357                              )
358                  );
359
360  // website
361  if (!empty($comment['website_url']))
362  {
363    $comm['website_url'] = strip_tags($comm['website_url']);
364    if (!preg_match('/^https?/i', $comment['website_url']))
365    {
366      $comment['website_url'] = 'http://'.$comment['website_url'];
367    }
368    if (!url_check_format($comment['website_url']))
369    {
370      $page['errors'][] = l10n('Your website URL is invalid');
371      $comment_action='reject';
372    }
373  }
374
375  if ( $comment_action!='reject' )
376  {
377    $user_where_clause = '';
378    if (!is_admin())
379    {
380      $user_where_clause = '   AND author_id = \''.
381        $GLOBALS['user']['id'].'\'';
382    }
383
384    $query = '
385UPDATE '.COMMENTS_TABLE.'
386  SET content = \''.$comment['content'].'\',
387      website_url = '.(!empty($comment['website_url']) ? '\''.$comment['website_url'].'\'' : 'NULL').',
388      validated = \''.($comment_action=='validate' ? 'true':'false').'\',
389      validation_date = '.($comment_action=='validate' ? 'NOW()':'NULL').'
390  WHERE id = '.$comment['comment_id'].
391$user_where_clause.'
392;';
393    $result = pwg_query($query);
394
395    // mail admin and ask to validate the comment
396    if ($result and $conf['email_admin_on_comment_validation'] and 'moderate' == $comment_action)
397    {
398      include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
399
400      $comment_url = get_absolute_root_url().'comments.php?comment_id='.$comment['comment_id'];
401
402      $keyargs_content = array(
403        get_l10n_args('Author: %s', stripslashes($GLOBALS['user']['username']) ),
404        get_l10n_args('Comment: %s', stripslashes($comment['content']) ),
405        get_l10n_args(''),
406        get_l10n_args('Manage this user comment: %s', $comment_url),
407        get_l10n_args('(!) This comment requires validation'),
408      );
409
410      pwg_mail_notification_admins(
411        get_l10n_args('Comment by %s', stripslashes($GLOBALS['user']['username']) ),
412        $keyargs_content
413      );
414    }
415    // just mail admin
416    elseif ($result)
417    {
418      email_admin('edit', array('author' => $GLOBALS['user']['username'],
419                                'content' => stripslashes($comment['content'])) );
420    }
421  }
422
423  return $comment_action;
424}
425
426/**
427 * Notifies admins about updated or deleted comment.
428 * Only used when no validation is needed, otherwise pwg_mail_notification_admins() is used.
429 *
430 * @param string $action edit, delete
431 * @param array $comment
432 */
433function email_admin($action, $comment)
434{
435  global $conf;
436
437  if (!in_array($action, array('edit', 'delete'))
438      or (($action=='edit') and !$conf['email_admin_on_comment_edition'])
439      or (($action=='delete') and !$conf['email_admin_on_comment_deletion']))
440  {
441    return;
442  }
443
444  include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
445
446  $keyargs_content = array(
447    get_l10n_args('Author: %s', $comment['author']),
448    );
449
450  if ($action=='delete')
451  {
452    $keyargs_content[] = get_l10n_args('This author removed the comment with id %d', $comment['comment_id']);
453  }
454  else
455  {
456    $keyargs_content[] = get_l10n_args('This author modified following comment:');
457    $keyargs_content[] = get_l10n_args('Comment: %s', $comment['content']);
458  }
459
460  pwg_mail_notification_admins(
461    get_l10n_args('Comment by %s', $comment['author']),
462    $keyargs_content
463    );
464}
465
466/**
467 * Returns the author id of a comment
468 *
469 * @param int $comment_id
470 * @param bool $die_on_error
471 * @return int
472 */
473function get_comment_author_id($comment_id, $die_on_error=true)
474{
475  $query = '
476SELECT
477    author_id
478  FROM '.COMMENTS_TABLE.'
479  WHERE id = '.$comment_id.'
480;';
481  $result = pwg_query($query);
482  if (pwg_db_num_rows($result) == 0)
483  {
484    if ($die_on_error)
485    {
486      fatal_error('Unknown comment identifier');
487    }
488    else
489    {
490      return false;
491    }
492  }
493
494  list($author_id) = pwg_db_fetch_row($result);
495
496  return $author_id;
497}
498
499/**
500 * Tries to validate a user comment.
501 *
502 * @param int|int[] $comment_id
503 */
504function validate_user_comment($comment_id)
505{
506  if (is_array($comment_id))
507    $where_clause = 'id IN('.implode(',', $comment_id).')';
508  else
509    $where_clause = 'id = '.$comment_id;
510
511  $query = '
512UPDATE '.COMMENTS_TABLE.'
513  SET validated = \'true\'
514    , validation_date = NOW()
515  WHERE '.$where_clause.'
516;';
517  pwg_query($query);
518
519  invalidate_user_cache_nb_comments();
520  trigger_notify('user_comment_validation', $comment_id);
521}
522
523/**
524 * Clears cache of nb comments for all users
525 */
526function invalidate_user_cache_nb_comments()
527{
528  global $user;
529
530  unset($user['nb_available_comments']);
531
532  $query = '
533UPDATE '.USER_CACHE_TABLE.'
534  SET nb_available_comments = NULL
535;';
536  pwg_query($query);
537}
538
539?>
Note: See TracBrowser for help on using the repository browser.