Index: docs/CHANGES.htm
===================================================================
--- docs/CHANGES.htm	(.../1.1.6.6)	(revision 1372)
+++ docs/CHANGES.htm	(.../1.1.6.7)	(revision 1372)
@@ -2,7 +2,7 @@
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html>
 <head>
-    <title>WikkaReleaseNotes1166</title>
+    <title>WikkaReleaseNotes1167</title>
     <meta http-equiv="Content-Type" content="text/html;
 charset=iso-8859-1" />
     <style type="text/css">
@@ -1152,66 +1152,31 @@
 <a class="" href="http://docs.wikkawiki.org/WikkaReleaseNotes">Wikka Changelog</a><br />
 <hr />
 
-<h2> <a class="" href="http://docs.wikkawiki.org/WhatsNew1166">Wikka 1.1.6.6</a> Release Notes </h2>
+<h2> <a class="" href="http://docs.wikkawiki.org/WhatsNew1166">Wikka 1.1.6.7</a> Release Notes </h2>
 
-<span class="notes">Released on XXX XX, XXXX</span><br />
+<span class="notes">Released on Jun 15, 2009</span><br />
 <br />
 <div class="floatr"><h5>See also:</h5>
 
-<ul><li><strong><a class="" href="http://docs.wikkawiki.org/WhatsNew1166">What's new in 1.1.6.6</a></strong>
-</li><li><a class="" href="http://docs.wikkawiki.org/Installing1166">Installation &amp; upgrade notes for 1.1.6.6</a></li></ul>
+<ul><li><strong><a class="missingpage" href="http://docs.wikkawiki.org/WhatsNew1167/edit" title="Create this page">What's new in 1.1.6.7</a></strong>
+</li><li><a class="missingpage" href="http://docs.wikkawiki.org/Installing1167/edit" title="Create this page">Installation &amp; upgrade notes for 1.1.6.7</a>
+</li><li> <a class="" href="http://docs.wikkawiki.org/InstallingPlugins">How to use the plugins folder</a></li></ul>
 </div><h5>Acknowledgments</h5>
 
-Thanks to doomedfox, Vincent Mayoux, martin_misuth, Krzysztof Trybowski, bikoz, toringe, Eclipse, apxrms.<br />
+Thanks to Ian Andolina, Sven Krewitt (Secunia).<br />
 <br />
 <h5>Security fixes</h5>
 
-<ul><li> Removed generic references to <tt>$_REQUEST</tt> global variable. Ticket: 312
-</li><li> Restricted size of note field in editor. Ticket: 826
-</li><li> New antispam measure: Random tokens added to submitted forms to discourage scripted comment/page spam attacks. Ticket: 154
-</li><li> Pages that are not accessible to the current user are now filtered from the backlinks handler. Ticket: 851 </li></ul>
+<ul><li> Added random tokens (form IDs) to form submissions to mitigate CSRF attacks. Ticket: 154
+</li><li> Added validation checks for GET params on admin pages to mitigate XSS attacks. Ticket: 879</li></ul>
 <br />
-<h5>Bug fixes</h5>
-
-<ul><li> Under some conditions, a user attempting to log out will discover he/she is not able to do so. Ticket: 800
-</li><li> Prevent filename inheritance across multiple code blocks in grabcode handler. Ticket: 783
-</li><li> <tt>meta_keyword</tt> and <tt>meta_description</tt> config entries now escaped to ensure XHTML validation. Ticket: 816
-</li><li> Fixed DB error generated during some page ACL operations. Ticket: 811
-</li><li> Floats properly cleared when closing main <tt>&lt;div&gt;</tt>. Ticket: 683
-</li><li> Comment search filters now work correctly for registered users. Ticket: 810
-</li><li> Fixed bug that prevented file downloads in IE. Ticket: 848</li></ul>
-<br />
-<h5>New features</h5>
-
-<ul><li> <a class="ext" href="http://www.universaleditbutton.org">Universal Edit Button</a> support. Ticket: 779
-</li><li> Redirection on login. Users attempting to write-access a wiki page are now redirected to the page after logging in. Ticket: 245
-</li><li> Full text search now has option to perform case-sensitive searches (non-case-sensitive searches are performed by default). Ticket: 821
-</li><li> <a class="" href="http://docs.wikkawiki.org/RevActionInfo">{{rev}}</a> action: a simple action to display the current revision number of a page. Ticket: 813
-</li><li> Fast switch between source view and rendered view for old page revisions. Ticket: 844 <span class="notes">(not included in RC1)</span>
-</li><li> Fast switch between <em>full diff</em> and <em>simple diff</em> mode. Ticket: 844 <span class="notes">(not included in RC1)</span>
-</li><li> Support for multiple paths in config file to permit <a class="" href="http://docs.wikkawiki.org/InstallingPlugins">directory overrides for plugins</a> (actions, handlers, templates, formatters, and CSS files). Ticket: 805</li></ul>
-<br />
 <h5>Misc</h5>
 
-<ul><li> Added support for <tt>width</tt> and <tt>height</tt> parameters in <a class="" href="http://docs.wikkawiki.org/AddingImages">image</a> action. Ticket: 853
-</li><li> CSS-driven link tails (replace the hardcoded <tt>external_link_tail</tt>). Ticket: 35 <span class="notes">(not included in RC1)</span>
-</li><li> Added new library function, <tt>AddCustomHeaders()</tt>, to facilitate customization of output based upon runtime config options. Ticket: 804
-</li><li> Minor code cleanup. Ticket: 828
-</li><li> Added a courtesy link pointing to new page created by clone handler. Ticket: 832
-</li><li> Normalized separators used in config file. Ticket: 842
-</li><li> Removed unnecessary JS dependencies in core actions, handlers and installer. Ticket: 353
-</li><li> Diff to output differences in raw wiki markup. Ticket: 770 <span class="notes">(not included in RC1)</span>
-</li><li> Semantically correct use of <tt>&lt;ins&gt;</tt> and <tt>&lt;del&gt;</tt> in the formatter and diff handler. Ticket: 274 <span class="notes">(not included in RC1)</span>
-</li><li> Added meta generator tag. Ticket: 839
-</li><li> Added link to the configuration settings documentation page from <tt>wikka.config.php</tt>. Ticket: 841
-</li><li> New logo. Ticket: 784 <span class="notes">(not included in RC1)</span>
-</li><li> New feed icon. Ticket: 150 <span class="notes">(not included in RC1)</span>
-</li><li> Improved XHTML source layout for readability. Ticket: 784 <span class="notes">(not included in RC1)</span>
-</li><li> Fixed issue that may result in incorrect display of page generation time. Ticket: 850.</li></ul>
+<ul><li> Shortened default timeout when Wikka server not reachable for version checks; produce a more meaningful error message. Ticket: 884</li></ul>
 <br />
 <hr />
 
 CategoryEN
-<div class="smallprint">Page was generated in 0.1302 seconds</div>
+<div class="smallprint">Page was generated in 0.0303 seconds</div>
 </body>
 </html>
\ No newline at end of file
Index: docs/CHANGES.txt
===================================================================
--- docs/CHANGES.txt	(.../1.1.6.6)	(revision 1372)
+++ docs/CHANGES.txt	(.../1.1.6.7)	(revision 1372)
@@ -1,79 +1,43 @@
-_W_i_k_k_a_ _C_h_a_n_g_e_l_o_g
-===============================================================================
-********** _WW_ii_kk_kk_aa_ _11_.._11_.._66_.._66 RReelleeaassee NNootteess **********
-Released on XXX XX, XXXX
 
-**** SSeeee aallssoo:: ****
-    * _WW_hh_aa_tt_''_ss_ _nn_ee_ww_ _ii_nn_ _11_.._11_.._66_.._66
-    * _I_n_s_t_a_l_l_a_t_i_o_n_ _&_ _u_p_g_r_a_d_e_ _n_o_t_e_s_ _f_o_r_ _1_._1_._6_._6
-**** AAcckknnoowwlleeddggmmeennttss ****
-Thanks to doomedfox, Vincent Mayoux, martin_misuth, Krzysztof Trybowski, bikoz,
-toringe, Eclipse, apxrms.
+   [1]Wikka Changelog
+     _________________________________________________________________
 
-**** SSeeccuurriittyy ffiixxeess ****
-    * Removed generic references to $_REQUEST global variable. Ticket: 312
-    * Restricted size of note field in editor. Ticket: 826
-    * New antispam measure: Random tokens added to submitted forms to
-      discourage scripted comment/page spam attacks. Ticket: 154
-    * Pages that are not accessible to the current user are now filtered from
-      the backlinks handler. Ticket: 851
+[2]Wikka 1.1.6.7 Release Notes
 
-**** BBuugg ffiixxeess ****
-    * Under some conditions, a user attempting to log out will discover he/she
-      is not able to do so. Ticket: 800
-    * Prevent filename inheritance across multiple code blocks in grabcode
-      handler. Ticket: 783
-    * meta_keyword and meta_description config entries now escaped to ensure
-      XHTML validation. Ticket: 816
-    * Fixed DB error generated during some page ACL operations. Ticket: 811
-    * Floats properly cleared when closing main <div>. Ticket: 683
-    * Comment search filters now work correctly for registered users. Ticket:
-      810
-    * Fixed bug that prevented file downloads in IE. Ticket: 848
+   Released on Jun 15, 2009
 
