• Howdy! Welcome to our community of more than 130.000 members devoted to web hosting. This is a great place to get special offers from web hosts and post your own requests or ads. To start posting sign up here. Cheers! /Peo, FreeWebSpace.net
managed wordpress hosting

THT - The Hosting Tool

JonnyH

The Hosting Tool
NLC
tht03xb3.png

From the creator of cP Creator brings you The Hosting Tool, this totally free script, released under the GNU-GPL takes all my past mistakes and rectifies them in a completely new script that will provide superb features in a free box.

This script is currently in development, please follow it below.
 
In cP Creator, there was just one class, it wasn't really supported or organised, just a bunch of functions in a file that did certain things when you wanted it to. Well if it did those things.

In THT the script is broke up into three main areas. Order, Admin, Client. They're split up into three different folders along with includes and themes.

There is also three main classes so far and a compiler. The compiler defines the script, creates all the classes in the folder and automatically any new ones. It also contains validation like PHP Version, because this is a PHP 5 only script.

The 4 main classes so far are DB, Style, Server, Main. Database contains all the db queries, fetch array, num rows, query. It also creates the connection on construct. Style contains all the template functions, header and footers. Server has yet to be made but contains all the server code, that will call another peice of code depending what control panel it is. WHM etc.

An example of one of these classes are:
PHP:
<?php
//////////////////////////////
// The Hosting Tool
// Database (mySQL) Class
// By Jonny H
// Released under the GNU-GPL
//////////////////////////////

//Check if called by script
if(THT != 1){die();}

//Create the class
class db {
	private $sql = array(), $con, $prefix, $db; #Variables, only accesible in class
	
	# Start the functions #
	
	public function __construct() { # Connect SQL as class is called
		include(LINK."conf.inc.php"); # Get the config
		$this->sql = $sql; # Assign the settings to DB Class
		$this->con = @mysql_connect($this->sql['host'], $this->sql['user'], $this->sql['pass']); #Connect to SQL
		if(!$this->con) { # If SQL didn't connect
			die("Fatal: Coudn't connect to mySQL, please check your details!");
		}
		else {
			$this->db = @mysql_select_db($this->sql['db'], $this->con); # Select the mySQL DB
			if(!$this->db) {
				die("Fatal: Couldn't select the database, check your db setting!");
			}
			else {
				$this->prefix = $this->sql['pre'];
			}
		}
	}
	
	private function error($name, $mysqlerror, $func) { #Shows a SQL error from main class
		$error['Error'] = $name;
		$error['Function'] = $func;
		$error['mySQL Error'] = $mysqlerror;
		global $main;
		$main->error($error);
	}
	
	public function query($sql) { # Run any query and return the results
		$sql = preg_replace("/<PRE>/si", $this->prefix, $sql); #Replace prefix variable with right value
		$sql = @mysql_query($sql, $this->con); # Run query
		if(!$sql) {
			$this->error("mySQL Query Failed", mysql_error(), __FUNCTION__); # Call Error
		}
		return $sql; # Return SQL
	}
	
	public function num_rows($sql) { # Runs a query and returns the rows
		$sql = @mysql_num_rows($sql); # Run query
		if(!$sql) {
			$this->error("mySQL Num Rows Failed", mysql_error(), __FUNCTION__); # Call Error
		}
		return $sql; # Return SQL
	}
	
	public function fetch_array($sql) { # Gets a query and returns the rows/columns as array
		$sql = @mysql_fetch_array($sql); # Fetch the SQL Array, all the data
		if(!$sql) {
			$this->error("mySQL Fetch Array Failed", mysql_error(), __FUNCTION__); # Call Error
		}
		return $sql; # Return SQL
	}
	
	public function strip($value) { # Gets a string and returns a value without SQL Injection
		if(get_magic_quotes_gpc()) { # Check if Magid Quotes are on
			  $value = stripslashes($value); 
		}
		if(function_exists("mysql_real_escape_string")) { # Does mysql real escape string exist?
			  $value = mysql_real_escape_string($value);
		} 
		else { # If all else fails..
			  $value = addslashes($value);
		}
		return $value;
	}
}
//End SQL
?>
 
Good one Jonny' Glad to see you coding stuff like this again.
Will keep a close eye on it.
 
Good to see you back in action :)

What happend to not having time anyway?

I would guess that like most once he had nothing to do he got bored and then it started driving him nuts so he started coding :p

Thats my guess anyway
 
I've got a week off. I've finished all the assignments I needed to do in that time.. So I decided to through together the ideas I had. I said in a previous post in cP Creator I wanted to get this out by the end of the week. When college starts again, work flows in.

Cheers for the replies guys. Makes it worthwhile.

Also, would anyone be able to provide a free account, I need a home for this place. Would it be possible to have around 500mb space and 5GB Bandwidth with dev WHM access?

