Location: PHPKode > projects > Lame Node System > lns-0.6-11/include/UserInput.php
<?php

/************************************************************************
 *																		*
 * Copyright (C) 2001 Stuart Reeves										*
 *																		*
 * 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.							*
 * 																		*
 * The GNU General Public License is available from:					*
 * http://www.gnu.org/copyleft/gpl.html									*
 *																		*
 ************************************************************************/

/* Stuart's lns (lame node system) */


/* UserInput provides a method of checking user-entered data so that various problems, such as 
 * disallowed HTML and invalid names, are flagged */

class UserInput
{


	// Basic entered information from the user
	var $nodename, 
		$link, 
		$author,
		$contact, 
		$text,
		$protected,
		$metatype,
		$silentupdate;
	
	var $username,
		$superuser,
		$timestamp;
	
	
	// Constructor
	function UserInput($nodename, 
					   $author, 
					   $contact, 
					   $link, 
					   $text, 
					   $protected, 
					   $metatype,
					   $silentupdate) {
					   
		$this->nodename = $nodename;
		$this->link		= $link;
		$this->author 	= $author;
		$this->contact 	= $contact;
		$this->text 	= $text;
		$this->metatype = $metatype;

		if ($silentupdate)
			$this->silentupdate = true;
		else
			$this->silentupdate = false;

		if ($protected)
			$this->protected = true;
		else
			$this->protected = false;
		
		$this->superuser = false;
	}	
	
		
	/* Various get functions */
	
	function getNodename() { 
		return $this->nodename;//stripslashes(htmlentities($this->nodename, ENT_QUOTES))); 
	}
	
	function getAuthor() { 
		return $this->author;
	}
	
	function getContact() {
		return $this->contact;
	}
	
	function getLink() {
		return $this->link;
	}
	
	function setLink($link) {
		$this->link = $link;
	}
	
	function getText() {
		return $this->text;
	}

	function setText($text) {
		$this->text = $text;
	}

	function getProtected() {
		return $this->protected;
	}
	
	function getMetatype() {
		return $this->metatype;
	}

	function setMetatype($metatype) {
		$this->metatype = $metatype;
	}

	function getSilentupdate() {
		return $this->silentupdate;
	}


	/* Sets the currently logged in username. This automatically fills in the author and
	 * contact details.
	 * 
	 * Args:	$username		- Current session username */
	 
	function setUsername($username) {
		if (isset($username)) {
			$this->username = $username;
			$this->author 	= $username;
			$this->contact	= "?node=" . FINGER_NODE . "&_username=$username";
		}
	}



	function setSuperuser($superuser) {
		$this->superuser = $superuser;
	}


	function setProtected($protected) {
		$this->protected = $protected;
	}
		


	/* Set the unique timestamp for this user input session. This means that a particular node is
	 * being edited. 
	 * 
	 * Args:	$timestamp			- The timestamp of the node to edit */

	function setTimestamp($timestamp) {
		$this->timestamp = $timestamp;
		
	}


		
	/* Checks whether a contact exists for the user input object.
	 * 
	 * Returns: true (boolean)  	- the contact field exists
	 *			false (boolean) 	- the contact field does not exist */
	
	function contactExists() {
		if($this->contact != "")
			return true;
		else 
			return false;
	}
	
	
	
	/* Parses the text input for link elements and line breaks
	 * 
	 * Args:	$args[0] (string)		- Optional argument for text to parse if this method is 
	 *									  being used statically
	 *
	 * Returns: $parsedText (string) 	- Parsed text according to rules in "header.php.inc" */

