request_handler.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: request__handler_8php-source.html 675 2008-12-26 00:27:14Z gwoo $ */
00003 /**
00004  * Request object for handling alternative HTTP requests
00005  *
00006  * Alternative HTTP requests can come from wireless units like mobile phones, palmtop computers, and the like.
00007  * These units have no use for Ajax requests, and this Component can tell how Cake should respond to the different
00008  * needs of a handheld computer and a desktop machine.
00009  *
00010  * CakePHP(tm) :  Rapid Development Framework <http://www.cakephp.org/>
00011  * Copyright 2005-2008, Cake Software Foundation, Inc.
00012  *                              1785 E. Sahara Avenue, Suite 490-204
00013  *                              Las Vegas, Nevada 89104
00014  *
00015  * Licensed under The MIT License
00016  * Redistributions of files must retain the above copyright notice.
00017  *
00018  * @filesource
00019  * @copyright       Copyright 2005-2008, Cake Software Foundation, Inc.
00020  * @link                http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00021  * @package         cake
00022  * @subpackage      cake.cake.libs.controller.components
00023  * @since           CakePHP(tm) v 0.10.4.1076
00024  * @version         $Revision: 675 $
00025  * @modifiedby      $LastChangedBy: gwoo $
00026  * @lastmodified    $Date: 2008-12-25 16:27:14 -0800 (Thu, 25 Dec 2008) $
00027  * @license         http://www.opensource.org/licenses/mit-license.php The MIT License
00028  */
00029 if (!defined('REQUEST_MOBILE_UA')) {
00030     define('REQUEST_MOBILE_UA',
00031             '(AvantGo|BlackBerry|DoCoMo|NetFront|Nokia|PalmOS|PalmSource|portalmmm|Plucker|ReqwirelessWeb|SonyEricsson|Symbian|UP\.Browser|Windows CE|Xiino)');
00032 }
00033 /**
00034  * Request object for handling alternative HTTP requests
00035  *
00036  * @package     cake
00037  * @subpackage  cake.cake.libs.controller.components
00038  *
00039  */
00040 class RequestHandlerComponent extends Object{
00041 /**
00042  * Enter description here...
00043  *
00044  * @var object
00045  * @access public
00046  */
00047     var $controller = true;
00048 /**
00049  * The layout that will be switched to for Ajax requests
00050  *
00051  * @var string
00052  * @access public
00053  * @see RequestHandler::setAjax()
00054  */
00055     var $ajaxLayout = 'ajax';
00056 /**
00057  * Determines whether or not callbacks will be fired on this component
00058  *
00059  * @var boolean
00060  * @access public
00061  */
00062     var $disableStartup = false;
00063 /**
00064  * Friendly content-type mappings used to set response types and determine
00065  * request types.  Can be modified with RequestHandler::setContent()
00066  *
00067  * @var array
00068  * @access private
00069  * @see RequestHandlerComponent::setContent
00070  */
00071     var $__requestContent = array(
00072         'js' => 'text/javascript',
00073         'css'   => 'text/css',
00074         'html'  => 'text/html',
00075         'form'  => 'application/x-www-form-urlencoded',
00076         'file'  => 'multipart/form-data',
00077         'xhtml' => array('application/xhtml+xml', 'application/xhtml', 'text/xhtml'),
00078         'xml' => array('application/xml', 'text/xml'),
00079         'rss' => 'application/rss+xml',
00080         'atom' => 'application/atom+xml'
00081     );
00082 /**
00083  * Content-types accepted by the client.  If extension parsing is enabled in the
00084  * Router, and an extension is detected, the corresponding content-type will be
00085  * used as the overriding primary content-type accepted.
00086  *
00087  * @var array
00088  * @access private
00089  */
00090     var $__acceptTypes = array();
00091 /**
00092  * Constructor.  Parses the accepted content types accepted by the client using
00093  * HTTP_ACCEPT
00094  *
00095  * @access public
00096  * @return void
00097  */
00098     function __construct() {
00099         $this->__acceptTypes = explode(',', env('HTTP_ACCEPT'));
00100 
00101         foreach ($this->__acceptTypes as $i => $type) {
00102             if (strpos($type, ';')) {
00103                 $type = explode(';', $type);
00104                 $this->__acceptTypes[$i] = $type[0];
00105             }
00106         }
00107         parent::__construct();
00108     }
00109 /**
00110  * Startup
00111  *
00112  * @param object A reference to the controller
00113  * @return null
00114  * @access public
00115  */
00116     function startup(&$controller) {
00117         if ($this->disableStartup) {
00118             return;
00119         }
00120         $this->setAjax($controller);
00121     }
00122 /**
00123  * Sets a controller's layout based on whether or not the current call is Ajax
00124  *
00125  * Add UTF-8 header for IE6 on XPsp2 bug if RequestHandlerComponent::isAjax()
00126  *
00127  * @param object The controller object
00128  * @return null
00129  * @access public
00130  */
00131     function setAjax(&$controller) {
00132         if ($this->isAjax()) {
00133             $controller->layout = $this->ajaxLayout;
00134             // Add UTF-8 header for IE6 on XPsp2 bug
00135             header ('Content-Type: text/html; charset=UTF-8');
00136         }
00137     }
00138 /**
00139  * Returns true if the current call is from Ajax, false otherwise
00140  *
00141  * @return bool True if call is Ajax
00142  * @access public
00143  */
00144     function isAjax() {
00145         if (env('HTTP_X_REQUESTED_WITH') != null) {
00146             return env('HTTP_X_REQUESTED_WITH') == "XMLHttpRequest";
00147         } else {
00148             return false;
00149         }
00150     }
00151 /**
00152  * Returns true if the current call accepts an XML response, false otherwise
00153  *
00154  * @return bool True if client accepts an XML response
00155  * @access public
00156  */
00157     function isXml() {
00158         return $this->accepts('xml');
00159     }
00160 /**
00161  * Returns true if the current call accepts an RSS response, false otherwise
00162  *
00163  * @return bool True if client accepts an RSS response
00164  * @access public
00165  */
00166     function isRss() {
00167         return $this->accepts('rss');
00168     }
00169 /**
00170  * Returns true if the current call accepts an RSS response, false otherwise
00171  *
00172  * @return bool True if client accepts an RSS response
00173  * @access public
00174  */
00175     function isAtom() {
00176         return $this->accepts('atom');
00177     }
00178 /**
00179  * Returns true if the current call a POST request
00180  *
00181  * @return bool True if call is a POST
00182  * @access public
00183  */
00184     function isPost() {
00185         return (strtolower(env('REQUEST_METHOD')) == 'post');
00186     }
00187 /**
00188  * Returns true if the current call a PUT request
00189  *
00190  * @return bool True if call is a PUT
00191  * @access public
00192  */
00193     function isPut() {
00194         return (strtolower(env('REQUEST_METHOD')) == 'put');
00195     }
00196 /**
00197  * Returns true if the current call a GET request
00198  *
00199  * @return bool True if call is a GET
00200  * @access public
00201  */
00202     function isGet() {
00203         return (strtolower(env('REQUEST_METHOD')) == 'get');
00204     }
00205 /**
00206  * Returns true if the current call a DELETE request
00207  *
00208  * @return bool True if call is a DELETE
00209  * @access public
00210  */
00211     function isDelete() {
00212         return (strtolower(env('REQUEST_METHOD')) == 'delete');
00213     }
00214 /**
00215  * Gets Prototype version if call is Ajax, otherwise empty string.
00216  * The Prototype library sets a special "Prototype version" HTTP header.
00217  *
00218  * @return string Prototype version of component making Ajax call
00219  * @access public
00220  */
00221     function getAjaxVersion() {
00222         if (env('HTTP_X_PROTOTYPE_VERSION') != null) {
00223             return env('HTTP_X_PROTOTYPE_VERSION');
00224         }
00225         return false;
00226     }
00227 /**
00228  * Adds/sets the Content-type(s) for the given name
00229  *
00230  * @param string $name The name of the Content-type, i.e. "html", "xml", "css"
00231  * @param mixed $type The Content-type or array of Content-types assigned to the name
00232  * @return void
00233  * @access public
00234  */
00235     function setContent($name, $type) {
00236         $this->__requestContent[$name] = $type;
00237     }
00238 /**
00239  * Gets the server name from which this request was referred
00240  *
00241  * @return string Server address
00242  * @access public
00243  */
00244     function getReferrer() {
00245         if (env('HTTP_HOST') != null) {
00246             $sess_host = env('HTTP_HOST');
00247         }
00248 
00249         if (env('HTTP_X_FORWARDED_HOST') != null) {
00250             $sess_host = env('HTTP_X_FORWARDED_HOST');
00251         }
00252         return trim(preg_replace('/:.*/', '', $sess_host));
00253     }
00254 /**
00255  * Gets remote client IP
00256  *
00257  * @return string Client IP address
00258  * @access public
00259  */
00260     function getClientIP() {
00261         if (env('HTTP_X_FORWARDED_FOR') != null) {
00262             $ipaddr = preg_replace('/,.*/', '', env('HTTP_X_FORWARDED_FOR'));
00263         } else {
00264             if (env('HTTP_CLIENT_IP') != null) {
00265                 $ipaddr = env('HTTP_CLIENT_IP');
00266             } else {
00267                 $ipaddr = env('REMOTE_ADDR');
00268             }
00269         }
00270 
00271         if (env('HTTP_CLIENTADDRESS') != null) {
00272             $tmpipaddr = env('HTTP_CLIENTADDRESS');
00273 
00274             if (!empty($tmpipaddr)) {
00275                 $ipaddr = preg_replace('/,.*/', '', $tmpipaddr);
00276             }
00277         }
00278         return trim($ipaddr);
00279     }
00280 /**
00281  * Returns true if user agent string matches a mobile web browser
00282  *
00283  * @return bool True if user agent is a mobile web browser
00284  * @access public
00285  */
00286     function isMobile() {
00287         return (preg_match('/' . REQUEST_MOBILE_UA . '/i', env('HTTP_USER_AGENT')) > 0);
00288     }
00289 /**
00290  * Strips extra whitespace from output
00291  *
00292  * @param string $str
00293  * @return string
00294  * @access public
00295  */
00296     function stripWhitespace($str) {
00297         $r = preg_replace('/[\n\r\t]+/', '', $str);
00298         return preg_replace('/\s{2,}/', ' ', $r);
00299     }
00300 /**
00301  * Strips image tags from output
00302  *
00303  * @param string $str
00304  * @return string
00305  * @access public
00306  */
00307     function stripImages($str) {
00308         $str = preg_replace('/(<a[^>]*>)(<img[^>]+alt=")([^"]*)("[^>]*>)(<\/a>)/i', '$1$3$5<br />', $str);
00309         $str = preg_replace('/(<img[^>]+alt=")([^"]*)("[^>]*>)/i', '$2<br />', $str);
00310         $str = preg_replace('/<img[^>]*>/i', '', $str);
00311         return $str;
00312     }
00313 /**
00314  * Strips scripts and stylesheets from output
00315  *
00316  * @param string $str
00317  * @return string
00318  * @access public
00319  */
00320     function stripScripts($str) {
00321         return preg_replace('/(<link[^>]+rel="[^"]*stylesheet"[^>]*>|<img[^>]*>|style="[^"]*")|<script[^>]*>.*?<\/script>|<style[^>]*>.*?<\/style>|<!--.*?-->/i', '', $str);
00322     }
00323 /**
00324  * Strips extra whitespace, images, scripts and stylesheets from output
00325  *
00326  * @param string $str
00327  * @return string
00328  * @access public
00329  */
00330     function stripAll($str) {
00331         $str = $this->stripWhitespace($str);
00332         $str = $this->stripImages($str);
00333         $str = $this->stripScripts($str);
00334         return $str;
00335     }
00336 /**
00337  * Strips the specified tags from output
00338  *
00339  * @return string
00340  * @access public
00341  */
00342     function stripTags() {
00343         $params = params(func_get_args());
00344         $str = $params[0];
00345 
00346         for ($i = 1; $i < count($params); $i++) {
00347             $str = preg_replace('/<' . $params[$i] . '[^>]*>/i', '', $str);
00348             $str = preg_replace('/<\/' . $params[$i] . '[^>]*>/i', '', $str);
00349         }
00350         return $str;
00351     }
00352 
00353 /**
00354  * Determines which content types the client accepts
00355  *
00356  * @param mixed $type Can be null (or no parameter), a string type name, or an
00357  *                  array of types
00358  * @return mixed If null or no parameter is passed, returns an array of content
00359  *              types the client accepts.  If a string is passed, returns true
00360  *              if the client accepts it.  If an array is passed, returns true
00361  *              if the client accepts one or more elements in the array.
00362  * @access public
00363  */
00364     function accepts($type = null) {
00365         if ($type == null) {
00366             return $this->__acceptTypes;
00367         } elseif (is_array($type)) {
00368             foreach ($type as $t) {
00369                 if ($this->accepts($t) == true) {
00370                     return true;
00371                 }
00372             }
00373             return false;
00374         } elseif (is_string($type)) {
00375             // If client only accepts */*, then assume default HTML browser
00376             if ($type == 'html' && $this->__acceptTypes === array('*/*')) {
00377                 return true;
00378             }
00379 
00380             if (!in_array($type, array_keys($this->__requestContent))) {
00381                 return false;
00382             }
00383 
00384             $content = $this->__requestContent[$type];
00385 
00386             if (is_array($content)) {
00387                 foreach ($content as $c) {
00388                     if (in_array($c, $this->__acceptTypes)) {
00389                         return true;
00390                     }
00391                 }
00392             } else {
00393                 if (in_array($content, $this->__acceptTypes)) {
00394                     return true;
00395                 }
00396             }
00397         }
00398     }
00399 /**
00400  * Determines which content types the client prefers
00401  *
00402  * @param mixed $type
00403  * @returns mixed
00404  * @access public
00405  */
00406     function prefers($type = null) {
00407         if ($type == null) {
00408             return $this->accepts(null);
00409         }
00410     }
00411 }
00412 ?>