qa-page-question-submit.php 18 KB
Newer Older
Gideon Greenspan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
<?php

/*
	Question2Answer (c) Gideon Greenspan

	http://www.question2answer.org/

	
	File: qa-include/qa-page-question-submit.php
	Version: See define()s at top of qa-include/qa-base.php
	Description: Common functions for question page form submission, either regular or via Ajax


	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	More about this license: http://www.question2answer.org/license.php
*/

	if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
		header('Location: ../');
		exit;
	}


	require_once QA_INCLUDE_DIR.'qa-app-post-create.php';
	require_once QA_INCLUDE_DIR.'qa-app-post-update.php';


	function qa_page_q_single_click_q($question, $answers, $commentsfollows, $closepost, &$error)
/*
	Checks for a POSTed click on $question by the current user and returns true if it was permitted and processed. Pass
	in the question's $answers, all $commentsfollows from it or its answers, and its closing $closepost (or null if
	none). If there is an error to display, it will be passed out in $error.
*/
	{
		require_once QA_INCLUDE_DIR.'qa-app-post-update.php';
		require_once QA_INCLUDE_DIR.'qa-app-limits.php';

		$userid=qa_get_logged_in_userid();
		$handle=qa_get_logged_in_handle();
		$cookieid=qa_cookie_get();
		
Gideon Greenspan committed
51
		if (qa_clicked('q_doreopen') && $question['reopenable'] && qa_page_q_click_check_form_code($question, $error) ) {
Gideon Greenspan committed
52 53 54 55
			qa_question_close_clear($question, $closepost, $userid, $handle, $cookieid);
			return true;
		}
		
Gideon Greenspan committed
56 57 58 59 60
		if ( (qa_clicked('q_dohide') && $question['hideable']) || (qa_clicked('q_doreject') && $question['moderatable']) )
			if (qa_page_q_click_check_form_code($question, $error)) {
				qa_question_set_hidden($question, true, $userid, $handle, $cookieid, $answers, $commentsfollows, $closepost);
				return true;
			}
Gideon Greenspan committed
61
		
Gideon Greenspan committed
62 63 64
		if ( (qa_clicked('q_doreshow') && $question['reshowable']) || (qa_clicked('q_doapprove') && $question['moderatable']) )
			if (qa_page_q_click_check_form_code($question, $error)) {
				if ($question['moderatable'] || $question['reshowimmed']) {
Gideon Greenspan committed
65
					$status=QA_POST_STATUS_NORMAL;
Gideon Greenspan committed
66 67 68 69 70 71 72 73 74 75 76

				} else {
					$in=qa_page_q_prepare_post_for_filters($question);
					$filtermodules=qa_load_modules_with('filter', 'filter_question'); // run through filters but only for queued status

					foreach ($filtermodules as $filtermodule) {
						$tempin=$in; // always pass original question in because we aren't modifying anything else
						$filtermodule->filter_question($tempin, $temperrors, $question);
						$in['queued']=$tempin; // only preserve queued status in loop
					}
					
Gideon Greenspan committed
77
					$status=$in['queued'] ? QA_POST_STATUS_QUEUED : QA_POST_STATUS_NORMAL;
Gideon Greenspan committed
78 79 80 81 82
				}
				
				qa_question_set_status($question, $status, $userid, $handle, $cookieid, $answers, $commentsfollows, $closepost);
				return true;
			}
Gideon Greenspan committed
83
		
Gideon Greenspan committed
84 85
		if (qa_clicked('q_doclaim') && $question['claimable'] && qa_page_q_click_check_form_code($question, $error) ) {
			if (qa_user_limits_remaining(QA_LIMIT_QUESTIONS)) { // already checked 'permit_post_q'
Gideon Greenspan committed
86 87 88 89 90 91 92
				qa_question_set_userid($question, $userid, $handle, $cookieid);
				return true;
	
			} else
				$error=qa_lang_html('question/ask_limit');
		}
		
Gideon Greenspan committed
93
		if (qa_clicked('q_doflag') && $question['flagbutton'] && qa_page_q_click_check_form_code($question, $error)) {
Gideon Greenspan committed
94 95 96 97 98 99 100 101 102 103
			require_once QA_INCLUDE_DIR.'qa-app-votes.php';
			
			$error=qa_flag_error_html($question, $userid, qa_request());
			if (!$error) {
				if (qa_flag_set_tohide($question, $userid, $handle, $cookieid, $question))
					qa_question_set_hidden($question, true, null, null, null, $answers, $commentsfollows, $closepost); // hiding not really by this user so pass nulls
				return true;
			}
		}
		
Gideon Greenspan committed
104
		if (qa_clicked('q_dounflag') && $question['unflaggable'] && qa_page_q_click_check_form_code($question, $error)) {
Gideon Greenspan committed
105 106 107 108 109 110
			require_once QA_INCLUDE_DIR.'qa-app-votes.php';
			
			qa_flag_clear($question, $userid, $handle, $cookieid);
			return true;
		}
		
Gideon Greenspan committed
111
		if (qa_clicked('q_doclearflags') && $question['clearflaggable'] && qa_page_q_click_check_form_code($question, $error)) {
Gideon Greenspan committed
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
			require_once QA_INCLUDE_DIR.'qa-app-votes.php';
		
			qa_flags_clear_all($question, $userid, $handle, $cookieid);
			return true;
		}
		
		return false;
	}
	
	
	function qa_page_q_single_click_a($answer, $question, $answers, $commentsfollows, $allowselectmove, &$error)
