Location: PHPKode > projects > FtpREadmin > ftpreadmin-0.2/class/ftpREadmin.class.php
<?php
/* ftpREadmin (ProFTPd MySQL Admin with Quota), Copyright (C) 2008 Vaidotas Gaidelis
 * ftpREadmin comes with ABSOLUTELY NO WARRANTY.
 * This is free software, and you are welcome to redistribute it
 * under the terms of the GNU General Public License.
 * Read 'COPYING' for further information.
 */

/**
* @name ftpREadmin Class
* @version 0.2
* @abstract PHP 5 proftpd admin manager with MySQL database and quota suppot
**/

class ftpREadmin {
	
	/* Array for config options. It is set in constructor. */
	public $confArr = array();

	/* The username of a member */
	private $username;
	
	/* The password of a member */
	private $password;
	
	/* The error string */
	private $error;
	
	/* Runs when an instance of the class is created. It automatically connects
	 * to the MySQL server and checks if the IP is not banned before continuing
	 */
	public function __construct($confArr) {
		session_start();
		$this->confArr = $confArr;
		$this->connectToMySQL();
		$this->checkUserIP();
		if (!isset($_SESSION['auth'])) {
			$_SESSION['auth'] = 0;
		}
	}
	
	/* Return the error*/
	public function getError() {
		return $this->error;
	}
	
	/* Return the username of a member*/
	public function getUsername() {
		return $this->username;
	}
	
	/* Return the plain text password of a member */
	public function getPassword() {
		return $this->password;
	}
	
	/* Return the encrypted password of a member */
	public function getEncryptedPassword() {
		return sha1($this->password);
	}
	
	/* Get a member's IP Address and convert it to long */
	public function getUserIP() {
		return ip2long(getenv("REMOTE_ADDR"));
	}
	
	/* Connection to a MySQL database using the defined connection details */
	public function connectToMySQL() {
		@mysql_connect(DB_HOST, DB_USER, DB_PASS) OR die("Cannot connect to MySQL server!");
		mysql_select_db(DB_NAME) OR die("Cannot select database!");
	}
			
	/* Validate a member login from data in a MySQL Database. */
	public function verifyLogin($username, $password) {
		$this->username = $username;
		if (empty($username) || empty($password)) {
			throw new Exception($this->confArr['error_empty_login']);
		} else {
			$query = sprintf("SELECT * FROM ftpadmins WHERE username = '%s' AND
											password = sha1('%s') LIMIT 0,1",
											$this->clean($username),
											$this->clean($password));
			
			$result = mysql_query($query) OR die('Cannot perform query!');
			
			if (mysql_num_rows($result) == 1) {
				
				$ip = $this->getUserIP();
				mysql_query("DELETE FROM ftplogins WHERE IP='$ip'");
				$this->sessionVerify();
				header("Location: secure.php");
			} else {
				$ip = $this->getUserIP();
				mysql_query("INSERT INTO ftplogins(IP) VALUES('$ip')");
				$_SESSION['auth'] = 0;
				throw new Exception($this->confArr['error_validate_login']);
			}
		}
		mysql_free_result($result);
	}
	
	/* Compare the member's IP with the IPs recorded in the database.
	If the IP appears more than 5 times, display the ban message
	*/
	public function checkUserIP() {
		$ip = $this->getUserIP();
		$query = "SELECT IP FROM ftplogins WHERE IP= '$ip' LIMIT 0,".$this->confArr['max_retries'];
		$result = mysql_query($query) OR die("Cannot perform query!");
		$max_retries = $this->confArr['max_retries'];
		if (mysql_num_rows($result) >= $max_retries) {
			throw new Exception($this->confArr['error_banned_login']);
			exit;
		}
		
		mysql_free_result($result);
	}
	
	/* Verify the session login. Used for protected pages on your website */
	public function sessionVerify() {
		session_regenerate_id();
		$_SESSION['auth'] = 1;
		$_SESSION['name'] = $this->username;
	}
	
	/* Checks if the Session data is correct before continuing the script */
	public function verifyAccess() {
		if (isset($_SESSION['name']) && $_SESSION['auth'] == 1) {
			return true;
		}
		header("Location: index.php");
		exit;
	}
	
