[pLog-svn] r2317 - plog/branches/plog-1.0.2/class/net/http

Jon Daley plogworld at jon.limedaley.com
Thu Jul 14 05:52:02 GMT 2005


 	Yeah, I am testing away now.  It seems fine.  I hadn't realized 
one of my installations was on 1.0.1 final, so couldn't figure out why it 
was still breaking...

On Thu, 14 Jul 2005, Oscar Renalias wrote:
> looks good, but we should test this anyway...
>
> Oscar
>
> On 7/14/05, jondaley at devel.plogworld.net <jondaley at devel.plogworld.net> wrote:
>> Author: jondaley
>> Date: 2005-07-14 04:56:06 +0000 (Thu, 14 Jul 2005)
>> New Revision: 2317
>>
>> Modified:
>>    plog/branches/plog-1.0.2/class/net/http/httpcache.class.php
>> Log:
>> new version of author's code.  applied part of rev 90, all other local customizations have been ignored.  Reasons:  rev 2265, no real change. rev: 695: I don't think this is a good idea.  we shouldn't allow proxies to cache any document that is being returned as a 304, since it might have authenticated/specific data in it.  It probably isn't a security risk, since we store the sessions on the server, but secret plugins, etc. would be incorrectly cached.   rev 90: there is a bug in the change, where cacheSeconds can't ever be zero, since it is always changed at the top of the function, so this code couldn't have done what you thought it did. The author fixed the IE incompatibility, so I am not getting crashes, which was my main goal of all this.Any thoughts?
>>
>> Modified: plog/branches/plog-1.0.2/class/net/http/httpcache.class.php
>> ===================================================================
>> --- plog/branches/plog-1.0.2/class/net/http/httpcache.class.php 2005-07-14 04:12:27 UTC (rev 2316)
>> +++ plog/branches/plog-1.0.2/class/net/http/httpcache.class.php 2005-07-14 04:56:06 UTC (rev 2317)
>> @@ -1,199 +1,211 @@
>>  <?php
>>
>> -       include_once( PLOG_CLASS_PATH."class/net/http/httpvars.class.php" );
>> +include_once( PLOG_CLASS_PATH."class/net/http/httpvars.class.php" );
>>
>> -
>> -//In RSS/ATOM feedMode, contains the date of the clients last update.
>> -$clientCacheDate=0; //Global variable because PHP4 does not allow conditional arguments by reference
>> -
>> -/**
>> - *
>> +/*
>>   * \ingroup Net_HTTP
>> - *
>> - *
>>   * Enable support for HTTP/1.x conditional requests in PHP.
>>   * Goal: Optimisation
>>   * - If the client sends a HEAD request, avoid transferring data and return the correct headers.
>>   * - If the client already has the same version in its cache, avoid transferring data again (304 Not Modified).
>>   * - Possibility to control cache for client and proxies (public or private policy, life time).
>>   * - When $feedMode is set to true, in the case of a RSS/ATOM feed,
>> - *  it puts a timestamp in the global variable $clientCacheDate to allow the sending of only the articles newer than the client's cache.
>> - * - When $compression is set to true, compress the data before sending it to the client and persitent connections are allowed. (Beta1 version)
>> + *   it puts a timestamp in the global variable $clientCacheDate to allow the sending of only the articles newer than the client's cache.
>> + * - When $compression is set to true, compress the data before sending it to the client and persitent connections are allowed.
>> + * - When $session is set to true, automatically checks if $_SESSION has been modified during the last generation the document.
>>   *
>> - *Interface:
>> + * Interface:
>>   * - function httpConditional($UnixTimeStamp,$cacheSeconds=0,$cachePrivacy=0,$feedMode=false,$compression=false)
>> - * [Required] $UnixTimeStamp: Date of the last modification of the data to send to the client (Unix Timestamp format).
>> - * [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.
>> - * [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.
>> - * [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.
>> - * [implied] $compression=false: Enable the compression and allows persistant connections.
>> - * Return: 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.
>> + *  [Required] $UnixTimeStamp: Date of the last modification of the data to send to the client (Unix Timestamp format).
>> + *  [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.
>> + *  [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.
>> + *  [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.
>> + *  [implied] $compression=false: Enable the compression and allows persistant connections (automatic detection of the capacities of the client).
>> + *  [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.
>> + *  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.
>>   *
>>   * Typical use:
>> - *
>> - * <pre>
>>   * <?php
>> - * require_once('http-conditional.php');
>> - * //Date of the last modification of the content (Unix Timestamp format).
>> - * //Examples: query the database, or last modification of this script.
>> - * $dateLastModification=...;
>> - * if (httpConditional($dateLastModification))
>> - * {
>> - *  ... //Close database connections, and other cleaning.
>> - *  exit(); //No need to send anything
>> - * }
>> - * //Do not send any text to the client before this line.
>> - * ... //Rest of the script, just as you would do normally.
>> + *  require_once('http-conditional.php');
>> + *  //Date of the last modification of the content (Unix Timestamp format).
>> + *  //Examples: query the database, or last modification of a static file.
>> + *  $dateLastModification=...;
>> + *  if (httpConditional($dateLastModification))
>> + *  {
>> + *   ... //Close database connections, and other cleaning.
>> + *   exit(); //No need to send anything
>> + *  }
>> + *  //Do not send any text to the client before this line.
>> + *  ... //Rest of the script, just as you would do normally.
>>   * ?>
>> - * </pre>
>>   *
>> - * Version 1.3, 2004-08-05, http://alexandre.alapetite.net/doc-alex/php-http-304/
>> + * Version 1.6.1, 2005-04-03, http://alexandre.alapetite.net/doc-alex/php-http-304/
>>   *
>>   * ------------------------------------------------------------------
>>   * Written by Alexandre Alapetite, http://alexandre.alapetite.net/cv/
>>   *
>> - * Copyright 2004, Licence: Creative Commons "Attribution-ShareAlike 2.0" BY-SA,
>> - * http://creativecommons.org/licenses/by-sa/2.0/
>> + * Copyright 2004-2005, Licence: Creative Commons "Attribution-ShareAlike 2.0 France" BY-SA (FR),
>> + * http://creativecommons.org/licenses/by-sa/2.0/fr/
>>   * http://alexandre.alapetite.net/divers/apropos/#by-sa
>>   * - Attribution. You must give the original author credit
>>   * - Share Alike. If you alter, transform, or build upon this work,
>> - *  you may distribute the resulting work only under a license identical to this one
>> + *   you may distribute the resulting work only under a license identical to this one
>> + * - The French law is authoritative
>>   * - Any of these conditions can be waived if you get permission from Alexandre Alapetite
>>   * - Please send to Alexandre Alapetite the modifications you make,
>> - *  in order to improve this file for the benefit of everybody
>> + *   in order to improve this file for the benefit of everybody
>>   *
>>   * If you want to distribute this code, please do it as a link to:
>>   * http://alexandre.alapetite.net/doc-alex/php-http-304/
>>   */
>> +
>> +//In RSS/ATOM feedMode, contains the date of the clients last update.
>> +$clientCacheDate=0; //Global public variable because PHP4 does not allow conditional arguments by reference
>> +$_sessionMode=false; //Global private variable
>> +
>>  class HttpCache {
>> -       function httpConditional($UnixTimeStamp,$cacheSeconds=0,$cachePrivacy=0,$feedMode=false,$compression=false)
>> -       {//Credits: http://alexandre.alapetite.net/doc-alex/php-http-304/
>> -        //RFC2616 HTTP/1.1: http://www.w3.org/Protocols/rfc2616/rfc2616.html
>> -        //RFC1945 HTTP/1.0: http://www.w3.org/Protocols/rfc1945/rfc1945.txt
>> -
>> -                       $SERVER = HttpVars::getServer();
>> -
>> -                       if( $cacheSeconds == 0 )
>> -                               $cacheSeconds = 788400000;
>> -
>> -                       if (headers_sent()) return false;
>> -
>> -                       if (isset($SERVER['SCRIPT_FILENAME'])) $scriptName=$SERVER['SCRIPT_FILENAME'];
>> -                       elseif (isset($SERVER['PATH_TRANSLATED'])) $scriptName=$SERVER['PATH_TRANSLATED'];
>> -                       else return false;
>> -
>> -                       if ((!$feedMode)&&(($modifScript=filemtime($scriptName))>$UnixTimeStamp))
>> -                               $UnixTimeStamp=$modifScript;
>> -                       $UnixTimeStamp=min($UnixTimeStamp,time());
>> -                       $is304=true;
>> -                       $is412=false;
>> -                       $nbCond=0;
>> -
>> -                       //rfc2616-sec3.html#sec3.3.1
>> -                       $dateLastModif=gmdate('D, d M Y H:i:s \G\M\T',$UnixTimeStamp);
>> -                       $dateCacheClient='Tue, 10 Jan 1980 20:30:40 GMT';
>> -
>> -                       //rfc2616-sec14.html#sec14.19 //='"0123456789abcdef0123456789abcdef"'
>> -                       if (isset($SERVER['QUERY_STRING'])) $myQuery='?'.$SERVER['QUERY_STRING'];
>> -                       else $myQuery='';
>> -                       $etagServer='"'.md5($scriptName.$myQuery.'#'.$dateLastModif).'"';
>> -
>> -                       if ((!$is412)&&isset($SERVER['HTTP_IF_MATCH']))
>> -                       {//rfc2616-sec14.html#sec14.24
>> -                               $etagsClient=stripslashes($SERVER['HTTP_IF_MATCH']);
>> -                               $is412=(($etagClient!='*')&&(strpos($etagsClient,$etagServer)===false));
>> -                       }
>> -                       if ($is304&&isset($SERVER['HTTP_IF_MODIFIED_SINCE']))
>> -                       {//rfc2616-sec14.html#sec14.25 //rfc1945.txt
>> -                               $nbCond++;
>> -                               $dateCacheClient=strtok($SERVER['HTTP_IF_MODIFIED_SINCE'], ";");
>> -                               $is304=($dateCacheClient==$dateLastModif);
>> -                       }
>> -                       if ($is304&&isset($SERVER['HTTP_IF_NONE_MATCH']))
>> -                       {//rfc2616-sec14.html#sec14.26
>> -                               $nbCond++;
>> -                               $etagClient=stripslashes($SERVER['HTTP_IF_NONE_MATCH']);
>> -                               $is304=(($etagClient==$etagServer)||($etagClient=='*'));
>> -                       }
>> -                       if ((!$is412)&&isset($SERVER['HTTP_IF_UNMODIFIED_SINCE']))
>> -                       {//rfc2616-sec14.html#sec14.28
>> -                               $dateCacheClient=$SERVER['HTTP_IF_UNMODIFIED_SINCE'];
>> -                               $is412=($dateCacheClient!=$dateLastModif);
>> -                       }
>> -                       if ($feedMode)
>> -                       {//Special RSS/ATOM
>> -                               global $clientCacheDate;
>> -                               $clientCacheDate=strtotime($dateCacheClient);
>> -                               $cachePrivacy=0;
>> -                       }
>> -
>> -                       if ($is412)
>> -                       {//rfc2616-sec10.html#sec10.4.13
>> -                               header('HTTP/1.1 412 Precondition Failed');
>> -                               header('Cache-Control: private, max-age=0, must-revalidate');
>> -                               header('Content-Type: text/plain');
>> -                               echo "HTTP/1.1 Error 412 Precondition Failed: Precondition request failed positive evaluation\n";
>> -                               return true;
>> -                       }
>> -                       elseif ($is304&&($nbCond>0))
>> -                       {//rfc2616-sec10.html#sec10.3.5
>> -                               header('HTTP/1.0 304 Not Modified');
>> -
>> -                               header('Etag: '.$etagServer);
>> -                               if ($feedMode) header('Connection: close'); //Comment this line under IIS
>> -
>> -                               if ($cacheSeconds==0)
>> -                               {
>> -                                       $cache='private, must-revalidate, ';
>> -                                       //$cacheSeconds=-1500000; //HTTP/1.0
>> -                               }
>> -                               elseif ($cachePrivacy==0) $cache='private, ';
>> -                               elseif ($cachePrivacy==2) $cache='public, ';
>> -                               else $cache='';
>> -                               $cache.='max-age='.floor($cacheSeconds);
>> -                               header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T',time()+$cacheSeconds)); //HTTP/1.0 //rfc2616-sec14.html#sec14.21a
>> -                               header('Cache-Control: '.$cache); //rfc2616-sec14.html#sec14.9
>> -                               header('Pragma: public');
>> -
>> -                               return true;
>> -                       }
>> -                       else
>> -                       {//rfc2616-sec10.html#sec10.2.1
>> -                        //rfc2616-sec14.html#sec14.3
>> -
>> -                               if ($compression&&isset($SERVER['HTTP_ACCEPT_ENCODING'])&&
>> -                                       extension_loaded('zlib')&&(!ini_get('zlib.output_compression')))
>> -                                       ob_start('_httpConditionalCallBack');
>> -                               //header('HTTP/1.0 200 OK');
>> -                               if ($cacheSeconds==0)
>> -                               {
>> -                                       $cache='private, must-revalidate, ';
>> -                                       //$cacheSeconds=-1500000; //HTTP/1.0
>> -                               }
>> +    function httpConditional($UnixTimeStamp,$cacheSeconds=0,
>> +                             $cachePrivacy=0,$feedMode=false,
>> +                             $compression=false,$session=false){
>> +            //Credits: http://alexandre.alapetite.net/doc-alex/php-http-304/
>> +            //RFC2616 HTTP/1.1: http://www.w3.org/Protocols/rfc2616/rfc2616.html
>> +            //RFC1945 HTTP/1.0: http://www.w3.org/Protocols/rfc1945/rfc1945.txt
>>
>> -                               elseif ($cachePrivacy==0) $cache='private, ';
>> -                               elseif ($cachePrivacy==2) $cache='public, ';
>> -                               else $cache='';
>> -                               $cache.='max-age='.floor($cacheSeconds);
>> -                               header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T',time()+$cacheSeconds)); //HTTP/1.0 //rfc2616-sec14.html#sec14.21a
>> -                               header('Cache-Control: '.$cache); //rfc2616-sec14.html#sec14.9
>> -
>> -                               header('Last-Modified: '.$dateLastModif);
>> -                               header('Etag: '.$etagServer);
>> -                               if ($feedMode) header('Connection: close'); //rfc2616-sec14.html#sec14.10 //Comment this line under IIS
>> -                               return $SERVER['REQUEST_METHOD']=='HEAD'; //rfc2616-sec9.html#sec9.4
>> -                       }
>> -       }
>> +        if (headers_sent()) return false;
>>
>> -}
>> +        if (isset($_SERVER['SCRIPT_FILENAME'])) $scriptName=$_SERVER['SCRIPT_FILENAME'];
>> +        elseif (isset($_SERVER['PATH_TRANSLATED'])) $scriptName=$_SERVER['PATH_TRANSLATED'];
>> +        else return false;
>>
>> -function _httpConditionalCallBack($buffer,$mode=5)
>> -{//Private function automatically called at the end of the script when compression is enabled
>> - //rfc2616-sec14.html#sec14.11
>> - //You can adjust the level of compression with zlib.output_compression_level in php.ini
>> -       $buffer=ob_gzhandler($buffer,$mode); //Will check HTTP_ACCEPT_ENCODING and put correct headers
>> -       header('Content-Length: '.strlen($buffer));
>> -       return $buffer;
>> +        if ((!$feedMode)&&(($modifScript=filemtime($scriptName))>$UnixTimeStamp))
>> +            $UnixTimeStamp=$modifScript;
>> +        $UnixTimeStamp=min($UnixTimeStamp,time());
>> +        $is304=true;
>> +        $is412=false;
>> +        $nbCond=0;
>> +
>> +            //rfc2616-sec3.html#sec3.3.1
>> +        $dateLastModif=gmdate('D, d M Y H:i:s \G\M\T',$UnixTimeStamp);
>> +        $dateCacheClient='Thu, 10 Jan 1980 20:30:40 GMT';
>> +
>> +            //rfc2616-sec14.html#sec14.19 //='"0123456789abcdef0123456789abcdef"'
>> +        if (isset($_SERVER['QUERY_STRING'])) $myQuery='?'.$_SERVER['QUERY_STRING'];
>> +        else $myQuery='';
>> +        if ($session&&isset($_SESSION))
>> +        {
>> +            global $_sessionMode;
>> +            $_sessionMode=$session;
>> +            $myQuery.=print_r($_SESSION,true).session_name().'='.session_id();
>> +        }
>> +        $etagServer='"'.md5($scriptName.$myQuery.'#'.$dateLastModif).'"';
>> +
>> +        if ((!$is412)&&isset($_SERVER['HTTP_IF_MATCH']))
>> +        {//rfc2616-sec14.html#sec14.24
>> +            $etagsClient=stripslashes($_SERVER['HTTP_IF_MATCH']);
>> +            $is412=(($etagClient!='*')&&(strpos($etagsClient,$etagServer)===false));
>> +        }
>> +        if ($is304&&isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
>> +        {//rfc2616-sec14.html#sec14.25 //rfc1945.txt
>> +            $nbCond++;
>> +            $dateCacheClient=$_SERVER['HTTP_IF_MODIFIED_SINCE'];
>> +            $p=strpos($dateCacheClient,';');
>> +            if ($p!==false)
>> +                $dateCacheClient=substr($dateCacheClient,0,$p);
>> +            $is304=($dateCacheClient==$dateLastModif);
>> +        }
>> +        if ($is304&&isset($_SERVER['HTTP_IF_NONE_MATCH']))
>> +        {//rfc2616-sec14.html#sec14.26
>> +            $nbCond++;
>> +            $etagClient=stripslashes($_SERVER['HTTP_IF_NONE_MATCH']);
>> +            $is304=(($etagClient==$etagServer)||($etagClient=='*'));
>> +        }
>> +        if ((!$is412)&&isset($_SERVER['HTTP_IF_UNMODIFIED_SINCE']))
>> +        {//rfc2616-sec14.html#sec14.28
>> +            $dateCacheClient=$_SERVER['HTTP_IF_UNMODIFIED_SINCE'];
>> +            $p=strpos($dateCacheClient,';');
>> +            if ($p!==false)
>> +                $dateCacheClient=substr($dateCacheClient,0,$p);
>> +            $is412=($dateCacheClient!=$dateLastModif);
>> +        }
>> +        if ($feedMode)
>> +        {//Special RSS/ATOM
>> +            global $clientCacheDate;
>> +            $clientCacheDate=strtotime($dateCacheClient);
>> +            $cachePrivacy=0;
>> +        }
>> +
>> +        if ($is412)
>> +        {//rfc2616-sec10.html#sec10.4.13
>> +            header('HTTP/1.1 412 Precondition Failed');
>> +            header('Cache-Control: private, max-age=0, must-revalidate');
>> +            header('Content-Type: text/plain');
>> +            echo "HTTP/1.1 Error 412 Precondition Failed: Precondition request failed positive evaluation\n";
>> +            return true;
>> +        }
>> +        elseif ($is304&&($nbCond>0))
>> +        {//rfc2616-sec10.html#sec10.3.5
>> +            header('HTTP/1.0 304 Not Modified');
>> +            header('Etag: '.$etagServer);
>> +            if ($feedMode) header('Connection: close'); //Comment this line under IIS
>> +            return true;
>> +        }
>> +        else
>> +        {//rfc2616-sec10.html#sec10.2.1
>> +                //rfc2616-sec14.html#sec14.3
>> +            if ($compression) ob_start('_httpConditionalCallBack'); //Will check HTTP_ACCEPT_ENCODING
>> +                //header('HTTP/1.0 200 OK');
>> +            if ($cacheSeconds==0)
>> +            {
>> +                $cache='private, must-revalidate, ';
>> +                    //$cacheSeconds=-1500000; //HTTP/1.0
>> +            }
>> +            elseif ($cachePrivacy==0) $cache='private, ';
>> +            elseif ($cachePrivacy==2) $cache='public, ';
>> +            else $cache='';
>> +            $cache.='max-age='.floor($cacheSeconds);
>> +            header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T',time()+$cacheSeconds)); //HTTP/1.0 //rfc2616-sec14.html#sec14.21
>> +            header('Cache-Control: '.$cache); //rfc2616-sec14.html#sec14.9
>> +            header('Last-Modified: '.$dateLastModif);
>> +            header('Etag: '.$etagServer);
>> +            if ($feedMode) header('Connection: close'); //rfc2616-sec14.html#sec14.10 //Comment this line under IIS
>> +            return $_SERVER['REQUEST_METHOD']=='HEAD'; //rfc2616-sec9.html#sec9.4
>> +        }
>> +    }
>> +
>> +    function _httpConditionalCallBack($buffer,$mode=5){
>> +            //Private function automatically called at the end of the script when compression is enabled
>> +            //rfc2616-sec14.html#sec14.11
>> +            //You can adjust the level of compression with zlib.output_compression_level in php.ini
>> +        if (extension_loaded('zlib')&&(!ini_get('zlib.output_compression')))
>> +        {
>> +            $buffer2=ob_gzhandler($buffer,$mode); //Will check HTTP_ACCEPT_ENCODING and put correct headers
>> +            if (strlen($buffer2)>1) //When ob_gzhandler succeeded
>> +                $buffer=$buffer2;
>> +        }
>> +        header('Content-Length: '.strlen($buffer)); //Allows persistant connections //rfc2616-sec14.html#sec14.13
>> +        return $buffer;
>> +    }
>> +
>> +    function httpConditionalRefresh($UnixTimeStamp){
>> +            //Update HTTP headers if the content has just been modified by the client's request
>> +            //See an example on http://alexandre.alapetite.net/doc-alex/compteur/
>> +        if (headers_sent()) return false;
>> +
>> +        if (isset($_SERVER['SCRIPT_FILENAME'])) $scriptName=$_SERVER['SCRIPT_FILENAME'];
>> +        elseif (isset($_SERVER['PATH_TRANSLATED'])) $scriptName=$_SERVER['PATH_TRANSLATED'];
>> +        else return false;
>> +
>> +        $dateLastModif=gmdate('D, d M Y H:i:s \G\M\T',$UnixTimeStamp);
>> +
>> +        if (isset($_SERVER['QUERY_STRING'])) $myQuery='?'.$_SERVER['QUERY_STRING'];
>> +        else $myQuery='';
>> +        global $_sessionMode;
>> +        if ($_sessionMode&&isset($_SESSION))
>> +            $myQuery.=print_r($_SESSION,true).session_name().'='.session_id();
>> +        $etagServer='"'.md5($scriptName.$myQuery.'#'.$dateLastModif).'"';
>> +
>> +        header('Last-Modified: '.$dateLastModif);
>> +        header('Etag: '.$etagServer);
>> +    }
>>  }
>> -
>>  ?>
>> \ No newline at end of file
>>
>> _______________________________________________
>> pLog-svn mailing list
>> pLog-svn at devel.plogworld.net
>> http://devel.plogworld.net/mailman/listinfo/plog-svn
>>
> _______________________________________________
> pLog-svn mailing list
> pLog-svn at devel.plogworld.net
> http://devel.plogworld.net/mailman/listinfo/plog-svn
>

**************************************************************
*         Jon Daley         *  Better to light a candle than *
*                           *     to curse the darkness.     *
* http://jon.limedaley.com/ *             -- Chinese Proverb *
**************************************************************



More information about the pLog-svn mailing list