./paulOr

Eat bandwidth for breakfast!

Following on from yesterdays blog post regarding gauging cPanel disk space with Google Charts API, we will now replicate this to create the bandwidth meter.

To get the disk space usage, we run the accountsummary function and return all the data, this data includes near enough every specific peace of information you would need regarding an account - except for total/average uses... No idea why. I sort of see the point (multiple domains on 1 account) but we should atleast get an overall or an average reading in accountsummary.

Anyway, to get bandwidth readings, we do a similar query, this time using the showbw function.

$query = "https://127.0.0.1:2087/json-api/showbw?search=paulor&searchtype=user";


This will return a JSON feed containing all my main domain, subdomains, addon domains & parked domains, each with individual bandwidth usage, there is also a TOTAL bandwidth usage and a limit value. Its all pretty self explanitory, so ill just give you the code.

Click here for a demo of the bandwidth gauge.

<?php

	## WHM ROOT USER & HASH
	$whmusername = "root";
	$whmhash = "098A7SDF89AS07DF897ASDF987SD987VXZC897BV98Z7XCV8755
	06ZXC7V908Z7XC9V870X97ZC98V790Z7V9087CV907ZXC7V9ZCV9087ZX987V98
	077ZXCV7ZX8C7V897ZXC8V78ZX7VC87XZC87V89XZ7CV878X9ZC7V8XZ7CV897Z
	08X89CV789XZ7CV897ZXC8V789XCZ7V87ZXC8V798XZ7CV897XZC89V7ZX89C7V
	0989XZ7CV897XZC8V789ZX7VC89Z7XCV87Z89XC7V89Z7XCV8ZX7V987XZVCGFD";

	## THE QUERY TO THE API
	$query = "https://127.0.0.1:2087/json-api/showbw?search=paulor&searchtype=user";

	## CRAZY CURL STUFF TO AUTH AND RETURN DATA
	$curl = curl_init();
	curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,0);
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,0);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER,1);
	$header[0] = "Authorization: WHM $whmusername:" . preg_replace("'(\r|\n)'","",$whmhash);
	curl_setopt($curl,CURLOPT_HTTPHEADER,$header);
	curl_setopt($curl, CURLOPT_URL, $query);
	$result = curl_exec($curl);
	if ($result == false) {
		error_log("curl_exec threw error \"" . curl_error($curl) . "\" for $query");
	}
	curl_close($curl);

	## COVERT BYTES TO MEGABYTES
	function MBFormat($bytes,$decimals=1) {
		return round($bytes/(1024*1024));
	} 

	## DECODE JSON
	$obj = json_decode($result);

	## ROUND THE DIGITS
	$bw_limit = round(MBFormat($obj->bandwidth[0]->acct[0]->limit)); // LIMIT
	$bw_used = round(MBFormat($obj->bandwidth[0]->totalused)); // USED

	echo '<strong>Bandwidth Used:</strong> '.$bw_used.'MB<br />';
	echo '<strong>Bandwidth Limit:</strong> '.$bw_limit.'MB';

	## NOW JAVASCRIPT FROM GOOGLE CHARTS :]
?>

<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
	google.load('visualization', '1', {packages: ['gauge']});
</script>
<script type="text/javascript">
	var gauge;
	var gaugeData;
	var gaugeOptions;
	function drawGauge() {
		gaugeData = new google.visualization.DataTable();
		gaugeData.addColumn('number', 'B/W Usage');
		gaugeData.addRows(1);
		gaugeData.setCell(0, 0, <?php echo $bw_used; ?>);
		gauge = new google.visualization.Gauge(document.getElementById('gauge'));
		gaugeOptions = {
			min: 100,
			max: <?php echo $bw_limit; ?>,
			yellowFrom: <?php echo ($bw_limit-20000); ?>,
			yellowTo: <?php echo ($bw_limit-10000); ?>,
			redFrom: <?php echo ($bw_limit-10000); ?>,
			redTo: <?php echo ($bw_limit); ?>,
			minorTicks: 10
		};
		gauge.draw(gaugeData, gaugeOptions);
	}

	function changeTemp(dir) {
		gaugeData.setValue(0, 0, gaugeData.getValue(0, 0) + dir * 25);
		gauge.draw(gaugeData, gaugeOptions);
	}
	google.setOnLoadCallback(drawGauge);
</script>

<div id="gauge" style="width: 300px; height: 300px;"></div>


Click here for a demo of the bandwidth gauge.

