Bir URL PHP bir görüntü olup olmadığını belirlemek için en iyi yolu

4 Cevap php

PHP kullanarak, nasıl ben bunu bir görüntü olup olmadığını belirleyebilirsiniz, bir URL verilir?

URL için bağlam yok - bu sadece bir düz metin dosyası, ya da kendi başına belki sadece bir dize ortasında.

Ben bu sayfada birçok URL'ler için denebilecek kadar yüksek yük (örneğin URL içeriğini okumak) istemiyorum. Bu kısıtlama göz önüne alındığında, tüm görüntüler tespit esastır değil, ama oldukça iyi bir tahmin istiyorum.

Şu anda sadece dosya uzantısı arıyorum, ama bu daha iyi bir yolu var olmalıdır gibi hissediyor.

İşte ben şu anda ne var:

  function isImage( $url )
  {
    $pos = strrpos( $url, ".");
	if ($pos === false)
	  return false;
	$ext = strtolower(trim(substr( $url, $pos)));
	$imgExts = array(".gif", ".jpg", ".jpeg", ".png", ".tiff", ".tif"); // this is far from complete but that's always going to be the case...
	if ( in_array($ext, $imgExts) )
	  return true;
    return false;
  }

Edit: durumunda burada Emil H'leri cevabını tekniği kullanılarak nihai işlevi herkesten yararlıdır:

  function isImage($url)
  {
     $params = array('http' => array(
                  'method' => 'HEAD'
               ));
     $ctx = stream_context_create($params);
     $fp = @fopen($url, 'rb', false, $ctx);
     if (!$fp) 
        return false;  // Problem with url

    $meta = stream_get_meta_data($fp);
    if ($meta === false)
    {
        fclose($fp);
        return false;  // Problem reading data from url
    }

    $wrapper_data = $meta["wrapper_data"];
    if(is_array($wrapper_data)){
      foreach(array_keys($wrapper_data) as $hh){
          if (substr($wrapper_data[$hh], 0, 19) == "Content-Type: image") // strlen("Content-Type: image") == 19 
          {
            fclose($fp);
            return true;
          }
      }
    }

    fclose($fp);
    return false;
  }

4 Cevap

Bir HTTP HEAD isteği kullanımı ve içerik türünü kontrol edebilir. Bu iyi bir uzlaşma olabilir. Bu PHP Streams kullanılarak yapılabilir. Wez Furlong bir article bu mesaja istekleri göndermek için bu yaklaşımı nasıl kullanılacağını gösterir, ancak kolayca yerine HEAD istekleri göndermek için adapte edilebilir. Sen stream_get_meta_data() kullanarak bir http yanıtı başlıkları alabilirsiniz.

Tabii ki bu gerçekten% 100 değildir. Bazı sunucular yanlış başlıklarını gönderin. Ancak görüntüler bir komut dosyası aracılığıyla teslim ve doğru dosya uzantısı mevcut değildir vardır davalarını olacaktır. Gerçekten emin olmak için tek yolu aslında görüntü almak için - hepsi, ya da ilk birkaç bayt, thomasrutter önerdiği ya gibi.

Bir kaç farklı yaklaşım vardır.

  • Dosyanın başında bir sihirli sayı bakarak içeriği koklayın. Örneğin, GIF (ASCII) dosyasının ilk beş bayt olarak GIF87 veya GIF89 kullanır. Görüntü zararlı içerik içeren görüntü veya eğer bir hata varsa ne yazık ki bu anlatamam. Burada resim dosyaları çeşitli (bu kullanmak için çekinmeyin) için bazı sihirli numaraları:

    "\xff\xd8\xff" => 'image/jpeg',
    "\x89PNG\x0d\x0a\x1a\x0a" => 'image/png',
    "II*\x00" => 'image/tiff',
    "MM\x00*" => 'image/tiff',
    "\x00\x00\x01\x00" => 'image/ico',
    "\x00\x00\x02\x00" => 'image/ico',
    "GIF89a" => 'image/gif',
    "GIF87a" => 'image/gif',
    "BM" => 'image/bmp',
    

    Bu gibi içeriği koklama muhtemelen en iyi şartları uygun olacak; Eğer sadece okumak ve bu nedenle (başlığına geçmiş) dosyasının ilk birkaç byte indirmek gerekecek.

  • Bu hata olmadan yükler görmek için GD kütüphanesini kullanarak görüntüyü yükleyin. Görüntü hatasız ya da değil, geçerli ise, bu size söyleyebilir. Bu tam görüntü indirerek gerektirir, çünkü ne yazık ki bu muhtemelen gereksinimlerini uymuyor.

  • Eğer gerçekten tüm görüntü için bir HTTP isteği yapmak istemiyorsanız, o zaman bu HTTP başlıklarını koklama ve alma hem dışladı. Ancak, bir şey de bağlantılı olduğu bağlamı tarafından bir görüntü olup olmadığını belirlemek için deneyebilirsiniz. Bir şeyin

Ne yazık ki, bu bir dosya geçerli bir resim gibi bir zararlı site tarafından Java gibi idam edilebilir zararlı içerik içeren bir ZIP dosyası ikisi de mümkündür - bkz the GIFAR exploit. Neredeyse kesinlikle GD gibi bir kütüphanede görüntü yükleme ve yumuşatıcı veya keskinleştirme (evrişim filtresi kullanarak yani) küçük bir miktar ve taze bir dosyaya {[kaydederek gibi, bunun üzerine bazı önemsiz olmayan filtre gerçekleştirerek bu güvenlik açığını önlemek için (1)]} genelinde herhangi bir meta veri aktarımı.

Şey tek başına içerik türüne göre bir görüntü olup olmadığını belirlemeye çalışırken dosya uzantısını kontrol gibi neredeyse güvenilmez, oldukça güvenilmez. Bir

Biz görüntü türünü kontrol etmek exif_imagetype kullanabilirsiniz, bu yüzden başka herhangi bir içerik türlerine izin değil. GIF resim türüne izin nasıl göstereceğim sadece resimlere izin ve biz Aşağıdaki örnek kod, birkaç görüntü türlerine onları kısıtlayabilirsiniz.

if (exif_imagetype('image.gif') != IMAGETYPE_GIF) {
    echo 'The picture is not a gif';
}

Görüntü türleri aşağıdaki kullanabilirsiniz,

 IMAGETYPE_GIF
 IMAGETYPE_JPEG
 IMAGETYPE_PNG
 IMAGETYPE_SWF
 IMAGETYPE_PSD
 IMAGETYPE_BMP
 IMAGETYPE_TIFF_II (intel byte order)
 IMAGETYPE_TIFF_MM (motorola byte order)
 IMAGETYPE_JPC
 IMAGETYPE_JP2
 IMAGETYPE_JPX
 IMAGETYPE_JB2
 IMAGETYPE_SWC
 IMAGETYPE_IFF
 IMAGETYPE_WBMP
 IMAGETYPE_XBM
 IMAGETYPE_ICO

Daha fazla bilgi için: link

Düzenleme: popüler görüntü uzantısı ile statik görüntüler için.

<?php
$imgExts = array("gif", "jpg", "jpeg", "png", "tiff", "tif");
$url ='path/to/image.png';
$urlExt = pathinfo($url, PATHINFO_EXTENSION);
if (in_array($urlExt, $imgExts)) {
    echo 'Yes, '.$url.' is an Image';
}

?>