includes/functions.php
changeset 343 7e6537fd4730
parent 335 59fee40b4644
child 344 0fa28c5aabe9
--- a/includes/functions.php	Tue Nov 16 12:44:22 2010 -0500
+++ b/includes/functions.php	Tue Jul 12 22:13:37 2011 -0400
@@ -323,6 +323,92 @@
 
 }
 
+/**
+ * Generates a confirmation form if a CSRF check fails. Will terminate execution.
+ */
+
+function csrf_request_confirm()
+{
+	global $db, $session, $paths, $template, $plugins; // Common objects
+	
+	// If the token was overridden with the correct one, the user confirmed the action using this form. Continue exec.
+	if ( isset($_POST['cstok']) || isset($_GET['cstok']) )
+	{
+		// using the if() check makes sure that the token isn't in a cookie, since $_REQUEST includes $_COOKIE.
+		$token_check =& $_REQUEST['cstok'];
+		if ( $token_check === $session->csrf_token )
+		{
+			// overridden token matches, continue exec
+			return true;
+		}
+	}
+	
+	@ob_end_clean();
+	
+	$template->tpl_strings['PAGE_NAME'] = 'Invalid form confirmation key';
+	$template->header();
+	
+	// initial info
+	echo '<p>Your browser sent an invalid confirmation key for a form. Your session may have expired, or you may have been redirected here from a remote site in an attack known as Cross-Site Request Forgery (CSRF). If you are sure you want to continue with this action, you may click the button below. Otherwise, return to the main page and do not proceed.</p>';
+	
+	// start form
+	$form_method = ( empty($_POST) ) ? 'get' : 'post';
+	echo '<form action="' . htmlspecialchars($_SERVER['REQUEST_URI']) . '" method="' . $form_method . '" enctype="multipart/form-data">';
+	
+	echo '<fieldset enano:expand="closed">';
+	echo '<legend>View request and form data</legend><div>';
+	
+	if ( empty($_POST) )
+	{
+		// GET request
+		echo csrf_confirm_get_recursive();
+	}
+	else
+	{
+		// POST request
+		echo csrf_confirm_post_recursive();
+	}
+	echo '</div></fieldset>';
+	// insert the right CSRF token
+	echo '<input type="hidden" name="cstok" value="' . $session->csrf_token . '" />';
+	echo '<p><input type="submit" value="Continue" /></p>';
+	echo '</form><script type="text/javascript">addOnloadHook(function(){load_component(\'expander\');});</script>';
+	
+	$template->footer();
+	
+	exit;
+}
+
+function csrf_confirm_get_recursive($_inner = false, $pfx = false, $data = false)
+{
+	// make posted arrays work right
+	if ( !$data )
+		( $_inner == 'post' ) ? $data =& $_POST : $data =& $_GET;
+	foreach ( $data as $key => $value )
+	{
+		$pfx_this = ( empty($pfx) ) ? $key : "{$pfx}[{$key}]";
+		if ( is_array($value) )
+		{
+			csrf_confirm_get_recursive(true, $pfx_this, $value);
+		}
+		else if ( empty($value) )
+		{
+			echo htmlspecialchars($pfx_this . " = <nil>") . "<br />\n";
+			echo '<input type="hidden" name="' . htmlspecialchars($pfx_this) . '" value="" />';
+		}
+		else
+		{
+			echo htmlspecialchars($pfx_this . " = " . $value) . "<br />\n";
+			echo '<input type="hidden" name="' . htmlspecialchars($pfx_this) . '" value="' . htmlspecialchars($value) . '" />';
+		}
+	}
+}
+
+function csrf_confirm_post_recursive()
+{
+	csrf_confirm_get_recursive('post');
+}
+
 // Removed wikiFormat() from here, replaced with RenderMan::render
 
 /**