Along time ago, I used to be cPanels #1 fan, after using alternative control panels, that quickly faded due to WHM/cPanels bulky nature. I recently came back to using cPanel, as its the industries #1 control panel & my clients adore it, now, I'm glad I gave it that all important second chance.

cPanel is adorable. Its hard & common exterior is found throughout the web, hundreds of thousands of web hosts use, millions of users interact with it each day. Because of this, the folk over at cPanel have created an amazing set of APIs, intelligently structured & a breeze to use.

cPanel has an absolutely stunning XML API, its simple, its fast & and opens doors to so much more. I introduce to you, my first (of many) cPanel related tutorial. Showing accounts disk usage, with Google Charts. Lets roll!

First of all, for this, you need WHM access, Ill post other user related examples soon, lets start off simple though :]. Login to WHM and go to Setup Remote Access Key. Once you have this massive hash read on.

Have a look at what we are making first of all :]

<?php

	## ROOT USERNAME AND ACCESS KEY
	$whmusername = "root";
	$whmhash = "098A7SDF89AS07DF897ASDF987SD987VXZC897BV98Z7XCV87
	ZXC7V908Z7XC9V870X97ZC98V790Z7V9087CV907ZXC7V9ZCV9087ZX987V98
	7ZXCV7ZX8C7V897ZXC8V78ZX7VC87XZC87V89XZ7CV878X9ZC7V8XZ7CV897Z
	X89CV789XZ7CV897ZXC8V789XCZ7V87ZXC8V798XZ7CV897XZC89V7ZX89C7V
	89XZ7CV897XZC8V789ZX7VC89Z7XCV87Z89XC7V89Z7XCV8ZX7V987XZVCGFD"; // ONLY AN EXAMPLE ;)

	## THE QUERY WE ARE SENDING TO THE SERVER
	$query = "https://127.0.0.1:2087/json-api/accountsummary?user=paulor";

	## CRAZY CURL STUFF TO AUTHENTICATE, CHECK FOR ERRORS AND
	## RETURN OUT JSON ENCODED DATA
	$curl = curl_init();
	curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,0);
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,0);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER,1);
	$header[0] = "Authorization: WHM $whmusername:" . preg_replace("'(\r|\n)'","",$whmhash);
	curl_setopt($curl,CURLOPT_HTTPHEADER,$header);
	curl_setopt($curl, CURLOPT_URL, $query);
	$result = curl_exec($curl);
	if ($result == false) {
		error_log("curl_exec threw error \"" . curl_error($curl) . "\" for $query");
	}
	curl_close($curl);

?>


What we are doing here is connecting to cPanels XMLAPI via cURL, authenticating with the server and then returning any errors, the $query string, is what we are pulling from cPanel, in this case, its near enough all the information that the account with the username 'paulor' has, such as: creation date, plans, disk space, suspended?, ftp accounts, sql accounts, email accounts etc etc etc, what it does lack however, for reasons still unknown to me, is bandwidth usage and limits. Thats a different query alltogether.

We query WHM with this query and it returns to us a lovely JSON feed.
<?php

	$obj = json_decode($result);
	$array = $obj->{'acct'};

	$space_used = str_replace('M', '', $array[0]->diskused);
	$space_avail = str_replace('M', '', $array[0]->disklimit);

?>


First we are decoding the JSON results and then putting the account details into an array, next, because we are making a disk space meter, we don't want the MB (or M in this case) to be attached to the end of the value, so we just chop that off with str_replace().

We are then going to use the Google Charts API to make our gauge and show the results.
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
	google.load('visualization', '1', {packages: ['gauge']});
</script>
<script type="text/javascript">
	var gauge;
	var gaugeData;
	var gaugeOptions;
	function drawGauge() {
		gaugeData = new google.visualization.DataTable();
		gaugeData.addColumn('number', 'Disk Usage');
		gaugeData.addRows(1);
		gaugeData.setCell(0, 0, <?php echo $space_used; ?>);
		gauge = new google.visualization.Gauge(document.getElementById('gauge'));
		gaugeOptions = {
			min: 100,
			max: <?php echo $space_avail; ?>,
			yellowFrom: 300,
			yellowTo: 400,
			redFrom: 400,
			redTo: 500,
			minorTicks: 10
		};
		gauge.draw(gaugeData, gaugeOptions);
	}

	function changeTemp(dir) {
		gaugeData.setValue(0, 0, gaugeData.getValue(0, 0) + dir * 25);
		gauge.draw(gaugeData, gaugeOptions);
	}

	google.setOnLoadCallback(drawGauge);