/*
	Checks for a POSTed click on $answer by the current user and returns true if it was permitted and processed. Pass in
	the $question, all of its $answers, and all $commentsfollows from it or its answers. Set $allowselectmove to whether
	it is legitimate to change the selected answer for the question from one to another (this can't be done via Ajax).
	If there is an error to display, it will be passed out in $error.
*/
	{
		$userid=qa_get_logged_in_userid();
		$handle=qa_get_logged_in_handle();
		$cookieid=qa_cookie_get();
		
		$prefix='a'.$answer['postid'].'_';
		
Gideon Greenspan committed
136
		if (qa_clicked($prefix.'doselect') && $question['aselectable'] && ($allowselectmove || ( (!isset($question['selchildid'])) && !qa_opt('do_close_on_select'))) && qa_page_q_click_check_form_code($answer, $error) ) {
Gideon Greenspan committed
137 138 139 140
			qa_question_set_selchildid($userid, $handle, $cookieid, $question, $answer['postid'], $answers);
			return true;
		}
		
Gideon Greenspan committed
141
		if (qa_clicked($prefix.'dounselect') && $question['aselectable'] && ($question['selchildid']==$answer['postid']) && ($allowselectmove || !qa_opt('do_close_on_select')) && qa_page_q_click_check_form_code($answer, $error)) {
Gideon Greenspan committed
142 143 144 145
			qa_question_set_selchildid($userid, $handle, $cookieid, $question, null, $answers);
			return true;
		}

Gideon Greenspan committed
146 147 148 149 150
		if ( (qa_clicked($prefix.'dohide') && $answer['hideable']) || (qa_clicked($prefix.'doreject') && $answer['moderatable']) )
			if (qa_page_q_click_check_form_code($answer, $error)) {
				qa_answer_set_hidden($answer, true, $userid, $handle, $cookieid, $question, $commentsfollows);
				return true;
			}
Gideon Greenspan committed
151
		
Gideon Greenspan committed
152 153 154
		if ( (qa_clicked($prefix.'doreshow') && $answer['reshowable']) || (qa_clicked($prefix.'doapprove') && $answer['moderatable']) )
			if (qa_page_q_click_check_form_code($answer, $error)) {
				if ($answer['moderatable'] || $answer['reshowimmed']) {
Gideon Greenspan committed
155
					$status=QA_POST_STATUS_NORMAL;
Gideon Greenspan committed
156 157 158 159 160 161 162 163 164 165 166
					
				} else {
					$in=qa_page_q_prepare_post_for_filters($answer);
					$filtermodules=qa_load_modules_with('filter', 'filter_answer'); // run through filters but only for queued status
					
					foreach ($filtermodules as $filtermodule) {
						$tempin=$in; // always pass original answer in because we aren't modifying anything else
						$filtermodule->filter_answer($tempin, $temperrors, $question, $answer);
						$in['queued']=$tempin; // only preserve queued status in loop
					}
					
Gideon Greenspan committed
167
					$status=$in['queued'] ? QA_POST_STATUS_QUEUED : QA_POST_STATUS_NORMAL;
Gideon Greenspan committed
168 169 170 171 172
				}
				
				qa_answer_set_status($answer, $status, $userid, $handle, $cookieid, $question, $commentsfollows);
				return true;
			}
Gideon Greenspan committed
173
		
Gideon Greenspan committed
174
		if (qa_clicked($prefix.'dodelete') && $answer['deleteable'] && qa_page_q_click_check_form_code($answer, $error)) {
Gideon Greenspan committed
175 176 177 178
			qa_answer_delete($answer, $question, $userid, $handle, $cookieid);
			return true;
		}
		
Gideon Greenspan committed
179 180
		if (qa_clicked($prefix.'doclaim') && $answer['claimable'] && qa_page_q_click_check_form_code($answer, $error)) {
			if (qa_user_limits_remaining(QA_LIMIT_ANSWERS)) { // already checked 'permit_post_a'
Gideon Greenspan committed
181 182 183 184 185 186 187
				qa_answer_set_userid($answer, $userid, $handle, $cookieid);
				return true;
			
			} else
				$error=qa_lang_html('question/answer_limit');
		}
		
Gideon Greenspan committed
188
		if (qa_clicked($prefix.'doflag') && $answer['flagbutton'] && qa_page_q_click_check_form_code($answer, $error)) {
Gideon Greenspan committed
189 190 191 192 193 194 195 196 197 198 199
			require_once QA_INCLUDE_DIR.'qa-app-votes.php';
			
			$error=qa_flag_error_html($answer, $userid, qa_request());
			if (!$error) {
				if (qa_flag_set_tohide($answer, $userid, $handle, $cookieid, $question))
					qa_answer_set_hidden($answer, true, null, null, null, $question, $commentsfollows); // hiding not really by this user so pass nulls
					
				return true;
			}
		}

Gideon Greenspan committed
200
		if (qa_clicked($prefix.'dounflag') && $answer['unflaggable'] && qa_page_q_click_check_form_code($answer, $error)) {
Gideon Greenspan committed
201 202 203 204 205 206
			require_once QA_INCLUDE_DIR.'qa-app-votes.php';
			
			qa_flag_clear($answer, $userid, $handle, $cookieid);
			return true;
		}
		
Gideon Greenspan committed
207
		if (qa_clicked($prefix.'doclearflags') && $answer['clearflaggable'] && qa_page_q_click_check_form_code($answer, $error)) {
Gideon Greenspan committed
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
			require_once QA_INCLUDE_DIR.'qa-app-votes.php';
			
			qa_flags_clear_all($answer, $userid, $handle, $cookieid);
			return true;
		}

		return false;
	}
	
	
	function qa_page_q_single_click_c($comment, $question, $parent, &$error)
