Image_Remote
[ class tree: Image_Remote ] [ index: Image_Remote ] [ all elements ]

Source for file Remote.php

Documentation is available at Remote.php

  1. <?php
  2.  
  3. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  4. // +----------------------------------------------------------------------+
  5. // | PHP Version 4                                                        |
  6. // +----------------------------------------------------------------------+
  7. // | Copyright (c) 1997-2003 The PHP Group                                |
  8. // +----------------------------------------------------------------------+
  9. // | This source file is subject to version 2.0 of the PHP license,       |
  10. // | that is bundled with this package in the file LICENSE, and is        |
  11. // | available at through the world-wide-web at                           |
  12. // | http://www.php.net/license/2_02.txt.                                 |
  13. // | If you did not receive a copy of the PHP license and are unable to   |
  14. // | obtain it through the world-wide-web, please send a note to          |
  15. // | license@php.net so we can mail you a copy immediately.               |
  16. // +----------------------------------------------------------------------+
  17. // | Authors: Mika Tuupola <tuupola@appelsiini.net>                       |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: Remote.php,v 1.3 2003/01/03 15:25:35 tuupola Exp $
  21.  
  22. define("GIF_SIGNATURE_LENGTH",      3);
  23. define("GIF_VERSION_LENGTH",        3);
  24. define("GIF_LSW_LENGTH",            2);
  25. define("GIF_LSH_LENGTH",            2);
  26.  
  27. define("PNG_SIGNATURE_LENGTH",      8);
  28. define("PNG_IHDR_LENGTH_LENGTH",    4);
  29. define("PNG_IHDR_CHUNKTYPE_LENGTH"4);
  30. define("PNG_IHDR_IMW_LENGTH",       4);
  31. define("PNG_IHDR_IMH_LENGTH",       4);
  32.  
  33. define("JPG_PARAM_LENGTH_LENGTH",   2);
  34. define("JPG_DATA_PRECISION_LENGTH"1);
  35. define("JPG_IMW_LENGTH_LENGTH",     2);
  36. define("JPG_IMH_LENGTH_LENGTH",     2);
  37. define("JPG_NUM_COMPONENTS_LENGTH"1);
  38.  
  39. // The following jpeg defines were taken from rdjpgcom.c, which is part
  40. // of the Independent JPEG Group's software.
  41. // Copyright (C) 1994-1997, Thomas G. Lane.
  42. //
  43. // ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz
  44.  
  45. define("M_SOF0",  0xC0);   /* Start Of Frame N */
  46. define("M_SOF1",  0xC1);   /* N indicates which compression process */
  47. define("M_SOF2",  0xC2);   /* Only SOF0-SOF2 are now in common use */
  48. define("M_SOF3",  0xC3);
  49. define("M_SOF5",  0xC5);   /* NB: codes C4 and CC are NOT SOF markers */
  50. define("M_SOF6",  0xC6);
  51. define("M_SOF7",  0xC7);
  52. define("M_SOF9",  0xC9);
  53. define("M_SOF10"0xCA);
  54. define("M_SOF11"0xCB);
  55. define("M_SOF13"0xCD);
  56. define("M_SOF14"0xCE);
  57. define("M_SOF15"0xCF);
  58. define("M_SOI",   0xD8);   /* Start Of Image (beginning of datastream) */
  59. define("M_EOI",   0xD9);   /* End Of Image (end of datastream) */
  60. define("M_SOS",   0xDA);   /* Start Of Scan (begins compressed data) */
  61. define("M_APP0",  0xE0);   /* Application-specific marker, type N */
  62. define("M_APP12"0xEC);   /* (we don't bother to list all 16 APPn's) */
  63. define("M_COM",   0xFE);   /* COMment */
  64.  
  65. require_once('PEAR.php');
  66.  
  67. /**
  68.   * Image_Remote - retrieve size from remote image files.
  69.   *
  70.   * Class can be used to get size information from remote
  71.   * image files without downloading the whole image file.
  72.   * It mimics the GetImageSize() PHP function but works on
  73.   * remote images. Gif, jpeg and png currently supported.
  74.   * 
  75.   * NOTE: Since PHP 4.0.5 URL support was added also to PHP's native
  76.   * GetImageSize().
  77.   *
  78.   * Usage:
  79.   *   
  80.   *   $i = new Image_Remote("http://www.example.com/test.jpg");
  81.   *   if (PEAR::isError($i)) {
  82.   *       print "ERROR: " . $i->getMessage();
  83.   *   } else {
  84.   *       $size    = $i->getImageSize();
  85.   *       $comment = $i->getImageComment();
  86.   *   }
  87.   *   
  88.   *
  89.   * @access public
  90.   * @author Mika Tuupola <tuupola@appelsiini.net>
  91.   * @version $Revision: 1.3 $
  92.   */
  93.  
  94.  
  95. class Image_Remote
  96. {
  97.  
  98.   /**
  99.     * The URL to fetch size from
  100.     *
  101.     * @var  string 
  102.     */
  103.     var $url;         
  104.  
  105.   /**
  106.     * Parsed URL
  107.     *
  108.     * @var  array 
  109.     */
  110.     var $purl;  
  111.  
  112.   /**
  113.     * Filesize of the remote image
  114.     *
  115.     * @var  integer 
  116.     */      
  117.  
  118.     var $filesize;    // filesize of the remote file
  119.  
  120.   /**
  121.     * Mimetype of the remote image
  122.     *
  123.     * @var  string 
  124.     */
  125.     var $mimetype;   
  126.  
  127.   /**
  128.     * Imagetype of the remote image
  129.     *
  130.     * @var  integer 
  131.     */
  132.     var $imagetype;  
  133.  
  134.   /**
  135.     * Width of the remote image
  136.     *
  137.     * @var  integer 
  138.     */
  139.     var $width;       // image width
  140.  
  141.   /**
  142.     * Height of the remote image
  143.     *
  144.     * @var  integer 
  145.     */
  146.     var $height;      // image height
  147.  
  148.   /**
  149.     * Some useless extrainfo
  150.     *
  151.     * @var  string 
  152.     */
  153.     var $extra;       // some useless extrainfo
  154.  
  155.   /**
  156.     * JPEG comment
  157.     *
  158.     * @var  string 
  159.     */
  160.     var $comment
  161.  
  162.   /**
  163.     * Error of the last method call
  164.     *
  165.     * @var  string 
  166.     */
  167.     var $errstr;      // error of the last method call
  168.  
  169.   /**
  170.     * Constructor
  171.     * 
  172.     * @param     string     foo URL of the remote image. Currently supports only http.
  173.     * @return     object 
  174.     *
  175.     */
  176.  
  177.     function Image_Remote($input
  178.     {
  179.         $this->purl parse_url($input);  
  180.  
  181.         if ($this->purl[scheme== 'http'{
  182.             $this->url $input;
  183.  
  184.             // assign default port if not given
  185.             if (!($this->purl[port])) {
  186.                 $this->purl[port= 80;
  187.             }
  188.             $this->errstr "";
  189.             // actually fetch the info
  190.             Image_Remote::_fetchImageInfo();
  191.  
  192.         else {
  193.             $this->errstr "Only http supported.";
  194.         }
  195.     
  196.         if ($this->errstr{
  197.             $this = new PEAR_Error($this->errstr);
  198.         }
  199.  
  200.     // constructor
  201.  
  202.   
  203.   /**
  204.     * Return information on the remote image.
  205.     *
  206.     * Imitates PHP's native GetImageSize.
  207.     * 
  208.     * http://www.php.net/manual/function.getimagesize.php
  209.     *
  210.     * @access     public
  211.     * @return     array 
  212.     */
  213.     function getImageSize(
  214.     {
  215.         $retval = array(0,0,0,"");
  216.  
  217.         $retval[0$this->width;  
  218.         $retval[1$this->height;  
  219.         $retval[2$this->imagetype;
  220.         $retval[3= "WIDTH=\"$retval[0]\" HEIGHT=\"$retval[1]\"";
  221.  
  222.         return($retval);   
  223.     }
  224.  
  225.   /**
  226.     * Return the URL of the remote image.
  227.     *
  228.     * This is actually the same URL which was given to the constructor.
  229.     * However it sometimes comes handy to be able to retrieve the URL
  230.     * again from the object.
  231.     * 
  232.     * @access    public
  233.     * @return     string 
  234.     */
  235.  
  236.     function getImageURL(
  237.     {
  238.         $retval $this->url;
  239.         return($retval);
  240.     }
  241.  
  242.   /**
  243.     * Return the Comment found in the remote image.
  244.     *
  245.     * This comment is being used to specify the JPG image.
  246.     * http://www.w3.org/Graphics/JPEG/itu-t81.pdf
  247.     * 
  248.     * @access    public
  249.     * @return    string 
  250.     * @author    Urs Gehrig <urs@circle.ch>
  251.     */
  252.     function getImageComment(
  253.     {
  254.         $retval $this->comment;
  255.         return($retval);
  256.     }
  257.  
  258.   /**
  259.     * Fetch information of the remote image.
  260.     *
  261.     * @access    private
  262.     * @return     boolean 
  263.     */
  264.     function _fetchImageInfo(
  265.     {
  266.  
  267.         // default to success.
  268.         $retval = 1;
  269.         // Open the connection and get the headers
  270.         $fp fsockopen ($this->purl[host]$this->purl[port]&$errno&$errstr30);
  271.         if (!$fp{
  272.             $this->errstr = "Could not open socket $errstr ($errno)\n";
  273.             $retval = 0;
  274.         else {
  275.  
  276.             // get the headers.
  277.             fputs ($fp"GET " $this->purl[path$this->purl[query" HTTP/1.1\r\n");
  278.             fputs ($fp"Host: " $this->purl[host"\r\n");
  279.             fputs ($fp"User-Agent: PEAR Image_Remote class ( http://pear.php.net) \r\n");
  280.             fputs ($fp"Connection: close\r\n\r\n");
  281.             $line trim(fgets($fp,128));
  282.             while ($line{
  283.                 // Extract redirection
  284.                 if (preg_match("/^HTTP\/1\.[0-1] (3[0-9][0-9] .*)/"$line$matches)) {
  285.                     $this->errstr $matches[1" not implemented yet!";
  286.                     $retval = 0;
  287.                 }
  288.                 // Extract client error
  289.                     if (preg_match("/^HTTP\/1\.[0-1] (4[0-9][0-9] .*)/"$line$matches)) {
  290.                     $this->errstr $matches[1];
  291.                     $retval = 0;
  292.                 }
  293.                 // Extract server error
  294.                 if (preg_match("/^HTTP\/1\.[0-1] (5[0-9][0-9] .*)/"$line$matches)) {
  295.                     $this->errstr $matches[1];
  296.                     $retval = 0;
  297.                 }
  298.                 // Extract mime type
  299.                 if (preg_match("/Content-Type: (.*)/"$line$matches)) {
  300.                     $tempmime chop($matches[1]);
  301.                 }
  302.                 // Extract filesize
  303.                  if (preg_match("/Content-Length: ([0-9]*)/"$line$matches)) {
  304.                    $tempfilesize $matches[1];
  305.                 }
  306.                 $line trim(fgets($fp,128));
  307.             }
  308.  
  309.             // If we got correct mimetype etc (we trust what the webserver says), 
  310.             // continue to fetch the actual data. 
  311.       
  312.             // if no error yet
  313.             if ($retval{
  314.             // if correct mimetype
  315.                 if (preg_match("/image\/(gif|jpeg|x-jpeg|x-png|png)/"$tempmime)) {
  316.                     $this->mimetype $tempmime;
  317.                     $this->filesize $tempfilesize;
  318.  
  319.                     SWITCH ($tempmime{
  320.                         case 'image/gif':
  321.                             Image_Remote::_fetchAndParseGIFHeader($fp);
  322.                             $this->imagetype = 1;
  323.                             break;
  324.                         case 'image/png':
  325.                         case 'image/x-png':
  326.                             Image_Remote::_fetchAndParsePNGHeader($fp);
  327.                             $this->imagetype = 3;
  328.                             break;
  329.                         case 'image/jpeg':
  330.                         case 'image/x-jpeg':
  331.                             Image_Remote::_fetchAndParseJPGHeader($fp);
  332.                             $this->imagetype = 2;
  333.                             break;
  334.                     }
  335.  
  336.                 else {
  337.                     $this->errstr = "Unsupported mimetype $tempmime.";
  338.                     $retval = 0;
  339.                 }
  340.             
  341.             fclose($fp);
  342.         }
  343.         return($retval);
  344.     // _fetchImageInfo
  345.  
  346.  
  347.   /**
  348.     * Parse GIF header
  349.     *
  350.     * @access    private
  351.     * @return     void 
  352.     */
  353.     function _fetchAndParseGIFHeader($fd
  354.     {
  355.         if (!$fd{
  356.             $this->errstr "No socket.";
  357.         else {
  358.             $signature fread($fdGIF_SIGNATURE_LENGTH);
  359.             $version   fread($fdGIF_VERSION_LENGTH);
  360.             $wbytes    fread($fdGIF_LSW_LENGTH);
  361.             $hbytes    fread($fdGIF_LSH_LENGTH);
  362.  
  363.             // Host Byte Order
  364.             $this->width  = Image_Remote::_htodecs($wbytes);
  365.             $this->height = Image_Remote::_htodecs($hbytes);
  366.  
  367.             $this->extra  $signature $version;    
  368.         }
  369.     }
  370.  
  371.   /**
  372.     * Parse PNG header
  373.     *
  374.     * @access    private
  375.     * @return     void 
  376.     */
  377.     function _fetchAndParsePNGHeader($fd
  378.     {
  379.  
  380.         if (!$fd{
  381.             $this->errstr "No socket.";
  382.         else {
  383.             $signature fread($fdPNG_SIGNATURE_LENGTH);
  384.             $ihdrl     fread($fdPNG_IHDR_LENGTH_LENGTH);
  385.             $ihdrct    fread($fdPNG_IHDR_CHUNKTYPE_LENGTH);
  386.             $wbytes    fread($fdPNG_IHDR_IMW_LENGTH);
  387.             $hbytes    fread($fdPNG_IHDR_IMH_LENGTH);
  388.  
  389.             // Network Byte Order
  390.             $this->width  = Image_Remote::_ntodecl($wbytes);
  391.             $this->height = Image_Remote::_ntodecl($hbytes);
  392.  
  393.             $this->extra  $signature;       
  394.         }
  395.     }
  396.  
  397.     // The jpeg parser is basically port of code found from rdjpgcom.c, 
  398.     // which is  part of the Independent JPEG Group's software.
  399.     // Copyright (C) 1994-1997, Thomas G. Lane.
  400.     //
  401.     // ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz
  402.     //
  403.     // Similar port can be found in elqGetImageFormat() by Oyvind Hallsteinsen 
  404.     //
  405.     // ftp://ftp.elq.org/pub/php3/elqGetImageFormat/elqGetImageFormat.php3
  406.  
  407.   /**
  408.     * Parse JPEG header
  409.     *
  410.     * @access    private
  411.     * @return     void 
  412.     */
  413.     function _fetchAndParseJPGHeader($fd
  414.     {
  415.  
  416.         if (!$fd{
  417.             $this->errstr "No socket.";
  418.         else {
  419.             $done = 0;
  420.  
  421.             // first marker
  422.             $c1 ord(fread($fd1));
  423.             $c2 ord(fread($fd1));
  424.             if ($c1 != 0xFF || $c2 != M_SOI{
  425.                 $this->errstr="Not a jpeg file?";
  426.             else 
  427.  
  428.                 while (!($done)) {
  429.  
  430.                     if ($m_sof && $m_com{
  431.                         $done = 1;
  432.                     }
  433.         
  434.                     // find next marker
  435.                     $marker ord(fread($fd1));
  436.                     while ($marker != 0xFF{
  437.                         $marker ord(fread($fd1));
  438.                     }   
  439.                     do {
  440.                         $marker ord(fread($fd1));
  441.                     while ($marker == 0xFF);
  442.  
  443.                     SWITCH ($marker{
  444.                         case M_SOF0:
  445.                         case M_SOF1:
  446.                         case M_SOF2:
  447.                         case M_SOF3:
  448.                         case M_SOF5:
  449.                         case M_SOF6:
  450.                         case M_SOF7:
  451.                         case M_SOF9
  452.                         case M_SOF10:
  453.                         case M_SOF11:
  454.                         case M_SOF13:
  455.                         case M_SOF14:
  456.                         case M_SOF15:
  457.                             $length    fread($fdJPG_PARAM_LENGTH_LENGTH);
  458.                             $precision fread($fdJPG_DATA_PRECISION_LENGTH);
  459.                             $hbytes    fread($fdJPG_IMH_LENGTH_LENGTH);
  460.                             $wbytes    fread($fdJPG_IMW_LENGTH_LENGTH);
  461.                             $componentsfread($fdJPG_NUM_COMPONENTS_LENGTH);
  462.                
  463.                             // Network Byte Order
  464.                             $this->width  = Image_Remote::_ntodecs($wbytes);
  465.                             $this->height = Image_Remote::_ntodecs($hbytes);
  466.                          
  467.                             $this->extra  "";
  468.                             $m_sof = 1;
  469.                             break; 
  470.                          case M_COM:
  471.                              // Get length of comment
  472.                              $bytes fread($fdJPG_PARAM_LENGTH_LENGTH);
  473.                              $length = Image_Remote::_chartodec($bytes);
  474.                              $length -= JPG_PARAM_LENGTH_LENGTH;
  475.                        
  476.                              // Read comment
  477.                              $this->comment fread($fd$length);
  478.                              $m_com = 1;
  479.                              break;
  480.                         case M_SOS:  
  481.                             $done = 1; 
  482.                             break;
  483.  
  484.                         // By default we skip over unwanted markers and avoid
  485.                         // being fooled by 0xFF bytes in parameter segment.
  486.                         default:
  487.                             $lbytes fread($fdJPG_PARAM_LENGTH_LENGTH);
  488.                             $length = Image_Remote::_ntodecs($lbytes)
  489.                             if ($length JPG_PARAM_LENGTH_LENGTH{
  490.                                 $this->errstr="Erronous parameter length.";
  491.                                 $done = 1;
  492.                             
  493.                             // the length is included in param length and
  494.                             // allready read
  495.                             $length -= JPG_PARAM_LENGTH_LENGTH;
  496.                             fread($fd$length);
  497.                             break;
  498.                     }    
  499.                 }
  500.             }
  501.         }
  502.     }
  503.  
  504.   /**
  505.     * Host byte order to decimal long
  506.     *
  507.     * @access    private
  508.     * @return     integer 
  509.     */
  510.     function _htodecl($bytes
  511.     {
  512.         $b1 ord($bytes[0]);
  513.         $b2 (ord($bytes[1])<<8);
  514.         $b3 (ord($bytes[2])<<16);
  515.         $b4 (ord($bytes[3])<<24);
  516.         return($b1 $b2 $b3 $b4);
  517.     }
  518.  
  519.   /**
  520.     * Host byte order to decimal short
  521.     *
  522.     * @access    private
  523.     * @return     integer 
  524.     */
  525.     function _htodecs($bytes
  526.     {
  527.         $b1 ord($bytes[0]);
  528.         $b2 (ord($bytes[1]<< 8);
  529.         return($b1 $b2);
  530.     }
  531.  
  532.   /**
  533.     * Network byte order to decimal long
  534.     *
  535.     * @access    private
  536.     * @return     integer 
  537.     */
  538.     function _ntodecl($bytes
  539.     {
  540.         $b1 ord($bytes[3]);
  541.         $b2 (ord($bytes[2]<< 8);
  542.         $b3 (ord($bytes[1]<< 16);
  543.         $b4 (ord($bytes[0]<< 24);
  544.         return($b1 $b2 $b3 $b4)
  545.     }
  546.  
  547.   /**
  548.     * Network byte order to decimal short
  549.     *
  550.     * @access    private
  551.     * @return     integer 
  552.     */
  553.     function _ntodecs($bytes
  554.     {
  555.         $b1 ord($bytes[1]);
  556.         $b2 (ord($bytes[0]<< 8 );
  557.         return($b1 $b2);
  558.     }
  559.  
  560.    /**
  561.      * Convert char to decimal
  562.      *
  563.      * @access private
  564.      * @return   integer 
  565.      * @author Urs Gehrig <urs@circle.ch>
  566.      */
  567.      function _chartodec($bytes
  568.      {        
  569.          $b1 (ord($bytes[0]<< 8 );
  570.          $b2 ord($bytes[1]);
  571.          return($b1 $b2);
  572.      }
  573.  
  574. // class 
  575.  
  576. ?>

Documentation generated on Mon, 11 Mar 2019 15:29:19 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.