	/* Destroy session and log user out*/
	public function logOut() {
		$_SESSION['auth'] = 0;
		$_SESSION['name'] = '';
		session_destroy();
		header("Location: index.php");
		exit;
	}
	
	/* Return release version */
	public function getVersion(){
		return $this->confArr['version'];
	}
	
	/* Display table with users */
	public function getFtpUsers() {
		$query = "SELECT ftpuser.id, ftpuser.userid, ftpuser.passwd, ftpuser.homedir,
						 ftpuser.comment, ftpquotalimits.bytes_in_avail
				  FROM ftpuser LEFT JOIN ftpquotalimits ON ftpuser.userid = ftpquotalimits.name";
		$result = mysql_query($query) OR die("Cannot perform query!");
		$i = 0;

		$content = "
		<table class=\"list\">\n
			<tr>\n
				<th>E</th>\n
				<th>username</th>\n
				<th>password</th>\n
				<th>directory</th>\n
				<th>Comment</th>\n
				<th>Quota</th>\n
				<th>X</th>\n
			</tr>\n";

		while ($row = mysql_fetch_assoc($result)) {
			if ($i % 2 == 0) {
				$tdstyle="listeven";
			} else {
				$tdstyle="listodd";
			}
			
			$quota = $this->getUnits($row['bytes_in_avail']);
			$quotaU = $quota['value'] ." ". $quota['units'];
			$content .="<tr>
							<td class=\"".$tdstyle."\">
								<a href=\"secure.php?pg=users&amp;action=edit&amp;ftpUserId=".$row['id']."\">
									<img src=\"template/action_edit.png\" alt=\"edit user\"/>
								</a>
							</td>\n
							<td class=\"".$tdstyle."\">".$row['userid']."</td>\n
							<td class=\"".$tdstyle."\">".$row['passwd']."</td>\n
							<td class=\"".$tdstyle."\">".$row['homedir']."</td>\n
							<td class=\"".$tdstyle."\">&nbsp;".$row['comment']."</td>\n
							<td class=\"".$tdstyle."\">&nbsp;".$quotaU."</td>\n
							<td class=\"".$tdstyle."\">
								<a onClick=\"return confirmDLG('Really delete user?');\" href=\"secure.php?pg=users&amp;action=delete&amp;ftpUserId=".$row['id']."\">
									<img src=\"template/action_delete.png\" alt=\"delete user\"/>
								</a>
							</td>\n
						</tr>";
			$i++;
		}

		$content .="</table>";
		
		return $content;
	}

	/* Show table with user ally stats */
	public function getFtpUsersStats(){
		$query = "SELECT name, quota_type, bytes_in_used, bytes_out_used,
						 bytes_xfer_used
				  FROM ftpquotatallies";
		$result = mysql_query($query) OR die("Cannot perform query!");
		
		$i = 0;
		$content = "<table class=\"list\">\n
		<tr>\n
			<th>username</th>\n
			<th>Quota type</th>\n
			<th>In used</th>\n
			<th>Out used</th>\n
			<th>Xfer used</th>\n
		</tr>\n";
		
		while ($row = mysql_fetch_assoc($result)) {
			if ($i % 2 == 0) {
				$tdstyle="listeven";
			} else {
				$tdstyle="listodd";
			}
			
			$quotaIN = $this->getUnits($row['bytes_in_used']);
			$quotaOUT = $this->getUnits($row['bytes_out_used']);
			$quotaXFER = $this->getUnits($row['bytes_xfer_used']);
			$content .="<tr>
							<td class=\"".$tdstyle."\">".$row['name']."</td>\n
							<td class=\"".$tdstyle."\">".$row['quota_type']."</td>\n
							<td class=\"".$tdstyle."\">".$quotaIN['value'] ." ". $quotaIN['units']."</td>\n
							<td class=\"".$tdstyle."\">".$quotaOUT['value'] ." ". $quotaOUT['units']."</td>\n
							<td class=\"".$tdstyle."\">".$quotaXFER['value'] ." ". $quotaXFER['units']."</td>\n
						</tr>";
			
			$i++;
		}
		
		$content .="</table>";
		
		return $content;
	}
	
