Some websites use a small Favicon as a logo for their website. In some cases it would be nice if you are able to get this small image (icon) and use it for your PHP output. For example when you have a link to this site or when you are showing the RSS feed from this site.
I found 2 different scripts for getting the favicon from external websites using PHP scripting. Here are the scripts.
function getFavicon($url) {
$HTTPRequest = @fopen($url, 'r');
if ($HTTPRequest) {
stream_set_timeout($HTTPRequest, 0.1);
$html = fread($HTTPRequest, 4096);
$HTTPRequestData = stream_get_meta_data($HTTPRequest);
fclose($HTTPRequest);
if (!$HTTPRequestData['timed_out']) {
if (preg_match('/<link[^>]+rel="(?:shortcut )?icon"[^>]+?href="([^"]+?)"/si', $html, $matches)) {
$linkUrl = html_entity_decode($matches[1]);
if (substr($linkUrl, 0, 1) == '/') {
$urlParts = parse_url($url);
$faviconURL = $urlParts['scheme'].'://'.$urlParts['host'].$linkUrl;
} elseif (substr($linkUrl, 0, 7) == 'http://') {
$faviconURL = $linkUrl;
} elseif (substr($url, -1, 1) == '/') {
$faviconURL = $url.$linkUrl;
} else {
$faviconURL = $url.'/'.$linkUrl;
}
} else {
$urlParts = parse_url($url);
$faviconURL = $urlParts['scheme'].'://'.$urlParts['host'].'/favicon.ico';
}
$HTTPRequest = @fopen($faviconURL, 'r');
if ($HTTPRequest) {
stream_set_timeout($HTTPRequest, 0.1);
$favicon = fread($HTTPRequest, 8192);
$HTTPRequestData = stream_get_meta_data($HTTPRequest);
fclose($HTTPRequest);
if (!$HTTPRequestData['timed_out'] && strlen($favicon) < 8192) {
return $faviconURL;
}
}
}
}
return false;
}
And the other PHP script I found is:
<?php
################################################################################
#
# Favicon Class (work with favicons), ver. 1.0, June, 2006.
#
# (c) 2006 ControlStyle Company. All rights reserved.
# Developped by Nikolay I. Yarovoy, Dmitry V. Domojilov.
#
# http://www.controlstyle.com
# info@controlstyle.com
#
################################################################################
class favicon
{
var $ver = '1.1';
var $site_url = ''; # url of site
var $if_modified_since = 0; # cache
var $is_not_modified = false;
var $ico_type = 'ico'; # ico, gif or png only
var $ico_url = ''; # full uri to favicon
var $ico_exists = 'not checked'; # no comments
var $ico_data = ''; # ico binary data
var $output_data = ''; # output image binary data
# main proc
function favicon($site_url, $if_modified_since = 0)
{
$site_url = trim(str_replace('http://', '', trim($site_url)), '/');
$site_url = explode('/', $site_url);
$site_url = 'http://' . $site_url[0] . '/';
$this->site_url = $site_url;
$this->if_modified_since = $if_modified_since;
$this->get_ico_url();
$this->is_ico_exists();
$this->get_ico_data();
}
# get uri of favicon
function get_ico_url()
{
if ($this->ico_url == '')
{
$this->ico_url = $this->site_url . 'favicon.ico';
# get html of page
$h = @fopen($this->site_url, 'r');
if ($h)
{
$html = '';
while (!feof($h) and !preg_match('/<([s]*)body([^>]*)>/i', $html))
{
$html .= fread($h, 200);
}
fclose($h);
# search need <link> tag
if (preg_match('/<([^>]*)link([^>]*)(rel="icon"|rel="shortcut icon")([^>]*)>/iU', $html, $out))
{
$link_tag = $out[0];
if (preg_match('/href([s]*)=([s]*)"([^"]*)"/iU', $link_tag, $out))
{
$this->ico_type = (!(strpos($link_tag, 'png')===false)) ? 'png' : 'ico';
$ico_href = trim($out[3]);
if (strpos($ico_href, 'http://')===false)
{
$ico_href = rtrim($this->site_url, '/') . '/' . ltrim($ico_href, '/');
}
$this->ico_url = $ico_href;
}
}
}
}
return $this->ico_url;
}
# check that favicon is exists
function is_ico_exists()
{
if ($this->ico_exists=='not checked')
{
$h = @fopen($this->ico_url, 'r');
$this->ico_exists = ($h) ? true : false;
if ($h) fclose($h);
}
return $this->ico_exists;
}
# get ico data
function get_ico_data()
{
if ($this->ico_data=='' && $this->ico_url!=''
&& $this->ico_exists && !$this->is_not_modified)
{
# get ico data
$ico_z = parse_url($this->ico_url);
$ico_path = $ico_z['path'];
$ico_host = $ico_z['host'];
$ico_ims = gmdate('D, d M Y H:i:s', $this->if_modified_since) . ' GMT';
$fp = @fsockopen($ico_host, 80);
if ($fp)
{
$out = "GET {$ico_path} HTTP/1.1\r\n";
$out .= "Host: {$ico_host}\r\n";
$out .= "User-Agent=Mozilla/5.0 (Windows; U; Windows NT
5.1; ru; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3\r\n";
$out .= "If-Modified-Since: {$ico_ims}\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
$data = '';
while (!feof($fp)) $data .= fgets($fp, 128);
fclose($fp);
$response = substr($data, 0, 15);
$this->is_not_modified = !(strpos($response, '304')===false);
if ($this->is_not_modified)
{
$this->ico_data = 'not modified';
}
else
{
$data = explode("\r\n\r\n", $data);
if (count($data)>0)
{
unset($data[0]);
$this->ico_data = implode("\r\n\r\n", $data);
}
}
$this->output_data = '';
}
}
return $this->ico_data;
}
# get output data
function get_output_data()
{
if ($this->output_data=='')
{
if ($this->ico_data=='not modified')
{
# icon is not modified since defined time
$this->output_data = 'not modified';
}
elseif($this->ico_data=='')
{
# error(s) in getting icon data
$this->output_data = $this->empty_png();
}
else
{
# convert ico to png, gif & return
if (substr($this->ico_data, 0, 3)==='GIF') $this->ico_type = 'gif';
$this->output_data = $this->ico_data;
if ($this->ico_type==='ico')
{
$this->output_data = $this->ico2png($this->output_data);
}
if ($this->ico_type==='gif')
{
$this->output_data = $this->gif2png($this->output_data);
}
}
}
return $this->output_data;
}
# if error or icon is not found we output empty png image
function empty_png()
{
$res = '';
$im = imagecreatetruecolor(16, 16);
$color = imagecolorallocate($im, 255, 255, 255);
imagefill($im, 1, 1, $color);
# output png
ob_start();
# imagesavealpha($im, true);
imagepng($im);
imagedestroy($im);
$res = ob_get_clean();
return $res;
}
# Convert gif to png function,
# support gif-functions by GD is needed
function gif2png($gif)
{
$im2 = imagecreatefromstring($gif);
# background alpha is disabled because IE 5.5 + have bug with alpha-channels
# by default background color is white
# imagealphablending($im, false);
# imagefilledrectangle($im, 0, 0, 16, 16, $color);
# imagealphablending($im, true);
$im = imagecreatetruecolor(16, 16);
$color = imagecolorallocate($im, 255, 255, 255);
imagefill($im, 1, 1, $color);
imagecopy($im, $im2, 0, 0, 0, 0, 16, 16);
# output png
ob_start();
# imagesavealpha($im, true);
imagepng($im);
imagedestroy($im);
imagedestroy($im2);
$res = ob_get_clean();
return $res;
}
# Convert ico to png function,
# information about ico format is accessible on a site http://kainsk.tomsk.ru/g2003/sys26/oswin.htm,
function ico2png($ico)
{
$res = '';
while(!isset($tmp))
{
$tmp = '';
# get ICONDIR struct & check that it is correct ico format
$icondir = unpack('sidReserved/sidType/sidCount', substr($ico, 0, 6));
if ($icondir['idReserved']!=0 || $icondir['idType']!=1 || $icondir['idCount']<1) break;
$icondir['idEntries'] = array();
$entry = array();
for($i=0; $i<$icondir['idCount']; $i++)
{
$entry =
unpack('CbWidth/CbHeight/CbColorCount/CbReserved/swPlanes/swBitCount/LdwBytesInRes/LdwImageOffset',
substr($ico, 6 + $i*16, 16));
$icondir['idEntries'][] = $entry;
}
# select need icon & get it raw data
$iconres = '';
$bpx = 1; # bits per pixel
$idx = 0; # index of need icon
foreach($icondir['idEntries'] as $k=>$entry)
{
if ($entry['bWidth']==16 &&
isset($entry['swBitCount']) && $entry['swBitCount']>$bpx
&& $entry['swBitCount']<33)
{
$idx = $k;
$bpx = $entry['swBitCount'];
}
}
$iconres = substr($ico, $icondir['idEntries'][$idx]['dwImageOffset'], $icondir['idEntries'][$idx]['dwBytesInRes']);
unset($ico);
unset($icondir);
# getting bitmap info
$bitmap_info = array();
$bitmap_info['header'] =
unpack('LbiSize/LbiWidth/LbiHeight/SbiPlanes/SbiBitCount/LbiCompression/LbiSizeImage/LbiXPelsPerMeter/LbiYPelsPerMeter/LbiClrUsed/LbiClrImportant',
substr($iconres, 0, 40));
$bitmap_info['header']['biHeight'] = $bitmap_info['header']['biHeight'] / 2;
$number_color = 0;
if ($bitmap_info['header']['biBitCount'] > 16)
{
$number_color = 0;
$sizecolor =
$bitmap_info['header']['biWidth']*$bitmap_info['header']['biBitCount']
* $bitmap_info['header']['biHeight'] / 8;
}
elseif ( $bitmap_info['header']['biBitCount'] < 16)
{
$number_color = (int) pow(2, $bitmap_info['header']['biBitCount']);
$sizecolor =
$bitmap_info['header']['biWidth']*$bitmap_info['header']['biBitCount']
* $bitmap_info['header']['biHeight'] / 8;
if ($bitmap_info['header']['biBitCount']=='1') $sizecolor = $sizecolor * 2;
}
else return $res;
$rgb_table_size = 4 * $number_color;
for($i=0; $i<$number_color; $i++)
{
$bitmap_info['colors'][] = unpack('CrgbBlue/CrgbGreen/CrgbRed/CrgbReserved', substr($iconres, 40 + $i*4, 4));
}
$current_offset = 40 + $number_color * 4;
$arraycolor = array();
for($i=0; $i<$sizecolor; $i++)
{
$value = unpack('Cvalue', substr($iconres, $current_offset, 1));
$arraycolor[] = $value['value'];
$current_offset++;
}
# background alpha is disabled because IE 5.5 + have bug with alpha-channels
# by default background color is white
# imagealphablending($im, false);
# imagefilledrectangle($im, 0, 0, 16, 16, $color);
# imagealphablending($im, true);
$im = imagecreatetruecolor(16, 16);
$color = imagecolorallocate($im, 255, 255, 255);
imagefill($im, 1, 1, $color);
# getting mask
$alpha = '';
for($i=0; $i<16; $i++)
{
$z = unpack('Cx/Cy', substr($iconres, $current_offset, 2));
$z = str_pad(decbin($z['x']), 8, '0', STR_PAD_RIGHT) . str_pad(decbin($z['y']), 8, '0', STR_PAD_LEFT);
$alpha .= $z;
$current_offset = $current_offset + 4;
}
# drawing image
$ico_size = 16;
$off = 0; # range (0-255)
# cases for different color depth
switch ($bitmap_info['header']['biBitCount'])
{
###################### for 32 bit icons ######################
case 32:
for($y=0; $y<$ico_size; $y++)
{
for($x=0; $x<$ico_size; $x++)
{
$a = round((255-$arraycolor[$off*4+3])/2);
$a = ($a<0) ? 0 : $a;
$a = ($a>127) ? 127 : $a;
$color = imagecolorallocatealpha($im,
$arraycolor[$off*4+2], $arraycolor[$off*4+1], $arraycolor[$off*4], $a);
imagesetpixel($im, $x, $ico_size-1-$y, $color);
$off++;
}
}
break;
###################### for 24 bit icons ######################
case 24:
for($y=0; $y<$ico_size; $y++)
{
for($x=0; $x<$ico_size; $x++)
{
$valpha = ($alpha[$off]=='1') ? 127 : 0;
$color = imagecolorallocatealpha($im,
$arraycolor[$off*3+2], $arraycolor[$off*3+1], $arraycolor[$off*3],
$valpha);
imagesetpixel ($im, $x, $ico_size-1-$y, $color);
$off++;
}
}
break;
###################### for 08 bit icons ######################
case 8:
for($y=0; $y<$ico_size; $y++)
{
for($x=0; $x<$ico_size; $x++)
{
$valpha = ($alpha[$off]=='1') ? 127 : 0;
$c = $arraycolor[$off];
$c = $bitmap_info['colors'][$c];
$color = imagecolorallocatealpha($im, $c['rgbRed'], $c['rgbGreen'], $c['rgbBlue'], $valpha);
imagesetpixel ($im, $x, $ico_size-1-$y, $color);
$off++;
}
}
break;
###################### for 04 bit icons ######################
# 318 = 22 (header) + 40 (bitmap_info) + 16 * 4 (colors) + 128 (pixels) + 64 (mask)
case 4:
for($y=0; $y<$ico_size; $y++)
{
for($x=0; $x<$ico_size; $x++)
{
$valpha = ($alpha[$off]=='1') ? 127 : 0;
$c = ($arraycolor[floor($off/2)]);
$c = str_pad(decbin($c), 8, '0', STR_PAD_LEFT);
$m = (fmod($off+1, 2)==0) ? 1 : 0;
$c = bindec(substr($c, $m*4, 4));
$c = $bitmap_info['colors'][$c];
$color = imagecolorallocatealpha($im, $c['rgbRed'], $c['rgbGreen'], $c['rgbBlue'], $valpha);
imagesetpixel ($im, $x, $ico_size-1-$y, $color);
$off++;
}
}
break;
###################### for 01 bit icons ######################
# 198 = 22 (header) + 40 (bitmap_info) + 2 * 4 (colors) + 64 (pixels, but real 32 needed?) + 64 (mask)
case 1:
for($y=0; $y<$ico_size; $y++)
{
for($x=0; $x<$ico_size; $x++)
{
$valpha = ($alpha[$off]=='1') ? 127 : 0;
$c = ($arraycolor[floor($off/8)]); # меняем байт каждые 8 пикселей
$c = str_pad(decbin($c), 8, '0', STR_PAD_LEFT);
$m = fmod($off+8, 8) + 1; # bit number
$c = (int) substr($c, $m-1, 1);
$c = $bitmap_info['colors'][$c];
$color = imagecolorallocatealpha($im, $c['rgbRed'], $c['rgbGreen'], $c['rgbBlue'], $valpha);
imagesetpixel ($im, $x, $ico_size-1-$y, $color);
$off++;
}
$off = $off + 16;
}
break;
##############################################################
default:
return '';
}
# output png
ob_start();
# imagesavealpha($im, true);
imagepng($im);
imagedestroy($im);
$res = ob_get_clean();
}
return $res;
}
}
?>
And you can use the above PHP script with the following call:
<?php
require_once('favicon.inc.php');
$favicon = new favicon('http://www.controlstyle.ru/', 0);
$fv = $favicon->get_output_data();
if ($fv!=='')
{
header('Content-type: image/png');
echo $fv;
}
?>
What would be nice is some PHP code / script that can convert the found favicon to a GIF / JPG or PNG image so you can use it inside the HTML code.