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

Last change on this file since 26461 was 26461, checked in by mistic100, 7 years ago

Update headers to 2014. Happy new year!!

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