	/* Set form values from database and display form */
	public function editFtpUser($ftpUserID){
		/* A big query to select from two tables. Quota table's record is not necessarily exist */
		$query = "SELECT ftpuser.userid, ftpuser.passwd, ftpuser.homedir, ftpuser.comment,
						 ftpquotalimits.quota_type, ftpquotalimits.per_session, ftpquotalimits.limit_type,
						 ftpquotalimits.bytes_in_avail, ftpquotalimits.bytes_out_avail,
						 ftpquotalimits.bytes_xfer_avail
				  FROM ftpuser
				  LEFT JOIN ftpquotalimits
				  ON ftpuser.userid = ftpquotalimits.name WHERE ftpuser.id=$ftpUserID LIMIT 1";
		
		$result = mysql_query($query) OR die("Cannot perform query!");
		$row = mysql_fetch_assoc($result);
		switch ($row['quota_type']) {
		case "user":
			$quotaType['user'] = "selected";
			break;
		case "group":
			$quotaType['group'] = "selected";
			break;
		case "class":
			$quotaType['class'] = "selected";
			break;
		case "all":
			$quotaType['all'] = "selected";
			break;
		}
		if ($row['per_session'] == 'true') {
			$perSession[1] = 'checked';
		} else {
			$perSession[0] = 'checked';
		}
		if ($row['limit_type'] == 'soft') {
			$limitType['soft'] = 'checked';
		} else {
			$limitType['hard'] = 'checked';
		}
		
		$quotaIn = $this->getUnits($row['bytes_in_avail']);
		switch ($quotaIn['units']) {
		case "KB":
			$quotaInU['KB'] = "selected";
			break;
		case "MB":
			$quotaInU['MB'] = "selected";
			break;
		case "GB":
			$quotaInU['GB'] = "selected";
			break;
		}
		
		$quotaOut = $this->getUnits($row['bytes_out_avail']);
		switch ($quotaOut['units']) {
		case "KB":
			$quotaOutU['KB'] = "selected";
			break;
		case "MB":
			$quotaOutU['MB'] = "selected";
			break;
		case "GB":
			$quotaOutU['GB'] = "selected";
			break;
		}
		
		$quotaXfer = $this->getUnits($row['bytes_xfer_avail']);
		switch ($quotaXfer['units']) {
		case "KB":
			$quotaXferU['KB'] = "selected";
			break;
		case "MB":
			$quotaXferU['MB'] = "selected";
			break;
		case "GB":
			$quotaXferU['GB'] = "selected";
			break;
		}
		
		require_once('template/edit_user.tpl.php');
		return $content;
	}
	