-**** NNeeww ffeeaattuurreess ****
-    * _U_n_i_v_e_r_s_a_l_ _E_d_i_t_ _B_u_t_t_o_n support. Ticket: 779
-    * Redirection on login. Users attempting to write-access a wiki page are
-      now redirected to the page after logging in. Ticket: 245
-    * Full text search now has option to perform case-sensitive searches (non-
-      case-sensitive searches are performed by default). Ticket: 821
-    * _{_{_r_e_v_}_} action: a simple action to display the current revision number of
-      a page. Ticket: 813
-    * Fast switch between source view and rendered view for old page revisions.
-      Ticket: 844 (not included in RC1)
-    * Fast switch between ffuullll ddiiffff and ssiimmppllee ddiiffff mode. Ticket: 844 (not
-      included in RC1)
-    * Support for multiple paths in config file to permit _d_i_r_e_c_t_o_r_y_ _o_v_e_r_r_i_d_e_s
-      _f_o_r_ _p_l_u_g_i_n_s (actions, handlers, templates, formatters, and CSS files).
-      Ticket: 805
+See also:
 
-**** MMiisscc ****
-    * Added support for width and height parameters in _i_m_a_g_e action. Ticket:
-      853
-    * CSS-driven link tails (replace the hardcoded external_link_tail). Ticket:
-      35 (not included in RC1)
-    * Added new library function, AddCustomHeaders(), to facilitate
-      customization of output based upon runtime config options. Ticket: 804
-    * Minor code cleanup. Ticket: 828
-    * Added a courtesy link pointing to new page created by clone handler.
-      Ticket: 832
-    * Normalized separators used in config file. Ticket: 842
-    * Removed unnecessary JS dependencies in core actions, handlers and
-      installer. Ticket: 353
-    * Diff to output differences in raw wiki markup. Ticket: 770 (not included
-      in RC1)
-    * Semantically correct use of <ins> and <del> in the formatter and diff
-      handler. Ticket: 274 (not included in RC1)
-    * Added meta generator tag. Ticket: 839
-    * Added link to the configuration settings documentation page from
-      wikka.config.php. Ticket: 841
-    * New logo. Ticket: 784 (not included in RC1)
-    * New feed icon. Ticket: 150 (not included in RC1)
-    * Improved XHTML source layout for readability. Ticket: 784 (not included
-      in RC1)
-    * Fixed issue that may result in incorrect display of page generation time.
-      Ticket: 850.
+     * [3]What's new in 1.1.6.7
+     * [4]Installation & upgrade notes for 1.1.6.7
+     * [5]How to use the plugins folder
 
-===============================================================================
-CategoryEN
-Page was generated in 0.1302 seconds
+      Acknowledgments
+
+   Thanks to Ian Andolina, Sven Krewitt (Secunia).
+
+      Security fixes
+
+     * Added random tokens (form IDs) to form submissions to mitigate
+       CSRF attacks. Ticket: 154
+     * Added validation checks for GET params on admin pages to mitigate
+       XSS attacks. Ticket: 879
+
+      Misc
+
+     * Shortened default timeout when Wikka server not reachable for
+       version checks; produce a more meaningful error message. Ticket:
+       884
+     _________________________________________________________________
+
+   CategoryEN
+
+   Page was generated in 0.0296 seconds
+
+References
+
+   1. http://docs.wikkawiki.org/WikkaReleaseNotes
+   2. http://docs.wikkawiki.org/WhatsNew1166
+   3. http://docs.wikkawiki.org/WhatsNew1167
+   4. http://docs.wikkawiki.org/Installing1167/edit
+   5. http://docs.wikkawiki.org/InstallingPlugins
Index: libs/antispam.lib.php
===================================================================
--- libs/antispam.lib.php	(.../1.1.6.6)	(revision 1372)
+++ libs/antispam.lib.php	(.../1.1.6.7)	(revision 1372)
@@ -1,153 +0,0 @@
-<?php
-/**
- * Anti-spam routines 
- *
- * Various routines to detect, process and log spam content.
- *
- * @name	    antispam.lib.php 
- *
- * @package	    Lib	
- * @version		$Id$
- * @license		http://www.gnu.org/copyleft/gpl.html GNU General Public License
- * @since		Wikka 1.1.6.6
- * @filesource
- *
- * @author		{@link http://wikkawiki.org/JavaWoman Marjolein Katsma}
- *
- */
-/**
- * Create and store a secret session key.
- *
- * Creates a random value and a random field name to be used to pass on the value.
- * The key,value pair is stored in the session as a serialized array.
- *
- * @author		{@link http://wikkawiki.org/JavaWoman JavaWoman}
- * @copyright	Copyright © 2005, Marjolein Katsma
- * @license		http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- * @version		0.5
- *
- * @access		public
- *
- * @param		string	$keyname	required: name under which created secret key should be stored in the session
- * @return		array				fieldname and key value.
- */
-function createSessionKey($wakka, $keyname)
-{
-	// create key and field name for it
-	$key = md5(getmicrotime());
-	$field = 'f'.substr(md5($key.getmicrotime()),0,10);
-	// store session key
-	$_SESSION[$keyname] = serialize(array($field,$key));
-	# BEGIN DEBUG - do not activate on a production server!
-	# echo '<div class="debug">'."\n";
-	# echo 'Session key:<br/>';
-	# echo 'name: '.$keyname.' - field: '.$field.' - key: '.$key.'<br/>';
-	# echo '</div>'."\n";
-	# END DEBUG
-	// return name, value pair
-	return array($field,$key);
-}
-/**
- * Creates a form fieldset with hidden field to pass on the secret session key.
- *
- * The passed key,value pair is used to create the hidden field.
- *
- * @author		{@link http://wikkawiki.org/JavaWoman JavaWoman}
- * @copyright	Copyright © 2005, Marjolein Katsma
- * @license		http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- * @version		0.5
- *
- * @access		public
- *
- * @param		array	$aKey	required: fieldname, key value pair.
- * @return		string			fieldset for form with hidden field
- */
-function createSessionKeyFieldset($wakka, $aKey)
-{
-	// get parameters
-	list($field,$key) = $aKey;
-	// create form fieldset
-	$fieldset  = '<fieldset class="hidden">'."\n";
-	$fieldset .= '	<input type="hidden" name="'.$field.'" value="'.$key.'" />'."\n";
-	$fieldset .= '</fieldset>'."\n";
-	// return fieldset
-	return $fieldset;
-}
-/**
- * Retrieve the secret session key.
- *
- * Retrieves a named secret key and returns the result as an array with name,value pair.
- * Returns FALSE if the key is not found.
- *
- * @author		{@link http://wikkawiki.org/JavaWoman JavaWoman}
- * @copyright	Copyright © 2005, Marjolein Katsma
- * @license		http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- * @version		0.5
- *
- * @access		public
- *
- * @param		string	$keyname	required: name of secret key to retrieve from the session
- * @return		mixed				array with name,value pair on success, FALSE if entry not found.
- */
-function getSessionKey($wakka, $keyname)
-{
-	if (!isset($_SESSION[$keyname]))
-	{
-		return FALSE;
-	}
-	else
-	{
-		$aKey = unserialize($_SESSION[$keyname]);		# retrieve secret key data
-		unset($_SESSION[$keyname]);						# clear secret key
-		return $aKey;
-	}
-}
-/**
- * Check hidden session key: it must be passed and it must have the correct name & value.
- *
- * Looks for a given name,value pair passed either in POST (default) or in GET request.
- * Returns TRUE if the correct field and value is found, a reason for failure otherwise.
- * Make sure to check for identity TRUE (TRUE === returnval), do not evaluate return value
- * as boolean!!
- *
- * @author		{@link http://wikkawiki.org/JavaWoman JavaWoman}
- * @copyright	Copyright © 2005, Marjolein Katsma
- * @license		http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- * @version		0.5
- *
- * @access		public
- * @todo		- prepare strings for internationalization
- *
- * @param		array	$aKey	required: fieldname, key value pair.
- * @param		string	$method	optional: form method; default post;
- * @return		mixed			TRUE if correct name,value found; reason for failure otherwise.
- */
-function hasValidSessionKey($wakka, $aKey,$method='post')
-{
-	// get pair to look for
-	list($ses_field,$ses_key) = $aKey;
-	// check method and prepare what to look for
-	if (isset($method))
-	{
-		$aServervars = ($method == 'get') ? $_GET : $_POST;
-	}
-	else
-	{
-		$aServervars = $_POST;					# default
-	}
-
-	// check passed values
-	if (!isset($aServervars[$ses_field]))
-	{
-		return 'form no key';					# key not present
-	}
-	elseif ($aServervars[$ses_field] != $ses_key)
-	{
-		return 'form bad key';					# incorrect value passed
-	}
-	else
-	{
-		return TRUE;							# all is well
-	}
-}
-?>
\ No newline at end of file
Index: libs/Wakka.class.php
===================================================================
--- libs/Wakka.class.php	(.../1.1.6.6)	(revision 1372)
+++ libs/Wakka.class.php	(.../1.1.6.7)	(revision 1372)
@@ -734,7 +734,7 @@
 		$sql .= ' where latest = '.  "'Y'"  .' and match(tag, body'.$id.')';
 		$sql .= ' against('.  "'$search_phrase'"  .' IN BOOLEAN MODE)';
 		$sql .= ' order by time DESC';