/*
	Checks for a POSTed click on $comment by the current user and returns true if it was permitted and processed. Pass
	in the antecedent $question and the comment's $parent post. If there is an error to display, it will be passed out
	in $error.
*/
	{
		$userid=qa_get_logged_in_userid();
		$handle=qa_get_logged_in_handle();
		$cookieid=qa_cookie_get();
		
		$prefix='c'.$comment['postid'].'_';
		
Gideon Greenspan committed
231 232 233 234 235
		if ( (qa_clicked($prefix.'dohide') && $comment['hideable']) || (qa_clicked($prefix.'doreject') && $comment['moderatable']) )
			if (qa_page_q_click_check_form_code($parent, $error)) {
				qa_comment_set_hidden($comment, true, $userid, $handle, $cookieid, $question, $parent);
				return true;
			}
Gideon Greenspan committed
236
		
Gideon Greenspan committed
237 238 239
		if ( (qa_clicked($prefix.'doreshow') && $comment['reshowable']) || (qa_clicked($prefix.'doapprove') && $comment['moderatable']) )
			if (qa_page_q_click_check_form_code($parent, $error)) {
				if ($comment['moderatable'] || $comment['reshowimmed']) {
Gideon Greenspan committed
240
					$status=QA_POST_STATUS_NORMAL;
Gideon Greenspan committed
241 242 243 244 245 246 247 248 249 250 251
					
				} else {
					$in=qa_page_q_prepare_post_for_filters($comment);
					$filtermodules=qa_load_modules_with('filter', 'filter_comment'); // run through filters but only for queued status
					
					foreach ($filtermodules as $filtermodule) {
						$tempin=$in; // always pass original comment in because we aren't modifying anything else
						$filtermodule->filter_comment($tempin, $temperrors, $question, $parent, $comment);
						$in['queued']=$tempin; // only preserve queued status in loop
					}
					
Gideon Greenspan committed
252
					$status=$in['queued'] ? QA_POST_STATUS_QUEUED : QA_POST_STATUS_NORMAL;
Gideon Greenspan committed
253 254 255 256 257
				}
				
				qa_comment_set_status($comment, $status, $userid, $handle, $cookieid, $question, $parent);
				return true;
			}
Gideon Greenspan committed
258
		
Gideon Greenspan committed
259
		if (qa_clicked($prefix.'dodelete') && $comment['deleteable'] && qa_page_q_click_check_form_code($parent, $error)) {
Gideon Greenspan committed
260 261 262 263
			qa_comment_delete($comment, $question, $parent, $userid, $handle, $cookieid);
			return true;
		}
			
Gideon Greenspan committed
264 265
		if (qa_clicked($prefix.'doclaim') && $comment['claimable'] && qa_page_q_click_check_form_code($parent, $error)) {
			if (qa_user_limits_remaining(QA_LIMIT_COMMENTS)) {
Gideon Greenspan committed
266 267 268 269 270 271 272
				qa_comment_set_userid($comment, $userid, $handle, $cookieid);
				return true;
				
			} else
				$error=qa_lang_html('question/comment_limit');
		}
		
Gideon Greenspan committed
273
		if (qa_clicked($prefix.'doflag') && $comment['flagbutton'] && qa_page_q_click_check_form_code($parent, $error)) {
Gideon Greenspan committed
274 275 276 277 278 279 280 281 282 283 284
			require_once QA_INCLUDE_DIR.'qa-app-votes.php';
			
			$error=qa_flag_error_html($comment, $userid, qa_request());
			if (!$error) {
				if (qa_flag_set_tohide($comment, $userid, $handle, $cookieid, $question))
					qa_comment_set_hidden($comment, true, null, null, null, $question, $parent); // hiding not really by this user so pass nulls
				
				return true;
			}
		}

Gideon Greenspan committed
285
		if (qa_clicked($prefix.'dounflag') && $comment['unflaggable'] && qa_page_q_click_check_form_code($parent, $error)) {
Gideon Greenspan committed
286 287 288 289 290 291
			require_once QA_INCLUDE_DIR.'qa-app-votes.php';
			
			qa_flag_clear($comment, $userid, $handle, $cookieid);
			return true;
		}
		
Gideon Greenspan committed
292
		if (qa_clicked($prefix.'doclearflags') && $comment['clearflaggable'] && qa_page_q_click_check_form_code($parent, $error)) {
Gideon Greenspan committed
293 294 295 296 297 298 299 300 301 302
			require_once QA_INCLUDE_DIR.'qa-app-votes.php';
			
			qa_flags_clear_all($comment, $userid, $handle, $cookieid);
			return true;
		}
		
		return false;
	}
	
	