	function getParsedText() {
	
		$args 		= func_get_args();
		$parsedText = "";
		
		if (isset($args[0]))
			$parsedText = $args[0];
		else
			$parsedText = $this->text;
		
		if (DISALLOW_NODETEXT_HTML)
			$parsedText = htmlspecialchars($this->text);
		
		// Replace special link brackets ("[" and "]"). We perform two regexp replacements firstly
		// for the "[displayed text|nodename]" syntax, and then for any undetected "[nodename]" 
		// directives.
		$parsedText = preg_replace(NODE_PARSE_REGEXP, NODE_PARSE_REPLACE, $parsedText);
		$parsedText = preg_replace(NODE_PARSE_REGEXP2, NODE_PARSE_REPLACE2, $parsedText);
		//if ($parseText == $this->text)
		//	echo "Error<br />\n";
		
		// Replace newline chars with HTML <br />
		$parsedText = preg_replace("/([^>]{1})\r/", "$1<br />\n", $parsedText);	
		
		return $parsedText;
	}
	

	
	/* Cleans up the nodename string according to header rules.
	 * 
	 * Returns: $nodename (string) 		- the cleaned up nodename string */

	function getCleanNodename($nodename) {

		// Nodename is disallowed dangerous URL-parsed characters, like "&" and "="
		$nodename = trim(preg_replace(DISALLOWED_NODENAME_CHARS, "", $nodename));
		$nodename = htmlentities($nodename, ENT_QUOTES);
		$nodename = stripslashes($nodename);

		return $nodename;
	}
	

	function getCleanAuthor($author) {
	
		// Check that correct info has been input
		if ($author == "")
			$author = "Anonymous";
		else {
			// Author is allowed most characters, but no HTML tags
			$author = strip_tags($author);
			$author = stripslashes($author);
			$author	= htmlspecialchars($author, ENT_QUOTES);
		}
	
		return $author;
	}


	function getCleanContact($contact) {

		// Contact is not allowed inverted commas and the like. Special URL-parsed chars like 
		// "&" are not allowed for obvious reasons.
		$contact = strip_tags($contact);
		$contact = stripslashes($contact);
		$contact = trim(preg_replace(DISALLOWED_CONTACT_CHARS, "", $contact));

		// Check contact information		
		if ($contact != "") {

			if (strchr($contact, "@")) {
				if (substr($contact, 0, 7) != "mailto:")
					$contact = "mailto:$contact";
			} else if (substr($contact, 0, 7) != "http://")
				$contact = "http://$contact";
	
		}

		return $contact;
	}
	
	
	function getCleanText($text) {
		$text = strip_tags($text, ALLOWED_HTML);
		$text = stripslashes($text);
		// Temporary fix to disallow JavaScript
		$text = preg_replace("/(<[\w\s\=\-\"]*\")(javascript:[^\"]*)(\">)/", 
							 "$1$3", $text);	
		
		return $text;
	}


	function getCleanLink($link) {
		// For external links or for files, assuming any input link is HTTP by default 
		// (unless protocol is specified)
		if ($link != "") {
			$link 		 = strip_tags($link);
			$slashes_pos = strpos($link, "://");
			$protocol	 = substr($link, 0, $slashes_pos);
		
			if ($protocol == "") $link = "http://$link";
		}

		return $link;
	}


	
	/* Tests validity of user input to the object created.
	 * 
	 * Returns: true (boolean)  	- The nodename exists
	 *			false (boolean) 	- The nodename does not exist */
	 
	function check() {
	
		// Check the nodename is there
		if ($this->nodename != "") {
	
			$this->nodename = $this->getCleanNodename($this->nodename);
			
			// Extra fields for anonymous users
			if (!isset($this->username)) {
				$this->author	= $this->getCleanAuthor($this->author);
				$this->contact  = $this->getCleanContact($this->contact);						
			}
	
			// Check the other required fields are there
			if ($this->text != "" || $this->link != "") {
				$this->text 	= $this->getCleanText($this->text);
				$this->link		= $this->getCleanLink($this->link);
			} else
				return false;
				
			return true;
			
		} else
			return false;

	}
	

	
	/* Submits input data to the database. Note that nodes are never, by default, set to hidden.
	 * 
	 * Args:	$host				- Database server hostname
	 *			$user				- Database username
	 *			$passwd 			- Database password
	 *			$db 				- Database name
	 *			$table				- Table name
	 *
	 * Returns: 1 (integer)  		- Node creation was successful
	 *			-1 (integer) 		- Node creation failed due to protected node 
	 *			0 (integer)			- Creation failed due to access error */
	