-
+		
 		$data = $this->LoadAll($sql);
 
 		return $data;
@@ -898,6 +898,118 @@
 			return FALSE;
 		}
 	}
+	
+	// SESSION
+	
+	/**
+	 * Create and store a secret session key.
+	 *
+	 * Creates a random value and a random field name to be used to pass on the value.
+	 * The key,value pair is stored in the session as a serialized array.
+	 *
+	 * @author		{@link http://wikkawiki.org/JavaWoman JavaWoman}
+	 * @copyright	Copyright © 2005, Marjolein Katsma
+	 * @license		http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+	 * @version		0.5
+	 *
+	 * @access		public
+	 *
+	 * @param		string	$keyname	required: name under which created secret key should be stored in the session
+	 * @return		array				fieldname and key value.
+	 */
+	function createSessionKey($keyname)
+	{
+		// create key and field name for it
+		$key = md5(getmicrotime());
+		$field = 'f'.substr(md5($key.getmicrotime()),0,10);
+		// store session key
+		$_SESSION[$keyname] = serialize(array($field,$key));
+		# BEGIN DEBUG - do not activate on a production server!
+		# echo '<div class="debug">'."\n";
+		# echo 'Session key:<br/>';
+		# echo 'name: '.$keyname.' - field: '.$field.' - key: '.$key.'<br/>';
+		# echo '</div>'."\n";
+		# END DEBUG
+		// return name, value pair
+		return array($field,$key);
+	}
+	/**
+	 * Retrieve the secret session key.
+	 *
+	 * Retrieves a named secret key and returns the result as an array with name,value pair.
+	 * Returns FALSE if the key is not found.
+	 *
+	 * @author		{@link http://wikkawiki.org/JavaWoman JavaWoman}
+	 * @copyright	Copyright © 2005, Marjolein Katsma
+	 * @license		http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+	 * @version		0.5
+	 *
+	 * @access		public
+	 *
+	 * @param		string	$keyname	required: name of secret key to retrieve from the session
+	 * @return		mixed				array with name,value pair on success, FALSE if entry not found.
+	 */
+	function getSessionKey($keyname)
+	{
+		if (!isset($_SESSION[$keyname]))
+		{
+			return FALSE;
+		}
+		else
+		{
+			$aKey = unserialize($_SESSION[$keyname]);		# retrieve secret key data
+			unset($_SESSION[$keyname]);						# clear secret key
+			return $aKey;
+		}
+	}
+	/**
+	 * Check hidden session key: it must be passed and it must have the correct name & value.
+	 *
+	 * Looks for a given name,value pair passed either in POST (default) or in GET request.
+	 * Returns TRUE if the correct field and value is found, a reason for failure otherwise.
+	 * Make sure to check for identity TRUE (TRUE === returnval), do not evaluate return value
+	 * as boolean!!
+	 *
+	 * @author		{@link http://wikkawiki.org/JavaWoman JavaWoman}
+	 * @copyright	Copyright © 2005, Marjolein Katsma
+	 * @license		http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+	 * @version		0.5
+	 *
+	 * @access		public
+	 * @todo		- prepare strings for internationalization
+	 *
+	 * @param		array	$aKey	required: fieldname, key value pair.
+	 * @param		string	$method	optional: form method; default post;
+	 * @return		mixed			TRUE if correct name,value found; reason for failure otherwise.
+	 */
+	function hasValidSessionKey($aKey, $method='post')
+	{
+		// get pair to look for
+		list($ses_field,$ses_key) = $aKey;
+		// check method and prepare what to look for
+		if (isset($method))
+		{
+			$aServervars = ($method == 'get') ? $_GET : $_POST;
+		}
+		else
+		{
+			$aServervars = $_POST;					# default
+		}
+	
+		// check passed values
+		if (!isset($aServervars[$ses_field]))
+		{
+			return 'form no key';					# key not present
+		}
+		elseif ($aServervars[$ses_field] != $ses_key)
+		{
+			return 'form bad key';					# incorrect value passed
+		}
+		else
+		{
+			return TRUE;							# all is well
+		}
+	}
 
 	// HTTP/GET/POST/LINK RELATED
 
@@ -989,7 +1101,7 @@
 
 		// is this an interwiki link?
 		// before the : should be a WikiName; anything after can be (nearly) anything that's allowed in a URL