PM me if interested. I can have your banner on the homepage.
 
Also, would anyone be able to provide a free account, I need a home for this place. Would it be possible to have around 500mb space and 5GB Bandwidth with dev WHM access?

PM me if interested. I can have your banner on the homepage.

Jonny' I would be happy to sponsor this project.
Hook up with me. :)
 
I was going to use an old account but Dan, that's an offer I can't turn down. You got MSN?
 
6 Hard hours of straight development time have officially fried my mind. I've been working constantly on the ACP alone and managed to get its system up and running. Here's some screens. Keep in mind this is VERY early on in development. Most things may change:




As you can see really, I tried to go for the basic iPanel look, basic boxes, basic text but does the job. Like before it's easy to integrate with headers and footers, unlike cP Creator this doesn't work with wrappers. One thing that is noticeably different in the ACP is the addition of the sub side menu.
 
Last edited:
Sounds like a good project Johnny.

No one likes to see global used in OO programming, it's one of those things that causes errors later during development. To avoid this, you have a couple of options, I would say the best is to have a tht class, my suggested methods would be ...

PHP:
<?php
final class tht
{
	/**
	* @var		array
	* A SQL safe COPY of _REQUEST
	**/
	private 	$request 	= array( ) ;
	/**
	* @var		resource
	* MySQL connection
	**/
	private 	$mysql 		= null ;
	/**
	* @var		array
	* Internal errors
	**/
	private		$errors		= array( ) ;
	/**
	* @var		integer
	* Number of queries so far
	**/
	private		$count		= 0 ;
	/**
	* @param	array	configuration loaded from disk
	* Although methods/variables are static, __constructing allows
	* for population of the objects static member variables with useful data
	**/
	function __construct( &$config )
	{
		// Do whatever you normally would with request to make it sql safe
		if( $_REQUEST )
		{
			if( get_magic_quotes_gpc( ) )
			{
				self::$request = self::apply( $_REQUEST, 'stripslashes' );
			}
			else self::$request = $_REQUEST ;
			
			// now tht::request( 'key' ); will return _REQUEST['key'] SQL safe
		}
		// Connect to MySQL with config loaded from disk
		if( ( self::$mysql = mysql_connect( $config['hostname'], $config['username'], $config['password'] ) ) )
		{
			// Make sure we have the required database available
			if( mysql_select_db( $config['database'], self::$mysql ) )
			{
				// start filling other members with useful data
				// config was passed by reference, so you could be useful and fill it with configuration data
				// from the database, then you can keep passing this config array by reeference to other objects
				// used in execution
			}
			else self::error( __METHOD__, "Failed to select %s on %s, MySQL said: %s", __FILE__, __LINE__, $config['database'], $config['hostname'], mysql_error( self::$mysql ) );
		}
		else self::error( __METHOD__, "Failed to connect to %s as %s with password supplied, MySQL said: %s", __FILE__, __LINE__, $config['hostname'], $config['username'], mysql_error( ) );
	}
	/**
	* @param		array		the array to apply the callback too
	* @param		string		the name of the callback to apply to array
	* Recursively applies a callback to every member in an array and returns a COPY
	**/
	static function apply( $array, $callback = null )
	{
		$clean = array( );
		
		foreach( $array as $key => $value )
		{
			if( is_array( $value ) )
			{
				$clean[$key] = self::apply( $value, $callback );
			}
			else $clean[$key] = call_user_func( $callback, $value );
		}
		
		return $clean ;
	}
	/**
	* @param		string		the name of the member to fetch
	* If key is omitted return the whole request array ( for templates perhaps )
	**/
	static function request( $key = null )
	{
		switch( is_null( $key ) )
		{
			case true: 	return self::$request; break;
			case false: return self::$request[$key]; break;
		}
		return $key ;
	}
	/**
	* @param		string		method the error occured in
	* @param		string		message describing the error ( sprintf compatible )
	* @param		string		file the error occured in
	* @param		line		line the error occured in
	* @param		format		variable number of parameters to format message with ( see __construct )
	* Set an internal error, and format it too ...
	**/
	static function error( $method, $message, $file, $line, $format = null )
	{
		if( ( $format = func_get_args( ) ) )
		{
			if( ( $method = array_shift( $format ) ) )
			{
				if( ( $message = array_shift( $format ) ) )
				{
					if( ( $file = array_shift( $format ) ) )
					{
						if( ( $line = array_shift( $format ) ) )
						{
							return ( $this->errors[] = vsprintf
							( 
								"{$method}: {$message} in {$file} on line {$line}",
								$format
							) );
						}
					}
				}
			}
		}
	}
	/**
	* @param		boolean		delete errors where true and errors exist
	* Return all the formatted errors, optionally delete them before returning
	**/
	static function errors( $delete = false )
	{
		$errors = array( );
		
		if( count( self::$errors ) )
		{
			$errors = self::$errors ;
			
			switch( $delete )
			{
				case true: self::$errors = array( ); break;
			}
		}
		
		return $errors ;
	}
	/**
	* @param		string		the SQL to send
	* @param		mixed		variable length list of things to escape and format sql with
	* tht::query( "SELECT * FROM settings" );
	* tht::query( "SELECT * FROM table WHERE column = '%d'", tht::request('key') );
	* returns MySQL resource, sets errors and escapes anything after sql
	**/
	static function & query( $sql, $format = null )
	{
		if( self::$mysql )
		{
			if( ( $format = func_get_args( ) ) )
			{
				if( ( $sql = array_shift( $format ) ) )
				{
					$result = null ;
					
					if( $format )
					{
						foreach( $format as $key => $value )
						{
							if( $value )
							{
								$format[$key] = mysql_real_escape_string( $value, self::$mysql );
							}
						}
						
						if( !( $sql = vsprintf( $sql, $format ) ) )
						{
							return self::error( __METHOD__, "Failed to format SQL with %d parameters", __FILE__, __LINE__, count( $format ) );
						}
					}
					
					if( ( $result = mysql_query( $sql, self::$mysql ) ) )
					{
						self::$count++;
					}
					else self::error( __METHOD__, "Failed to execute query, MySQL said: %s", __FILE__, __LINE__, mysql_error( self::$mysql ) );
					
					return $result ;
				}
				else self::error( __METHOD__, "Method called improperly", __FILE__, __LINE__ );
			}
			else self::error( __METHOD__, "Method called improperly", __FILE__, __LINE__ );
		}
		else self::error( __METHOD__, "An attempt was made to execute SQL on an invalid connection", __FILE__, __LINE__ );
	}
	/**
	* @param	resource	MySQL result from tht::query
	* wrap of mysql_fetch_assoc for uniform code
	* don't try to error handle tht::next because while $x = tht::next($result)
	* will cause errors when there are none except no more results
	**/
	static function next( &$result )
	{
		if( $result )
		{
			return mysql_fetch_assoc( $result );
		}
	}
	/**
	* @param	resource	MySQL result from tht::query
	* wrap of mysql_fetch_assoc for uniform code
	* you could beef it up some with error handling on non-existent results etc
	**/
	static function field( &$result, $index = 0, $column = null )
	{
		if( $result )
		{
			return mysql_fetch_result( $result, $index, $column );
		}
	}
	/**
	* @param	tht|resource|null	what to count ??
	* tht::count( 'tht' ) = number of queries executed so far
	* tht::count( $result ) = number of rows contained by $result
	* tht::count( ) = number of rows affected by the execution of $result
	**/
	static function count( $what = null )
	{
		switch( $what )
		{
			case __CLASS__: return self::$count; break;
			case null; return mysql_affected_rows( self::$mysql ); break;
			default: return mysql_num_rows( $what ); break;
		}
	}
	/**
	* wrap of mysql_close for uniform code
	**/
	static function close( )
	{	
		if( self::$mysql )
		{
			@mysql_close( self::$mysql );
		}
		self::$mysql = null ;
	}
}
?>

