18 * @license GNU General Public License <http://www.gnu.org/licenses/gpl-2.0.html> |
18 * @license GNU General Public License <http://www.gnu.org/licenses/gpl-2.0.html> |
19 */ |
19 */ |
20 |
20 |
21 class Comments |
21 class Comments |
22 { |
22 { |
23 # |
23 # |
24 # VARIABLES |
24 # VARIABLES |
25 # |
25 # |
26 |
26 |
27 /** |
27 /** |
28 * Current list of comments. |
28 * Current list of comments. |
29 * @var array |
29 * @var array |
30 */ |
30 */ |
31 |
31 |
32 var $comments = Array(); |
32 var $comments = Array(); |
33 |
33 |
34 /** |
34 /** |
35 * Object to track permissions. |
35 * Object to track permissions. |
36 * @var object |
36 * @var object |
37 */ |
37 */ |
38 |
38 |
39 var $perms; |
39 var $perms; |
40 |
40 |
41 # |
41 # |
42 # METHODS |
42 # METHODS |
43 # |
43 # |
44 |
44 |
45 /** |
45 /** |
46 * Constructor. |
46 * Constructor. |
47 * @param string Page ID of the page to load comments for |
47 * @param string Page ID of the page to load comments for |
48 * @param string Namespace of the page to load comments for |
48 * @param string Namespace of the page to load comments for |
49 */ |
49 */ |
50 |
50 |
51 function __construct($page_id, $namespace) |
51 function __construct($page_id, $namespace) |
52 { |
52 { |
53 global $db, $session, $paths, $template, $plugins; // Common objects |
53 global $db, $session, $paths, $template, $plugins; // Common objects |
54 |
54 |
55 // Initialize permissions |
55 // Initialize permissions |
56 if ( $page_id == $paths->page_id && $namespace == $paths->namespace ) |
56 if ( $page_id == $paths->page_id && $namespace == $paths->namespace ) |
57 $this->perms =& $GLOBALS['session']; |
57 $this->perms =& $GLOBALS['session']; |
58 else |
58 else |
59 $this->perms = $session->fetch_page_acl($page_id, $namespace); |
59 $this->perms = $session->fetch_page_acl($page_id, $namespace); |
60 |
60 |
61 $this->page_id = $db->escape($page_id); |
61 $this->page_id = $db->escape($page_id); |
62 $this->namespace = $db->escape($namespace); |
62 $this->namespace = $db->escape($namespace); |
63 } |
63 } |
64 |
64 |
65 /** |
65 /** |
66 * Processes a command in JSON format. |
66 * Processes a command in JSON format. |
67 * @param mixed Either the JSON-encoded input string, probably something sent from the Javascript/AJAX frontend, or an equivalent array |
67 * @param mixed Either the JSON-encoded input string, probably something sent from the Javascript/AJAX frontend, or an equivalent array |
68 */ |
68 */ |
69 |
69 |
70 function process_json($json) |
70 function process_json($json) |
71 { |
71 { |
72 global $db, $session, $paths, $template, $plugins; // Common objects |
72 global $db, $session, $paths, $template, $plugins; // Common objects |
73 global $lang; |
73 global $lang; |
74 |
74 |
75 $is_json = !is_array($json); |
75 $is_json = !is_array($json); |
76 |
76 |
77 if ( $is_json ) |
77 if ( $is_json ) |
78 { |
78 { |
79 $data = enano_json_decode($json); |
79 $data = enano_json_decode($json); |
80 $data = decode_unicode_array($data); |
80 $data = decode_unicode_array($data); |
81 } |
81 } |
82 else |
82 else |
83 { |
83 { |
84 $data =& $json; |
84 $data =& $json; |
85 } |
85 } |
86 if ( !isset($data['mode']) ) |
86 if ( !isset($data['mode']) ) |
87 { |
87 { |
88 $ret = Array('mode'=>'error','error'=>'No mode defined!'); |
88 $ret = Array('mode'=>'error','error'=>'No mode defined!'); |
89 echo enano_json_encode($ret); |
89 echo enano_json_encode($ret); |
90 return $ret; |
90 return $ret; |
91 } |
91 } |
92 if ( getConfig('enable_comments', '1') == '0' ) |
92 if ( getConfig('enable_comments', '1') == '0' ) |
93 { |
93 { |
94 $ret = Array('mode'=>'error','error'=>'Comments are not enabled on this site.'); |
94 $ret = Array('mode'=>'error','error'=>'Comments are not enabled on this site.'); |
95 echo enano_json_encode($ret); |
95 echo enano_json_encode($ret); |
96 return $ret; |
96 return $ret; |
97 } |
97 } |
98 $ret = Array(); |
98 $ret = Array(); |
99 $ret['mode'] = $data['mode']; |
99 $ret['mode'] = $data['mode']; |
100 if ( isset($data['passback']) ) |
100 if ( isset($data['passback']) ) |
101 $ret['passback'] = $data['passback']; |
101 $ret['passback'] = $data['passback']; |
102 switch ( $data['mode'] ) |
102 switch ( $data['mode'] ) |
103 { |
103 { |
104 case 'fetch': |
104 case 'fetch': |
105 if ( !$template->theme_loaded ) |
105 if ( !$template->theme_loaded ) |
106 $template->load_theme(); |
106 $template->load_theme(); |
107 if ( !isset($data['have_template']) ) |
107 if ( !isset($data['have_template']) ) |
108 { |
108 { |
109 $ret['template'] = file_get_contents(ENANO_ROOT . '/themes/' . $template->theme . '/comment.tpl'); |
109 $ret['template'] = file_get_contents(ENANO_ROOT . '/themes/' . $template->theme . '/comment.tpl'); |
110 } |
110 } |
111 $approve_clause = $this->perms->get_permissions('mod_comments') ? '' : " AND approved = " . COMMENT_APPROVED; |
111 $approve_clause = $this->perms->get_permissions('mod_comments') ? '' : " AND approved = " . COMMENT_APPROVED; |
112 // Get totals |
112 // Get totals |
113 $q = $db->sql_query('SELECT approved FROM ' . table_prefix . "comments WHERE page_id = '$this->page_id' AND namespace = '$this->namespace'{$approve_clause};"); |
113 $q = $db->sql_query('SELECT approved FROM ' . table_prefix . "comments WHERE page_id = '$this->page_id' AND namespace = '$this->namespace'{$approve_clause};"); |
114 if ( !$q ) |
114 if ( !$q ) |
115 $db->die_json(); |
115 $db->die_json(); |
116 $counts = array('total' => 0, 'approved' => 0, 'unapproved' => 0, 'spam' => 0); |
116 $counts = array('total' => 0, 'approved' => 0, 'unapproved' => 0, 'spam' => 0); |
117 while ( $row = $db->fetchrow() ) |
117 while ( $row = $db->fetchrow() ) |
118 { |
118 { |
119 $counts['total']++; |
119 $counts['total']++; |
120 switch($row['approved']): |
120 switch($row['approved']): |
121 case COMMENT_APPROVED: $counts['approved']++; break; |
121 case COMMENT_APPROVED: $counts['approved']++; break; |
122 case COMMENT_UNAPPROVED: $counts['unapproved']++; break; |
122 case COMMENT_UNAPPROVED: $counts['unapproved']++; break; |
123 case COMMENT_SPAM: $counts['spam']++; break; |
123 case COMMENT_SPAM: $counts['spam']++; break; |
124 endswitch; |
124 endswitch; |
125 } |
125 } |
126 $counts['unapproved'] = $counts['total'] - $counts['approved']; |
126 $counts['unapproved'] = $counts['total'] - $counts['approved']; |
127 $data['counts'] = $counts; |
127 $data['counts'] = $counts; |
128 // FIXME, this should be a user preference eventually |
128 // FIXME, this should be a user preference eventually |
129 $ret['per_page'] = $per_page = getConfig('comments_per_page', 10); |
129 $ret['per_page'] = $per_page = getConfig('comments_per_page', 10); |
130 $page = ( !empty($data['pagenum']) ) ? intval($data['pagenum']) : 0; |
130 $page = ( !empty($data['pagenum']) ) ? intval($data['pagenum']) : 0; |
131 if ( $page > 0 ) |
131 if ( $page > 0 ) |
132 { |
132 { |
133 $ret['mode'] = 'refetch'; |
133 $ret['mode'] = 'refetch'; |
134 } |
134 } |
135 $limit_clause = "LIMIT $per_page OFFSET " . ($page * $per_page); |
135 $limit_clause = "LIMIT $per_page OFFSET " . ($page * $per_page); |
136 $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 |
136 $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 |
137 LEFT JOIN '.table_prefix.'users AS u |
137 LEFT JOIN '.table_prefix.'users AS u |
138 ON (u.user_id=c.user_id) |
138 ON (u.user_id=c.user_id) |
139 LEFT JOIN '.table_prefix.'buddies AS b |
139 LEFT JOIN '.table_prefix.'buddies AS b |
140 ON ( ( b.user_id=' . $session->user_id.' AND b.buddy_user_id=c.user_id ) OR b.user_id IS NULL) |
140 ON ( ( b.user_id=' . $session->user_id.' AND b.buddy_user_id=c.user_id ) OR b.user_id IS NULL) |
141 LEFT JOIN '.table_prefix.'ranks AS r |
141 LEFT JOIN '.table_prefix.'ranks AS r |
142 ON ( ( u.user_rank = r.rank_id ) ) |
142 ON ( ( u.user_rank = r.rank_id ) ) |
143 WHERE page_id=\'' . $this->page_id . '\' |
143 WHERE page_id=\'' . $this->page_id . '\' |
144 AND namespace=\'' . $this->namespace . '\' |
144 AND namespace=\'' . $this->namespace . '\' |
145 ' . $approve_clause . ' |
145 ' . $approve_clause . ' |
146 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 |
146 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 |
147 ORDER BY c.time ASC |
147 ORDER BY c.time ASC |
148 ' . $limit_clause . ';'); |
148 ' . $limit_clause . ';'); |
149 $ret['comments'] = Array(); |
149 $ret['comments'] = Array(); |
150 if (!$q) |
150 if (!$q) |
151 $db->die_json(); |
151 $db->die_json(); |
152 if ( $row = $db->fetchrow($q) ) |
152 if ( $row = $db->fetchrow($q) ) |
153 { |
153 { |
154 do { |
154 do { |
155 |
155 |
156 if ( !$this->perms->get_permissions('mod_comments') && $row['approved'] != COMMENT_APPROVED ) |
156 if ( !$this->perms->get_permissions('mod_comments') && $row['approved'] != COMMENT_APPROVED ) |
157 continue; |
157 continue; |
158 |
158 |
159 // Localize the rank |
159 // Localize the rank |
160 $row = array_merge($row, $session->get_user_rank(intval($row['user_id']))); |
160 $row = array_merge($row, $session->get_user_rank(intval($row['user_id']))); |
161 |
161 |
162 // Send the source |
162 // Send the source |
163 $row['comment_source'] = $row['comment_data']; |
163 $row['comment_source'] = $row['comment_data']; |
164 |
164 |
165 // Format text |
165 // Format text |
166 $row['comment_data'] = RenderMan::render($row['comment_data']); |
166 $row['comment_data'] = RenderMan::render($row['comment_data']); |
167 |
167 |
168 // Hide it if it's a post from a foe |
168 // Hide it if it's a post from a foe |
169 if ( $row['is_buddy'] == 1 && $row['is_friend'] == 0 ) |
169 if ( $row['is_buddy'] == 1 && $row['is_friend'] == 0 ) |
170 { |
170 { |
171 $seed = md5(sha1(mt_rand() . microtime())); |
171 $seed = md5(sha1(mt_rand() . microtime())); |
172 $wrapper = ' |
172 $wrapper = ' |
173 <div id="posthide_'.$seed.'" style="display: none;"> |
173 <div id="posthide_'.$seed.'" style="display: none;"> |
174 ' . $row['comment_data'] . ' |
174 ' . $row['comment_data'] . ' |
175 </div> |
175 </div> |
176 <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> |
176 <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> |
177 '; |
177 '; |
178 $row['comment_data'] = $wrapper; |
178 $row['comment_data'] = $wrapper; |
179 } |
179 } |
180 |
180 |
181 // Format date |
181 // Format date |
182 $row['time'] = enano_date(ED_DATE | ED_TIME, $row['time']); |
182 $row['time'] = enano_date(ED_DATE | ED_TIME, $row['time']); |
183 |
183 |
184 // Format signature |
184 // Format signature |
185 $row['signature'] = ( !empty($row['signature']) ) ? RenderMan::render($row['signature']) : ''; |
185 $row['signature'] = ( !empty($row['signature']) ) ? RenderMan::render($row['signature']) : ''; |
186 |
186 |
187 // Do we have the IP? |
187 // Do we have the IP? |
188 $row['have_ip'] = ( $row['have_ip'] == 1 ); |
188 $row['have_ip'] = ( $row['have_ip'] == 1 ); |
189 |
189 |
190 // Avatar URL |
190 // Avatar URL |
191 $row['avatar_path'] = make_avatar_url($row['user_id'], $row['avatar_type'], $row['email']); |
191 $row['avatar_path'] = make_avatar_url($row['user_id'], $row['avatar_type'], $row['email']); |
192 |
192 |
193 // Add the comment to the list |
193 // Add the comment to the list |
194 $ret['comments'][] = $row; |
194 $ret['comments'][] = $row; |
195 |
195 |
196 } while ( $row = $db->fetchrow($q) ); |
196 } while ( $row = $db->fetchrow($q) ); |
197 } |
197 } |
198 $db->free_result(); |
198 $db->free_result(); |
199 $ret['count_appr'] = $counts['approved']; |
199 $ret['count_appr'] = $counts['approved']; |
200 $ret['count_total'] = $counts['total']; |
200 $ret['count_total'] = $counts['total']; |
201 $ret['count_visible'] = $this->perms->get_permissions('mod_comments') ? $counts['total'] : $counts['approved']; |
201 $ret['count_visible'] = $this->perms->get_permissions('mod_comments') ? $counts['total'] : $counts['approved']; |
202 $ret['count_unappr'] = $counts['unapproved']; |
202 $ret['count_unappr'] = $counts['unapproved']; |
203 $ret['auth_mod_comments'] = $this->perms->get_permissions('mod_comments'); |
203 $ret['auth_mod_comments'] = $this->perms->get_permissions('mod_comments'); |
204 $ret['auth_post_comments'] = $this->perms->get_permissions('post_comments'); |
204 $ret['auth_post_comments'] = $this->perms->get_permissions('post_comments'); |
205 $ret['auth_edit_comments'] = $this->perms->get_permissions('edit_comments'); |
205 $ret['auth_edit_comments'] = $this->perms->get_permissions('edit_comments'); |
206 $ret['auth_edit_wysiwyg'] = $this->perms->get_permissions('edit_wysiwyg'); |
206 $ret['auth_edit_wysiwyg'] = $this->perms->get_permissions('edit_wysiwyg'); |
207 $ret['user_id'] = $session->user_id; |
207 $ret['user_id'] = $session->user_id; |
208 $ret['username'] = $session->username; |
208 $ret['username'] = $session->username; |
209 $ret['logged_in'] = $session->user_logged_in; |
209 $ret['logged_in'] = $session->user_logged_in; |
210 |
210 |
211 $ret['user_level'] = Array(); |
211 $ret['user_level'] = Array(); |
212 $ret['user_level']['guest'] = USER_LEVEL_GUEST; |
212 $ret['user_level']['guest'] = USER_LEVEL_GUEST; |
213 $ret['user_level']['member'] = USER_LEVEL_MEMBER; |
213 $ret['user_level']['member'] = USER_LEVEL_MEMBER; |
214 $ret['user_level']['mod'] = USER_LEVEL_MOD; |
214 $ret['user_level']['mod'] = USER_LEVEL_MOD; |
215 $ret['user_level']['admin'] = USER_LEVEL_ADMIN; |
215 $ret['user_level']['admin'] = USER_LEVEL_ADMIN; |
216 |
216 |
217 $ret['approval_needed'] = ( getConfig('approve_comments', '0') == '1' ); |
217 $ret['approval_needed'] = ( getConfig('approve_comments', '0') == '1' ); |
218 $ret['guest_posting'] = getConfig('comments_need_login'); |
218 $ret['guest_posting'] = getConfig('comments_need_login'); |
219 |
219 |
220 if ( $ret['guest_posting'] == '1' && !$session->user_logged_in ) |
220 if ( $ret['guest_posting'] == '1' && !$session->user_logged_in ) |
221 { |
221 { |
222 $session->kill_captcha(); |
222 $session->kill_captcha(); |
223 $ret['captcha'] = $session->make_captcha(); |
223 $ret['captcha'] = $session->make_captcha(); |
224 } |
224 } |
225 break; |
225 break; |
226 case 'edit': |
226 case 'edit': |
227 $cid = (string)$data['id']; |
227 $cid = (string)$data['id']; |
228 if ( !ctype_digit($cid) || intval($cid) < 1 ) |
228 if ( !ctype_digit($cid) || intval($cid) < 1 ) |
229 { |
229 { |
230 echo '{"mode":"error","error":"HACKING ATTEMPT"}'; |
230 echo '{"mode":"error","error":"HACKING ATTEMPT"}'; |
231 return false; |
231 return false; |
232 } |
232 } |
233 $cid = intval($cid); |
233 $cid = intval($cid); |
234 $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.';'); |
234 $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.';'); |
235 if(!$q) |
235 if(!$q) |
236 $db->die_json(); |
236 $db->die_json(); |
237 $row = $db->fetchrow(); |
237 $row = $db->fetchrow(); |
238 $uid = intval($row['user_id']); |
238 $uid = intval($row['user_id']); |
239 $can_edit = ( ( $uid == $session->user_id && $uid != 1 && $this->perms->get_permissions('edit_comments') ) || ( $this->perms->get_permissions('mod_comments') ) ); |
239 $can_edit = ( ( $uid == $session->user_id && $uid != 1 && $this->perms->get_permissions('edit_comments') ) || ( $this->perms->get_permissions('mod_comments') ) ); |
240 if(!$can_edit) |
240 if(!$can_edit) |
241 { |
241 { |
242 echo '{"mode":"error","error":"HACKING ATTEMPT"}'; |
242 echo '{"mode":"error","error":"HACKING ATTEMPT"}'; |
243 return false; |
243 return false; |
244 } |
244 } |
245 $data['data'] = str_replace("\r", '', $data['data']); // Windows compatibility |
245 $data['data'] = str_replace("\r", '', $data['data']); // Windows compatibility |
246 $text = RenderMan::preprocess_text($data['data'], true, false); |
246 $text = RenderMan::preprocess_text($data['data'], true, false); |
247 $text2 = $db->escape($text); |
247 $text2 = $db->escape($text); |
248 $subj = $db->escape(htmlspecialchars($data['subj'])); |
248 $subj = $db->escape(htmlspecialchars($data['subj'])); |
249 $q = $db->sql_query('UPDATE '.table_prefix.'comments SET subject=\'' . $subj . '\',comment_data=\'' . $text2 . '\' WHERE comment_id=' . $cid . ';'); |
249 $q = $db->sql_query('UPDATE '.table_prefix.'comments SET subject=\'' . $subj . '\',comment_data=\'' . $text2 . '\' WHERE comment_id=' . $cid . ';'); |
250 if(!$q) |
250 if(!$q) |
251 $db->die_json(); |
251 $db->die_json(); |
252 $ret = Array( |
252 $ret = Array( |
253 'mode' => 'redraw', |
253 'mode' => 'redraw', |
254 'id' => $data['local_id'], |
254 'id' => $data['local_id'], |
255 'subj' => htmlspecialchars($data['subj']), |
255 'subj' => htmlspecialchars($data['subj']), |
256 'text' => RenderMan::render($text), |
256 'text' => RenderMan::render($text), |
257 'src' => $text, |
257 'src' => $text, |
258 'approved' => $row['approved'] |
258 'approved' => $row['approved'] |
259 ); |
259 ); |
260 break; |
260 break; |
261 case 'delete': |
261 case 'delete': |
262 $cid = (string)$data['id']; |
262 $cid = (string)$data['id']; |
263 if ( !ctype_digit($cid) || intval($cid) < 1 ) |
263 if ( !ctype_digit($cid) || intval($cid) < 1 ) |
264 { |
264 { |
265 echo '{"mode":"error","error":"HACKING ATTEMPT"}'; |
265 echo '{"mode":"error","error":"HACKING ATTEMPT"}'; |
266 return false; |
266 return false; |
267 } |
267 } |
268 $cid = intval($cid); |
268 $cid = intval($cid); |
269 $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.';'); |
269 $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.';'); |
270 if(!$q) |
270 if(!$q) |
271 $db->die_json(); |
271 $db->die_json(); |
272 $row = $db->fetchrow(); |
272 $row = $db->fetchrow(); |
273 $uid = intval($row['user_id']); |
273 $uid = intval($row['user_id']); |
274 $can_edit = ( ( $uid == $session->user_id && $uid != 1 && $this->perms->get_permissions('edit_comments') ) || ( $this->perms->get_permissions('mod_comments') ) ); |
274 $can_edit = ( ( $uid == $session->user_id && $uid != 1 && $this->perms->get_permissions('edit_comments') ) || ( $this->perms->get_permissions('mod_comments') ) ); |
275 if(!$can_edit) |
275 if(!$can_edit) |
276 { |
276 { |
277 echo '{"mode":"error","error":"HACKING ATTEMPT"}'; |
277 echo '{"mode":"error","error":"HACKING ATTEMPT"}'; |
278 return false; |
278 return false; |
279 } |
279 } |
280 $q = $db->sql_query('DELETE FROM '.table_prefix.'comments WHERE comment_id='.$cid.';'); |
280 $q = $db->sql_query('DELETE FROM '.table_prefix.'comments WHERE comment_id='.$cid.';'); |
281 if(!$q) |
281 if(!$q) |
282 $db->die_json(); |
282 $db->die_json(); |
283 $ret = Array( |
283 $ret = Array( |
284 'mode' => 'annihilate', |
284 'mode' => 'annihilate', |
285 'id' => $data['local_id'] |
285 'id' => $data['local_id'] |
286 ); |
286 ); |
287 break; |
287 break; |
288 case 'submit': |
288 case 'submit': |
289 |
289 |
290 // Now for a huge round of security checks... |
290 // Now for a huge round of security checks... |
291 |
291 |
292 $errors = Array(); |
292 $errors = Array(); |
293 |
293 |
294 // Authorization |
294 // Authorization |
295 // Like the rest of the ACL system, this call is a one-stop check for ALL ACL entries. |
295 // Like the rest of the ACL system, this call is a one-stop check for ALL ACL entries. |
296 if ( !$this->perms->get_permissions('post_comments') ) |
296 if ( !$this->perms->get_permissions('post_comments') ) |
297 $errors[] = 'The site security policy prevents your user account from posting comments;'; |
297 $errors[] = 'The site security policy prevents your user account from posting comments;'; |
298 |
298 |
299 // Guest authorization |
299 // Guest authorization |
300 if ( getConfig('comments_need_login') == '2' && !$session->user_logged_in ) |
300 if ( getConfig('comments_need_login') == '2' && !$session->user_logged_in ) |
301 $errors[] = $lang->get('comment_err_need_login'); |
301 $errors[] = $lang->get('comment_err_need_login'); |
302 |
302 |
303 // CAPTCHA code |
303 // CAPTCHA code |
304 if ( getConfig('comments_need_login') == '1' && !$session->user_logged_in ) |
304 if ( getConfig('comments_need_login') == '1' && !$session->user_logged_in ) |
305 { |
305 { |
306 $real_code = $session->get_captcha($data['captcha_id']); |
306 $real_code = $session->get_captcha($data['captcha_id']); |
307 if ( strtolower($real_code) !== strtolower($data['captcha_code']) ) |
307 if ( strtolower($real_code) !== strtolower($data['captcha_code']) ) |
308 $errors[] = $lang->get('comment_err_captcha_wrong'); |
308 $errors[] = $lang->get('comment_err_captcha_wrong'); |
309 $session->kill_captcha(); |
309 $session->kill_captcha(); |
310 } |
310 } |
311 |
311 |
312 // Spam check |
312 // Spam check |
313 $spam_policy = getConfig('comment_spam_policy', 'moderate'); |
313 $spam_policy = getConfig('comment_spam_policy', 'moderate'); |
314 $sc_name = ( $session->user_logged_in ) ? $session->username : $data['name']; |
314 $sc_name = ( $session->user_logged_in ) ? $session->username : $data['name']; |
315 $sc_mail = ( $session->user_logged_in ) ? $session->email : false; |
315 $sc_mail = ( $session->user_logged_in ) ? $session->email : false; |
316 $sc_url = ( $session->user_logged_in ) ? @$session->user_extra['user_homepage'] : false; |
316 $sc_url = ( $session->user_logged_in ) ? @$session->user_extra['user_homepage'] : false; |
317 $spamcheck = $spam_policy === 'accept' ? true : spamalyze($data['text'], $sc_name, $sc_mail, $sc_url); |
317 $spamcheck = $spam_policy === 'accept' ? true : spamalyze($data['text'], $sc_name, $sc_mail, $sc_url); |
318 if ( !$spamcheck && $spam_policy === 'reject' ) |
318 if ( !$spamcheck && $spam_policy === 'reject' ) |
319 { |
319 { |
320 $errors[] = $lang->get('comment_err_spamcheck_failed_rejected'); |
320 $errors[] = $lang->get('comment_err_spamcheck_failed_rejected'); |
321 } |
321 } |
322 |
322 |
323 if ( count($errors) > 0 ) |
323 if ( count($errors) > 0 ) |
324 { |
324 { |
325 $ret = Array( |
325 $ret = Array( |
326 'mode' => 'error', |
326 'mode' => 'error', |
327 'error' => implode("\n", $errors) |
327 'error' => implode("\n", $errors) |
328 ); |
328 ); |
329 } |
329 } |
330 else |
330 else |
331 { |
331 { |
332 // We're authorized! |
332 // We're authorized! |
333 |
333 |
334 // Preprocess |
334 // Preprocess |
335 $name = ( $session->user_logged_in ) ? htmlspecialchars($session->username) : htmlspecialchars($data['name']); |
335 $name = ( $session->user_logged_in ) ? htmlspecialchars($session->username) : htmlspecialchars($data['name']); |
336 $subj = htmlspecialchars($data['subj']); |
336 $subj = htmlspecialchars($data['subj']); |
337 $text = RenderMan::preprocess_text($data['text'], true, false); |
337 $text = RenderMan::preprocess_text($data['text'], true, false); |
338 $src = $text; |
338 $src = $text; |
339 $sql_subj = $db->escape($subj); |
339 $sql_subj = $db->escape($subj); |
340 $sql_text = $db->escape($text); |
340 $sql_text = $db->escape($text); |
341 $text = RenderMan::render($text); |
341 $text = RenderMan::render($text); |
342 $appr = ( getConfig('approve_comments', '0') == '1' ) ? COMMENT_UNAPPROVED : COMMENT_APPROVED; |
342 $appr = ( getConfig('approve_comments', '0') == '1' ) ? COMMENT_UNAPPROVED : COMMENT_APPROVED; |
343 if ( $spam_policy === 'moderate' && !$spamcheck ) |
343 if ( $spam_policy === 'moderate' && !$spamcheck ) |
344 $appr = COMMENT_SPAM; |
344 $appr = COMMENT_SPAM; |
345 $time = time(); |
345 $time = time(); |
346 $date = enano_date(ED_DATE | ED_TIME, $time); |
346 $date = enano_date(ED_DATE | ED_TIME, $time); |
347 $ip = $_SERVER['REMOTE_ADDR']; |
347 $ip = $_SERVER['REMOTE_ADDR']; |
348 if ( !is_valid_ip($ip) ) |
348 if ( !is_valid_ip($ip) ) |
349 die('Hacking attempt'); |
349 die('Hacking attempt'); |
350 |
350 |
351 // Send it to the database |
351 // Send it to the database |
352 $q = $db->sql_query('INSERT INTO '.table_prefix.'comments(page_id,namespace,name,subject,comment_data,approved, time, user_id, ip_address) VALUES' . "\n " . |
352 $q = $db->sql_query('INSERT INTO '.table_prefix.'comments(page_id,namespace,name,subject,comment_data,approved, time, user_id, ip_address) VALUES' . "\n " . |
353 "('$this->page_id', '$this->namespace', '$name', '$sql_subj', '$sql_text', $appr, $time, {$session->user_id}, '$ip');"); |
353 "('$this->page_id', '$this->namespace', '$name', '$sql_subj', '$sql_text', $appr, $time, {$session->user_id}, '$ip');"); |
354 if(!$q) |
354 if(!$q) |
355 $db->die_json(); |
355 $db->die_json(); |
356 |
356 |
357 // Re-fetch |
357 // Re-fetch |
358 $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 |
358 $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 |
359 LEFT JOIN '.table_prefix.'users AS u |
359 LEFT JOIN '.table_prefix.'users AS u |
360 ON (u.user_id=c.user_id) |
360 ON (u.user_id=c.user_id) |
361 WHERE page_id=\'' . $this->page_id . '\' |
361 WHERE page_id=\'' . $this->page_id . '\' |
362 AND namespace=\'' . $this->namespace . '\' |
362 AND namespace=\'' . $this->namespace . '\' |
363 AND time='.$time.' ORDER BY comment_id DESC LIMIT 1;'); |
363 AND time='.$time.' ORDER BY comment_id DESC LIMIT 1;'); |
364 if(!$q) |
364 if(!$q) |
365 $db->die_json(); |
365 $db->die_json(); |
366 |
366 |
367 $row = $db->fetchrow(); |
367 $row = $db->fetchrow(); |
368 $db->free_result(); |
368 $db->free_result(); |
369 $row['time'] = $date; |
369 $row['time'] = $date; |
370 $row['comment_data'] = $text; |
370 $row['comment_data'] = $text; |
371 $row['comment_source'] = $src; |
371 $row['comment_source'] = $src; |
372 $ret = Array( |
372 $ret = Array( |
373 'mode' => 'materialize' |
373 'mode' => 'materialize' |
374 ); |
374 ); |
375 $ret = enano_safe_array_merge($ret, $row); |
375 $ret = enano_safe_array_merge($ret, $row); |
376 |
376 |
377 $ret['auth_mod_comments'] = $this->perms->get_permissions('mod_comments'); |
377 $ret['auth_mod_comments'] = $this->perms->get_permissions('mod_comments'); |
378 $ret['auth_post_comments'] = $this->perms->get_permissions('post_comments'); |
378 $ret['auth_post_comments'] = $this->perms->get_permissions('post_comments'); |
379 $ret['auth_edit_comments'] = $this->perms->get_permissions('edit_comments'); |
379 $ret['auth_edit_comments'] = $this->perms->get_permissions('edit_comments'); |
380 $ret['user_id'] = $session->user_id; |
380 $ret['user_id'] = $session->user_id; |
381 $ret['rank_data'] = $session->get_user_rank($session->user_id); |
381 $ret['rank_data'] = $session->get_user_rank($session->user_id); |
382 $ret['username'] = $session->username; |
382 $ret['username'] = $session->username; |
383 $ret['logged_in'] = $session->user_logged_in; |
383 $ret['logged_in'] = $session->user_logged_in; |
384 $ret['signature'] = RenderMan::render($row['signature']); |
384 $ret['signature'] = RenderMan::render($row['signature']); |
385 |
385 |
386 $ret['user_level_list'] = Array(); |
386 $ret['user_level_list'] = Array(); |
387 $ret['user_level_list']['guest'] = USER_LEVEL_GUEST; |
387 $ret['user_level_list']['guest'] = USER_LEVEL_GUEST; |
388 $ret['user_level_list']['member'] = USER_LEVEL_MEMBER; |
388 $ret['user_level_list']['member'] = USER_LEVEL_MEMBER; |
389 $ret['user_level_list']['mod'] = USER_LEVEL_MOD; |
389 $ret['user_level_list']['mod'] = USER_LEVEL_MOD; |
390 $ret['user_level_list']['admin'] = USER_LEVEL_ADMIN; |
390 $ret['user_level_list']['admin'] = USER_LEVEL_ADMIN; |
391 $ret['avatar_path'] = make_avatar_url($row['user_id'], $row['avatar_type'], $row['email']); |
391 $ret['avatar_path'] = make_avatar_url($row['user_id'], $row['avatar_type'], $row['email']); |
392 } |
392 } |
393 |
393 |
394 break; |
394 break; |
395 case 'approve': |
395 case 'approve': |
396 if ( !$this->perms->get_permissions('mod_comments') ) |
396 if ( !$this->perms->get_permissions('mod_comments') ) |
397 { |
397 { |
398 $ret = Array( |
398 $ret = Array( |
399 'mode' => 'error', |
399 'mode' => 'error', |
400 'error' => 'You are not authorized to moderate comments.' |
400 'error' => 'You are not authorized to moderate comments.' |
401 ); |
401 ); |
402 echo enano_json_encode($ret); |
402 echo enano_json_encode($ret); |
403 return $ret; |
403 return $ret; |
404 } |
404 } |
405 |
405 |
406 $cid = (string)$data['id']; |
406 $cid = (string)$data['id']; |
407 if ( !ctype_digit($cid) || intval($cid) < 1 ) |
407 if ( !ctype_digit($cid) || intval($cid) < 1 ) |
408 { |
408 { |
409 echo '{"mode":"error","error":"HACKING ATTEMPT"}'; |
409 echo '{"mode":"error","error":"HACKING ATTEMPT"}'; |
410 return false; |
410 return false; |
411 } |
411 } |
412 $cid = intval($cid); |
412 $cid = intval($cid); |
413 $q = $db->sql_query('SELECT subject,approved FROM '.table_prefix.'comments WHERE comment_id='.$cid.';'); |
413 $q = $db->sql_query('SELECT subject,approved FROM '.table_prefix.'comments WHERE comment_id='.$cid.';'); |
414 if(!$q || $db->numrows() < 1) |
414 if(!$q || $db->numrows() < 1) |
415 $db->die_json(); |
415 $db->die_json(); |
416 $row = $db->fetchrow(); |
416 $row = $db->fetchrow(); |
417 $db->free_result(); |
417 $db->free_result(); |
418 $appr = ( $row['approved'] == '1' ) ? '0' : '1'; |
418 $appr = ( $row['approved'] == '1' ) ? '0' : '1'; |
419 $q = $db->sql_query('UPDATE '.table_prefix."comments SET approved=$appr WHERE comment_id=$cid;"); |
419 $q = $db->sql_query('UPDATE '.table_prefix."comments SET approved=$appr WHERE comment_id=$cid;"); |
420 if (!$q) |
420 if (!$q) |
421 $db->die_json(); |
421 $db->die_json(); |
422 |
422 |
423 $ret = Array( |
423 $ret = Array( |
424 'mode' => 'redraw', |
424 'mode' => 'redraw', |
425 'approved' => $appr, |
425 'approved' => $appr, |
426 'subj' => $row['subject'], |
426 'subj' => $row['subject'], |
427 'id' => $data['local_id'], |
427 'id' => $data['local_id'], |
428 'approve_updated' => 'yes' |
428 'approve_updated' => 'yes' |
429 ); |
429 ); |
430 |
430 |
431 break; |
431 break; |
432 case 'view_ip': |
432 case 'view_ip': |
433 if ( !$session->get_permissions('mod_comments') ) |
433 if ( !$session->get_permissions('mod_comments') ) |
434 { |
434 { |
435 return array( |
435 return array( |
436 'mode' => 'error', |
436 'mode' => 'error', |
437 'error' => 'Unauthorized' |
437 'error' => 'Unauthorized' |
438 ); |
438 ); |
439 } |
439 } |
440 // fetch comment info |
440 // fetch comment info |
441 if ( !is_int($data['id']) ) |
441 if ( !is_int($data['id']) ) |
442 { |
442 { |
443 return array( |
443 return array( |
444 'mode' => 'error', |
444 'mode' => 'error', |
445 'error' => 'Unauthorized' |
445 'error' => 'Unauthorized' |
446 ); |
446 ); |
447 } |
447 } |
448 $id =& $data['id']; |
448 $id =& $data['id']; |
449 $q = $db->sql_query('SELECT ip_address, name FROM ' . table_prefix . 'comments WHERE comment_id = ' . $id . ';'); |
449 $q = $db->sql_query('SELECT ip_address, name FROM ' . table_prefix . 'comments WHERE comment_id = ' . $id . ';'); |
450 if ( !$q || $db->numrows() < 1 ) |
450 if ( !$q || $db->numrows() < 1 ) |
451 { |
451 { |
452 $db->die_json(); |
452 $db->die_json(); |
453 } |
453 } |
454 list($ip_addr, $name) = $db->fetchrow_num($q); |
454 list($ip_addr, $name) = $db->fetchrow_num($q); |
455 $db->free_result(); |
455 $db->free_result(); |
456 $name = $db->escape($name); |
456 $name = $db->escape($name); |
457 $username = $db->escape($session->username); |
457 $username = $db->escape($session->username); |
458 // log this action |
458 // log this action |
459 $q = $db->sql_query('INSERT INTO ' . table_prefix . "logs(time_id, log_type, action, page_text, author, author_uid, edit_summary) VALUES\n " |
459 $q = $db->sql_query('INSERT INTO ' . table_prefix . "logs(time_id, log_type, action, page_text, author, author_uid, edit_summary) VALUES\n " |
460 . "( " . time() . ", 'security', 'view_comment_ip', '$name', '$username', $session->user_id, '{$_SERVER['REMOTE_ADDR']}' );"); |
460 . "( " . time() . ", 'security', 'view_comment_ip', '$name', '$username', $session->user_id, '{$_SERVER['REMOTE_ADDR']}' );"); |
461 if ( !$q ) |
461 if ( !$q ) |
462 $db->die_json(); |
462 $db->die_json(); |
463 |
463 |
464 // send packet |
464 // send packet |
465 $ret = array( |
465 $ret = array( |
466 'mode' => 'redraw', |
466 'mode' => 'redraw', |
467 'ip_addr' => $ip_addr, |
467 'ip_addr' => $ip_addr, |
468 'local_id' => $data['local_id'] |
468 'local_id' => $data['local_id'] |
469 ); |
469 ); |
470 break; |
470 break; |
471 default: |
471 default: |
472 $ret = Array( |
472 $ret = Array( |
473 'mode' => 'error', |
473 'mode' => 'error', |
474 'error' => $data['mode'] . ' is not a valid request mode' |
474 'error' => $data['mode'] . ' is not a valid request mode' |
475 ); |
475 ); |
476 break; |
476 break; |
477 } |
477 } |
478 if ( $is_json ) |
478 if ( $is_json ) |
479 echo enano_json_encode($ret); |
479 echo enano_json_encode($ret); |
480 |
480 |
481 return $ret; |
481 return $ret; |
482 } |
482 } |
483 |
483 |
484 } // class Comments |
484 } // class Comments |
485 |
485 |