[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/se3-wpkg/sources/www/inc/ -> http-conditional.php (source)

   1  <?php
   2  /*
   3   Enable support for HTTP/1.x conditional requests in PHP.
   4   Goal: Optimisation
   5   - If the client sends a HEAD request, avoid transferring data and return the correct headers.
   6   - If the client already has the same version in its cache, avoid transferring data again (304 Not Modified).
   7   - Possibility to control cache for client and proxies (public or private policy, life time).
   8   - When $feedMode is set to true, in the case of a RSS/ATOM feed,
   9     it puts a timestamp in the global variable $clientCacheDate to allow the sending of only the articles newer than the client's cache.
  10   - When $compression is set to true, compress the data before sending it to the client and persitent connections are allowed.
  11   - When $session is set to true, automatically checks if $_SESSION has been modified during the last generation the document.
  12  
  13   Interface:
  14   - function httpConditional($UnixTimeStamp,$cacheSeconds=0,$cachePrivacy=0,$feedMode=false,$compression=false)
  15    [Required] $UnixTimeStamp: Date of the last modification of the data to send to the client (Unix Timestamp format).
  16    [Implied] $cacheSeconds=0: Lifetime in seconds of the document. If $cacheSeconds>0, the document will be cashed and not revalidated against the server for this delay.
  17    [Implied] $cachePrivacy=0: 0=private, 1=normal (public), 2=forced public. When public, it allows a cashed document ($cacheSeconds>0) to be shared by several users.
  18    [Implied] $feedMode=false: Special RSS/ATOM feeds. When true, it sets $cachePrivacy to 0 (private), does not use the modification time of the script itself, and puts the date of the client's cache (or a old date from 1980) in the global variable $clientCacheDate.
  19    [implied] $compression=false: Enable the compression and allows persistant connections (automatic detection of the capacities of the client).
  20    [implied] $session=false: To be turned on when sessions are used. Checks if the data contained in $_SESSION has been modified during the last generation the document.
  21    Returns: True if the connection can be closed (e.g.: the client has already the lastest version), false if the new content has to be send to the client.
  22  
  23   Typical use:
  24   <?php
  25    require_once('http-conditional.php');
  26    //Date of the last modification of the content (Unix Timestamp format).
  27    //Examples: query the database, or last modification of a static file.
  28    $dateLastModification=...;
  29    if (httpConditional($dateLastModification))
  30    {
  31     ... //Close database connections, and other cleaning.
  32     exit(); //No need to send anything
  33    }
  34    //Do not send any text to the client before this line.
  35    ... //Rest of the script, just as you would do normally.
  36   ?>
  37  
  38   Version 1.6.2 beta, 2006-03-03, http://alexandre.alapetite.net/doc-alex/php-http-304/
  39  
  40   ------------------------------------------------------------------
  41   Written by Alexandre Alapetite, http://alexandre.alapetite.net/cv/
  42  
  43   Copyright 2004-2005, Licence: Creative Commons "Attribution-ShareAlike 2.0 France" BY-SA (FR),
  44   http://creativecommons.org/licenses/by-sa/2.0/fr/
  45   http://alexandre.alapetite.net/divers/apropos/#by-sa
  46   - Attribution. You must give the original author credit
  47   - Share Alike. If you alter, transform, or build upon this work,
  48     you may distribute the resulting work only under a license identical to this one
  49     (Can be included in GPL/LGPL projects)
  50   - The French law is authoritative
  51   - Any of these conditions can be waived if you get permission from Alexandre Alapetite
  52   - Please send to Alexandre Alapetite the modifications you make,
  53     in order to improve this file for the benefit of everybody
  54  
  55   If you want to distribute this code, please do it as a link to:
  56   http://alexandre.alapetite.net/doc-alex/php-http-304/
  57  */
  58  
  59  //In RSS/ATOM feedMode, contains the date of the clients last update.
  60  $clientCacheDate=0; //Global public variable because PHP4 does not allow conditional arguments by reference
  61  $_sessionMode=false; //Global private variable
  62  
  63  function httpConditional($UnixTimeStamp,$cacheSeconds=0,$cachePrivacy=0,$feedMode=false,$compression=false,$session=false)
  64  {//Credits: http://alexandre.alapetite.net/doc-alex/php-http-304/
  65   //RFC2616 HTTP/1.1: http://www.w3.org/Protocols/rfc2616/rfc2616.html
  66   //RFC1945 HTTP/1.0: http://www.w3.org/Protocols/rfc1945/rfc1945.txt
  67  
  68   if (headers_sent()) return false;
  69  
  70   if (isset($_SERVER['SCRIPT_FILENAME'])) $scriptName=$_SERVER['SCRIPT_FILENAME'];
  71   elseif (isset($_SERVER['PATH_TRANSLATED'])) $scriptName=$_SERVER['PATH_TRANSLATED'];
  72   else return false;
  73  
  74   if ((!$feedMode)&&(($modifScript=filemtime($scriptName))>$UnixTimeStamp))
  75    $UnixTimeStamp=$modifScript;
  76   $UnixTimeStamp=min($UnixTimeStamp,time());
  77   $is304=true;
  78   $is412=false;
  79   $nbCond=0;
  80  
  81   //rfc2616-sec3.html#sec3.3.1
  82   $dateLastModif=gmdate('D, d M Y H:i:s \G\M\T',$UnixTimeStamp);
  83   $dateCacheClient='Thu, 10 Jan 1980 20:30:40 GMT';
  84  
  85   //rfc2616-sec14.html#sec14.19 //='"0123456789abcdef0123456789abcdef"'
  86   if (isset($_SERVER['QUERY_STRING'])) $myQuery='?'.$_SERVER['QUERY_STRING'];
  87   else $myQuery='';
  88   if ($session&&isset($_SESSION))
  89   {
  90    global $_sessionMode;
  91    $_sessionMode=$session;
  92    $myQuery.=print_r($_SESSION,true).session_name().'='.session_id();
  93   }
  94   $etagServer='"'.md5($scriptName.$myQuery.'#'.$dateLastModif).'"';
  95  
  96   if ((!$is412)&&isset($_SERVER['HTTP_IF_MATCH']))
  97   {//rfc2616-sec14.html#sec14.24
  98    $etagsClient=stripslashes($_SERVER['HTTP_IF_MATCH']);
  99    $is412=(($etagClient!='*')&&(strpos($etagsClient,$etagServer)===false));
 100   }
 101   if ($is304&&isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
 102   {//rfc2616-sec14.html#sec14.25 //rfc1945.txt
 103    $nbCond++;
 104    $dateCacheClient=$_SERVER['HTTP_IF_MODIFIED_SINCE'];
 105    $p=strpos($dateCacheClient,';');
 106    if ($p!==false)
 107     $dateCacheClient=substr($dateCacheClient,0,$p);
 108    $is304=($dateCacheClient==$dateLastModif);
 109   }
 110   if ($is304&&isset($_SERVER['HTTP_IF_NONE_MATCH']))
 111   {//rfc2616-sec14.html#sec14.26
 112    $nbCond++;
 113    $etagClient=stripslashes($_SERVER['HTTP_IF_NONE_MATCH']);
 114    $is304=(($etagClient==$etagServer)||($etagClient=='*'));
 115   }
 116   if ((!$is412)&&isset($_SERVER['HTTP_IF_UNMODIFIED_SINCE']))
 117   {//rfc2616-sec14.html#sec14.28
 118    $dateCacheClient=$_SERVER['HTTP_IF_UNMODIFIED_SINCE'];
 119    $p=strpos($dateCacheClient,';');
 120    if ($p!==false)
 121     $dateCacheClient=substr($dateCacheClient,0,$p);
 122    $is412=($dateCacheClient!=$dateLastModif);
 123   }
 124   if ($feedMode)
 125   {//Special RSS/ATOM
 126    global $clientCacheDate;
 127    $clientCacheDate=strtotime($dateCacheClient);
 128    $cachePrivacy=0;
 129   }
 130  
 131   if ($is412)
 132   {//rfc2616-sec10.html#sec10.4.13
 133    header('HTTP/1.1 412 Precondition Failed');
 134    header('Cache-Control: private, max-age=0, must-revalidate');
 135    header('Content-Type: text/plain');
 136    echo "HTTP/1.1 Error 412 Precondition Failed: Precondition request failed positive evaluation\n";
 137    return true;
 138   }
 139   elseif ($is304&&($nbCond>0))
 140   {//rfc2616-sec10.html#sec10.3.5
 141    header('HTTP/1.0 304 Not Modified');
 142    header('Etag: '.$etagServer);
 143    if ($feedMode) header('Connection: close'); //Comment this line under IIS
 144    return true;
 145   }
 146   else
 147   {//rfc2616-sec10.html#sec10.2.1
 148    //rfc2616-sec14.html#sec14.3
 149    if ($compression) ob_start('_httpConditionalCallBack'); //Will check HTTP_ACCEPT_ENCODING
 150    //header('HTTP/1.0 200 OK');
 151    if ($cacheSeconds==0)
 152    {
 153     $cache='private, must-revalidate, no-store, ';
 154     header('Pragma: no-cache');
 155    }
 156    elseif ($cachePrivacy==0) $cache='private, ';
 157    elseif ($cachePrivacy==2) $cache='public, ';
 158    else $cache='';
 159    $cache.='max-age='.floor($cacheSeconds);
 160    //header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T',time()+$cacheSeconds)); //HTTP/1.0 //rfc2616-sec14.html#sec14.21
 161    header('Cache-Control: '.$cache); //rfc2616-sec14.html#sec14.9
 162    header('Last-Modified: '.$dateLastModif);
 163    header('Etag: '.$etagServer);
 164    if ($feedMode) header('Connection: close'); //rfc2616-sec14.html#sec14.10 //Comment this line under IIS
 165    return $_SERVER['REQUEST_METHOD']=='HEAD'; //rfc2616-sec9.html#sec9.4
 166   }
 167  }
 168  
 169  function _httpConditionalCallBack($buffer,$mode=5)
 170  {//Private function automatically called at the end of the script when compression is enabled
 171   //rfc2616-sec14.html#sec14.11
 172   //You can adjust the level of compression with zlib.output_compression_level in php.ini
 173   if (extension_loaded('zlib')&&(!ini_get('zlib.output_compression')))
 174   {
 175    $buffer2=ob_gzhandler($buffer,$mode); //Will check HTTP_ACCEPT_ENCODING and put correct headers such as Vary //rfc2616-sec14.html#sec14.44
 176    if (strlen($buffer2)>1) //When ob_gzhandler succeeded
 177     $buffer=$buffer2;
 178   }
 179   header('Content-Length: '.strlen($buffer)); //Allows persistant connections //rfc2616-sec14.html#sec14.13
 180   return $buffer;
 181  }
 182  
 183  function httpConditionalRefresh($UnixTimeStamp)
 184  {//Update HTTP headers if the content has just been modified by the client's request
 185   //See an example on http://alexandre.alapetite.net/doc-alex/compteur/
 186   if (headers_sent()) return false;
 187  
 188   if (isset($_SERVER['SCRIPT_FILENAME'])) $scriptName=$_SERVER['SCRIPT_FILENAME'];
 189   elseif (isset($_SERVER['PATH_TRANSLATED'])) $scriptName=$_SERVER['PATH_TRANSLATED'];
 190   else return false;
 191  
 192   $dateLastModif=gmdate('D, d M Y H:i:s \G\M\T',$UnixTimeStamp);
 193  
 194   if (isset($_SERVER['QUERY_STRING'])) $myQuery='?'.$_SERVER['QUERY_STRING'];
 195   else $myQuery='';
 196   global $_sessionMode;
 197   if ($_sessionMode&&isset($_SESSION))
 198    $myQuery.=print_r($_SESSION,true).session_name().'='.session_id();
 199   $etagServer='"'.md5($scriptName.$myQuery.'#'.$dateLastModif).'"';
 200  
 201   header('Last-Modified: '.$dateLastModif);
 202   header('Etag: '.$etagServer);
 203  }
 204  ?>


Generated: Tue Mar 17 22:47:18 2015 Cross-referenced by PHPXref 0.7.1