includes/comment.php
changeset 1 fe660c52c48f
child 16 64e0d3d4cf14
equal deleted inserted replaced
0:902822492a68 1:fe660c52c48f
       
     1 <?php
       
     2 
       
     3 /*
       
     4  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
       
     5  * Version 1.0 (Banshee)
       
     6  * Copyright (C) 2006-2007 Dan Fuhry
       
     7  *
       
     8  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
       
     9  * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
       
    10  *
       
    11  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
       
    12  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
       
    13  */
       
    14 
       
    15 /**
       
    16  * Class that handles comments. Has HTML/Javascript frontend support.
       
    17  * @package Enano CMS
       
    18  * @subpackage Comment manager
       
    19  * @license GNU General Public License <http://www.gnu.org/licenses/gpl.html>
       
    20  */
       
    21 
       
    22 class Comments
       
    23 {
       
    24   #
       
    25   # VARIABLES
       
    26   #
       
    27   
       
    28   /**
       
    29    * Current list of comments.
       
    30    * @var array
       
    31    */
       
    32   
       
    33   var $comments = Array();
       
    34   
       
    35   /**
       
    36    * Object to track permissions.
       
    37    * @var object
       
    38    */
       
    39   
       
    40   var $perms;
       
    41   
       
    42   #
       
    43   # METHODS
       
    44   #
       
    45   
       
    46   /**
       
    47    * Constructor.
       
    48    * @param string Page ID of the page to load comments for
       
    49    * @param string Namespace of the page to load comments for
       
    50    */
       
    51   
       
    52   function __construct($page_id, $namespace)
       
    53   {
       
    54     global $db, $session, $paths, $template, $plugins; // Common objects
       
    55     
       
    56     // Initialize permissions
       
    57     if ( $page_id == $paths->cpage['urlname_nons'] && $namespace == $paths->namespace )
       
    58       $this->perms =& $GLOBALS['session'];
       
    59     else
       
    60       $this->perms = $session->fetch_page_acl($page_id, $namespace);
       
    61     
       
    62     $this->page_id = $db->escape($page_id);
       
    63     $this->namespace = $db->escape($namespace);
       
    64   }
       
    65   
       
    66   /**
       
    67    * PHP 4 constructor.
       
    68    * @see Comments::__construct
       
    69    */
       
    70   function Comments($page_id, $namespace)
       
    71   {
       
    72     $this->__construct($page_id, $namespace);
       
    73   }
       
    74   
       
    75   /**
       
    76    * Processes a command in JSON format.
       
    77    * @param string The JSON-encoded input, probably something sent from the Javascript/AJAX frontend
       
    78    */
       
    79    
       
    80   function process_json($json)
       
    81   {
       
    82     global $db, $session, $paths, $template, $plugins; // Common objects
       
    83     $parser = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
       
    84     $data = $parser->decode($json);
       
    85     if ( !isset($data['mode']) )
       
    86     {
       
    87       return $parser->encode(Array('mode'=>'error','error'=>'No mode defined!'));
       
    88     }
       
    89     $ret = Array();
       
    90     $ret['mode'] = $data['mode'];
       
    91     switch ( $data['mode'] )
       
    92     {
       
    93       case 'fetch':
       
    94         if ( !$template->theme_loaded )
       
    95           $template->load_theme();
       
    96         if ( !isset($data['have_template']) )
       
    97         {
       
    98           $ret['template'] = file_get_contents(ENANO_ROOT . '/themes/' . $template->theme . '/comment.tpl');
       
    99         }
       
   100         $q = $db->sql_query('SELECT c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,u.user_level,u.user_id,u.signature FROM '.table_prefix.'comments AS c
       
   101                                LEFT JOIN '.table_prefix.'users AS u
       
   102                                  ON (u.user_id=c.user_id)
       
   103                                WHERE page_id=\'' . $this->page_id . '\'
       
   104                                  AND namespace=\'' . $this->namespace . '\';');
       
   105         $count_appr = 0;
       
   106         $count_total = 0;
       
   107         $count_unappr = 0;
       
   108         $ret['comments'] = Array();
       
   109         if (!$q)
       
   110           $db->die_json();
       
   111         if ( $row = $db->fetchrow() )
       
   112         {
       
   113           do {
       
   114             
       
   115             // Increment counters
       
   116             $count_total++;
       
   117             ( $row['approved'] == 1 ) ? $count_appr++ : $count_unappr++;
       
   118             
       
   119             if ( !$this->perms->get_permissions('mod_comments') && $row['approved'] == 0 )
       
   120               continue;
       
   121             
       
   122             // Send the source
       
   123             $row['comment_source'] = $row['comment_data'];
       
   124             
       
   125             // Format text
       
   126             $row['comment_data'] = RenderMan::render($row['comment_data']);
       
   127             
       
   128             // Format date
       
   129             $row['time'] = date('F d, Y h:i a', $row['time']);
       
   130             
       
   131             // Format signature
       
   132             $row['signature'] = ( !empty($row['signature']) ) ? RenderMan::render($row['signature']) : '';
       
   133             
       
   134             // Add the comment to the list
       
   135             $ret['comments'][] = $row;
       
   136             
       
   137           } while ( $row = $db->fetchrow() );
       
   138         }
       
   139         $db->free_result();
       
   140         $ret['count_appr'] = $count_appr;
       
   141         $ret['count_total'] = $count_total;
       
   142         $ret['count_unappr'] = $count_unappr;
       
   143         $ret['auth_mod_comments'] = $this->perms->get_permissions('mod_comments');
       
   144         $ret['auth_post_comments'] = $this->perms->get_permissions('post_comments');
       
   145         $ret['auth_edit_comments'] = $this->perms->get_permissions('edit_comments');
       
   146         $ret['user_id'] = $session->user_id;
       
   147         $ret['username'] = $session->username;
       
   148         $ret['logged_in'] = $session->user_logged_in;
       
   149         
       
   150         $ret['user_level'] = Array();
       
   151         $ret['user_level']['guest'] = USER_LEVEL_GUEST;
       
   152         $ret['user_level']['member'] = USER_LEVEL_MEMBER;
       
   153         $ret['user_level']['mod'] = USER_LEVEL_MOD;
       
   154         $ret['user_level']['admin'] = USER_LEVEL_ADMIN;
       
   155         
       
   156         $ret['approval_needed'] = ( getConfig('approve_comments') == '1' );
       
   157         $ret['guest_posting'] = getConfig('comments_need_login');
       
   158         
       
   159         if ( $ret['guest_posting'] == '1' && !$session->user_logged_in )
       
   160         {
       
   161           $session->kill_captcha();
       
   162           $ret['captcha'] = $session->make_captcha();
       
   163         }
       
   164         break;
       
   165       case 'edit':
       
   166         $cid = (string)$data['id'];
       
   167         if ( !preg_match('#^([0-9]+)$#i', $cid) || intval($cid) < 1 )
       
   168         {
       
   169           echo '{"mode":"error","error":"HACKING ATTEMPT"}';
       
   170           return false;
       
   171         }
       
   172         $cid = intval($cid);
       
   173         $q = $db->sql_query('SELECT c.user_id,c.approved FROM '.table_prefix.'comments c LEFT JOIN '.table_prefix.'users u ON (u.user_id=c.user_id) WHERE comment_id='.$cid.';');
       
   174         if(!$q)
       
   175           $db->die_json();
       
   176         $row = $db->fetchrow();
       
   177         $uid = intval($row['user_id']);
       
   178         $can_edit = ( ( $uid == $session->user_id && $uid != 1 && $this->perms->get_permissions('edit_comments') ) || ( $this->perms->get_permissions('mod_comments') ) );
       
   179         if(!$can_edit)
       
   180         {
       
   181           echo '{"mode":"error","error":"HACKING ATTEMPT"}';
       
   182           return false;
       
   183         }
       
   184         $data['data'] = str_replace("\r", '', $data['data']); // Windows compatibility
       
   185         $text = RenderMan::preprocess_text($data['data'], true, false);
       
   186         $text2 = $db->escape($text);
       
   187         $subj = $db->escape(htmlspecialchars($data['subj']));
       
   188         $q = $db->sql_query('UPDATE '.table_prefix.'comments SET subject=\'' . $subj . '\',comment_data=\'' . $text2 . '\' WHERE comment_id=' . $cid . ';');
       
   189         if(!$q)
       
   190           $db->die_json();
       
   191         $ret = Array(
       
   192             'mode' => 'redraw',
       
   193             'id'   => $data['local_id'],
       
   194             'subj' => htmlspecialchars($data['subj']),
       
   195             'text' => RenderMan::render($text),
       
   196             'src'  => $text,
       
   197             'approved' => $row['approved']
       
   198           );
       
   199         break;
       
   200       case 'delete':
       
   201         $cid = (string)$data['id'];
       
   202         if ( !preg_match('#^([0-9]+)$#i', $cid) || intval($cid) < 1 )
       
   203         {
       
   204           echo '{"mode":"error","error":"HACKING ATTEMPT"}';
       
   205           return false;
       
   206         }
       
   207         $cid = intval($cid);
       
   208         $q = $db->sql_query('SELECT c.user_id FROM '.table_prefix.'comments c LEFT JOIN '.table_prefix.'users u ON (u.user_id=c.user_id) WHERE comment_id='.$cid.';');
       
   209         if(!$q)
       
   210           $db->die_json();
       
   211         $row = $db->fetchrow();
       
   212         $uid = intval($row['user_id']);
       
   213         $can_edit = ( ( $uid == $session->user_id && $uid != 1 && $this->perms->get_permissions('edit_comments') ) || ( $this->perms->get_permissions('mod_comments') ) );
       
   214         if(!$can_edit)
       
   215         {
       
   216           echo '{"mode":"error","error":"HACKING ATTEMPT"}';
       
   217           return false;
       
   218         }
       
   219         $q = $db->sql_query('DELETE FROM '.table_prefix.'comments WHERE comment_id='.$cid.';');
       
   220         if(!$q)
       
   221           $db->die_json();
       
   222         $ret = Array(
       
   223             'mode' => 'annihilate',
       
   224             'id'   => $data['local_id']
       
   225           );
       
   226         break;
       
   227       case 'submit':
       
   228         
       
   229         // Now for a huge round of security checks...
       
   230         
       
   231         $errors = Array();
       
   232         
       
   233         // Authorization
       
   234         // Like the rest of the ACL system, this call is a one-stop check for ALL ACL entries.
       
   235         if ( !$this->perms->get_permissions('post_comments') )
       
   236           $errors[] = 'An ACL entry is preventing the comment from being posted.';
       
   237         
       
   238         // Guest authorization
       
   239         if ( getConfig('comments_need_login') == '2' && !$session->user_logged_in )
       
   240           $errors[] = 'You need to log in before posting comments.';
       
   241         
       
   242         // CAPTCHA code
       
   243         if ( getConfig('comments_need_login') == '1' && !$session->user_logged_in )
       
   244         {
       
   245           $real_code = $session->get_captcha($data['captcha_id']);
       
   246           if ( $real_code != $data['captcha_code'] )
       
   247             $errors[] = 'The confirmation code you entered was incorrect.';
       
   248         }
       
   249         
       
   250         if ( count($errors) > 0 )
       
   251         {
       
   252           $ret = Array(
       
   253             'mode' => 'error',
       
   254             'error' => implode("\n", $errors)
       
   255             );
       
   256         }
       
   257         else
       
   258         {
       
   259           // We're authorized!
       
   260           
       
   261           // Preprocess
       
   262           $name = ( $session->user_logged_in ) ? htmlspecialchars($session->username) : htmlspecialchars($data['name']);
       
   263           $subj = htmlspecialchars($data['subj']);
       
   264           $text = RenderMan::preprocess_text($data['text'], true, false);
       
   265           $src = $text;
       
   266           $sql_text = $db->escape($text);
       
   267           $text = RenderMan::render($text);
       
   268           $appr = ( getConfig('approve_comments') == '1' ) ? '0' : '1';
       
   269           $time = time();
       
   270           $date = date('F d, Y h:i a', $time);
       
   271           
       
   272           // Send it to the database
       
   273           $q = $db->sql_query('INSERT INTO '.table_prefix.'comments(page_id,namespace,name,subject,comment_data,approved, time, user_id) VALUES' .
       
   274                               "('$this->page_id', '$this->namespace', '$name', '$subj', '$sql_text', $appr, $time, $session->user_id);");
       
   275           if(!$q)
       
   276             $db->die_json();
       
   277           
       
   278           // Re-fetch
       
   279           $q = $db->sql_query('SELECT c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,u.user_level,u.user_id,u.signature FROM '.table_prefix.'comments AS c
       
   280                                LEFT JOIN '.table_prefix.'users AS u
       
   281                                  ON (u.user_id=c.user_id)
       
   282                                WHERE page_id=\'' . $this->page_id . '\'
       
   283                                  AND namespace=\'' . $this->namespace . '\'
       
   284                                  AND time='.$time.' ORDER BY comment_id DESC LIMIT 1;');
       
   285           if(!$q)
       
   286             $db->die_json();
       
   287           
       
   288           $row = $db->fetchrow();
       
   289           $db->free_result();
       
   290           $row['time'] = $date;
       
   291           $row['comment_data'] = $text;
       
   292           $row['comment_source'] = $src;
       
   293           $ret = Array(
       
   294               'mode' => 'materialize'
       
   295             );
       
   296           $ret = enano_safe_array_merge($ret, $row);
       
   297           
       
   298           $ret['auth_mod_comments'] = $this->perms->get_permissions('mod_comments');
       
   299           $ret['auth_post_comments'] = $this->perms->get_permissions('post_comments');
       
   300           $ret['auth_edit_comments'] = $this->perms->get_permissions('edit_comments');
       
   301           $ret['user_id'] = $session->user_id;
       
   302           $ret['username'] = $session->username;
       
   303           $ret['logged_in'] = $session->user_logged_in;
       
   304           $ret['signature'] = RenderMan::render($row['signature']);
       
   305           
       
   306           $ret['user_level_list'] = Array();
       
   307           $ret['user_level_list']['guest'] = USER_LEVEL_GUEST;
       
   308           $ret['user_level_list']['member'] = USER_LEVEL_MEMBER;
       
   309           $ret['user_level_list']['mod'] = USER_LEVEL_MOD;
       
   310           $ret['user_level_list']['admin'] = USER_LEVEL_ADMIN;
       
   311           
       
   312         }
       
   313         
       
   314         break;
       
   315       case 'approve':
       
   316         if ( !$this->perms->get_permissions('mod_comments') )
       
   317         {
       
   318           $ret = Array(
       
   319           'mode' => 'error', 
       
   320           'error' => 'You are not authorized to moderate comments.'
       
   321           );
       
   322           echo $parser->encode($ret);
       
   323           return $ret;
       
   324         }
       
   325         
       
   326         $cid = (string)$data['id'];
       
   327         if ( !preg_match('#^([0-9]+)$#i', $cid) || intval($cid) < 1 )
       
   328         {
       
   329           echo '{"mode":"error","error":"HACKING ATTEMPT"}';
       
   330           return false;
       
   331         }
       
   332         $cid = intval($cid);
       
   333         $q = $db->sql_query('SELECT subject,approved FROM '.table_prefix.'comments WHERE comment_id='.$cid.';');
       
   334         if(!$q || $db->numrows() < 1)
       
   335           $db->die_json();
       
   336         $row = $db->fetchrow();
       
   337         $db->free_result();
       
   338         $appr = ( $row['approved'] == '1' ) ? '0' : '1';
       
   339         $q = $db->sql_query('UPDATE '.table_prefix."comments SET approved=$appr WHERE comment_id=$cid;");
       
   340         if (!$q)
       
   341           $db->die_json();
       
   342         
       
   343         $ret = Array(
       
   344             'mode' => 'redraw',
       
   345             'approved' => $appr,
       
   346             'subj' => $row['subject'],
       
   347             'id'   => $data['local_id']
       
   348           );
       
   349         
       
   350         break;
       
   351       default:
       
   352         $ret = Array(
       
   353           'mode' => 'error', 
       
   354           'error' => $data['mode'] . ' is not a valid request mode'
       
   355           );
       
   356         break;
       
   357     }
       
   358     echo $parser->encode($ret);
       
   359     return $ret;
       
   360   }
       
   361   
       
   362 } // class Comments
       
   363