-		if (preg_match('/^([A-ZÄÖÜ][A-Za-zÄÖÜßäöü]+)[:](\S*)$/', $tag, $matches))	// @@@ FIXME #34 (inconsistent with Formatter)
+		if (preg_match('/^([A-ÄÖÜ][A-Za-zÄÖÜßäöü]+)[:](\S*)$/', $tag, $matches))	// @@@ FIXME #34 (inconsistent with Formatter)
 		{
 			$url = $this->GetInterWikiUrl($matches[1], $matches[2]);
 			$class = 'interwiki';
@@ -1215,7 +1327,16 @@
 		{
 			$attrClass = ' class="'.$class.'"';
 		}
-
+		
+		// add validation key fields
+		if('post' == $formMethod)
+		{
+			$tmp = $this->createSessionKey($id);
+			$hidden[$tmp[0]] = $tmp[1];
+			unset($tmp);
+			$hidden['form_id'] = $id;	
+		}
+		
 		// build HTML fragment
 		$fragment = '<form'.$attrAction.$attrMethod.$attrEnctype.$attrId.$attrClass.'>'."\n";
 		// construct and add hidden fields (necessary if we are NOT using rewrite mode)
Index: wikka.php
===================================================================
--- wikka.php	(.../1.1.6.6)	(revision 1372)
+++ wikka.php	(.../1.1.6.7)	(revision 1372)
@@ -65,7 +65,7 @@
 /**
  * Defines the current Wikka version. Do not change the version number or you will have problems upgrading.
  */
-if (!defined('WAKKA_VERSION')) define('WAKKA_VERSION', '1.1.6.6');
+if (!defined('WAKKA_VERSION')) define('WAKKA_VERSION', '1.1.6.7');
 
 /**#@+
  * Simple constant. May be made a configurable value.
@@ -424,4 +424,4 @@
  * Output the page.
  */
 echo $page_output;
-?>
\ No newline at end of file
+?>
Index: actions/usersettings.php
===================================================================
--- actions/usersettings.php	(.../1.1.6.6)	(revision 1372)
+++ actions/usersettings.php	(.../1.1.6.7)	(revision 1372)
@@ -158,6 +158,17 @@
 // user is still logged in
 else if ($user = $this->GetUser())
 {
+	// validate data source
+	$keep_post_data = FALSE;
+	if (isset($_POST['form_id']) && FALSE != ($aKey = $this->getSessionKey($_POST['form_id'])))	# check if page key was stored in session
+	{
+		if (TRUE == ($rc = $this->hasValidSessionKey($aKey)))	# check if correct name,key pair was passed
+		{
+			$keep_post_data  = TRUE;
+		}
+	}
+	if(!$keep_post_data) unset($_POST);
+	
 	// is user trying to update user settings?
 	if (isset($_POST['action']) && ($_POST['action'] == 'update'))
 	{
Index: actions/adminpages.php
===================================================================
--- actions/adminpages.php	(.../1.1.6.6)	(revision 1372)
+++ actions/adminpages.php	(.../1.1.6.7)	(revision 1372)
@@ -393,21 +393,17 @@
 	else
 	{
 		// process URL variables
-		# JW 2005-07-19 some modifications to avoid notices but these are still not actually secure
 
 		// number of records per page
-		if (isset($_POST['l']))
+		$l = ADMINPAGES_DEFAULT_RECORDS_LIMIT;
+		if (isset($_POST['l']) && (int)$_POST['l'] > 0)
 		{
-			$l = $_POST['l'];
+			$l = (int)$_POST['l'];
 		}
-		elseif (isset($_GET['l']))
+		elseif (isset($_GET['l']) && (int)$_GET['l'] > 0)
 		{
-			$l = $_GET['l'];
+			$l = (int)$_GET['l'];
 		}
-		else
-		{
-			$l = ADMINPAGES_DEFAULT_RECORDS_LIMIT;
-		}
 
 		// last edit date range
 		$start_YY = (isset($_POST['start_YY'])) ? $this->htmlspecialchars_ent($_POST['start_YY']) : ADMINPAGES_DEFAULT_START_YEAR;
@@ -424,25 +420,32 @@
 		$end_ss = (isset($_POST['end_ss'])) ? $this->htmlspecialchars_ent($_POST['end_ss']) : ADMINPAGES_DEFAULT_END_SECOND;
 
 		// sort field
-		$sort = (isset($_GET['sort'])) ? $_GET['sort'] : ADMINPAGES_DEFAULT_SORT_FIELD;
+		$sort = ADMINPAGES_DEFAULT_SORT_FIELD;
+		$sort_fields = array('owner', 'tag', 'user', 'time');
+		if(isset($_GET['sort']) && in_array($_GET['sort'], $sort_fields)) $sort = $_GET['sort'];
+
 		// sort order
-		$d = (isset($_GET['d'])) ? $_GET['d'] : ADMINPAGES_DEFAULT_SORT_ORDER;
+		$d = ADMINPAGES_DEFAULT_SORT_ORDER;
+		$sort_order = array('asc', 'desc');
+		if(isset($_GET['d']) && in_array($_GET['d'], $sort_order)) $d = $_GET['d'];
 		// start record
-		$s = (isset($_GET['s'])) ? $_GET['s'] : ADMINPAGES_DEFAULT_START;
+		$s = ADMINPAGES_DEFAULT_START;
+		if (isset($_GET['s']) && (int)$_GET['s'] >=0) $s = (int)$_GET['s']; 
 
+
 		// search string
-		if (isset($_POST['q']))
+		$search = ADMINPAGES_DEFAULT_SEARCH;
+		$search_disp = ADMINPAGES_DEFAULT_SEARCH;
+		if (isset($_POST['search']))
 		{
-			$q = $_POST['q'];
+			$search = mysql_real_escape_string($_POST['search']);
+			$search_disp = $this->htmlspecialchars_ent($_POST['search']);
 		}
-		elseif (isset($_GET['q']))
+		elseif (isset($_GET['search']))
 		{
-			$q = $_GET['q'];
+			$search = mysql_real_escape_string($_GET['search']);
+			$search_disp = $this->htmlspecialchars_ent($_GET['search']);
 		}
-		else
-		{
-			$q = ADMINPAGES_DEFAULT_SEARCH;
-		}
 
 		// select all	added JW 2005-07-19
 		$checked = '';
@@ -457,7 +460,7 @@
 		// build pager form	
 		$form_filter = $this->FormOpen('','','post','page_admin_panel');
 		$form_filter .= '<fieldset><legend>'.ADMINPAGES_FORM_LEGEND.'</legend>'."\n";
-		$form_filter .= '<label for="q">'.ADMINPAGES_FORM_SEARCH_STRING_LABEL.'</label> <input type ="text" id="q" name="q" title="'.ADMINPAGES_FORM_SEARCH_STRING_TITLE.'" size="20" maxlength="50" value="'.$q.'"/> <input type="submit" value="'.ADMINPAGES_FORM_SEARCH_SUBMIT.'" /><br />'."\n";
+		$form_filter .= '<label for="search">'.ADMINPAGES_FORM_SEARCH_STRING_LABEL.'</label> <input type ="text" id="search" name="search" title="'.ADMINPAGES_FORM_SEARCH_STRING_TITLE.'" size="20" maxlength="50" value="'.$search_disp.'"/> <input type="submit" value="'.ADMINPAGES_FORM_SEARCH_SUBMIT.'" /><br />'."\n";
 		// build date range fields
 		$form_filter .= '<label>'.ADMINPAGES_FORM_DATE_RANGE_STRING_LABEL.'</label>&nbsp;<input class="datetime" type="text" name="start_YY" size="4" maxlength="4" value="'.$start_YY.'"/>-<input class="datetime" type="text" name="start_MM" size="2" maxlength="2" value="'.$start_MM.'"/>-<input class="datetime" type="text" name="start_DD" size="2" maxlength="2" value="'.$start_DD.'"/>&nbsp;<input class="datetime" type="text" name="start_hh" size="2" maxlength="2" value="'.$start_hh.'"/>:<input class="datetime" type="text" name="start_mm" size="2" maxlength="2" value="'.$start_mm.'"/>:<input class="datetime" type="text" name="start_ss" size="2" maxlength="2" value="'.$start_ss.'"/>&nbsp;'.ADMINPAGES_FORM_DATE_RANGE_CONNECTOR_LABEL.'&nbsp;<input class="datetime" type="text" name="end_YY" size="4" maxlength="4" value="'.$end_YY.'"/>-<input class="datetime" type="text" name="end_MM" size="2" maxlength="2" value="'.$end_MM.'"/>-<input class="datetime" type="text" name="end_DD" size="2" maxlength="2" value="'.$end_DD.'"/>&nbsp;<input class="datetime" type="text" name="end_hh" size="2" maxlength="2" value="'.$end_hh.'"/>:<input class="datetime" type="text" name="end_mm" size="2" maxlength="2" value="'.$end_mm.'"/>:<input class="datetime" type="text" name="end_ss" size="2" maxlength="2" value="'.$end_ss.'"/><br />'."\n";
 
@@ -535,7 +538,7 @@
 		}
 
 		// restrict MySQL query by search string	 modified JW 2005-07-19
-		$where = ('' == $q) ? "`latest` = 'Y'" : "`tag` LIKE '%".$q."%' AND `latest` = 'Y'";
+		$where = ('' == $search) ? "`latest` = 'Y'" : "`tag` LIKE '%".$search."%' AND `latest` = 'Y'";
 		if (!empty($start_ts) && !empty($end_ts))
 		{
 			$where .= " AND time > '".$start_ts."' AND time < '".$end_ts."'"; 
@@ -560,11 +563,11 @@
 		$ul = ($s+2*$l) > $numpages ? $numpages : ($s+2*$l);
 		if ($s > 0)
 		{
-			$prev = '<a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.($s-$l)).  '&amp;q='.$q.  '&amp;start_ts='.urlencode($start_ts).  '&amp;end_ts='.urlencode($end_ts).  '" title="'.sprintf(ADMINPAGES_FORM_PAGER_LINK, ($s-$l+1), $s).'">'.($s-$l+1).'-'.$s.'</a> |  '."\n";
+			$prev = '<a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.($s-$l)).  '&amp;search='.urlencode($search).  '&amp;start_ts='.urlencode($start_ts).  '&amp;end_ts='.urlencode($end_ts).  '" title="'.sprintf(ADMINPAGES_FORM_PAGER_LINK, ($s-$l+1), $s).'">'.($s-$l+1).'-'.$s.'</a> |  '."\n";
 		}
 		if ($numpages > ($s + $l))
 		{
-			$next = ' | <a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.($s+$l)).'&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts).'" title="'.sprintf(ADMINPAGES_FORM_PAGER_LINK, $ll, $ul).'">'.$ll.(($ll==$ul)?'':('-'.$ul)).'</a>'."\n";
+			$next = ' | <a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.($s+$l)).'&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts).'" title="'.sprintf(ADMINPAGES_FORM_PAGER_LINK, $ll, $ul).'">'.$ll.(($ll==$ul)?'':('-'.$ul)).'</a>'."\n";
 		}
 		$form_filter .= ADMINPAGES_FORM_RESULT_INFO.' ('.$numpages.'): '.$prev.(($s+$l)>$numpages?($s+1).'-'.$numpages:($s+1).'-'.($s+$l)).$next.'<br />'."\n";
 		$form_filter .= '<span class="sortorder">'.ADMINPAGES_FORM_RESULT_SORTED_BY.' <tt>'.$sort.', '.$d.'</tt></span>'."\n";
@@ -581,7 +584,7 @@
 				$count = ', COUNT(*) as edits';
 				$group = 'GROUP BY tag';	
 				$where .= 'AND 1';
-				//$where = ('' == $q) ? "1" : "`tag` LIKE '%".$q."%'";
+				//$where = ('' == $search) ? "1" : "`tag` LIKE '%".$search."%'";
 				$table = 'pages';	
 				break;
 			case 'comments': #to implement
@@ -602,11 +605,11 @@
 		if ($pagedata)
 		{
 			// build table headers
-			$tagheader = '<a href="'.$this->Href('','', (($sort == 'tag' && $d == 'asc')? 'l='.$l.'&amp;sort=tag&amp;d=desc&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts) : 'l='.$l.'&amp;sort=tag&amp;d=asc&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts))).'" title="'.ADMINPAGES_TABLE_HEADING_PAGENAME_TITLE.'">'.ADMINPAGES_TABLE_HEADING_PAGENAME.'</a>';
-			$ownerheader = '<a href="'.$this->Href('','', (($sort == 'owner' && $d == 'asc')? 'l='.$l.'&amp;sort=owner&amp;d=desc&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts) : 'l='.$l.'&amp;sort=owner&amp;d=asc&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts))).'" title="'.ADMINPAGES_TABLE_HEADING_OWNER_TITLE.'">'.ADMINPAGES_TABLE_HEADING_OWNER.'</a>';
-			$userheader = '<a href="'.$this->Href('','', (($sort == 'user' && $d == 'asc')? 'l='.$l.'&amp;sort=user&amp;d=desc&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts) : 'l='.$l.'&amp;sort=user&amp;d=asc&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts))).'" title="'.ADMINPAGES_TABLE_HEADING_LASTAUTHOR_TITLE.'">'.ADMINPAGES_TABLE_HEADING_LASTAUTHOR.'</a>';
-			$lasteditheader = '<a href="'.$this->Href('','', (($sort == 'time' && $d == 'desc')? 'l='.$l.'&amp;sort=time&amp;d=asc&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts) : 'l='.$l.'&amp;sort=time&amp;d=desc&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts))).'" title="'.ADMINPAGES_TABLE_HEADING_LASTEDIT_TITLE.'">'.ADMINPAGES_TABLE_HEADING_LASTEDIT.'</a>';
-			/* $revisionsheader = '<a href="'.$this->Href('','', (($sort == 'edits' && $d == 'desc')? 'l='.$l.'&amp;sort=edits&amp;d=asc&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts) : 'l='.$l.'&amp;sort=edits&amp;d=desc&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts))).'" title="'.ADMINPAGES_TABLE_HEADING_REVISIONS_TITLE.'"><img src="'.ADMINPAGES_REVISIONS_ICON.'" alt="'.ADMINPAGES_TABLE_HEADING_REVISIONS_ALT.'"/></a>'; */ #not implemented
+			$tagheader = '<a href="'.$this->Href('','', (($sort == 'tag' && $d == 'asc')? 'l='.$l.'&amp;sort=tag&amp;d=desc&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts) : 'l='.$l.'&amp;sort=tag&amp;d=asc&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts))).'" title="'.ADMINPAGES_TABLE_HEADING_PAGENAME_TITLE.'">'.ADMINPAGES_TABLE_HEADING_PAGENAME.'</a>';
+			$ownerheader = '<a href="'.$this->Href('','', (($sort == 'owner' && $d == 'asc')? 'l='.$l.'&amp;sort=owner&amp;d=desc&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts) : 'l='.$l.'&amp;sort=owner&amp;d=asc&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts))).'" title="'.ADMINPAGES_TABLE_HEADING_OWNER_TITLE.'">'.ADMINPAGES_TABLE_HEADING_OWNER.'</a>';
+			$userheader = '<a href="'.$this->Href('','', (($sort == 'user' && $d == 'asc')? 'l='.$l.'&amp;sort=user&amp;d=desc&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts) : 'l='.$l.'&amp;sort=user&amp;d=asc&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts))).'" title="'.ADMINPAGES_TABLE_HEADING_LASTAUTHOR_TITLE.'">'.ADMINPAGES_TABLE_HEADING_LASTAUTHOR.'</a>';
+			$lasteditheader = '<a href="'.$this->Href('','', (($sort == 'time' && $d == 'desc')? 'l='.$l.'&amp;sort=time&amp;d=asc&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts) : 'l='.$l.'&amp;sort=time&amp;d=desc&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts))).'" title="'.ADMINPAGES_TABLE_HEADING_LASTEDIT_TITLE.'">'.ADMINPAGES_TABLE_HEADING_LASTEDIT.'</a>';
+			/* $revisionsheader = '<a href="'.$this->Href('','', (($sort == 'edits' && $d == 'desc')? 'l='.$l.'&amp;sort=edits&amp;d=asc&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts) : 'l='.$l.'&amp;sort=edits&amp;d=desc&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts))).'" title="'.ADMINPAGES_TABLE_HEADING_REVISIONS_TITLE.'"><img src="'.ADMINPAGES_REVISIONS_ICON.'" alt="'.ADMINPAGES_TABLE_HEADING_REVISIONS_ALT.'"/></a>'; */ #not implemented
 
 			$data_table = '<table id="adminpages" summary="'.ADMINPAGES_TABLE_SUMMARY.'" border="1px" class="data">'."\n".
 			'<thead>'."\n".