	/* Update ftp user info and quotas. */
	public function updateFtpUser($ftpUserId, $userid, $passwd, $comment,
				  $quota_type, $per_session, $limit_type,
				  $bytes_in_avail,   $quota_in_units,
				  $bytes_out_avail,  $quota_out_units,
				  $bytes_xfer_avail, $xfer_units) {
		
		$query = "UPDATE ftpuser SET passwd='$passwd', comment='$comment'
				  WHERE id=$ftpUserId LIMIT 1";
		$result = mysql_query($query);
		if (!$result) {
			$this->error = "Error: Cannot update user info!\n<br/>";
		} else {
			$content = "User " . $userid . " updated successfuly.\n<br/>";
		}
		
			$bytes_in_avail = $this->getBytes($bytes_in_avail, $quota_in_units);
			$bytes_out_avail = $this->getBytes($bytes_out_avail, $quota_out_units);
			$bytes_xfer_avail = $this->getBytes($bytes_xfer_avail, $xfer_units);
				
			$query = "SELECT name FROM ftpquotalimits WHERE name ='$userid'";
			$result = mysql_query($query);
			/* If there is allready quota defined, update values */
			if(mysql_numrows($result) == 1 ) {
				$query = "UPDATE ftpquotalimits
					  SET quota_type='$quota_type', per_session='$per_session',
						  limit_type='$limit_type', bytes_in_avail='$bytes_in_avail',
						  bytes_out_avail='$bytes_out_avail', bytes_xfer_avail='$bytes_xfer_avail'
					  WHERE name='$userid' LIMIT 1";
				$result = mysql_query($query);
				if (!$result) {
					$this->error .= "Error: Cannot update user quota!\n<br/>";
				} else {
					$content .= "Users " . $userid . " quota updated successfuly.\n<br/>";
				}
			/* If there is no quota defined, insert values */
			} else {
				/* if quota non zero, create quotas */
				if ($bytes_in_avail != 0 || $bytes_out_avail != 0 || $bytes_xfer_avail != 0) {
					$query = "INSERT INTO ftpquotalimits(name, quota_type, per_session, limit_type, bytes_in_avail,
														 bytes_out_avail, bytes_xfer_avail)
							  VALUES ('$userid', '$quota_type', '$per_session', '$limit_type', '$bytes_in_avail',
									  '$bytes_out_avail', '$bytes_xfer_avail')";
					$result = mysql_query($query);
				
					if (!$result) {
						$this->error = "Error: Cannot perform quota query!";
					} else {
						$content .= " Quota added successfuly.";
					}
				}
			}
		return $content;
	}
	
	/* FTP admin settings and IP ban management */
	public function ftpREadminSettings() {
		/* Get admin's user name */
		$query = "SELECT user_id, username FROM ftpadmins LIMIT 1";
		$result = mysql_query($query);
		$user = mysql_fetch_row($result);

		require_once('template/settings.tpl.php');
		
		return $content;
	}
	
	/* Get list of banned IP's */
	public function getBannedIPs() {
		$query = "SELECT IP FROM ftplogins GROUP BY IP
				  HAVING count(IP) >=". $this->confArr['max_retries'];
		$result = mysql_query($query) OR die("Cannot perform query!");
		$i = 0;
		while ($row = mysql_fetch_row($result)) {
			$i++;
			if ($i % 2 == 0) {
				$tdstyle="listeven";
			} else {
				$tdstyle="listodd";
			}
			$result_arr = $row;

			$IPList .="<tr>
					<td class=\"".$tdstyle."\">".long2ip($row[0])."</td>\n
					<td class=\"".$tdstyle."\">
						<a onClick=\"return confirm('Really unban this IP?');\" href=\"secure.php?pg=settings&amp;action=unban&amp;bannedIP=".$row[0]."\">
							<img src=\"template/action_delete.png\" alt=\"remove ban\"/>
						</a>
					</td>\n
					</tr>";
		}
		return $IPList;
	}
	
	/* Update admin's user and password in database  */
	public function updateFtpAdmin($user_id, $user, $password) {
		/* Password not changed, change username */
		if ($password == ''){
			$query = "UPDATE ftpadmins SET username='$user' WHERE user_id=$user_id";
		} else {
			$password = sha1($password);
			$query = "UPDATE ftpadmins SET username='$user', password='$password'
					  WHERE user_id=$user_id";
		}
		$result = mysql_query($query);
		if (!$result) {
				$this->error .= "Error: Cannot update admin data!\n<br/>";
			} else {
				$content .= "Admin account updated.\n<br/>";
			}
		return $content;
	}
	
	/* Unban IP from database */
	public function removeBan($longIP){
		$query = "DELETE FROM ftplogins WHERE IP=".$longIP;
		$result = mysql_query($query);
		if (!$result) {
			$this->error = "Error: Cannot remove IP ban!";
		} else {
			$content = "IP " . long2ip($longIP) . " unbanned successfuly.\n<br/>";
		}
		
		return $content;
	}
	
	/* Add ftp user and quota if exists */
	public function addFtpUser($userid, $passwd, $homedir, $comment,
							   $quota_type, $per_session, $limit_type,
							   $bytes_in_avail,   $quota_in_units,
							   $bytes_out_avail,  $quota_out_units,
							   $bytes_xfer_avail, $xfer_units) {
		
		$UID = $this->confArr['uid'];
		$GID = $this->confArr['gid'];
		$shell = $this->confArr['default_shell'];
		$userid = $this->clean($userid);
		$passwd = $this->clean($passwd);
		$homedir = $this->clean($homedir);
		$comment = $this->clean($comment);
		
		$query = "INSERT INTO ftpuser(userid, passwd, uid, gid, homedir, shell, comment)
				  VALUES ('$userid', '$passwd', $UID, $GID, '$homedir', '$shell', '$comment')";
		$result = mysql_query($query);
		
		if (!$result) {
			$this->error = "Error: Cannot perform user query!";
		} else {
			$content = "User " . $userid . " added successfuly.\n<br/>";
		}
		
		/* if quota non zero, create quota record */
		if ($bytes_in_avail != 0 || $bytes_out_avail != 0 || $bytes_xfer_avail != 0) {
			
			/* Get in bytes */
			$bytes_in_avail = $this->getBytes($bytes_in_avail, $quota_in_units);
			$bytes_out_avail = $this->getBytes($bytes_out_avail, $quota_out_units);
			$bytes_xfer_avail = $this->getBytes($bytes_xfer_avail, $xfer_units);
			
			$query = "INSERT INTO ftpquotalimits(name, quota_type, per_session, limit_type, bytes_in_avail,
												 bytes_out_avail, bytes_xfer_avail)
					  VALUES ('$userid', '$quota_type', '$per_session', '$limit_type', '$bytes_in_avail',
							  '$bytes_out_avail', '$bytes_xfer_avail')";
			$result = mysql_query($query);
			
			if (!$result) {
				$this->error = "Error: Cannot perform quota query!";
			} else {
				$content .= " Quota added successfuly.";
			}
		}
		
		return $content;
	}
	
	/* Simply display add ftp user form from template */
	public function showAddFtpUserForm() {
		require_once('template/add_user.tpl.php');
		return $content;
	}
	
	/*
	Method deleteFtpUser() deletes only record form database, no files
	are deleted. To enable file deletion from server you should change
	global permissions in proftpd.conf. I consider it as a security issue,
	so I will not implement this feature until someone will suggest better
	sollution.
	*/
	public function deleteFtpUser($ftpUserId){
		/* Get user name and homedir for output and quota */
		$userQuery = "SELECT userid, homedir FROM ftpuser WHERE id=$ftpUserId LIMIT 1";
		$result = mysql_query($userQuery);
		$row = mysql_fetch_assoc($result);
		if (!$result || !$row) {
			$this->error = "Error: something went wrong with user select!\n<br/>";
		} else {
			
			$content = "Shell command: <pre># rm -rf ".$row['homedir']."\n</pre>";
		}
		
		/* Delete quotas and quota tallies */
		$quotaQuery = "DELETE FROM ftpquotalimits WHERE name='".$row['userid']."' LIMIT 1";
		$result = mysql_query($quotaQuery);
		
		$tallyQuery = "DELETE FROM ftpquotatallies WHERE name='".$row['userid']."' LIMIT 1";
		$result = mysql_query($tallyQuery);
		
		/* Delete user from database */
		$query = "DELETE FROM ftpuser WHERE id=$ftpUserId LIMIT 1";
		$result = mysql_query($query);
		if (!$result || !$row) {
			$this->error .= "Error: something went wrong with deletion!\n<br/>";
		} else {
			$content .= "User ".$row['userid']." deleted successfuly.\n<br/>";
		}
		return $content;
	}
	
	/* Escape the input */
	public function clean($input) {
		return mysql_real_escape_string($input);
	}
			
	/* Convert KB, MB or GB to bytes */
	public function getBytes($value, $units){
		switch ($units) {
		case 'KB':
			$result = $value * 1024;
			break;
		case 'MB':
			$result = $value * 1048576;
			break;
		case 'GB':
			$result = $value * 1073741824;
			break;
		}
		return $result;
	}
	 
	/* Converts bytes to KB, MB or GB and returns assoc array with value and measure */
	public function getUnits($value){
		$size = $value / 1024;
		if ($size < 1024) {
			$sizeArr['value'] = number_format($size, 0);
			$sizeArr['units'] = 'KB';
		} else {
			if ($size / 1024 < 1024) {
				$sizeArr['value'] = number_format($size / 1024, 0);
				$sizeArr['units'] = 'MB';
			} else if ($size / 1024 / 1024 < 1024) {
				$sizeArr['value'] = number_format($size / 1024 / 1024, 0);
				$sizeArr['units'] = 'GB';
			}
		}
		return $sizeArr;
	}

}
?>
Return current item: FtpREadmin