Source for file TeraWurflWebservice.php
Documentation is available at TeraWurflWebservice.php
* Tera_WURFL - PHP MySQL driven WURFL
* Tera-WURFL was written by Steve Kamerman, and is based on the
* Java WURFL Evolution package by Luca Passani and WURFL PHP Tools by Andrea Trassati.
* This version uses a MySQL database to store the entire WURFL file, multiple patch
* files, and a persistent caching mechanism to provide extreme performance increases.
* @author Steve Kamerman <stevekamerman AT gmail.com>
* @version Stable 2.1.3 $Date: 2010/09/18 15:43:21
* @license http://www.mozilla.org/MPL/ MPL Vesion 1.1
* The server-side Tera-WURFL webservice provider. Normally used with webservice.php
* Allow clients to query the webservice only from the listed networks. Setting this
* variable to false disables the filter and allows connections from ANY client IP.
* To allow only certain networks, put them in CIDR notation in an array. For example,
* to allow only the range 172.16.10.0/24 and the single IP 192.168.2.17 you would use
* public static $ALLOWED_CLIENT_IPS = array('172.16.10.0/24','192.168.2.17/32');
* NOTE: 127.0.0.1/32 is automatically allowed, however, some clients may use a different
* loopback address like 127.1.1.1. In this case, add 127.0.0.0/8 to your list.
* Unauthorized attempts to use this webservice are logged to the Tera-WURFL log file
* with a severity of LOG_WARNING.
public static $ALLOWED_CLIENT_IPS = false;
public static $FORMAT_XML = 'xml';
public static $FORMAT_JSON = 'json';
* Log all errors from the webservice
* The directory where the error log is stored. Set to null to use the Tera-WURFL data/ directory
* Log all access of the webservice
* The directory where the access log is stored. Set to null to use the Tera-WURFL data/ directory
public function __construct($userAgent,$searchPhrase,$data_format= 'xml',$teraWurflInstance= null){
$this->logError("Denied webservice access to client {$_SERVER['REMOTE_ADDR']}",LOG_WARNING);
echo "access is denied from ". $_SERVER['REMOTE_ADDR'];
* Get the response that would normally be sent to the client.
* @return String Response
* Send the HTTP Headers for the return data
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header("Content-Type: application/json");
header("Content-Type: text/xml");
* Send the complete response to the client, including the HTTP Headers and the response.
* See if a given ip ($ip) is in a given CIDR network ($cidr_range)
* @param String CIDR Network (e.g. "192.168.2.0/24")
* @param String IP Address
* @return Bool IP Address is in CIDR Network
// Thanks Bill Grady for posting a *working* IP in CIDR network function!
// Source: http://billgrady.com/wp/2009/05/21/ip-matching-with-cidr-notation-in-php/
// Get the base and the bits from the CIDR
list ($base, $bits) = explode('/', $cidr_network);
if($bits < 8 || $bits > 32){
throw new Exception("Error: Invalid CIDR mask specified.");
// Now split it up into it's classes
list ($a, $b, $c, $d) = explode('.', $base);
// Now do some bit shifting/switching to convert to ints
$i = ($a << 24) + ($b << 16) + ( $c << 8 ) + $d;
$mask = $bits == 0 ? 0: (~ 0 << (32 - $bits));
// Here's our highest int
$high = $i | (~ $mask & 0xFFFFFFFF);
// Now split the ip we're checking against up into classes
list ($a, $b, $c, $d) = explode('.', $ip);
// Now convert the ip we're checking against to an int
$check = ($a << 24) + ($b << 16) + ( $c << 8 ) + $d;
// If the ip is within the range, including highest/lowest values,
// then it's witin the CIDR range
if ($check >= $low && $check <= $high) return true;
* Is the connecting client allowed to use this webservice
if(!self::$ALLOWED_CLIENT_IPS || $_SERVER['REMOTE_ADDR'] == '127.0.0.1') return true;
$ip = $_SERVER['REMOTE_ADDR'];
foreach(self::$ALLOWED_CLIENT_IPS as $cidr_range){
if(self::ipInCIDRNetwork($cidr_range,$ip)) return true;
* Converts PHP variables to an XML friendly string
if(is_null($in) || !isset ($in))return '';
* Add an error to the errors array that will be sent in the response
* @param String Capability name that is in error
* @param String Description of the error
protected function addError($name,$desc){
if($this->enable_error_log) $this->logError("Client ". $_SERVER['REMOTE_ADDR']. " requested an invalid capability: $name",LOG_WARNING);
$this->out_errors[] = array('name'=> $name,'desc'=> $desc);
* Search through all the capabilities and place the requested ones in search_results to
* be sent in the response.
* @param String Search phrase (e.g. "is_wireless_device|streaming|tera_wurfl")
protected function search($searchPhrase){
if (!empty($searchPhrase)){
$capabilities = explode('|',$_REQUEST['search']);
foreach($capabilities as $cap){
foreach($this->wurflObj->capabilities[$cap] as $group_cap => $value){
$this->addError($cap,"The group or capability is not valid.");
* Flatten the multi-tiered capabilities array into a list of capabilities.
foreach($this->wurflObj->capabilities as $key => $value){
foreach($value as $subkey => $subvalue){
* Generate the XML response
$this->xml = '<?xml version="1.0" encoding="iso-8859-1"?>'. "\n";
$this->xml .= "<TeraWURFLQuery>\n";
$this->xml .= sprintf("\t". '<device apiVersion="%s" mtime="%s" useragent="%s" id="%s">'. "\n",
str_replace('&','&',$this->wurflObj->capabilities['user_agent']),
$this->xml .= "\t\t<capability name=\"$cap_name\" value=\"$value\"/>\n";
$this->xml .= "\t</device>\n";
$this->xml .= "</TeraWURFLQuery>";
'apiVersion' => $this->wurflObj->release_version,
'useragent' => $this->wurflObj->capabilities['user_agent'],
'id' => $this->wurflObj->capabilities['id'],
$this->json = json_encode($data);
* Generate the errors section of the XML response
* @return String XML errors section
$xml .= "\t\t<error name=\"{$error['name']}\" description=\"{$error['desc']}\"/>\n";
* Log this access with the IP of the requestor and the user agent
$_textToLog = sprintf('%s [%s %s][%s] %s',
@file_put_contents($logfile,$_textToLog,FILE_APPEND);
* Log an error in the TeraWurflWebservice log file
* @param String The error message text
` * @param Int The log level / severity of the error
* @param String The function or code that was being run when the error occured
protected function logError($text, $requestedLogLevel= LOG_NOTICE, $func= "TeraWurflWebservice"){
if($requestedLogLevel == LOG_ERR) $this->errors[] = $text;
if (TeraWurflConfig::$LOG_LEVEL == 0 || ($requestedLogLevel- 1) >= TeraWurflConfig::$LOG_LEVEL ) {
if ( $requestedLogLevel == LOG_ERR ) {
$warn_banner = 'ERROR: ';
} else if ( $requestedLogLevel == LOG_WARNING ) {
$warn_banner = 'WARNING: ';
@file_put_contents($logfile,$_textToLog,FILE_APPEND);
$this->logError($exception->getMessage(),LOG_ERR);
|