@@ -781,7 +784,7 @@
 
 			// multiple-page operations (forthcoming)		JW 2005-07-19 accesskey removed (causes more problems than it solves)
 			$form_mass .= '<fieldset><legend>'.ADMINPAGES_FORM_MASSACTION_LEGEND.'</legend>';
-			$form_mass .= '[<a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.$s.'&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts).'&amp;selectall=1').'" title="'.ADMINPAGES_CHECK_ALL_TITLE.'">'.ADMINPAGES_CHECK_ALL.'</a> | <a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.$s.'&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts).'&amp;selectall=0').'" title="'.ADMINPAGES_UNCHECK_ALL_TITLE.'">'.ADMINPAGES_UNCHECK_ALL.'</a>]<br />';
+			$form_mass .= '[<a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.$s.'&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts).'&amp;selectall=1').'" title="'.ADMINPAGES_CHECK_ALL_TITLE.'">'.ADMINPAGES_CHECK_ALL.'</a> | <a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.$s.'&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts).'&amp;selectall=0').'" title="'.ADMINPAGES_UNCHECK_ALL_TITLE.'">'.ADMINPAGES_UNCHECK_ALL.'</a>]<br />';
 			$form_mass .= '<label for="action" >'.ADMINPAGES_FORM_MASSACTION_LABEL.'</label> <select title="'.ADMINPAGES_FORM_MASSACTION_SELECT_TITLE.'" id="action" name="action">';
 			$form_mass .= '<option value="" selected="selected">---</option>';
 			// Temporarily disabling all but massrevert
@@ -804,7 +807,7 @@
 		else
 		{
 			// no records matching the search string: print error message
-			echo '<p><em class="error">'.sprintf(ADMINPAGES_ERROR_NO_MATCHES, $q).'</em></p>';
+			echo '<p><em class="error">'.sprintf(ADMINPAGES_ERROR_NO_MATCHES, $search_disp).'</em></p>';
 		}
 	}
 }
@@ -813,4 +816,4 @@
 	// current user is not admin: show plain page index
 	echo $this->Action('pageindex');
 }