Gideon Greenspan committed
303
	function qa_page_q_click_check_form_code($post, &$error)
Gideon Greenspan committed
304 305 306 307
/*
	Check the form security (anti-CSRF protection) for one of the buttons shown for post $post. Return true if the
	security passed, otherwise return false and set an error message in $error
*/
Gideon Greenspan committed
308 309 310 311 312 313 314 315 316 317
	{
		$result=qa_check_form_security_code('buttons-'.$post['postid'], qa_post_text('code'));
		
		if (!$result)
			$error=qa_lang_html('misc/form_security_again');
		
		return $result;
	}
	
	
Gideon Greenspan committed
318 319 320 321 322 323 324 325
	function qa_page_q_add_a_submit($question, $answers, $usecaptcha, &$in, &$errors)
/*
	Processes a POSTed form to add an answer to $question, returning the postid if successful, otherwise null. Pass in
	other $answers to the question and whether a $usecaptcha is required. The form fields submitted will be passed out
	as an array in $in, as well as any $errors on those fields.
*/
	{
		$in=array(
Gideon Greenspan committed
326
			'name' => qa_post_text('a_name'),
Gideon Greenspan committed
327 328
			'notify' => qa_post_text('a_notify') ? true : false,
			'email' => qa_post_text('a_email'),
Gideon Greenspan committed
329
			'queued' => qa_user_moderation_reason(qa_user_level_for_post($question)) ? true : false,
Gideon Greenspan committed
330 331 332 333 334
		);
		
		qa_get_post_content('a_editor', 'a_content', $in['editor'], $in['content'], $in['format'], $in['text']);
		
		$errors=array();
Gideon Greenspan committed
335 336 337 338 339 340 341 342 343 344 345

		if (!qa_check_form_security_code('answer-'.$question['postid'], qa_post_text('code')))
			$errors['content']=qa_lang_html('misc/form_security_again');
		
		else {
			$filtermodules=qa_load_modules_with('filter', 'filter_answer');
			foreach ($filtermodules as $filtermodule) {
				$oldin=$in;
				$filtermodule->filter_answer($in, $errors, $question, null);
				qa_update_post_text($in, $oldin);
			}
Gideon Greenspan committed
346
			
Gideon Greenspan committed
347 348 349 350 351 352 353 354 355 356 357
			if ($usecaptcha)
				qa_captcha_validate_post($errors);
				
			if (empty($errors)) {
				$testwords=implode(' ', qa_string_to_words($in['content']));
				
				foreach ($answers as $answer)
					if (!$answer['hidden'])
						if (implode(' ', qa_string_to_words($answer['content'])) == $testwords)
							$errors['content']=qa_lang_html('question/duplicate_content');
			}
Gideon Greenspan committed
358
			
Gideon Greenspan committed
359 360 361 362 363 364 365 366 367 368
			if (empty($errors)) {
				$userid=qa_get_logged_in_userid();
				$handle=qa_get_logged_in_handle();
				$cookieid=isset($userid) ? qa_cookie_get() : qa_cookie_get_create(); // create a new cookie if necessary
				
				$answerid=qa_answer_create($userid, $handle, $cookieid, $in['content'], $in['format'], $in['text'], $in['notify'], $in['email'],
					$question, $in['queued'], $in['name']);
				
				return $answerid;
			}
Gideon Greenspan committed
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
		}
		
		return null;
	}
	

	function qa_page_q_add_c_submit($question, $parent, $commentsfollows, $usecaptcha, &$in, &$errors)