	function createNode($host, $user, $passwd, $db, $table) {


		$query 		= "SELECT * FROM $table WHERE nodename = '$this->nodename'";
	
		$link 		= mysql_connect($host, $user, $passwd);
		$dbselect	= mysql_select_db($db, $link);
		$dbquery	= mysql_query($query, $link);
		
		$code 		= 0;

		// We must iterate through all the rows. If any are protected or hidden, we consider the 
		// whole node to be protected/hidden (i.e. not editable/addable to).
		while ($nodedata = mysql_fetch_object($dbquery)) {
			if (($nodedata->protected == 't' && !$this->superuser) || $nodedata->hidden == 't') {
				$code = -1;
				break;
			}
		}
	
		// If the previous security check has passed, insert the data as a new row or update 
		// that entry.
		if ($code != -1) {				
			
			$parsedText = $this->getParsedText();
			$parsedText = addslashes($parsedText);
	
			// Set the protection based on whether the submitter is a superuser or not
			$protText = "f";
			if ($this->superuser && $this->protected)
				$protText = "t";

			// Set the raw type: normal node, picture node or external link node
			$rawType = RAWTYPE_DEFAULT;
			
			if ($this->link != "") {
					
				// Cut up the link to see if it is a picture or not
				$filetype = substr($this->link, 
								   strrpos($this->link, ".") + 1,
							  	   strlen($this->link));
				
				if (preg_match(IMAGE_TYPES, $filetype))
					$rawType = RAWTYPE_IMAGE;
				else
					$rawType = RAWTYPE_EXT_LINK;
			}

	
			// Anonymous users
			if (!isset($this->username)) {

				// Anonymous users cannot make METATYPE_HOME nodes
				if ($this->metatype != METATYPE_HOME) {
					$query = "INSERT INTO $table VALUES (\"$this->nodename\", 
														 \"$this->link\", 
														 NULL, 
														 \"$this->author\",
														 \"$this->contact\", 
														 \"$parsedText\", 
														 \"$protText\",
														 \"\",
														 NULL,
														 \"$rawType\",
														 \"$this->metatype\")";
					$code = 1;
				} else
					$code = -1;
			} else {
								
				// If the timestamp is set, then we assume we are in edit mode
				if (isset($this->timestamp)) {

					// Check the ownership of the node to edit.
					$userQuery = "SELECT username FROM $table WHERE ts = '$this->timestamp'";
					$dbquery   = mysql_query($userQuery, $link);
					
					if (mysql_num_rows($dbquery) == 1) {
						
						$nodedata = mysql_fetch_object($dbquery);
						
						if ($nodedata->username == $this->username) {
							
							// Set the update to be ``silent'', i.e. timestamp is preserved
							$tsText = "";
							if ($this->silentupdate)
								$tsText = "ts = ts,";
								
							$query = "UPDATE $table SET $tsText
														text 	   = '$parsedText', 
														link	   = '$this->link',
														protected  = '$protText',
														rawtype    = '$rawType',
														metatype   = '$this->metatype'
													WHERE username = '$this->username' 
													AND   ts 	   = '$this->timestamp'";
							$code = 1;
						} else
							$code = 0;
					} else
						$code = 0;
			
				} else {
				
					// Make sure there are no other nodes with a metatype of METATYPE_HOME (we 
					// only allow one METATYPE_HOME node per user).
					if ($this->metatype == METATYPE_HOME) {
						$homeQuery = "SELECT * FROM $table WHERE metatype = '" . METATYPE_HOME . 
									 "' AND username = '$this->username'";
						// Return -1 if the user's home node already exists
						if (mysql_num_rows(mysql_query($homeQuery, $link)) == 1) {
							mysql_close($link);
							return -1;
						}
					}

					$query = "INSERT INTO $table VALUES (\"$this->nodename\", 
												 \"$this->link\", 
												 NULL, 
												 \"$this->username\",
												 \"\?node=" . FINGER_NODE . 
													"\&_username=$this->username\", 
												 \"$parsedText\", 
												 \"$protText\",
												 \"\",
												 \"$this->username\",
												 \"$rawType\",
												 \"$this->metatype\")";
					$code = 1;
				}
			}
			
			// Perform query and recreate indices for searches
			if ($code == 1) {
				mysql_query($query, $link);
				mysql_query("REPAIR TABLE $table QUICK");
			}
			
		} // End if
		
		mysql_close($link);
		return $code;
	}
	