-?>
+?>
\ No newline at end of file
Index: actions/adminusers.php
===================================================================
--- actions/adminusers.php	(.../1.1.6.6)	(revision 1372)
+++ actions/adminusers.php	(.../1.1.6.7)	(revision 1372)
@@ -330,38 +330,42 @@
 	else 
 	{
 		// process URL variables
-		# JW 2005-07-19 some modifications to avoid notices but these are still not actually secure
 	
 		// number of records per page
-		if (isset($_POST['l']))
+		$l = ADMINUSERS_DEFAULT_RECORDS_LIMIT;
+		if (isset($_POST['l']) && (int)$_POST['l'] > 0)
 		{
-			$l = $_POST['l'];
+			$l = (int)$_POST['l'];
 		}
-		elseif (isset($_GET['l']))
+		elseif (isset($_GET['l']) && (int)$_GET['l'] > 0)
 		{
-			$l = $_GET['l'];
+			$l = (int)$_GET['l'];
 		}
-		else
-		{
-			$l = ADMINUSERS_DEFAULT_RECORDS_LIMIT;
-		}
 
 		// sort field
-		$sort = (isset($_GET['sort'])) ? $_GET['sort'] : ADMINUSERS_DEFAULT_SORT_FIELD;
+		$sort = ADMINUSERS_DEFAULT_SORT_FIELD;
+		$sort_fields = array('name', 'email', 'signuptime');
+		if(isset($_GET['sort']) && in_array($_GET['sort'], $sort_fields)) $sort = $_GET['sort'];
 		// sort order
-		$d = (isset($_GET['d'])) ? $_GET['d'] : ADMINUSERS_DEFAULT_SORT_ORDER;
+		$d = ADMINUSERS_DEFAULT_SORT_ORDER;
+		$sort_order = array('asc', 'desc');
+		if(isset($_GET['d']) && in_array($_GET['d'], $sort_order)) $d = $_GET['d'];
 		// start record
-		$s = (isset($_GET['s'])) ? $_GET['s'] : ADMINUSERS_DEFAULT_START;
+		$s = ADMINUSERS_DEFAULT_START;
+		if (isset($_GET['s']) && (int)$_GET['s'] >=0) $s = (int)$_GET['s']; 
 	
 		// search string
-		$q = '';
-		if (isset($_POST['q']))
+		$search = ADMINUSERS_DEFAULT_SEARCH;
+		$search_disp = ADMINUSERS_DEFAULT_SEARCH;
+		if (isset($_POST['search']))
 		{
-			$q = $_POST['q'];
+			$search = mysql_real_escape_string($_POST['search']);
+			$search_disp = $this->htmlspecialchars_ent($_POST['search']);
 		}
-		elseif (isset($_GET['q']))
+		elseif (isset($_GET['search']))
 		{
-			$q = $_GET['q'];
+			$search = mysql_real_escape_string($_GET['search']);
+			$search_disp = $this->htmlspecialchars_ent($_GET['search']);
 		}
 		elseif(isset($_POST['submit']) && $_POST['submit'] == ADMINUSERS_FORM_SEARCH_SUBMIT)
 		{
@@ -378,7 +382,7 @@
 	
 		// restrict MySQL query by search string
 		$where = "(status IS NULL OR status != 'deleted') AND ";
-		$where .= ('' == $q) ? '1' : "name LIKE '%".$q."%'";
+		$where .= ('' == $search) ? '1' : "name LIKE '%".$search."%'";
 		// get total number of users
 		$numusers = $this->getCount('users', $where);
 		// If the user doesn't specifically want to change the records
@@ -399,7 +403,7 @@
 		// build pager form	
 		$form_filter = $this->FormOpen('','','post','user_admin_panel');
 		$form_filter .= '<fieldset><legend>'.ADMINUSERS_FORM_LEGEND.'</legend>'."\n";
-		$form_filter .= '<label for="q">'.ADMINUSERS_FORM_SEARCH_STRING_LABEL.'</label> <input type ="text" id="q" name="q" title="'.ADMINUSERS_FORM_SEARCH_STRING_TITLE.'" size="20" maxlength="50" value="'.$q.'"/> <input name="submit" type="submit" value="'.ADMINUSERS_FORM_SEARCH_SUBMIT.'" /><br />'."\n";
+		$form_filter .= '<label for="search">'.ADMINUSERS_FORM_SEARCH_STRING_LABEL.'</label> <input type ="text" id="search" name="search" title="'.ADMINUSERS_FORM_SEARCH_STRING_TITLE.'" size="20" maxlength="50" value="'.$search_disp.'"/> <input name="submit" type="submit" value="'.ADMINUSERS_FORM_SEARCH_SUBMIT.'" /><br />'."\n";
 		// get values range for drop-down
 		$users_opts = optionRanges($user_limits,$numusers, ADMINUSERS_DEFAULT_MIN_RECORDS_DISPLAY);
 		$form_filter .= '<label for="l">'.ADMINUSERS_FORM_PAGER_LABEL_BEFORE.'</label> '."\n";
@@ -417,11 +421,11 @@
 		$ul = ($s+2*$l) > $numusers ? $numusers : ($s+2*$l);
 		if ($s > 0)
 		{
-			$prev = '<a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.($s-$l)).  '&amp;q='.$q.  '&amp;start_ts='.urlencode($start_ts).  '&amp;end_ts='.urlencode($end_ts).  '" title="'.sprintf(ADMINUSERS_FORM_PAGER_LINK, ($s-$l+1), $s).'">'.($s-$l+1).'-'.$s.'</a> |  '."\n";
+			$prev = '<a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.($s-$l)).  '&amp;search='.urlencode($search).  '&amp;start_ts='.urlencode($start_ts).  '&amp;end_ts='.urlencode($end_ts).  '" title="'.sprintf(ADMINUSERS_FORM_PAGER_LINK, ($s-$l+1), $s).'">'.($s-$l+1).'-'.$s.'</a> |  '."\n";
 		}
 		if ($numusers > ($s + $l))
 		{
-			$next = ' | <a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.($s+$l)).'&amp;q='.$q.'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts).'" title="'.sprintf(ADMINUSERS_FORM_PAGER_LINK, $ll, $ul).'">'.$ll.(($ll==$ul)?'':('-'.$ul)).'</a>'."\n";
+			$next = ' | <a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.($s+$l)).'&amp;search='.urlencode($search).'&amp;start_ts='.urlencode($start_ts).'&amp;end_ts='.urlencode($end_ts).'" title="'.sprintf(ADMINUSERS_FORM_PAGER_LINK, $ll, $ul).'">'.$ll.(($ll==$ul)?'':('-'.$ul)).'</a>'."\n";
 		}
 		$form_filter .= ADMINUSERS_FORM_RESULT_INFO.' ('.$numusers.'): '.$prev.(($s+$l)>$numusers?($s+1).'-'.$numusers:($s+1).'-'.($s+$l)).$next.'<br />'."\n";
 		$form_filter .= '<span class="sortorder">'.ADMINUSERS_FORM_RESULT_SORTED_BY.' <tt>'.$sort.', '.$d.'</tt></span>'."\n";
@@ -443,7 +447,7 @@
 			$data_table = '<table id="adminusers" summary="'.ADMINUSERS_TABLE_SUMMARY.'" border="1px" class="data">'."\n".
 				'<thead>'."\n".
 	  			'	<tr>'."\n".
-				'		<th> </th>'."\n".
+				'		<th> </th>'."\n".
 				'		<th>'.$nameheader.'</th>'."\n".
 				'		<th>'.$emailheader.'</th>'."\n".
 				'		<th>'.$timeheader.'</th>'."\n".
@@ -519,7 +523,7 @@
 			$form_mass .= $data_table;			
 			$form_mass .= '<fieldset>'."\n".
 				'	<legend>'.ADMINUSERS_FORM_MASSACTION_LEGEND.'</legend>'."\n".
-				'	[<a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.$s.'&amp;q='.$q.'&amp;selectall=1').'" title="'.ADMINUSERS_SELECT_ALL_TITLE.'">'.ADMINUSERS_SELECT_ALL.'</a> | <a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.$s.'&amp;q='.$q.'&amp;selectall=0').'" title="'.ADMINUSERS_DESELECT_ALL_TITLE.'">'.ADMINUSERS_DESELECT_ALL.'</a>]<br />'."\n".
+				'	[<a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.$s.'&amp;search='.urlencode($search).'&amp;selectall=1').'" title="'.ADMINUSERS_SELECT_ALL_TITLE.'">'.ADMINUSERS_SELECT_ALL.'</a> | <a href="'.$this->Href('','','l='.$l.'&amp;sort='.$sort.'&amp;d='.$d.'&amp;s='.$s.'&amp;search='.urlencode($search).'&amp;selectall=0').'" title="'.ADMINUSERS_DESELECT_ALL_TITLE.'">'.ADMINUSERS_DESELECT_ALL.'</a>]<br />'."\n".
 				'	<label for="action" >'.ADMINUSERS_FORM_MASSACTION_LABEL.'</label>'."\n".
 				'	<select title="'.ADMINUSERS_FORM_MASSACTION_SELECT_TITLE.'" id="action" name="action">'."\n".
 				'		<option value="" selected="selected">---</option>'."\n".
@@ -536,7 +540,7 @@
 		else
 		{
 			// no records matching the search string: print error message
-			echo '<p><em class="error">'.sprintf(ADMINUSERS_ERROR_NO_MATCHES, $q).'</em></p>';
+			echo '<p><em class="error">'.sprintf(ADMINUSERS_ERROR_NO_MATCHES, $search_disp).'</em></p>';
 		}
 	}
 }
@@ -545,4 +549,4 @@
 	// user is not admin
 	echo $this->Action('lastusers');
 }
-?>
+?>
\ No newline at end of file
Index: actions/checkversion.php
===================================================================
--- actions/checkversion.php	(.../1.1.6.6)	(revision 1372)
+++ actions/checkversion.php	(.../1.1.6.7)	(revision 1372)
@@ -28,7 +28,7 @@
 	define('CHECKVERSION_HOST', 'wikkawiki.org');	
 	define('CHECKVERSION_RELEASE_FILE', '/downloads/latest_wikka_version.txt');	
 	define('CHECKVERSION_DOWNLOAD_URL', 'http://docs.wikkawiki.org/WhatsNew');	
-	define('CHECKVERSION_CONNECTION_TIMEOUT', 10);
+	define('CHECKVERSION_CONNECTION_TIMEOUT', 5);
 	$latest = '';
 	//color scheme array (ported from {{since}})
 	$c = array(
@@ -86,6 +86,18 @@
 				{
 					echo '<span class="debug">[Cannot initiate socket connection]</span>'."\n";
 				}
+				else
+				{
+					// Display warning message
+					$s = "D";
+					echo '<div title="Cannot initiate network connection" style="text-align: center; float: left; width: 300px; border: 1px solid '.$c[$s][0].'; background-color: '.$c[$s][1].'; color: '.$c[$s][2].'; margin: 10px 0">'."\n";
+					echo '<div style="padding: 0 3px 0 3px; background-color: '.$c[$s][3].'; font-size: 85%; font-weight: bold">CHECKVERSION FAILED</div>'."\n";
+					echo '<div style="padding: 0 3px 2px 3px; font-size: 85%; line-height: 150%; border-top: 1px solid '.$c[$s][4].';">'."\n";
+					echo 'The network connection with the WikkaWiki server could not be established. To prevent delays in loading this page, please set enable_version_check to 0 in your wikka.config.php file.'."\n";
+					echo '</div>'."\n";
+					echo '</div>'."\n";
+					echo '<div class="clear"></div>'."\n";
+				}
 				return;
 			}
 			else
@@ -107,8 +119,8 @@
 						break;
 
 						case "debug":
-						//display raw version number
-						echo '<span class="debug">['.$latest.']</span>'."\n";
+						//display raw version number and //checkversion_host ip
+						echo '<span class="debug">['.$latest.' from host '.$ip.']</span>'."\n";
 						break;
 						
 						default:						