/*
	Processes a POSTed form to add a comment, returning the postid if successful, otherwise null. Pass in the antecedent
	$question and the comment's $parent post. Set $usecaptcha to whether a captcha is required. Pass an array which
	includes the other comments with the same parent in $commentsfollows (it can contain other posts which are ignored).
	The form fields submitted will be passed out as an array in $in, as well as any $errors on those fields.
*/
	{
		$parentid=$parent['postid'];
		
		$prefix='c'.$parentid.'_';
		
		$in=array(
Gideon Greenspan committed
388
			'name' => qa_post_text($prefix.'name'),
Gideon Greenspan committed
389 390
			'notify' => qa_post_text($prefix.'notify') ? true : false,
			'email' => qa_post_text($prefix.'email'),
Gideon Greenspan committed
391
			'queued' => qa_user_moderation_reason(qa_user_level_for_post($parent)) ? true : false,
Gideon Greenspan committed
392 393 394 395 396 397
		);
		
		qa_get_post_content($prefix.'editor', $prefix.'content', $in['editor'], $in['content'], $in['format'], $in['text']);

		$errors=array();
		
Gideon Greenspan committed
398 399
		if (!qa_check_form_security_code('comment-'.$parent['postid'], qa_post_text($prefix.'code')))
			$errors['content']=qa_lang_html('misc/form_security_again');
Gideon Greenspan committed
400
		
Gideon Greenspan committed
401 402 403 404 405 406 407
		else {
			$filtermodules=qa_load_modules_with('filter', 'filter_comment');
			foreach ($filtermodules as $filtermodule) {
				$oldin=$in;
				$filtermodule->filter_comment($in, $errors, $question, $parent, null);
				qa_update_post_text($in, $oldin);
			}
Gideon Greenspan committed
408
			
Gideon Greenspan committed
409 410 411 412 413 414 415 416 417 418 419
			if ($usecaptcha)
				qa_captcha_validate_post($errors);
	
			if (empty($errors)) {
				$testwords=implode(' ', qa_string_to_words($in['content']));
				
				foreach ($commentsfollows as $comment)
					if (($comment['basetype']=='C') && ($comment['parentid']==$parentid) && !$comment['hidden'])
						if (implode(' ', qa_string_to_words($comment['content'])) == $testwords)
							$errors['content']=qa_lang_html('question/duplicate_content');
			}
Gideon Greenspan committed
420
			
Gideon Greenspan committed
421 422 423 424 425 426 427 428 429 430
			if (empty($errors)) {
				$userid=qa_get_logged_in_userid();
				$handle=qa_get_logged_in_handle();
				$cookieid=isset($userid) ? qa_cookie_get() : qa_cookie_get_create(); // create a new cookie if necessary
							
				$commentid=qa_comment_create($userid, $handle, $cookieid, $in['content'], $in['format'], $in['text'], $in['notify'], $in['email'],
					$question, $parent, $commentsfollows, $in['queued'], $in['name']);
				
				return $commentid;
			}
Gideon Greenspan committed
431 432 433 434 435
		}
		
		return null;
	}
	
Gideon Greenspan committed
436 437
	
	function qa_page_q_prepare_post_for_filters($post)
Gideon Greenspan committed
438 439 440
/*
	Return the array of information to be passed to filter modules for the post in $post (from the database)
*/
Gideon Greenspan committed
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
	{
		$in=array(
			'content' => $post['content'],
			'format' => $post['format'],
			'text' => qa_viewer_text($post['content'], $post['format']),
			'notify' => isset($post['notify']) ? true : false,
			'email' => qa_email_validate($post['notify']) ? $post['notify'] : null,
			'queued' => qa_user_moderation_reason(qa_user_level_for_post($post)) ? true : false,
		);
		
		if ($post['basetype']=='Q') {
			$in['title']=$post['title'];
			$in['tags']=qa_tagstring_to_tags($post['tags']);
			$in['categoryid']=$post['categoryid'];
			$in['extra']=$post['extra'];
		}
		
		return $in;
	}
	
Gideon Greenspan committed
461 462 463 464

/*
	Omit PHP closing tag to help avoid accidental output
*/