--- a/includes/comment.php Sun Mar 28 21:49:26 2010 -0400
+++ b/includes/comment.php Sun Mar 28 23:10:46 2010 -0400
@@ -20,466 +20,466 @@
class Comments
{
- #
- # VARIABLES
- #
-
- /**
- * Current list of comments.
- * @var array
- */
-
- var $comments = Array();
-
- /**
- * Object to track permissions.
- * @var object
- */
-
- var $perms;
-
- #
- # METHODS
- #
-
- /**
- * Constructor.
- * @param string Page ID of the page to load comments for
- * @param string Namespace of the page to load comments for
- */
-
- function __construct($page_id, $namespace)
- {
- global $db, $session, $paths, $template, $plugins; // Common objects
-
- // Initialize permissions
- if ( $page_id == $paths->page_id && $namespace == $paths->namespace )
- $this->perms =& $GLOBALS['session'];
- else
- $this->perms = $session->fetch_page_acl($page_id, $namespace);
-
- $this->page_id = $db->escape($page_id);
- $this->namespace = $db->escape($namespace);
- }
-
- /**
- * Processes a command in JSON format.
- * @param mixed Either the JSON-encoded input string, probably something sent from the Javascript/AJAX frontend, or an equivalent array
- */
-
- function process_json($json)
- {
- global $db, $session, $paths, $template, $plugins; // Common objects
- global $lang;
-
- $is_json = !is_array($json);
-
- if ( $is_json )
- {
- $data = enano_json_decode($json);
- $data = decode_unicode_array($data);
- }
- else
- {
- $data =& $json;
- }
- if ( !isset($data['mode']) )
- {
- $ret = Array('mode'=>'error','error'=>'No mode defined!');
- echo enano_json_encode($ret);
- return $ret;
- }
- if ( getConfig('enable_comments', '1') == '0' )
- {
- $ret = Array('mode'=>'error','error'=>'Comments are not enabled on this site.');
- echo enano_json_encode($ret);
- return $ret;
- }
- $ret = Array();
- $ret['mode'] = $data['mode'];
- if ( isset($data['passback']) )
- $ret['passback'] = $data['passback'];
- switch ( $data['mode'] )
- {
- case 'fetch':
- if ( !$template->theme_loaded )
- $template->load_theme();
- if ( !isset($data['have_template']) )
- {
- $ret['template'] = file_get_contents(ENANO_ROOT . '/themes/' . $template->theme . '/comment.tpl');
- }
- $approve_clause = $this->perms->get_permissions('mod_comments') ? '' : " AND approved = " . COMMENT_APPROVED;
- // Get totals
- $q = $db->sql_query('SELECT approved FROM ' . table_prefix . "comments WHERE page_id = '$this->page_id' AND namespace = '$this->namespace'{$approve_clause};");
- if ( !$q )
- $db->die_json();
- $counts = array('total' => 0, 'approved' => 0, 'unapproved' => 0, 'spam' => 0);
- while ( $row = $db->fetchrow() )
- {
- $counts['total']++;
- switch($row['approved']):
- case COMMENT_APPROVED: $counts['approved']++; break;
- case COMMENT_UNAPPROVED: $counts['unapproved']++; break;
- case COMMENT_SPAM: $counts['spam']++; break;
- endswitch;
- }
- $counts['unapproved'] = $counts['total'] - $counts['approved'];
- $data['counts'] = $counts;
- // FIXME, this should be a user preference eventually
- $ret['per_page'] = $per_page = getConfig('comments_per_page', 10);
- $page = ( !empty($data['pagenum']) ) ? intval($data['pagenum']) : 0;
- if ( $page > 0 )
- {
- $ret['mode'] = 'refetch';
- }
- $limit_clause = "LIMIT $per_page OFFSET " . ($page * $per_page);
- $q = $db->sql_query('SELECT c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,( c.ip_address IS NOT NULL ) AS have_ip,u.user_level,u.user_id,u.email,u.signature,u.user_has_avatar,u.avatar_type, b.buddy_id IS NOT NULL AS is_buddy, ( b.is_friend IS NOT NULL AND b.is_friend=1 ) AS is_friend FROM '.table_prefix.'comments AS c
- LEFT JOIN '.table_prefix.'users AS u
- ON (u.user_id=c.user_id)
- LEFT JOIN '.table_prefix.'buddies AS b
- ON ( ( b.user_id=' . $session->user_id.' AND b.buddy_user_id=c.user_id ) OR b.user_id IS NULL)
- LEFT JOIN '.table_prefix.'ranks AS r
- ON ( ( u.user_rank = r.rank_id ) )
- WHERE page_id=\'' . $this->page_id . '\'
- AND namespace=\'' . $this->namespace . '\'
- ' . $approve_clause . '
- GROUP BY c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,c.ip_address,u.user_level,u.user_id,u.email,u.signature,u.user_has_avatar,u.avatar_type,b.buddy_id,b.is_friend
- ORDER BY c.time ASC
- ' . $limit_clause . ';');
- $ret['comments'] = Array();
- if (!$q)
- $db->die_json();
- if ( $row = $db->fetchrow($q) )
- {
- do {
-
- if ( !$this->perms->get_permissions('mod_comments') && $row['approved'] != COMMENT_APPROVED )
- continue;
-
- // Localize the rank
- $row = array_merge($row, $session->get_user_rank(intval($row['user_id'])));
-
- // Send the source
- $row['comment_source'] = $row['comment_data'];
-
- // Format text
- $row['comment_data'] = RenderMan::render($row['comment_data']);
-
- // Hide it if it's a post from a foe
- if ( $row['is_buddy'] == 1 && $row['is_friend'] == 0 )
- {
- $seed = md5(sha1(mt_rand() . microtime()));
- $wrapper = '
- <div id="posthide_'.$seed.'" style="display: none;">
- ' . $row['comment_data'] . '
- </div>
- <p><span style="opacity: 0.4; filter: alpha(opacity=40);">' . $lang->get('comment_msg_foe_comment_hidden') . '</span> <span style="text-align: right;"><a href="#showpost" onclick="document.getElementById(\'posthide_'.$seed.'\').style.display=\'block\'; this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode); return false;">' . $lang->get('comment_btn_display_foe_comment') . '</a></span></p>
- ';
- $row['comment_data'] = $wrapper;
- }
-
- // Format date
- $row['time'] = enano_date(ED_DATE | ED_TIME, $row['time']);
-
- // Format signature
- $row['signature'] = ( !empty($row['signature']) ) ? RenderMan::render($row['signature']) : '';
-
- // Do we have the IP?
- $row['have_ip'] = ( $row['have_ip'] == 1 );
-
- // Avatar URL
- $row['avatar_path'] = make_avatar_url($row['user_id'], $row['avatar_type'], $row['email']);
-
- // Add the comment to the list
- $ret['comments'][] = $row;
-
- } while ( $row = $db->fetchrow($q) );
- }
- $db->free_result();
- $ret['count_appr'] = $counts['approved'];
- $ret['count_total'] = $counts['total'];
- $ret['count_visible'] = $this->perms->get_permissions('mod_comments') ? $counts['total'] : $counts['approved'];
- $ret['count_unappr'] = $counts['unapproved'];
- $ret['auth_mod_comments'] = $this->perms->get_permissions('mod_comments');
- $ret['auth_post_comments'] = $this->perms->get_permissions('post_comments');
- $ret['auth_edit_comments'] = $this->perms->get_permissions('edit_comments');
- $ret['auth_edit_wysiwyg'] = $this->perms->get_permissions('edit_wysiwyg');
- $ret['user_id'] = $session->user_id;
- $ret['username'] = $session->username;
- $ret['logged_in'] = $session->user_logged_in;
-
- $ret['user_level'] = Array();
- $ret['user_level']['guest'] = USER_LEVEL_GUEST;
- $ret['user_level']['member'] = USER_LEVEL_MEMBER;
- $ret['user_level']['mod'] = USER_LEVEL_MOD;
- $ret['user_level']['admin'] = USER_LEVEL_ADMIN;
-
- $ret['approval_needed'] = ( getConfig('approve_comments', '0') == '1' );
- $ret['guest_posting'] = getConfig('comments_need_login');
-
- if ( $ret['guest_posting'] == '1' && !$session->user_logged_in )
- {
- $session->kill_captcha();
- $ret['captcha'] = $session->make_captcha();
- }
- break;
- case 'edit':
- $cid = (string)$data['id'];
- if ( !ctype_digit($cid) || intval($cid) < 1 )
- {
- echo '{"mode":"error","error":"HACKING ATTEMPT"}';
- return false;
- }
- $cid = intval($cid);
- $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.';');
- if(!$q)
- $db->die_json();
- $row = $db->fetchrow();
- $uid = intval($row['user_id']);
- $can_edit = ( ( $uid == $session->user_id && $uid != 1 && $this->perms->get_permissions('edit_comments') ) || ( $this->perms->get_permissions('mod_comments') ) );
- if(!$can_edit)
- {
- echo '{"mode":"error","error":"HACKING ATTEMPT"}';
- return false;
- }
- $data['data'] = str_replace("\r", '', $data['data']); // Windows compatibility
- $text = RenderMan::preprocess_text($data['data'], true, false);
- $text2 = $db->escape($text);
- $subj = $db->escape(htmlspecialchars($data['subj']));
- $q = $db->sql_query('UPDATE '.table_prefix.'comments SET subject=\'' . $subj . '\',comment_data=\'' . $text2 . '\' WHERE comment_id=' . $cid . ';');
- if(!$q)
- $db->die_json();
- $ret = Array(
- 'mode' => 'redraw',
- 'id' => $data['local_id'],
- 'subj' => htmlspecialchars($data['subj']),
- 'text' => RenderMan::render($text),
- 'src' => $text,
- 'approved' => $row['approved']
- );
- break;
- case 'delete':
- $cid = (string)$data['id'];
- if ( !ctype_digit($cid) || intval($cid) < 1 )
- {
- echo '{"mode":"error","error":"HACKING ATTEMPT"}';
- return false;
- }
- $cid = intval($cid);
- $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.';');
- if(!$q)
- $db->die_json();
- $row = $db->fetchrow();
- $uid = intval($row['user_id']);
- $can_edit = ( ( $uid == $session->user_id && $uid != 1 && $this->perms->get_permissions('edit_comments') ) || ( $this->perms->get_permissions('mod_comments') ) );
- if(!$can_edit)
- {
- echo '{"mode":"error","error":"HACKING ATTEMPT"}';
- return false;
- }
- $q = $db->sql_query('DELETE FROM '.table_prefix.'comments WHERE comment_id='.$cid.';');
- if(!$q)
- $db->die_json();
- $ret = Array(
- 'mode' => 'annihilate',
- 'id' => $data['local_id']
- );
- break;
- case 'submit':
-
- // Now for a huge round of security checks...
-
- $errors = Array();
-
- // Authorization
- // Like the rest of the ACL system, this call is a one-stop check for ALL ACL entries.
- if ( !$this->perms->get_permissions('post_comments') )
- $errors[] = 'The site security policy prevents your user account from posting comments;';
-
- // Guest authorization
- if ( getConfig('comments_need_login') == '2' && !$session->user_logged_in )
- $errors[] = $lang->get('comment_err_need_login');
-
- // CAPTCHA code
- if ( getConfig('comments_need_login') == '1' && !$session->user_logged_in )
- {
- $real_code = $session->get_captcha($data['captcha_id']);
- if ( strtolower($real_code) !== strtolower($data['captcha_code']) )
- $errors[] = $lang->get('comment_err_captcha_wrong');
- $session->kill_captcha();
- }
-
- // Spam check
- $spam_policy = getConfig('comment_spam_policy', 'moderate');
- $sc_name = ( $session->user_logged_in ) ? $session->username : $data['name'];
- $sc_mail = ( $session->user_logged_in ) ? $session->email : false;
- $sc_url = ( $session->user_logged_in ) ? @$session->user_extra['user_homepage'] : false;
- $spamcheck = $spam_policy === 'accept' ? true : spamalyze($data['text'], $sc_name, $sc_mail, $sc_url);
- if ( !$spamcheck && $spam_policy === 'reject' )
- {
- $errors[] = $lang->get('comment_err_spamcheck_failed_rejected');
- }
-
- if ( count($errors) > 0 )
- {
- $ret = Array(
- 'mode' => 'error',
- 'error' => implode("\n", $errors)
- );
- }
- else
- {
- // We're authorized!
-
- // Preprocess
- $name = ( $session->user_logged_in ) ? htmlspecialchars($session->username) : htmlspecialchars($data['name']);
- $subj = htmlspecialchars($data['subj']);
- $text = RenderMan::preprocess_text($data['text'], true, false);
- $src = $text;
- $sql_subj = $db->escape($subj);
- $sql_text = $db->escape($text);
- $text = RenderMan::render($text);
- $appr = ( getConfig('approve_comments', '0') == '1' ) ? COMMENT_UNAPPROVED : COMMENT_APPROVED;
- if ( $spam_policy === 'moderate' && !$spamcheck )
- $appr = COMMENT_SPAM;
- $time = time();
- $date = enano_date(ED_DATE | ED_TIME, $time);
- $ip = $_SERVER['REMOTE_ADDR'];
- if ( !is_valid_ip($ip) )
- die('Hacking attempt');
-
- // Send it to the database
- $q = $db->sql_query('INSERT INTO '.table_prefix.'comments(page_id,namespace,name,subject,comment_data,approved, time, user_id, ip_address) VALUES' . "\n " .
- "('$this->page_id', '$this->namespace', '$name', '$sql_subj', '$sql_text', $appr, $time, {$session->user_id}, '$ip');");
- if(!$q)
- $db->die_json();
-
- // Re-fetch
- $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.email,u.signature,u.user_has_avatar,u.avatar_type FROM '.table_prefix.'comments AS c
- LEFT JOIN '.table_prefix.'users AS u
- ON (u.user_id=c.user_id)
- WHERE page_id=\'' . $this->page_id . '\'
- AND namespace=\'' . $this->namespace . '\'
- AND time='.$time.' ORDER BY comment_id DESC LIMIT 1;');
- if(!$q)
- $db->die_json();
-
- $row = $db->fetchrow();
- $db->free_result();
- $row['time'] = $date;
- $row['comment_data'] = $text;
- $row['comment_source'] = $src;
- $ret = Array(
- 'mode' => 'materialize'
- );
- $ret = enano_safe_array_merge($ret, $row);
-
- $ret['auth_mod_comments'] = $this->perms->get_permissions('mod_comments');
- $ret['auth_post_comments'] = $this->perms->get_permissions('post_comments');
- $ret['auth_edit_comments'] = $this->perms->get_permissions('edit_comments');
- $ret['user_id'] = $session->user_id;
- $ret['rank_data'] = $session->get_user_rank($session->user_id);
- $ret['username'] = $session->username;
- $ret['logged_in'] = $session->user_logged_in;
- $ret['signature'] = RenderMan::render($row['signature']);
-
- $ret['user_level_list'] = Array();
- $ret['user_level_list']['guest'] = USER_LEVEL_GUEST;
- $ret['user_level_list']['member'] = USER_LEVEL_MEMBER;
- $ret['user_level_list']['mod'] = USER_LEVEL_MOD;
- $ret['user_level_list']['admin'] = USER_LEVEL_ADMIN;
- $ret['avatar_path'] = make_avatar_url($row['user_id'], $row['avatar_type'], $row['email']);
- }
-
- break;
- case 'approve':
- if ( !$this->perms->get_permissions('mod_comments') )
- {
- $ret = Array(
- 'mode' => 'error',
- 'error' => 'You are not authorized to moderate comments.'
- );
- echo enano_json_encode($ret);
- return $ret;
- }
-
- $cid = (string)$data['id'];
- if ( !ctype_digit($cid) || intval($cid) < 1 )
- {
- echo '{"mode":"error","error":"HACKING ATTEMPT"}';
- return false;
- }
- $cid = intval($cid);
- $q = $db->sql_query('SELECT subject,approved FROM '.table_prefix.'comments WHERE comment_id='.$cid.';');
- if(!$q || $db->numrows() < 1)
- $db->die_json();
- $row = $db->fetchrow();
- $db->free_result();
- $appr = ( $row['approved'] == '1' ) ? '0' : '1';
- $q = $db->sql_query('UPDATE '.table_prefix."comments SET approved=$appr WHERE comment_id=$cid;");
- if (!$q)
- $db->die_json();
-
- $ret = Array(
- 'mode' => 'redraw',
- 'approved' => $appr,
- 'subj' => $row['subject'],
- 'id' => $data['local_id'],
- 'approve_updated' => 'yes'
- );
-
- break;
- case 'view_ip':
- if ( !$session->get_permissions('mod_comments') )
- {
- return array(
- 'mode' => 'error',
- 'error' => 'Unauthorized'
- );
- }
- // fetch comment info
- if ( !is_int($data['id']) )
- {
- return array(
- 'mode' => 'error',
- 'error' => 'Unauthorized'
- );
- }
- $id =& $data['id'];
- $q = $db->sql_query('SELECT ip_address, name FROM ' . table_prefix . 'comments WHERE comment_id = ' . $id . ';');
- if ( !$q || $db->numrows() < 1 )
- {
- $db->die_json();
- }
- list($ip_addr, $name) = $db->fetchrow_num($q);
- $db->free_result();
- $name = $db->escape($name);
- $username = $db->escape($session->username);
- // log this action
- $q = $db->sql_query('INSERT INTO ' . table_prefix . "logs(time_id, log_type, action, page_text, author, author_uid, edit_summary) VALUES\n "
- . "( " . time() . ", 'security', 'view_comment_ip', '$name', '$username', $session->user_id, '{$_SERVER['REMOTE_ADDR']}' );");
- if ( !$q )
- $db->die_json();
-
- // send packet
- $ret = array(
- 'mode' => 'redraw',
- 'ip_addr' => $ip_addr,
- 'local_id' => $data['local_id']
- );
- break;
- default:
- $ret = Array(
- 'mode' => 'error',
- 'error' => $data['mode'] . ' is not a valid request mode'
- );
- break;
- }
- if ( $is_json )
- echo enano_json_encode($ret);
-
- return $ret;
- }
-
+ #
+ # VARIABLES
+ #
+
+ /**
+ * Current list of comments.
+ * @var array
+ */
+
+ var $comments = Array();
+
+ /**
+ * Object to track permissions.
+ * @var object
+ */
+
+ var $perms;
+
+ #
+ # METHODS
+ #
+
+ /**
+ * Constructor.
+ * @param string Page ID of the page to load comments for
+ * @param string Namespace of the page to load comments for
+ */
+
+ function __construct($page_id, $namespace)
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+
+ // Initialize permissions
+ if ( $page_id == $paths->page_id && $namespace == $paths->namespace )
+ $this->perms =& $GLOBALS['session'];
+ else
+ $this->perms = $session->fetch_page_acl($page_id, $namespace);
+
+ $this->page_id = $db->escape($page_id);
+ $this->namespace = $db->escape($namespace);
+ }
+
+ /**
+ * Processes a command in JSON format.
+ * @param mixed Either the JSON-encoded input string, probably something sent from the Javascript/AJAX frontend, or an equivalent array
+ */
+
+ function process_json($json)
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ global $lang;
+
+ $is_json = !is_array($json);
+
+ if ( $is_json )
+ {
+ $data = enano_json_decode($json);
+ $data = decode_unicode_array($data);
+ }
+ else
+ {
+ $data =& $json;
+ }
+ if ( !isset($data['mode']) )
+ {
+ $ret = Array('mode'=>'error','error'=>'No mode defined!');
+ echo enano_json_encode($ret);
+ return $ret;
+ }
+ if ( getConfig('enable_comments', '1') == '0' )
+ {
+ $ret = Array('mode'=>'error','error'=>'Comments are not enabled on this site.');
+ echo enano_json_encode($ret);
+ return $ret;
+ }
+ $ret = Array();
+ $ret['mode'] = $data['mode'];
+ if ( isset($data['passback']) )
+ $ret['passback'] = $data['passback'];
+ switch ( $data['mode'] )
+ {
+ case 'fetch':
+ if ( !$template->theme_loaded )
+ $template->load_theme();
+ if ( !isset($data['have_template']) )
+ {
+ $ret['template'] = file_get_contents(ENANO_ROOT . '/themes/' . $template->theme . '/comment.tpl');
+ }
+ $approve_clause = $this->perms->get_permissions('mod_comments') ? '' : " AND approved = " . COMMENT_APPROVED;
+ // Get totals
+ $q = $db->sql_query('SELECT approved FROM ' . table_prefix . "comments WHERE page_id = '$this->page_id' AND namespace = '$this->namespace'{$approve_clause};");
+ if ( !$q )
+ $db->die_json();
+ $counts = array('total' => 0, 'approved' => 0, 'unapproved' => 0, 'spam' => 0);
+ while ( $row = $db->fetchrow() )
+ {
+ $counts['total']++;
+ switch($row['approved']):
+ case COMMENT_APPROVED: $counts['approved']++; break;
+ case COMMENT_UNAPPROVED: $counts['unapproved']++; break;
+ case COMMENT_SPAM: $counts['spam']++; break;
+ endswitch;
+ }
+ $counts['unapproved'] = $counts['total'] - $counts['approved'];
+ $data['counts'] = $counts;
+ // FIXME, this should be a user preference eventually
+ $ret['per_page'] = $per_page = getConfig('comments_per_page', 10);
+ $page = ( !empty($data['pagenum']) ) ? intval($data['pagenum']) : 0;
+ if ( $page > 0 )
+ {
+ $ret['mode'] = 'refetch';
+ }
+ $limit_clause = "LIMIT $per_page OFFSET " . ($page * $per_page);
+ $q = $db->sql_query('SELECT c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,( c.ip_address IS NOT NULL ) AS have_ip,u.user_level,u.user_id,u.email,u.signature,u.user_has_avatar,u.avatar_type, b.buddy_id IS NOT NULL AS is_buddy, ( b.is_friend IS NOT NULL AND b.is_friend=1 ) AS is_friend FROM '.table_prefix.'comments AS c
+ LEFT JOIN '.table_prefix.'users AS u
+ ON (u.user_id=c.user_id)
+ LEFT JOIN '.table_prefix.'buddies AS b
+ ON ( ( b.user_id=' . $session->user_id.' AND b.buddy_user_id=c.user_id ) OR b.user_id IS NULL)
+ LEFT JOIN '.table_prefix.'ranks AS r
+ ON ( ( u.user_rank = r.rank_id ) )
+ WHERE page_id=\'' . $this->page_id . '\'
+ AND namespace=\'' . $this->namespace . '\'
+ ' . $approve_clause . '
+ GROUP BY c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,c.ip_address,u.user_level,u.user_id,u.email,u.signature,u.user_has_avatar,u.avatar_type,b.buddy_id,b.is_friend
+ ORDER BY c.time ASC
+ ' . $limit_clause . ';');
+ $ret['comments'] = Array();
+ if (!$q)
+ $db->die_json();
+ if ( $row = $db->fetchrow($q) )
+ {
+ do {
+
+ if ( !$this->perms->get_permissions('mod_comments') && $row['approved'] != COMMENT_APPROVED )
+ continue;
+
+ // Localize the rank
+ $row = array_merge($row, $session->get_user_rank(intval($row['user_id'])));
+
+ // Send the source
+ $row['comment_source'] = $row['comment_data'];
+
+ // Format text
+ $row['comment_data'] = RenderMan::render($row['comment_data']);
+
+ // Hide it if it's a post from a foe
+ if ( $row['is_buddy'] == 1 && $row['is_friend'] == 0 )
+ {
+ $seed = md5(sha1(mt_rand() . microtime()));
+ $wrapper = '
+ <div id="posthide_'.$seed.'" style="display: none;">
+ ' . $row['comment_data'] . '
+ </div>
+ <p><span style="opacity: 0.4; filter: alpha(opacity=40);">' . $lang->get('comment_msg_foe_comment_hidden') . '</span> <span style="text-align: right;"><a href="#showpost" onclick="document.getElementById(\'posthide_'.$seed.'\').style.display=\'block\'; this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode); return false;">' . $lang->get('comment_btn_display_foe_comment') . '</a></span></p>
+ ';
+ $row['comment_data'] = $wrapper;
+ }
+
+ // Format date
+ $row['time'] = enano_date(ED_DATE | ED_TIME, $row['time']);
+
+ // Format signature
+ $row['signature'] = ( !empty($row['signature']) ) ? RenderMan::render($row['signature']) : '';
+
+ // Do we have the IP?
+ $row['have_ip'] = ( $row['have_ip'] == 1 );
+
+ // Avatar URL
+ $row['avatar_path'] = make_avatar_url($row['user_id'], $row['avatar_type'], $row['email']);
+
+ // Add the comment to the list
+ $ret['comments'][] = $row;
+
+ } while ( $row = $db->fetchrow($q) );
+ }
+ $db->free_result();
+ $ret['count_appr'] = $counts['approved'];
+ $ret['count_total'] = $counts['total'];
+ $ret['count_visible'] = $this->perms->get_permissions('mod_comments') ? $counts['total'] : $counts['approved'];
+ $ret['count_unappr'] = $counts['unapproved'];
+ $ret['auth_mod_comments'] = $this->perms->get_permissions('mod_comments');
+ $ret['auth_post_comments'] = $this->perms->get_permissions('post_comments');
+ $ret['auth_edit_comments'] = $this->perms->get_permissions('edit_comments');
+ $ret['auth_edit_wysiwyg'] = $this->perms->get_permissions('edit_wysiwyg');
+ $ret['user_id'] = $session->user_id;
+ $ret['username'] = $session->username;
+ $ret['logged_in'] = $session->user_logged_in;
+
+ $ret['user_level'] = Array();
+ $ret['user_level']['guest'] = USER_LEVEL_GUEST;
+ $ret['user_level']['member'] = USER_LEVEL_MEMBER;
+ $ret['user_level']['mod'] = USER_LEVEL_MOD;
+ $ret['user_level']['admin'] = USER_LEVEL_ADMIN;
+
+ $ret['approval_needed'] = ( getConfig('approve_comments', '0') == '1' );
+ $ret['guest_posting'] = getConfig('comments_need_login');
+
+ if ( $ret['guest_posting'] == '1' && !$session->user_logged_in )
+ {
+ $session->kill_captcha();
+ $ret['captcha'] = $session->make_captcha();
+ }
+ break;
+ case 'edit':
+ $cid = (string)$data['id'];
+ if ( !ctype_digit($cid) || intval($cid) < 1 )
+ {
+ echo '{"mode":"error","error":"HACKING ATTEMPT"}';
+ return false;
+ }
+ $cid = intval($cid);
+ $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.';');
+ if(!$q)
+ $db->die_json();
+ $row = $db->fetchrow();
+ $uid = intval($row['user_id']);
+ $can_edit = ( ( $uid == $session->user_id && $uid != 1 && $this->perms->get_permissions('edit_comments') ) || ( $this->perms->get_permissions('mod_comments') ) );
+ if(!$can_edit)
+ {
+ echo '{"mode":"error","error":"HACKING ATTEMPT"}';
+ return false;
+ }
+ $data['data'] = str_replace("\r", '', $data['data']); // Windows compatibility
+ $text = RenderMan::preprocess_text($data['data'], true, false);
+ $text2 = $db->escape($text);
+ $subj = $db->escape(htmlspecialchars($data['subj']));
+ $q = $db->sql_query('UPDATE '.table_prefix.'comments SET subject=\'' . $subj . '\',comment_data=\'' . $text2 . '\' WHERE comment_id=' . $cid . ';');
+ if(!$q)
+ $db->die_json();
+ $ret = Array(
+ 'mode' => 'redraw',
+ 'id' => $data['local_id'],
+ 'subj' => htmlspecialchars($data['subj']),
+ 'text' => RenderMan::render($text),
+ 'src' => $text,
+ 'approved' => $row['approved']
+ );
+ break;
+ case 'delete':
+ $cid = (string)$data['id'];
+ if ( !ctype_digit($cid) || intval($cid) < 1 )
+ {
+ echo '{"mode":"error","error":"HACKING ATTEMPT"}';
+ return false;
+ }
+ $cid = intval($cid);
+ $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.';');
+ if(!$q)
+ $db->die_json();
+ $row = $db->fetchrow();
+ $uid = intval($row['user_id']);
+ $can_edit = ( ( $uid == $session->user_id && $uid != 1 && $this->perms->get_permissions('edit_comments') ) || ( $this->perms->get_permissions('mod_comments') ) );
+ if(!$can_edit)
+ {
+ echo '{"mode":"error","error":"HACKING ATTEMPT"}';
+ return false;
+ }
+ $q = $db->sql_query('DELETE FROM '.table_prefix.'comments WHERE comment_id='.$cid.';');
+ if(!$q)
+ $db->die_json();
+ $ret = Array(
+ 'mode' => 'annihilate',
+ 'id' => $data['local_id']
+ );
+ break;
+ case 'submit':
+
+ // Now for a huge round of security checks...
+
+ $errors = Array();
+
+ // Authorization
+ // Like the rest of the ACL system, this call is a one-stop check for ALL ACL entries.
+ if ( !$this->perms->get_permissions('post_comments') )
+ $errors[] = 'The site security policy prevents your user account from posting comments;';
+
+ // Guest authorization
+ if ( getConfig('comments_need_login') == '2' && !$session->user_logged_in )
+ $errors[] = $lang->get('comment_err_need_login');
+
+ // CAPTCHA code
+ if ( getConfig('comments_need_login') == '1' && !$session->user_logged_in )
+ {
+ $real_code = $session->get_captcha($data['captcha_id']);
+ if ( strtolower($real_code) !== strtolower($data['captcha_code']) )
+ $errors[] = $lang->get('comment_err_captcha_wrong');
+ $session->kill_captcha();
+ }
+
+ // Spam check
+ $spam_policy = getConfig('comment_spam_policy', 'moderate');
+ $sc_name = ( $session->user_logged_in ) ? $session->username : $data['name'];
+ $sc_mail = ( $session->user_logged_in ) ? $session->email : false;
+ $sc_url = ( $session->user_logged_in ) ? @$session->user_extra['user_homepage'] : false;
+ $spamcheck = $spam_policy === 'accept' ? true : spamalyze($data['text'], $sc_name, $sc_mail, $sc_url);
+ if ( !$spamcheck && $spam_policy === 'reject' )
+ {
+ $errors[] = $lang->get('comment_err_spamcheck_failed_rejected');
+ }
+
+ if ( count($errors) > 0 )
+ {
+ $ret = Array(
+ 'mode' => 'error',
+ 'error' => implode("\n", $errors)
+ );
+ }
+ else
+ {
+ // We're authorized!
+
+ // Preprocess
+ $name = ( $session->user_logged_in ) ? htmlspecialchars($session->username) : htmlspecialchars($data['name']);
+ $subj = htmlspecialchars($data['subj']);
+ $text = RenderMan::preprocess_text($data['text'], true, false);
+ $src = $text;
+ $sql_subj = $db->escape($subj);
+ $sql_text = $db->escape($text);
+ $text = RenderMan::render($text);
+ $appr = ( getConfig('approve_comments', '0') == '1' ) ? COMMENT_UNAPPROVED : COMMENT_APPROVED;
+ if ( $spam_policy === 'moderate' && !$spamcheck )
+ $appr = COMMENT_SPAM;
+ $time = time();
+ $date = enano_date(ED_DATE | ED_TIME, $time);
+ $ip = $_SERVER['REMOTE_ADDR'];
+ if ( !is_valid_ip($ip) )
+ die('Hacking attempt');
+
+ // Send it to the database
+ $q = $db->sql_query('INSERT INTO '.table_prefix.'comments(page_id,namespace,name,subject,comment_data,approved, time, user_id, ip_address) VALUES' . "\n " .
+ "('$this->page_id', '$this->namespace', '$name', '$sql_subj', '$sql_text', $appr, $time, {$session->user_id}, '$ip');");
+ if(!$q)
+ $db->die_json();
+
+ // Re-fetch
+ $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.email,u.signature,u.user_has_avatar,u.avatar_type FROM '.table_prefix.'comments AS c
+ LEFT JOIN '.table_prefix.'users AS u
+ ON (u.user_id=c.user_id)
+ WHERE page_id=\'' . $this->page_id . '\'
+ AND namespace=\'' . $this->namespace . '\'
+ AND time='.$time.' ORDER BY comment_id DESC LIMIT 1;');
+ if(!$q)
+ $db->die_json();
+
+ $row = $db->fetchrow();
+ $db->free_result();
+ $row['time'] = $date;
+ $row['comment_data'] = $text;
+ $row['comment_source'] = $src;
+ $ret = Array(
+ 'mode' => 'materialize'
+ );
+ $ret = enano_safe_array_merge($ret, $row);
+
+ $ret['auth_mod_comments'] = $this->perms->get_permissions('mod_comments');
+ $ret['auth_post_comments'] = $this->perms->get_permissions('post_comments');
+ $ret['auth_edit_comments'] = $this->perms->get_permissions('edit_comments');
+ $ret['user_id'] = $session->user_id;
+ $ret['rank_data'] = $session->get_user_rank($session->user_id);
+ $ret['username'] = $session->username;
+ $ret['logged_in'] = $session->user_logged_in;
+ $ret['signature'] = RenderMan::render($row['signature']);
+
+ $ret['user_level_list'] = Array();
+ $ret['user_level_list']['guest'] = USER_LEVEL_GUEST;
+ $ret['user_level_list']['member'] = USER_LEVEL_MEMBER;
+ $ret['user_level_list']['mod'] = USER_LEVEL_MOD;
+ $ret['user_level_list']['admin'] = USER_LEVEL_ADMIN;
+ $ret['avatar_path'] = make_avatar_url($row['user_id'], $row['avatar_type'], $row['email']);
+ }
+
+ break;
+ case 'approve':
+ if ( !$this->perms->get_permissions('mod_comments') )
+ {
+ $ret = Array(
+ 'mode' => 'error',
+ 'error' => 'You are not authorized to moderate comments.'
+ );
+ echo enano_json_encode($ret);
+ return $ret;
+ }
+
+ $cid = (string)$data['id'];
+ if ( !ctype_digit($cid) || intval($cid) < 1 )
+ {
+ echo '{"mode":"error","error":"HACKING ATTEMPT"}';
+ return false;
+ }
+ $cid = intval($cid);
+ $q = $db->sql_query('SELECT subject,approved FROM '.table_prefix.'comments WHERE comment_id='.$cid.';');
+ if(!$q || $db->numrows() < 1)
+ $db->die_json();
+ $row = $db->fetchrow();
+ $db->free_result();
+ $appr = ( $row['approved'] == '1' ) ? '0' : '1';
+ $q = $db->sql_query('UPDATE '.table_prefix."comments SET approved=$appr WHERE comment_id=$cid;");
+ if (!$q)
+ $db->die_json();
+
+ $ret = Array(
+ 'mode' => 'redraw',
+ 'approved' => $appr,
+ 'subj' => $row['subject'],
+ 'id' => $data['local_id'],
+ 'approve_updated' => 'yes'
+ );
+
+ break;
+ case 'view_ip':
+ if ( !$session->get_permissions('mod_comments') )
+ {
+ return array(
+ 'mode' => 'error',
+ 'error' => 'Unauthorized'
+ );
+ }
+ // fetch comment info
+ if ( !is_int($data['id']) )
+ {
+ return array(
+ 'mode' => 'error',
+ 'error' => 'Unauthorized'
+ );
+ }
+ $id =& $data['id'];
+ $q = $db->sql_query('SELECT ip_address, name FROM ' . table_prefix . 'comments WHERE comment_id = ' . $id . ';');
+ if ( !$q || $db->numrows() < 1 )
+ {
+ $db->die_json();
+ }
+ list($ip_addr, $name) = $db->fetchrow_num($q);
+ $db->free_result();
+ $name = $db->escape($name);
+ $username = $db->escape($session->username);
+ // log this action
+ $q = $db->sql_query('INSERT INTO ' . table_prefix . "logs(time_id, log_type, action, page_text, author, author_uid, edit_summary) VALUES\n "
+ . "( " . time() . ", 'security', 'view_comment_ip', '$name', '$username', $session->user_id, '{$_SERVER['REMOTE_ADDR']}' );");
+ if ( !$q )
+ $db->die_json();
+
+ // send packet
+ $ret = array(
+ 'mode' => 'redraw',
+ 'ip_addr' => $ip_addr,
+ 'local_id' => $data['local_id']
+ );
+ break;
+ default:
+ $ret = Array(
+ 'mode' => 'error',
+ 'error' => $data['mode'] . ' is not a valid request mode'
+ );
+ break;
+ }
+ if ( $is_json )
+ echo enano_json_encode($ret);
+
+ return $ret;
+ }
+
} // class Comments