Index: handlers/page/delete.php
===================================================================
--- handlers/page/delete.php	(.../1.1.6.6)	(revision 1372)
+++ handlers/page/delete.php	(.../1.1.6.7)	(revision 1372)
@@ -3,26 +3,38 @@
 
 if (!defined('CANCEL_ACL_LABEL')) define('CANCEL_ACL_LABEL', 'Cancel');
 
+// cancel operation and return to the page
+if (isset($_POST['cancel']) && ($_POST['cancel'] == CANCEL_ACL_LABEL))
+{
+	$this->Redirect($this->Href());
+}
+
 if ($this->IsAdmin())
 {
-    if ($_POST)
+	if (isset($_POST['form_id']))
     {
-		if(isset($_POST['cancel']) && ($_POST['cancel'] == CANCEL_ACL_LABEL))
+	    $delete = FALSE;
+    	if (FALSE != ($aKey = $this->getSessionKey($_POST['form_id'])))	# check if form key was stored in session
 		{
-			$this->Redirect($this->Href());
+			if (TRUE == ($rc = $this->hasValidSessionKey($aKey)))	# check if correct name,key pair was passed
+			{
+				$delete = TRUE;
+			}
 		}
+		if (TRUE == DELETE)
+		{
+			$tag = $this->GetPageTag();
 
-        $tag = $this->GetPageTag();
-
-        //  delete the page, comments, related links, acls and referrers 
-        $this->Query("delete from ".$this->config["table_prefix"]."pages where tag = '".mysql_real_escape_string($tag)."'");
-        $this->Query("delete from ".$this->config["table_prefix"]."comments where page_tag = '".mysql_real_escape_string($tag)."'");
-        $this->Query("delete from ".$this->config["table_prefix"]."links where from_tag = '".mysql_real_escape_string($tag)."'");
-        $this->Query("delete from ".$this->config["table_prefix"]."acls where page_tag = '".mysql_real_escape_string($tag)."'");
-        $this->Query("delete from ".$this->config["table_prefix"]."referrers where page_tag = '".mysql_real_escape_string($tag)."'");
-
-        // redirect back to main page
-        $this->Redirect($this->config["base_url"], "Page has been deleted!");
+	        //  delete the page, comments, related links, acls and referrers 
+	        $this->Query("delete from ".$this->config["table_prefix"]."pages where tag = '".mysql_real_escape_string($tag)."'");
+	        $this->Query("delete from ".$this->config["table_prefix"]."comments where page_tag = '".mysql_real_escape_string($tag)."'");
+	        $this->Query("delete from ".$this->config["table_prefix"]."links where from_tag = '".mysql_real_escape_string($tag)."'");
+	        $this->Query("delete from ".$this->config["table_prefix"]."acls where page_tag = '".mysql_real_escape_string($tag)."'");
+	        $this->Query("delete from ".$this->config["table_prefix"]."referrers where page_tag = '".mysql_real_escape_string($tag)."'");
+	
+	        // redirect back to main page
+	        $this->Redirect($this->config["base_url"], "Page has been deleted!");
+    	}
     }
     else
     {
Index: handlers/page/addcomment.php
===================================================================
--- handlers/page/addcomment.php	(.../1.1.6.6)	(revision 1372)
+++ handlers/page/addcomment.php	(.../1.1.6.7)	(revision 1372)
@@ -1,14 +1,14 @@
 <?php
-//include antispam library
-include_once('libs/antispam.lib.php');
 
-//interface strings
+//interface strings
 if (!defined('ERROR_EMPTY_COMMENT')) define('ERROR_EMPTY_COMMENT', "Sorry, empty comments cannot be saved.");
 if (!defined('ERROR_NO_COMMENT_WRITE_ACCESS')) define('ERROR_NO_COMMENT_WRITE_ACCESS', "Sorry, you are not allowed to post comments to this page.");
-if (!defined('ERROR_COMMENT_NO_KEY')) define('ERROR_COMMENT_NO_KEY', "Your comment cannot be saved. Please contact the wiki administrator.");
-if (!defined('ERROR_COMMENT_INVALID_KEY')) define('ERROR_COMMENT_INVALID_KEY', "Your comment cannot be saved. Please contact the wiki administrator.");
-
-if (($this->HasAccess('comment') || $this->IsAdmin()) && $this->existsPage($this->tag))
+if (!defined('ERROR_COMMENT_NO_KEY')) define('ERROR_COMMENT_NO_KEY', "Your comment cannot be saved. Please contact the wiki administrator(1).");
+if (!defined('ERROR_COMMENT_INVALID_KEY')) define('ERROR_COMMENT_INVALID_KEY', "Your comment cannot be saved. Please contact the wiki administrator(2).");
+
+$redirectmessage = '';
+
+if (($this->HasAccess('comment') || $this->IsAdmin()) && $this->existsPage($this->tag))
 {
 	$body = (isset($_POST['body'])) ? trim($_POST['body']) : '';
 
@@ -16,26 +16,26 @@
 	{
 		$redirectmessage = ERROR_EMPTY_COMMENT;
 	}
-	elseif (FALSE === ($aKey = getSessionKey($this, $this->tag.'_commentkey')))	# check if page key was stored in session
+	elseif (FALSE === ($aKey = $this->getSessionKey($_POST['form_id'])))	# check if page key was stored in session
 	{
 		$redirectmessage = ERROR_COMMENT_NO_KEY;
 	}
-	elseif (TRUE !== ($rc = hasValidSessionKey($this, $aKey)))	# check if correct name,key pair was passed
+	elseif (TRUE !== ($rc = $this->hasValidSessionKey($aKey)))	# check if correct name,key pair was passed
 	{
 		$redirectmessage = ERROR_COMMENT_INVALID_KEY;
 	}
 	// all is kosher: store new comment
-	else
-	{
+	else
+	{
 		$body = nl2br($this->htmlspecialchars_ent($body));
-		$this->SaveComment($this->tag, $body);
-	}
-	
-	// redirect to parent page
-	$this->Redirect($this->Href(), $redirectmessage);
-}
-else
-{
-	echo '<div class="page"><em class="error">'.ERROR_NO_COMMENT_WRITE_ACCESS.'</em></div>'."\n";
-}
-?>
+		$this->SaveComment($this->tag, $body);
+	}
+	
+	// redirect to parent page
+	$this->Redirect($this->Href(), $redirectmessage);
+}
+else
+{
+	echo '<div class="page"><em class="error">'.ERROR_NO_COMMENT_WRITE_ACCESS.'</em></div>'."\n";
+}
+?>
Index: handlers/page/show.php
===================================================================
--- handlers/page/show.php	(.../1.1.6.6)	(revision 1372)
+++ handlers/page/show.php	(.../1.1.6.7)	(revision 1372)
@@ -34,9 +34,6 @@
  * 			necessary) - #312  
  */
 
-//include antispam library
-include_once('libs/antispam.lib.php');
-
 //constants
 define('SHOW_OLD_REVISION_SOURCE', 0); # if set to 1 shows by default the source of an old revision instead of the rendered version
 
@@ -162,7 +159,6 @@
 					}
 				}
 				// display comment form
-				$keyfield = createSessionKeyFieldset($this, createSessionKey($this, $this->tag.'_commentkey'));
 				echo '<div class="commentform">'."\n";
 				if ($this->HasAccess('comment'))
 				{?>
@@ -171,7 +167,6 @@
 						<textarea id="commentbox" name="body" rows="6" cols="78"></textarea><br />
 						<input type="submit" value="Add Comment" accesskey="s" />
             		</label>
-					<?php echo $keyfield; ?>
 					<?php echo $this->FormClose(); ?>
 				<?php
 				}
