Please critique away.
Code: Select all
<?php
/**
* Padlock - The PHP Application Developers Library and Opensource Code Kit
*
* @author Robert Gonzalez <robert@everah.com>
* @package Padlock
* @copyright None
* @license Creative Commons Attribution License 3.0 {@link http://creativecommons.org/licenses/by/3.0/}
*/
/**
* Padlock_Client_Profile is used to gather information about the client.
*
* This class gathers information about the client, such as the users browser,
* operating system and IP. Much of this information is broken down cleanly
* into smaller bits that can be used to build larger bits. A lot of it can be
* used for analysis as well.
*
* The two most significant parts of this class code were derived from phpSniff
* developed by Roger Raymond <epsilon7@users.sourceforge.net>. Those parts are
* the regular expression usage for snagging the users browser and operating
* system. The browser array was also borrowed from phpSniff.
*
* ----------------------------------------------------------------------------
*
* Usage:
* <code>
* The easiest way to use the class is to instantiate it:
* $client = new Padlock_Client_Profile();
* $client_details = $client->get_details();
* This will give you all of the details set by the class that were
* fetched from the client.
*
* To get a brief output of the clients browser and OS you can use the display() method:
* $client->display('<p>', '</p>', ' ');
* This will echo out a single line of text along the lines of:
* Browser: Mozilla Firefox 2.0.0.3 Operating System: Windows XP
*
* The display() method takes three params: opentag, closetag, separator
* </code>
* @version 0.1
* @package Padlock_Client_Profile
* @copyright None
* @license Creative Commons Attribution License 3.0 {@link http://creativecommons.org/licenses/by/3.0/}
* @author Robert Gonzalez <robert@everah.com>
*/
class Padlock_Client_Profile
{
/**
* Array to hold all user profile details
*
* @var array
* @access private
*/
private $details = array();
/**
* Array of browsers
*
* @author Roger Raymond <epsilon7@users.sourceforge.net>
* @access private
* @var array
*/
private $browser_list = array(
'microsoft internet explorer' => 'IE',
'msie' => 'IE',
'netscape6' => 'NS',
'netscape' => 'NS',
'galeon' => 'GA',
'phoenix' => 'PX',
'mozilla firebird' => 'FB',
'firebird' => 'FB',
'firefox' => 'FX',
'chimera' => 'CH',
'camino' => 'CA',
'epiphany' => 'EP',
'safari' => 'SF',
'k-meleon' => 'KM',
'mozilla' => 'MZ',
'opera' => 'OP',
'konqueror' => 'KQ',
'icab' => 'IC',
'lynx' => 'LX',
'links' => 'LI',
'ncsa mosaic' => 'MO',
'amaya' => 'AM',
'omniweb' => 'OW',
'hotjava' => 'HJ',
'browsex' => 'BX',
'amigavoyager' => 'AV',
'amiga-aweb' => 'AW',
'ibrowse' => 'IB'
);
/**
* Class constructor
*
* @access public
* @param boolean $echo True displays on construction
*/
public function __construct($echo = false)
{
// Fetch boy, fetch. Good dog. Sit Ubu.
$this->initialize();
// Should we display immediately?
if ($echo)
{
$this->display();
}
}
/**
* Initialze class data
*
* @access private
*/
private function initialize()
{
$this->set_useragent();
$this->set_os();
$this->set_browser();
$this->set_ip();
}
/**
* Output what we know in a clean little outputter
*
* @access public
* @param string $opentag The HTML tag to use to open the string
* @param string $closetag The HTML tag to use to close the string
* @param string $separator The HTML tag to use to separate the browser from OS in the string
* @return void Outputs a report of the browser stats or an error message if there is a problem
*/
public function display($opentag = '', $closetag = '', $separator = ' ')
{
if (isset($this->details['useragent']))
{
echo $opentag . 'Browser: ' . $this->get_browser() . $separator . 'Operating System: ' . $this->get_platform() . $closetag;
}
else
{
// This is literally the only place there would be an error to report
echo 'We were unable to detect your browser and operating system';
}
}
/**
* Adds an entry into the details array
*
* @access private
* @param string $token The name of the item we are adding
* @param string $value The value of the item we are adding
*/
private function add_detail($token, $value)
{
if (!isset($this->details[$token]))
{
$this->details[$token] = $value;
}
}
/**
* Sets the users complete user agent string
*
* @access private
* @return string The users user agent on success, boolean false on failure
*/
private function set_useragent()
{
$useragent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : getenv('HTTP_USER_AGENT');
if ($useragent === false)
{
throw new Exception('The user agent could not be fetched.');
}
$this->add_detail('useragent', $useragent);
}
/**
* Sets the IP property
*
* @author Robert Gonzalez <robert@everah.com>
* @access private
*/
private function set_ip()
{
$this->add_detail('client_ip', $this->get_ip_address());
}
/**
* Sets browser information
*
* @author Roger Raymond <epsilon7@users.sourceforge.net>
* @author Robert Gonzalez <robert@everah.com>
* @access private
* @return string browser name and version or false if unrecognized
*/
private function set_browser()
{
$browser_regex = $this->get_browser_regex_string();
$browser_name = 'Unknown';
$browser_abbreviation = 'Unknown';
$browser_major_version = 'Unknown';
$browser_minor_version = 'Unknown';
$browser_letter_version = null;
$browser_full_version = 'Unknown';
$browser_complete_name = 'Unknown';
if (preg_match_all($browser_regex, $this->details['useragent'], $results))
{
// get the position of the last browser found
$count = count($results[0])-1;
// Browser name
$browser_name = $results[1][$count];
// Major version
$browser_major_version = $results[2][$count];
// insert findings into the container
$browser_abbreviation = strtolower($results[1][$count]);
// parse the minor version string and look for alpha chars
preg_match('/([.\0-9]+)?([\.a-z0-9]+)?/i', $results[3][$count], $match);
// Minor version handling
$minor_version = isset($match[1]) ? $match[1] : '.0';
// Letter version handling
if (isset($match[2]))
{
$browser_letter_version = $match[2];
}
// Create the necessary detail values
$this->add_detail('browser_name', $browser_name);
$this->add_detail('browser_major_version', $browser_major_version);
$this->add_detail('browser_minor_version', $minor_version);
$this->add_detail('browser_full_version', $this->details['browser_major_version'].$this->details['browser_minor_version']);
$this->add_detail('browser_full_name', $this->details['browser_name']. ' ' . $this->details['browser_full_version']);
$this->add_detail('browser_abbreviation', $this->browser_list[$browser_abbreviation]);
// Handle the registration of the letter version
if (!is_null($browser_letter_version))
{
$this->add_detail('browser_letter_version', $browser_letter_version);
}
}
}
/**
* Sets operating system and platform details
*
* @author Roger Raymond <epsilon7@users.sourceforge.net>
* @access private
* @return string os name and version or false in unrecognized os
*/
private function set_os()
{
// regexes to use
$regex_windows = '/([^dar]win[dows]*)[\s]?([0-9a-z]*)[\w\s]?([a-z0-9.]*)/i';
$regex_mac = '/(68[k0]{1,3})|(ppc mac os x)|([p\S]{1,5}pc)|(darwin)/i';
$regex_os2 = '/os\/2|ibm-webexplorer/i';
$regex_sunos = '/(sun|i86)[os\s]*([0-9]*)/i';
$regex_irix = '/(irix)[\s]*([0-9]*)/i';
$regex_hpux = '/(hp-ux)[\s]*([0-9]*)/i';
$regex_aix = '/aix([0-9]*)/i';
$regex_dec = '/dec|osfl|alphaserver|ultrix|alphastation/i';
$regex_vms = '/vax|openvms/i';
$regex_sco = '/sco|unix_sv/i';
$regex_linux = '/x11|inux/i';
$regex_bsd = '/(free)?(bsd)/i';
$regex_amiga = '/amiga[os]?/i';
$client_platform = 'Unknown';
$client_os = 'Unknown';
// look for Windows Box
if (preg_match_all($regex_windows, $this->details['useragent'], $match))
{
/** Windows has some of the most ridiculous HTTP_USER_AGENT strings */
//$match[1][count($match[0])-1];
$v = $match[2][count($match[0])-1];
$v2 = $match[3][count($match[0])-1];
// Establish NT 5.1 as Windows XP
if (stristr($v,'NT') && $v2 == 5.1)
{
$v = 'XP';
}
// Establish NT 5.0 and Windows 2000 as win2k
elseif ($v == '2000')
{
$v = '2000';
}
elseif (stristr($v, 'NT') && $v2 == 5.0)
{
$v = '2000';
}
// Establish 9x 4.90 as Windows 98
elseif (stristr($v, '9x') && $v2 == 4.9)
{
$v = '98';
}
// See if we're running windows 3.1
elseif ($v.$v2 == '16bit')
{
$v = '3.1';
}
// otherwise display as is (31,95,98,NT,ME,XP)
else
{
$v .= $v2;
}
// update browser info container array
if (empty($v))
{
$v = 'Windows';
}
$client_os = $v;
$client_platform = 'Windows';
}
// look for amiga OS
elseif (preg_match($regex_amiga, $this->details['useragent'], $match))
{
$client_platform = 'Amiga';
if (stristr($this->details['useragent'], 'morphos'))
{
// checking for MorphOS
$client_os = 'MorphOS';
}
elseif (stristr($this->details['useragent'], 'mc680x0'))
{
// checking for MC680x0
$client_os = 'MC680x0';
}
elseif (stristr($this->details['useragent'], 'ppc'))
{
// checking for PPC
$client_os = 'PPC';
}
elseif (preg_match('/(AmigaOS [\.1-9]?)/i', $this->details['useragent'], $match))
{
// checking for AmigaOS version string
$client_os = $match[1];
}
}
// look for OS2
elseif (preg_match($regex_os2, $this->details['useragent']))
{
$client_os = 'OS2';
$client_platform = 'OS2';
}
// look for mac
// sets: platform = mac ; os = 68k or ppc
elseif (preg_match($regex_mac, $this->details['useragent'], $match))
{
$client_platform = 'Mac';
$os = !empty($match[1]) ? '68K' : '';
$os = !empty($match[2]) ? 'OSX' : $os;
$os = !empty($match[3]) ? 'PPC' : $os;
$os = !empty($match[4]) ? 'OSX' : $os;
$client_os = $os;
}
// look for *nix boxes
// sunos sets: platform = *nix ; os = sun|sun4|sun5|suni86
elseif (preg_match($regex_sunos, $this->details['useragent'], $match))
{
$client_platform = '*nix';
if (!stristr('sun', $match[1]))
{
$match[1] = 'Sun'.$match[1];
}
$client_os = $match[1].$match[2];
}
// irix sets: platform = *nix ; os = irix|irix5|irix6|...
elseif (preg_match($regex_irix, $this->details['useragent'], $match))
{
$client_platform = '*nix';
$client_os = $match[1].$match[2];
}
// hp-ux sets: platform = *nix ; os = hpux9|hpux10|...
elseif (preg_match($regex_hpux, $this->details['useragent'], $match))
{
$client_platform = '*nix';
$match[1] = str_replace('-', '', $match[1]);
$match[2] = (int) $match[2];
$client_os = $match[1].$match[2];
}
// aix sets: platform = *nix ; os = aix|aix1|aix2|aix3|...
elseif (preg_match($regex_aix, $this->details['useragent'], $match))
{
$client_platform = '*nix';
$client_os = 'aix'.$match[1];
}
// dec sets: platform = *nix ; os = dec
elseif (preg_match($regex_dec, $this->details['useragent'], $match))
{
$client_platform = '*nix';
$client_os = 'dec';
}
// vms sets: platform = *nix ; os = vms
elseif (preg_match($regex_vms, $this->details['useragent'], $match))
{
$client_platform = '*nix';
$client_os = 'vms';
}
// sco sets: platform = *nix ; os = sco
elseif (preg_match($regex_sco, $this->details['useragent'], $match))
{
$client_platform = '*nix';
$client_os = 'SCO';
}
// unixware sets: platform = *nix ; os = unixware
elseif (stristr($this->details['useragent'], 'unix_system_v'))
{
$client_platform = '*nix';
$client_os = 'Unixware';
}
// mpras sets: platform = *nix ; os = mpras
elseif (stristr($this->details['useragent'], 'ncr'))
{
$client_platform = '*nix';
$client_os = 'Mpras';
}
// reliant sets: platform = *nix ; os = reliant
elseif (stristr($this->details['useragent'], 'reliantunix'))
{
$client_platform = '*nix';
$client_os = 'Reliant';
}
// sinix sets: platform = *nix ; os = sinix
elseif (stristr($this->details['useragent'], 'sinix'))
{
$client_platform = '*nix';
$client_os = 'Sinix';
}
// bsd sets: platform = *nix ; os = bsd|freebsd
elseif (preg_match($regex_bsd, $this->details['useragent'], $match))
{
$client_platform = '*nix';
$client_os = $match[1].$match[2];
}
// last one to look for
// linux sets: platform = *nix ; os = linux
elseif (preg_match($regex_linux, $this->details['useragent'], $match))
{
$client_platform = '*nix';
$client_os = 'Linux';
}
$this->add_detail('client_platform', $client_platform);
$this->add_detail('client_os', $client_os);
}
/**
* This simply sets a regular expression string to use for browser comparison
*
* @author Roger Raymond <epsilon7@users.sourceforge.net>
* @access private
* @return string A regular expression string
*/
private function get_browser_regex_string()
{
$browsers = '';
while (list($k,) = each($this->browser_list))
{
if (!empty($browsers))
{
$browsers .= '|';
}
$browsers .= $k;
}
$version_string = '[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?';
return "/($browsers)$version_string/i";
}
/**
* Get the users IP address
*
* @access private
* @return string IP Address of the user
*/
private function get_ip_address()
{
return getenv('HTTP_CLIENT_IP') ? getenv('HTTP_CLIENT_IP') : getenv('REMOTE_ADDR');
}
/**
* Gets the users browser information
*
* @access public
* @return string The users browser
*/
public function get_browser()
{
return $this->get_detail('browser_full_name');
}
/**
* Gets the users complete user agent information
*
* @access public
* @return string The users browser
*/
public function get_useragent()
{
return $this->get_detail('useragent');
}
/**
* Gets the users operating system
*
* @access public
* @return string The users operating system
*/
public function get_os()
{
return $this->get_detail('client_os');
}
/**
* Gets the users operating system environment
*
* @access public
* @return string The users platform and operating system
*/
public function get_platform()
{
return $this->get_detail('client_platform') . ' ' . $this->get_detail('client_os');
}
/**
* Gets the users IP Address
*
* @access public
* @return string The users IP Address
*/
public function get_ip()
{
return $this->get_detail('client_ip');
}
/**
* Gets the detail requested
*
* @access public
* @return string A detail entry if it exists, false otherwise
*/
public function get_detail($detail)
{
if ($detail == 'all')
{
return $this->details;
}
else
{
return $this->has_detail($detail) ? $this->details[$detail] : 'Detail not found';
}
}
/**
* Gets all client details
*
* @access public
* @return array An array of all information fetched from the client
*/
public function get_details()
{
return $this->details;
}
/**
* Checks whether a detail is available or not
*
* @access private
* @return boolean True if the detail exists, false otherwise
*/
private function has_detail($detail)
{
return isset($this->details[$detail]);
}
}
?>Code: Select all
<?php
// Include the class
require_once 'utility.clientprofile.php';
// Instantiate it
$client = new Padlock_Client_Profile();
var_dump($client->get_details());
/**
* Will output something similar to:
* array(10) {
* ["useragent"]=>
* string(90) "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3"
* ["client_platform"]=>
* string(7) "Windows"
* ["client_os"]=>
* string(2) "XP"
* ["browser_name"]=>
* string(7) "Firefox"
* ["browser_major_version"]=>
* string(1) "2"
* ["browser_minor_version"]=>
* string(6) ".0.0.3"
* ["browser_full_version"]=>
* string(7) "2.0.0.3"
* ["browser_full_name"]=>
* string(15) "Firefox 2.0.0.3"
* ["browser_abbreviation"]=>
* string(2) "FX"
* ["client_ip"]=>
* string(9) "127.0.0.1"
* }
*/
echo 'The users IP is ' . $client->get_detail('client_ip');
// Or you could use $client->get_ip();
/**
* Outputs something like:
* The users IP is 127.0.0.1
*/
echo 'The client is on ' . $client->get_platform();
/**
* Outputs something like:
* The client is on Windows XP
*/
$client->display('<p>', '</p>', ' ');
/**
* Outputs something like:
* <p>Browser: Firefox 2.0.0.3 Operating System: Windows XP</p>
*/
?>