This way all the objects you create like Server, Client, Admin, Plugins etc will all have static access to the database, to error reporting, to SQL safe user input and whatever else you include ... that code is not tested, I didn't even read it twice, but you can see where it's going though ...

Just a suggestion, good luck with the new project :)
 
Packages & Servers
One of the main parts for a hosting script is obviously the packages & servers. Without these, it wouldn't be a hosting script, just a normal purchasing form with no hook on the end. That's why I'm putting a lot of effort to make the package and servers part as functional, flexible and bug free as I can possible create.

In THT the packages work in a similar way as cP Creator with slight differences to the modules as they were in cP Creator. Now types. The types are called only in 4 areas. Order, Admin, Client, Cron. The areas you expect them to really. They have one function a peice. In order it's signup, so the script could check posts for example. In Admin it's the acpArea, this displays for example a users forum username and monthly posts. In client, it's the clientPage hooked with a two sidebar variables. In Cron, it's a call that checks monthly posts and suspends if low. Here's a screenshot of the add packages:


Servers look the same as the do in cP Creator but backend they're very different. Even though I'm only doing this for cPanel/WHM to start off with, the base for adding more control panels is there and fully functional. They're set up in the way types are set up. The class retrieves the server type then calls the function assigned to that server type. There's 4 functions: create, suspend, unsuspend, terminate.
 
Hey hey hey nice to see you back in the game!!!! If you need any help with anything let me know! WHM account I can spare :D but looks like Dan beat me to you ah lol
 
Back
Top