Index: handlers/page/acls.php
===================================================================
--- handlers/page/acls.php	(.../1.1.6.6)	(revision 1372)
+++ handlers/page/acls.php	(.../1.1.6.7)	(revision 1372)
@@ -34,55 +34,73 @@
 
 if ($this->UserIsOwner())
 {
-	if ($_POST)
+	if (isset($_POST['form_id']))
 	{
-		if(isset($_POST['cancel']) && ($_POST['cancel'] == CANCEL_ACL_LABEL))
+
+		// validate data source 
+		$keep_post_data = FALSE; 
+		if (FALSE != ($aKey = $this->getSessionKey($_POST['form_id'])))     # check if page key was stored in session 
+		{ 
+			if (TRUE == ($rc = $this->hasValidSessionKey($aKey)))   # check if correct name,key pair was passed 
+			{ 
+				$keep_post_data  = TRUE; 
+			} 
+        } 
+        if(!$keep_post_data) unset($_POST); 
+		
+		// cancel action and return to the page
+		if (isset($_POST['cancel']) && ($_POST['cancel'] == CANCEL_ACL_LABEL))
 		{
 			$this->Redirect($this->Href());
 		}
-		$default_read_acl	= $this->GetConfigValue('default_read_acl');
-		$default_write_acl	= $this->GetConfigValue('default_write_acl');
-		$default_comment_acl	= $this->GetConfigValue('default_comment_acl');
-		$posted_read_acl	= $_POST['read_acl'];
-		$posted_write_acl	= $_POST['write_acl'];
-		$posted_comment_acl	= $_POST['comment_acl'];
-		$message = '';
-
-		// store lists only if ACLs have previously been defined,
-		// or if the posted values are different than the defaults
-
-		$page = $this->LoadSingle('SELECT * FROM '.$this->config['table_prefix'].
-		    "acls WHERE page_tag = '".mysql_real_escape_string($this->GetPageTag()).
-		    "' LIMIT 1");
-
-		if ($page ||
-		    ($posted_read_acl	 != $default_read_acl	||
-		     $posted_write_acl	 != $default_write_acl	||
-		     $posted_comment_acl != $default_comment_acl))
+		
+		// change ACL(s) and/or username
+		if (isset($_POST['store']) && ($_POST['store'] == STORE_ACL_LABEL))
 		{
-			$this->SaveACL($this->GetPageTag(), 'read', $this->TrimACLs($posted_read_acl));
-			$this->SaveACL($this->GetPageTag(), 'write', $this->TrimACLs($posted_write_acl));
-			$this->SaveACL($this->GetPageTag(), 'comment', $this->TrimACLs($posted_comment_acl));
-			$message = ACLS_UPDATED;
-		}
-
-		// change owner?
-		$newowner = $_POST['newowner'];
-
-		if (($newowner != 'same') &&
-		    ($this->GetPageOwner($this->GetPageTag()) != $newowner))
-		{
-			if ($newowner == '')
+			$default_read_acl	= $this->GetConfigValue('default_read_acl');
+			$default_write_acl	= $this->GetConfigValue('default_write_acl');
+			$default_comment_acl	= $this->GetConfigValue('default_comment_acl');
+			$posted_read_acl	= $_POST['read_acl'];
+			$posted_write_acl	= $_POST['write_acl'];
+			$posted_comment_acl	= $_POST['comment_acl'];
+			$message = '';
+	
+			// store lists only if ACLs have previously been defined,
+			// or if the posted values are different than the defaults
+	
+			$page = $this->LoadSingle('SELECT * FROM '.$this->config['table_prefix'].
+			    "acls WHERE page_tag = '".mysql_real_escape_string($this->GetPageTag()).
+			    "' LIMIT 1");
+	
+			if ($page ||
+			    ($posted_read_acl	 != $default_read_acl	||
+			     $posted_write_acl	 != $default_write_acl	||
+			     $posted_comment_acl != $default_comment_acl))
 			{
-				$newowner = NO_PAGE_OWNER;
+				$this->SaveACL($this->GetPageTag(), 'read', $this->TrimACLs($posted_read_acl));
+				$this->SaveACL($this->GetPageTag(), 'write', $this->TrimACLs($posted_write_acl));
+				$this->SaveACL($this->GetPageTag(), 'comment', $this->TrimACLs($posted_comment_acl));
+				$message = ACLS_UPDATED;
 			}
-
-			$this->SetPageOwner($this->GetPageTag(), $newowner);
-			$message .= sprintf(PAGE_OWNERSHIP_CHANGED, $newowner);
+	
+			// change owner?
+			$newowner = $_POST['newowner'];
+	
+			if (($newowner != 'same') &&
+			    ($this->GetPageOwner($this->GetPageTag()) != $newowner))
+			{
+				if ($newowner == '')
+				{
+					$newowner = NO_PAGE_OWNER;
+				}
+	
+				$this->SetPageOwner($this->GetPageTag(), $newowner);
+				$message .= sprintf(PAGE_OWNERSHIP_CHANGED, $newowner);
+			}
+	
+			// redirect back to page
+			$this->Redirect($this->Href(), $message);
 		}
-
-		// redirect back to page
-		$this->Redirect($this->Href(), $message);
 	}
 	else	// show form
 	{
@@ -110,7 +128,7 @@
 <tr>
 	<td colspan="2">
 	<br />
-	<input type="submit" value="<?php echo STORE_ACL_LABEL?>" />
+	<input type="submit" value="<?php echo STORE_ACL_LABEL?>" name="store" />
 	<input type="submit" value="<?php echo CANCEL_ACL_LABEL?>" name="cancel" />
 	</td>
 
Index: handlers/page/edit.php
===================================================================
--- handlers/page/edit.php	(.../1.1.6.6)	(revision 1372)
+++ handlers/page/edit.php	(.../1.1.6.7)	(revision 1372)
@@ -81,6 +81,7 @@
 $note = '';
 $ondblclick = ''; //#123
 
+// cancel operation and return to page
 if(isset($_POST['cancel']) && ($_POST['cancel'] == INPUT_BUTTON_CANCEL))
 {
 	$this->Redirect($this->Href());
@@ -120,7 +121,7 @@
 			$id = $page['id'];
 		}
 	}
-	if ($_POST)
+	if (isset($_POST['form_id']))
 	{
 		// strip CRLF line endings down to LF to achieve consistency ... plus it saves database space.
 		// Note: these codes must remain enclosed in double-quotes to work! -- JsnX
@@ -142,6 +143,14 @@
 		// only if saving:
 		if (isset($_POST['submit']) && $_POST['submit'] == 'Store')
 		{
+			if (FALSE != ($aKey = $this->getSessionKey($_POST['form_id'])))	# check if form key was stored in session
+			{
+				if (TRUE != ($rc = $this->hasValidSessionKey($aKey)))	# check if correct name,key pair was passed
+				{
+					$error = 'Something went wrong with your credentials. Page was not saved';
+				}
+			}
+			
 			// check for overwriting
 			if ($this->page)
 			{
Index: handlers/page/delcomment.php
===================================================================
--- handlers/page/delcomment.php	(.../1.1.6.6)	(revision 1372)
+++ handlers/page/delcomment.php	(.../1.1.6.7)	(revision 1372)
@@ -1,20 +1,52 @@
 <?php
+/**
+ * Delete a comment if the user is an admin, page owner or has posted the comment.
+ * 
+ * @package		Handlers
+ * @subpackage	Page
+ * @version		$Id$
+ * @license		http://www.gnu.org/copyleft/gpl.html GNU General Public License
+ * @filesource
+ * 
+ * @uses	Config::table_prefix
+ * @uses	Wakka::UserIsOwner()
+ * @uses	Wakka::LoadSingle()
+ * @uses	Wakka::GetUserName()
+ * @uses	Wakka::getSessionKey()
+ * @uses	Wakka::hasValidSessionKey()
+ * @uses	Wakka::Query()
+ * @uses	Href()
+ * 
+ */
 
-//select comment and delete it
-$comment_id = intval(trim($_POST["comment_id"]));
-$comment = $this->LoadSingle("select user from ".$this->config["table_prefix"]."comments where id = '".$comment_id."' limit 1");
-$current_user = $this->GetUserName();
+if (!defined('ERROR_COMMENT_NO_KEY')) define('ERROR_COMMENT_NO_KEY', "Your comment cannot be saved. Please contact the wiki administrator(1).");
+if (!defined('ERROR_COMMENT_INVALID_KEY')) define('ERROR_COMMENT_INVALID_KEY', "Your comment cannot be saved. Please contact the wiki administrator(2).");
+if(!defined('ERROR_COMMENT_INVALID_USER')) define('ERROR_COMMENT_INVALID_USER', "Sorry, you\'re not allowed to delete this comment!");
 
-if ($this->UserIsOwner() || $comment["user"]==$current_user)
+if(isset($_POST['form_id']) && isset($_POST["comment_id"])) 
 {
-	$this->Query("DELETE FROM ".$this->config["table_prefix"]."comments WHERE id = '".$comment_id."' LIMIT 1");
-
-	// redirect to page
-	$this->redirect($this->Href());
+	//select comment
+	$comment_id = intval(trim($_POST["comment_id"]));
+	$comment = $this->LoadSingle("select user from ".$this->config["table_prefix"]."comments where id = '".$comment_id."' limit 1");
+	$current_user = $this->GetUserName();	
+	
+    if (FALSE == ($aKey = $this->getSessionKey($_POST['form_id'])))	# check if form key was stored in session
+	{
+		$this->Redirect($this->Href(), ERROR_COMMENT_NO_KEY);
+	}
+	else if (TRUE != ($rc = $this->hasValidSessionKey($aKey)))	# check if correct name,key pair was passed
+	{
+		$this->Redirect($this->Href(), ERROR_COMMENT_INVALID_KEY);
+	}
+	else if (!$this->UserIsOwner() && !$comment["user"]==$current_user)
+	{
+		$this->Redirect($this->Href(), ERROR_COMMENT_INVALID_USER);
+	}
+	else
+	{
+		$this->Query("DELETE FROM ".$this->config["table_prefix"]."comments WHERE id = '".$comment_id."' LIMIT 1");
+		// redirect to page
+		$this->redirect($this->Href(), 'Comment succesfully deleted.');
+	}
 }
-else
-{
-	print("<div class=\"page\"><em class='error'>Sorry, you're not allowed to delete this comment!</em></div>\n");
-}
-
 ?>