</script>


Now you can see we have inserted the $space_used & $space_avail variables into the javascript, this is bog standard Google Interactive Charts javascript which you can grab from their website, We then set a div for it to show in.
<div id="gauge" style="width: 300px; height: 300px;"></div>


And we have a very sexy gauge to show diskspace usage.

You can see a live example here.

Now, isn't that great? What other cPanel API related gizmos would you be interested in?

Capturing your visitors location is great for many reasons while building statistical software, its also good just to know where people are that are visiting your website. Heres a quick and dirty way for capturing location data.

Download the IP2Country CSV File unzip it and fire it into your FTP dir, we need to gather all the data out of it and stick it into a MySQL database.

SQL Table

CREATE TABLE `country_ip` (
  `ip_from` DOUBLE NOT NULL ,
  `ip_to` DOUBLE NOT NULL ,
  `country` VARCHAR( 50 ) NOT NULL
) ENGINE = MYISAM
Then we create the file that will import all the information.
<?php
$file_arr = file('ip-to-country.csv');
foreach($file_arr as $line){
	$clean_line = trim(str_replace('"', "'", str_replace("'", "\'", $line)));
	$sql = mysql_query("INSERT INTO `country_ip` (`ip_from`,`ip_to`,`country`) VALUES($clean_line)");
}
echo 'Finished :]';
>>


Once you have ran the above code, it should insert all the data into your mysql database, you can go ahead and delete the ip-to-country.csv file now.

Next all we are doing is querying the database to find out the current visitors location, you can then do whatever you like with the data.
<?php
$ip = ip2long($_SERVER['REMOTE_ADDR']);
$ipc_q = mysql_query("SELECT * FROM `country_ip` WHERE `ip_from` <= '".$ip."' AND `ip_to` >= '".$ip."'");
$ipc = mysql_fetch_array($ipc_q);
>>


When someone visits paulOr.net quite a lot of details are being put into the database regarding each visitor, for example, I work out if the user has been on in the past 24 hours (unique), capture the users IP address, each page visited, visitors country and time/date of visit. From this information, I have created some nice analytical apps in the backend of paulOr.net to feast my eyes upon.

Implementing Facebook Connect

Posted on Thu 20th May 2010 · Development · 2 Comments

I had quite a struggle getting Facebook Connect working here, mostly due to getting a PHP error which I didn't read before Googling, take it from me, save yourself 2 hours of crying & make sure you have curlSSL compiled on your server (or just ask your host).

The first thing to do is head over Facebook Developers site and set yourself up a new application, take note of your App ID and API Secret keys, then edit your application making sure to set your callback URLs.

You are pretty much ready to go after that, all we need to do now is connect the site to Facebook via the Facebook PHP-SDK written by nshah.

Download the SDK and unpack it, go into the src folder and take out facebook.php and pop it into your websites root dir.

Now lets start with the code. In your index.php file (or similar) put this code in the head.

<?php
require_once ('facebook.php');
$facebook = new Facebook(array(
	'appId'  => '<--- APP ID --->',
	'secret' => '<--- API SECRET --->',
	'cookie' => true,
));

$session = $facebook->getSession();

$me = null;
if ($session) {
	try {
		$uid = $facebook->getUser();
		$me = $facebook->api('/me');
	} catch (FacebookApiException $e) {
		error_log($e);
	}
}
?>
We then need some javascript in the (no idea why - else it wont work).
<script type="text/javascript">
	window.fbAsyncInit = function() {
		FB.init({
			appId   : '<?php echo $facebook->getAppId(); ?>',
			session : <?php echo json_encode($session); ?>,
			status  : true,
			cookie  : true,
			xfbml   : true
	});
	FB.Event.subscribe('auth.login', function() {
	window.location.reload();
	});
	};

	(function() {
		var e = document.createElement('script');
		e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
		e.async = true;
		document.getElementById('fb-root').appendChild(e);
	}());
</script>
And now we can start playing. The following code will show a Connect to Facebook button if the user is not logged in, or it will show the users name and profile picture if they are.
<?php
	if($me) {
		echo $me['name'].'<br />';
		echo '<img src="https://graph.facebook.com/'.$uid.'/picture" alt="Facebook" />';
	} else {
?>

	<fb:login-button v="2"><fb:intl>Connect with Facebook</fb:intl></fb:login-button>

<?php
	}
?>
And thats about it, you can take it from there and do some crazy stuff. All-in-all its pretty easy to do and is far better / quicker / more reliable than Twitters @anywhere.

To the top!