	/* Deletes a node. The session username and timestamp variables must be set to proceed.
	 * If a superuser is logged in, then any nodes may be deleted, not just ones in edit. If the
	 * node to delete is part of a node where there are other writeups above it, then the content
	 * is deleted, but is left to indicate that something is missing.
	 * 
	 * Args:	$host ...
	 *				$table			- Database information
	 *
	 * Returns: 1 (integer)  		- Node deletion was successful
	 *			0 (integer) 		- Node deletion failed due to access error (e.g. username
	 *								  and/or timestamp were not set or username doesn't match 
	 *								  node's username) 
	 *			-1 (integer)		- Problem with database (i.e. non-unique timestamp or no 
	 *								  matching results) */
	
	function deleteNode($host, $user, $passwd, $db, $table) {

		if (isset($this->username) && isset($this->timestamp)) {

			
			$link 		= mysql_connect($host, $user, $passwd);
			$dbselect	= mysql_select_db($db, $link);

			/* Find out whether this node has other entries. If this is the case then the node
			 * to be deleted will be replaced with a marker indicating that there was once a node
			 * here. */
			$rowsQuery    = "SELECT nodename FROM $table WHERE nodename = '$this->nodename'
														       AND ts   > '$this->timestamp'";
			$uniqueQuery  = "SELECT username FROM $table WHERE nodename = '$this->nodename'
														       AND ts   = '$this->timestamp'";
	
			$rows    = mysql_num_rows(mysql_query($rowsQuery, $link));
			$dbquery = mysql_query($uniqueQuery, $link);
			$unique  = mysql_num_rows($dbquery);
			$code    = 0;
			
			if ($unique == 1) {
				$nodedata = mysql_fetch_object($dbquery);
				
				if ($this->superuser || $nodedata->username == $this->username) {
					if ($rows > 0) {
						// If there are several writeups for this node, then we delete the data
						// but leave the timestamp etc. as a marker
						$query = "UPDATE $table SET ts   	 = ts, 
													text 	 = '', 
													link 	 = '',
													author 	 = '',
													contact  = '',
													username = ''
												WHERE nodename = '$this->nodename'
													  AND ts   = '$this->timestamp'";
						mysql_query($query, $link);
					
					} else {
					
						// Check that there is not a deleted entry before this one (if this is
						// the case, we delete it)
						$totRowsQuery = "SELECT * FROM $table WHERE nodename = '$this->nodename'
															  		AND ts	 < '$this->timestamp'
															  ORDER BY ts DESC";
						$dbquery = mysql_query($totRowsQuery, $link);
						
						if (mysql_num_rows($dbquery) > 0) {
							$validEntry = false;
							while (!$validEntry && $nodedata = mysql_fetch_object($dbquery)) {
								// Remove each entry below this one that is also marked for 
								// deletion
								if ($nodedata->text == "" && $nodedata->link == "") {
									$query = "DELETE FROM $table 
													 WHERE nodename = '$nodedata->nodename'
													 	   AND ts	= '$nodedata->ts'";
									mysql_query($query, $link);
								} else
									$validEntry = true;
							}
						}
					
						// Deal with the case for a single node writeup
						$query = "DELETE FROM $table WHERE nodename = '$this->nodename' 
													 	   AND ts   = '$this->timestamp'";
						mysql_query($query, $link);
					}
					$code = 1;
				} else
					$code = 0;
					
			} else
				$code = -1;
			
			mysql_close($link);
			return $code;
			
		} else
			return 0;
	}



} // End class UserInput


?>

Return current item: Lame Node System