I've written a function to take an image path, add some text to the end of it, then join it back together. I'm trying to write an if else branch to test if the file exists after I've appended the new text to the image.
For example, if I request the image path:
http://example.com/image1.jpg
It could be modified to this:
http://example.com/image1-150x100.jpg
The function is intended for WordPress, so takes the $post->ID argument, the custom field name, width and height of the intended target.
Here is the function:
function get_galleria_image ( $post_id, $customFieldName, $width, $height ) {
$imagePath = get_post_meta($post_id, $customFieldName, true);
$splitImage = explode('.', $imagePath);
$count = count($splitImage);
$firstHalf = array_slice($splitImage, 0, $count-1);
$secondHalf = array_slice($splitImage, $count-1);
$secondHalf[0] = '-' . $width . 'x' . $height . '.' . $secondHalf[0];
$firstHalfJoined = implode('.', $firstHalf);
$completedString = $firstHalfJoined . $secondHalf[0];
// if the filename with the joined string does not exist, return the original image
if (file_exists($completedString)){
return $completedString;
} else {
return $imagePath;
}
}
I know this is crude, so any ideas to condense this code and make it "better" is welcomed. What I'm finding is that the function always returns the original image path. Can file_exists() take an absolute path like "http://example.com/image1.jpg', or will it only accept a root-style absolute path, like '/path/to/file/image1.jpg'?
file_exists wont accept url path. Try this for url path to check if the given url is an image or not
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;
}
As far as I know, file_exists() only checks if a file or directory on the local file system exits. You may want to connect to another server via fsockopen() and then check the HTTP-Code to find out if the file exists.
// you will need to set $host and $file
$sock = fsockopen ( $host );
fwrite ( $sock, "HEAD ".$image." HTTP/1.1\r\n" );
fwrite ( $sock, "Host: ".$file."\r\n" );
fwrite ( $sock, "Connection: close\r\n\r\n" );
// Get the first twelve characters of the response - enough to check the response code
if ( fgets ( $sock, 12 ) == "HTTP/1.1 404" )
//file doesn't exist
else
//file exists
fclose ( $sock );
to make more compact the first part of your procedure you can do something like:
$completedString = preg_replace("/(.+)\.([^.]+)$/siU", "$1" . "-" . $width ."x" . $height . "$2", $splitImage);
then use the function posted from #ayush to check the file on the remote server
if(#getimagesize($imghttppath))
{
echo '<img src="'. $imghttppath . '" />';
}
else
{
echo '<img src="http://www.domain.com/images/default.jpg" />';
}
It's kinda an unorthodox use of getimagesize, and it has to be # unless you turn off errors because it returns an error if the file doesn't exist. But it's about as simple as you can get. Works with External URLs, Local URLs, Local Absolute Paths, and Relative Paths to the working directory to check whether or not an image exists and is an actual image.
Related
So I've killed an entire day trying to do something that would take someone who actually knows how to write php less than 2mins. Frustrating, but I learn by doing and trying to figure things out.
I'll feel like a failure for not getting this, but 8hrs and counting (yeah I know lame) is enough.
Can somebody tell me what's wrong with this equation...
$dir = '../folder';
$images_array = glob($dir.'*.jpg');
$values['options'] = array( '<img src="$images_array"/>');
It's probably obvious, but all I need is for the images in mysite.com/folder to be loaded into the $values['options'] array.
If I simply state the path to a single image in then the image is displayed (obviously because it's not reliant on anything else.)
Thanks.
#hellcode
Sorry about the mess in the 'comment' below your response. Unfortunately I couldn't get this to work? Maybe I need to provide more context.
The images in the folder are going to be used as checkbox items in a form. This was my original code (not working):
add_filter('frm_setup_new_fields_vars', 'frm_set_checked', 20, 2);
function frm_set_checked($values, $field){
if($field->id == 187){
$dir = '../folder';
$images_array = glob($dir.'*.jpg');
$values['options'] = array( '<img src="$images_array"/>');
$values['use_key'] = true;
}
return $values;
}
I added your code like so:
add_filter('frm_setup_new_fields_vars', 'frm_set_checked', 20, 2);
function frm_set_checked($values, $field){
if($field->id == 187){
$dir = '../folder';
$images_array = glob($dir.'*.jpg');
$values['options'] = array();
foreach($images_array as $image) {
$values['options'][] = '<img src="'.$image.'"/>';
}
$values['use_key'] = true;
}
return $values;
}
But it didn't pull the files in unfortunately :(
Try:
$dir = '../folder';
$images_array = glob($dir.'*.jpg');
$values['options'] = array();
foreach($images_array as $image) {
$values['options'][] = '<img src="'.$image.'"/>';
}
Well, one problem may be that the glob() function uses the current directory, which can be anything, unless you use the chdir() function.
One thing that is definitely a problem is that you are using glob()'s return value, $images_array, as a string. Because it is an array that will not work.
Here is something that should work.
// Allowed image formats (also known as a "whitelist")
$allowedFormats = ['jpg', 'jpeg', 'gif', 'png'];
// Array for holding any found images
$foundImages = [];
// Get the real path from the relative path
$path = realpath('../folder');
if ($path === false) {
die('The path does not exist!');
}
// Open a folder handle
$folder = dir($path);
// Read what is in the folder
while (($item = $folder->read()) !== false) {
// .. is the parent folder, . is the current folder
if ($item === '..' or $item === '.') {
continue;
}
// Find the last dot in the filename
// If it was not found then not image file
$lastDot = strrpos($item, '.');
if ($lastDot === false) {
continue;
}
// Get the filetype and make sure it is
// an allowed format
$filetype = substr($item, $lastDot);
if ( ! in_array($filetype, $allowedFormats)) {
continue;
}
// Okay, looks like an image!
$foundImages[] = $item;
}
// Close the folder handle
$folder->close();
I'm not a native PHP developer but I make do with what I can find and hack together out there, so please excuse me if this doesn't make too much sense:
I have a simple (so it seems) script that takes two arguments in the URL. One is a simple string (title of the ZIP to be created) and the other is a serialized array of audio tracks that point to the files on the server that need zipping. These then pass just fine and are unserialized etc. Here's the script:
<?php
$audioTitleVar = unserialize(rawurldecode($_GET['audioTitle']));
$audioArrayVar = unserialize(rawurldecode($_GET['audioArray']));
function create_zip( $files = array(), $destination = '', $overwrite = true ) {
if(file_exists($destination) && !$overwrite) { return false; }
$valid_files = array();
if(is_array($files)) {
foreach($files as $file) {
if( file_exists($_SERVER['DOCUMENT_ROOT'] . str_replace("http://mydomain.com","", $file)) ) {
$valid_files[] = $_SERVER['DOCUMENT_ROOT'] . str_replace("http://mydomain.com","", $file);
}
}
}
if(count($valid_files)) {
$zip = new ZipArchive();
if($zip->open($destination,$overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
foreach( $valid_files as $file ) {
$just_name = preg_replace("/(.*)\/?([^\/]+)/","$2",$file);
$zip->addFile($file,$just_name);
//$zip->addFile($file,$file);
}
//echo '<p>The zip archive contains ' . $zip->numFiles . ' files with a status of ' . $zip->status . '</p>';
$zip->close();
return file_exists($destination);
} else {
return false;
}
}
$fileName = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/themes/jones/zip/' . $audioTitleVar . '.zip';
create_zip( $audioArrayVar, $fileName, true );
//echo '<p>File Path: ' . $fileName . '</p>';
var_dump(file_exists($fileName));
?>
I guess my real issue here, is that, although the script DOES NOT error...no ZIP is created. I have, over time placed outputs in the function at certain parts to see if it was even getting there, and it is - so I'm stumped on this.
What I really need is for one of you guys to scan the script over to see if there's anything glaringly obvious that just won't work!
Could it be a permissions thing? Should PHP be running in CGI mode or Apache? Or does this not make a difference?
The bones of this script were taken from: http://davidwalsh.name/create-zip-php but it's never worked even with that version alone.
PS - I'd just like to add, that if I uncomment the line that tells me how many files are in the ZIP etc, it seems to return the correct info...but the final check on whether the file exists returns false.
Ok, I have finally got it working.
Seems there was something in the addFile() that corrupted the code.
I changed this:
foreach( $valid_files as $file ) {
$just_name = preg_replace("/(.*)\/?([^\/]+)/","$2",$file);
$zip->addFile($file,$just_name);
//$zip->addFile($file,$file);
}
To this:
foreach( $valid_files as $file ) {
// Use basename to get JUST the file name from the path.
$zip->addFile($file, basename($file) );
}
The basename function gets only the file NAME to then place in the ZIP. Before it was the whole path on the server, and this was causing Windows to choke on it.
Hope this helps someone someday.
I need to see if a specific image exists on my cdn.
I've tried the following and it doesn't work:
if (file_exists(http://www.example.com/images/$filename)) {
echo "The file exists";
} else {
echo "The file does not exist";
}
Even if the image exists or doesn't exist, it always says "The file exists". I'm not sure why its not working...
You need the filename in quotation marks at least (as string):
if (file_exists('http://www.mydomain.com/images/'.$filename)) {
… }
Also, make sure $filename is properly validated. And then, it will only work when allow_url_fopen is activated in your PHP config
if (file_exists('http://www.mydomain.com/images/'.$filename)) {}
This didn't work for me. The way I did it was using getimagesize.
$src = 'http://www.mydomain.com/images/'.$filename;
if (#getimagesize($src)) {
Note that the '#' will mean that if the image does not exist (in which case the function would usually throw an error: getimagesize(http://www.mydomain.com/images/filename.png) [function.getimagesize]: failed) it will return false.
Try like this:
$file = '/path/to/foo.txt'; // 'images/'.$file (physical path)
if (file_exists($file)) {
echo "The file $file exists";
} else {
echo "The file $file does not exist";
}
Well, file_exists does not say if a file exists, it says if a path exists. ⚡⚡⚡⚡⚡⚡⚡
So, to check if it is a file then you should use is_file together with file_exists to know if there is really a file behind the path, otherwise file_exists will return true for any existing path.
Here is the function i use :
function fileExists($filePath)
{
return is_file($filePath) && file_exists($filePath);
}
Here is the simplest way to check if a file exist:
if(is_file($filename)){
return true; //the file exist
}else{
return false; //the file does not exist
}
A thing you have to understand first: you have no files.
A file is a subject of a filesystem, but you are making your request using HTTP protocol which supports no files but URLs.
So, you have to request an unexisting file using your browser and see the response code. if it's not 404, you are unable to use any wrappers to see if a file exists and you have to request your cdn using some other protocol, FTP for example
If the file is on your local domain, you don't need to put the full URL. Only the path to the file. If the file is in a different directory, then you need to preface the path with "."
$file = './images/image.jpg';
if (file_exists($file)) {}
Often times the "." is left off which will cause the file to be shown as not existing, when it in fact does.
public static function is_file_url_exists($url) {
if (#file_get_contents($url, 0, NULL, 0, 1)) {
return 1;
}
return 0;
}
There is a major difference between is_file and file_exists.
is_file returns true for (regular) files:
Returns TRUE if the filename exists and is a regular file, FALSE otherwise.
file_exists returns true for both files and directories:
Returns TRUE if the file or directory specified by filename exists; FALSE otherwise.
Note: Check also this stackoverflow question for more information on this topic.
You have to use absolute path to see if the file exists.
$abs_path = '/var/www/example.com/public_html/images/';
$file_url = 'http://www.example.com/images/' . $filename;
if (file_exists($abs_path . $filename)) {
echo "The file exists. URL:" . $file_url;
} else {
echo "The file does not exist";
}
If you are writing for CMS or PHP framework then as far as I know all of them have defined constant for document root path.
e.g WordPress uses ABSPATH which can be used globally for working with files on the server using your code as well as site url.
Wordpress example:
$image_path = ABSPATH . '/images/' . $filename;
$file_url = get_site_url() . '/images/' . $filename;
if (file_exists($image_path)) {
echo "The file exists. URL:" . $file_url;
} else {
echo "The file does not exist";
}
I'm going an extra mile here :). Because this code would no need much maintenance and pretty solid, I would write it with as shorthand if statement:
$image_path = ABSPATH . '/images/' . $filename;
$file_url = get_site_url() . '/images/' . $filename;
echo (file_exists($image_path))?'The file exists. URL:' . $file_url:'The file does not exist';
Shorthand IF statement explained:
$stringVariable = ($trueOrFalseComaprison > 0)?'String if true':'String if false';
you can use cURL. You can get cURL to only give you the headers, and not the body, which might make it faster. A bad domain could always take a while because you will be waiting for the request to time-out; you could probably change the timeout length using cURL.
Here is example:
function remoteFileExists($url) {
$curl = curl_init($url);
//don't fetch the actual page, you only want to check the connection is ok
curl_setopt($curl, CURLOPT_NOBODY, true);
//do request
$result = curl_exec($curl);
$ret = false;
//if request did not fail
if ($result !== false) {
//if request was ok, check response code
$statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($statusCode == 200) {
$ret = true;
}
}
curl_close($curl);
return $ret;
}
$exists = remoteFileExists('http://stackoverflow.com/favicon.ico');
if ($exists) {
echo 'file exists';
} else {
echo 'file does not exist';
}
You can use the file_get_contents function to access remote files. See http://php.net/manual/en/function.file-get-contents.php for details.
If you are using curl, you can try the following script:
function checkRemoteFile($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
// don't download content
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if(curl_exec($ch)!==FALSE)
{
return true;
}
else
{
return false;
}
}
Reference URL: https://hungred.com/how-to/php-check-remote-email-url-image-link-exist/
try this :
if (file_exists(FCPATH . 'uploads/pages/' . $image)) {
unlink(FCPATH . 'uploads/pages/' . $image);
}
If path to your image is relative to the application root it is better to use something like this:
function imgExists($path) {
$serverPath = $_SERVER['DOCUMENT_ROOT'] . $path;
return is_file($serverPath)
&& file_exists($serverPath);
}
Usage example for this function:
$path = '/tmp/teacher_photos/1546595125-IMG_14112018_160116_0.png';
$exists = imgExists($path);
if ($exists) {
var_dump('Image exists. Do something...');
}
I think it is good idea to create something like library to check image existence applicable for different situations. Above lots of great answers you can use to solve this task.
Here is one function that I use to check any kind of URL. It will check response code is URL exists or not.
/*
* Check is URL exists
*
* #param $url Some URL
* #param $strict You can add it true to check only HTTP 200 Response code
* or you can add some custom response code like 302, 304 etc.
*
* #return string or NULL
*/
function is_url_exists($url, $strict = false)
{
if (is_int($strict) && $strict >= 100 && $strict < 600 || is_array($strict)) {
if(is_array($strict)) {
$response = $strict;
} else {
$response = [$strict];
}
} else if ($strict === true || $strict === 1) {
$response = [200];
} else {
$response = [200,202,301,302,303];
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$return = curl_exec($ch);
if (!curl_errno($ch) && $return !== false) {
return ( in_array(curl_getinfo($ch, CURLINFO_HTTP_CODE), $response) !== false );
}
return false;
}
This is exactly what you need.
Read first 5 bytes form HTTP using fopen() and fread() then use this:
DEFINE("GIF_START","GIF");
DEFINE("PNG_START",pack("C",0x89)."PNG");
DEFINE("JPG_START",pack("CCCCCC",0xFF,0xD8,0xFF,0xE0,0x00,0x10));
to detect image.
file_exists reads not only files, but also paths. so when $filename is empty, the command would run as if it's written like this:
file_exists("http://www.example.com/images/")
if the directory /images/ exists, the function will still return true.
I usually write it like this:
// !empty($filename) is to prevent an error when the variable is not defined
if (!empty($filename) && file_exists("http://www.example.com/images/$filename"))
{
// do something
}
else
{
// do other things
}
file_exists($filepath) will return a true result for a directory and full filepath, so is not always a solution when a filename is not passed.
is_file($filepath) will only return true for fully filepaths
you need server path with file_exists
for example
if (file_exists('/httpdocs/images/'.$filename)) {echo 'File exist'; }
if(#getimagesize($image_path)){
...}
Is working for me.
Try it:
$imgFile = 'http://www.yourdomain.com/images/'.$fileName;
if (is_file($imgFile) && file_exists($imgFile)) {
echo 'File exists';
} else {
echo 'File not exist';
}
Another Way:
$imgFile = 'http://www.yourdomain.com/images/'.$fileName;
if (is_file($imgFile)) {.....
}
I want to get, requested website's favicon with PHP. I have been recommended using Google's favicon service but it is not functional. I want to do something on my own but don't know regex usage.
I found a class on Google that works on most cases but it has unacceptable error rate. You can have a look here: http://www.controlstyle.com/articles/programming/text/php-favicon/
Can somebody please help me about getting favicon using regex, please?
Use the S2 service provided by google. It is as simple as this
http://www.google.com/s2/favicons?domain=www.yourdomain.com
Scraping this would be much easier, that trying to do it yourself.
Quick and dirty:
<?php
$url = 'http://example.com/';
$doc = new DOMDocument();
$doc->strictErrorChecking = FALSE;
$doc->loadHTML(file_get_contents($url));
$xml = simplexml_import_dom($doc);
$arr = $xml->xpath('//link[#rel="shortcut icon"]');
echo $arr[0]['href'];
It looks like http://www.getfavicon.org/?url=domain.com (FAQ) reliably scrapes a website's favicon. I realise it's a 3rd-party service but I think it's a worthy alternative to the Google favicon service.
I've been doing something similar and I checked this with a bunch of URL and all seemed to work. URL doesn't have to be a base URL
function getFavicon($url){
# make the URL simpler
$elems = parse_url($url);
$url = $elems['scheme'].'://'.$elems['host'];
# load site
$output = file_get_contents($url);
# look for the shortcut icon inside the loaded page
$regex_pattern = "/rel=\"shortcut icon\" (?:href=[\'\"]([^\'\"]+)[\'\"])?/";
preg_match_all($regex_pattern, $output, $matches);
if(isset($matches[1][0])){
$favicon = $matches[1][0];
# check if absolute url or relative path
$favicon_elems = parse_url($favicon);
# if relative
if(!isset($favicon_elems['host'])){
$favicon = $url . '/' . $favicon;
}
return $favicon;
}
return false;
}
According to Wikipedia, there are 2 major methods which can be used by websites to have a favicon picked up by a browser. The first is as Steve mentioned, having the icon stored as favicon.ico in the root directory of the webserver. The second is to reference the favicon via the HTML link tag.
To cover all of these cases, the best idea would be to test for the presence of the favicon.ico file first, and if it is not present, search for either the <link rel="icon" or <link rel="shortcut icon" part in the source (limited to the HTML head node) until you find the favicon. It is up to you whether you choose to use regex, or some other string search option (not to mention the built in PHP ones). Finally, this question may be of some help to you.
I've implemented a favicon grabber of my own, and I detailed the usage in another StackOverflow post here: Get website's favicon with JS
Thanks, and let me know if it helps you. Also, any feedback is greatly appreciated.
First Method in which we can search it from fevicon.ico if found than it will show it up else not
<?php
$userPath=$_POST["url"];
$path="http://www.".$userPath."/favicon.ico";
$header= get_headers($path);
if(preg_match("|200|", $header[0]))
{
echo '<img src="'.$path.'">';
}
else
{
echo "<span class=error>Not found</span>";
}
?>
In other method you can search for icon and get that icon file
<?php
$website=$_POST["url"];
$fevicon= getFavicon($website);
echo '<img src="http://www.'.$website.'/'.$fevicon.'">';
function getFavicon($site)
{
$html=file_get_contents("http://www.".$site);
$dom=new DOMDocument();
#$dom->loadHTML($html);
$links=$dom->getElementsByTagName('link');
$fevicon='';
for($i=0;$i < $links->length;$i++ )
{
$link=$links->item($i);
if($link->getAttribute('rel')=='icon'||$link->getAttribute('rel')=="Shortcut Icon"||$link->getAttribute('rel')=="shortcut icon")
{
$fevicon=$link->getAttribute('href');
}
}
return $fevicon;
}
?>
PHP Grab Favicon
This is a comfortable way with many parameter to get the favicon from a page URL.
How it Works
Check if the favicon already exists local or no save is wished, if so return path & filename
Else load URL and try to match the favicon location with regex
If we have a match the favicon link will be made absolute
If we have no favicon we try to get one in domain root
If there is still no favicon we randomly try google, faviconkit & favicongrabber API
If favicon should be saved try to load the favicon URL
If wished save the Favicon for the next time and return the path & filename
So it combine both ways: Try to get the Favicon from the Page and if that don't work use an "API" Service that give back the Favicon ;-)
<?php
/*
PHP Grab Favicon
================
> This `PHP Favicon Grabber` use a given url, save a copy (if wished) and return the image path.
How it Works
------------
1. Check if the favicon already exists local or no save is wished, if so return path & filename
2. Else load URL and try to match the favicon location with regex
3. If we have a match the favicon link will be made absolute
4. If we have no favicon we try to get one in domain root
5. If there is still no favicon we randomly try google, faviconkit & favicongrabber API
6. If favicon should be saved try to load the favicon URL
7. If wished save the Favicon for the next time and return the path & filename
How to Use
----------
```PHP
$url = 'example.com';
$grap_favicon = array(
'URL' => $url, // URL of the Page we like to get the Favicon from
'SAVE'=> true, // Save Favicon copy local (true) or return only favicon url (false)
'DIR' => './', // Local Dir the copy of the Favicon should be saved
'TRY' => true, // Try to get the Favicon frome the page (true) or only use the APIs (false)
'DEV' => null, // Give all Debug-Messages ('debug') or only make the work (null)
);
echo '<img src="'.grap_favicon($grap_favicon).'">';
```
Todo
----
Optional split the download dir into several sub-dirs (MD5 segment of filename e.g. /af/cd/example.com.png) if there are a lot of favicons.
Infos about Favicon
-------------------
https://github.com/audreyr/favicon-cheat-sheet
###### Copyright 2019 Igor Gaffling
*/
$testURLs = array(
'http://aws.amazon.com',
'http://www.apple.com',
'http://www.dribbble.com',
'http://www.github.com',
'http://www.intercom.com',
'http://www.indiehackers.com',
'http://www.medium.com',
'http://www.mailchimp.com',
'http://www.netflix.com',
'http://www.producthunt.com',
'http://www.reddit.com',
'http://www.slack.com',
'http://www.soundcloud.com',
'http://www.stackoverflow.com',
'http://www.techcrunch.com',
'http://www.trello.com',
'http://www.vimeo.com',
'https://www.whatsapp.com/',
'https://www.gaffling.com/',
);
foreach ($testURLs as $url) {
$grap_favicon = array(
'URL' => $url, // URL of the Page we like to get the Favicon from
'SAVE'=> true, // Save Favicon copy local (true) or return only favicon url (false)
'DIR' => './', // Local Dir the copy of the Favicon should be saved
'TRY' => true, // Try to get the Favicon frome the page (true) or only use the APIs (false)
'DEV' => null, // Give all Debug-Messages ('debug') or only make the work (null)
);
$favicons[] = grap_favicon($grap_favicon);
}
foreach ($favicons as $favicon) {
echo '<img title="'.$favicon.'" style="width:32px;padding-right:32px;" src="'.$favicon.'">';
}
echo '<br><br><tt>Runtime: '.round((microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"]),2).' Sec.';
function grap_favicon( $options=array() ) {
// Ini Vars
$url = (isset($options['URL']))?$options['URL']:'gaffling.com';
$save = (isset($options['SAVE']))?$options['SAVE']:true;
$directory = (isset($options['DIR']))?$options['DIR']:'./';
$trySelf = (isset($options['TRY']))?$options['TRY']:true;
$DEBUG = (isset($options['DEV']))?$options['DEV']:null;
// URL to lower case
$url = strtolower($url);
// Get the Domain from the URL
$domain = parse_url($url, PHP_URL_HOST);
// Check Domain
$domainParts = explode('.', $domain);
if(count($domainParts) == 3 and $domainParts[0]!='www') {
// With Subdomain (if not www)
$domain = $domainParts[0].'.'.
$domainParts[count($domainParts)-2].'.'.$domainParts[count($domainParts)-1];
} else if (count($domainParts) >= 2) {
// Without Subdomain
$domain = $domainParts[count($domainParts)-2].'.'.$domainParts[count($domainParts)-1];
} else {
// Without http(s)
$domain = $url;
}
// FOR DEBUG ONLY
if($DEBUG=='debug')print('<b style="color:red;">Domain</b> #'.#$domain.'#<br>');
// Make Path & Filename
$filePath = preg_replace('#\/\/#', '/', $directory.'/'.$domain.'.png');
// If Favicon not already exists local
if ( !file_exists($filePath) or #filesize($filePath)==0 ) {
// If $trySelf == TRUE ONLY USE APIs
if ( isset($trySelf) and $trySelf == TRUE ) {
// Load Page
$html = load($url, $DEBUG);
// Find Favicon with RegEx
$regExPattern = '/((<link[^>]+rel=.(icon|shortcut icon|alternate icon)[^>]+>))/i';
if ( #preg_match($regExPattern, $html, $matchTag) ) {
$regExPattern = '/href=(\'|\")(.*?)\1/i';
if ( isset($matchTag[1]) and #preg_match($regExPattern, $matchTag[1], $matchUrl)) {
if ( isset($matchUrl[2]) ) {
// Build Favicon Link
$favicon = rel2abs(trim($matchUrl[2]), 'http://'.$domain.'/');
// FOR DEBUG ONLY
if($DEBUG=='debug')print('<b style="color:red;">Match</b> #'.#$favicon.'#<br>');
}
}
}
// If there is no Match: Try if there is a Favicon in the Root of the Domain
if ( empty($favicon) ) {
$favicon = 'http://'.$domain.'/favicon.ico';
// Try to Load Favicon
if ( !#getimagesize($favicon) ) {
unset($favicon);
}
}
} // END If $trySelf == TRUE ONLY USE APIs
// If nothink works: Get the Favicon from API
if ( !isset($favicon) or empty($favicon) ) {
// Select API by Random
$random = rand(1,3);
// Faviconkit API
if ($random == 1 or empty($favicon)) {
$favicon = 'https://api.faviconkit.com/'.$domain.'/16';
}
// Favicongrabber API
if ($random == 2 or empty($favicon)) {
$echo = json_decode(load('http://favicongrabber.com/api/grab/'.$domain,FALSE),TRUE);
// Get Favicon URL from Array out of json data (# if something went wrong)
$favicon = #$echo['icons']['0']['src'];
}
// Google API (check also md5() later)
if ($random == 3) {
$favicon = 'http://www.google.com/s2/favicons?domain='.$domain;
}
// FOR DEBUG ONLY
if($DEBUG=='debug')print('<b style="color:red;">'.$random.'. API</b> #'.#$favicon.'#<br>');
} // END If nothink works: Get the Favicon from API
// Write Favicon local
$filePath = preg_replace('#\/\/#', '/', $directory.'/'.$domain.'.png');
// If Favicon should be saved
if ( isset($save) and $save == TRUE ) {
// Load Favicon
$content = load($favicon, $DEBUG);
// If Google API don't know and deliver a default Favicon (World)
if ( isset($random) and $random == 3 and
md5($content) == '3ca64f83fdcf25135d87e08af65e68c9' ) {
$domain = 'default'; // so we don't save a default icon for every domain again
// FOR DEBUG ONLY
if($DEBUG=='debug')print('<b style="color:red;">Google</b> #use default icon#<br>');
}
// Write
$fh = #fopen($filePath, 'wb');
fwrite($fh, $content);
fclose($fh);
// FOR DEBUG ONLY
if($DEBUG=='debug')print('<b style="color:red;">Write-File</b> #'.#$filePath.'#<br>');
} else {
// Don't save Favicon local, only return Favicon URL
$filePath = $favicon;
}
} // END If Favicon not already exists local
// FOR DEBUG ONLY
if ($DEBUG=='debug') {
// Load the Favicon from local file
if ( !function_exists('file_get_contents') ) {
$fh = #fopen($filePath, 'r');
while (!feof($fh)) {
$content .= fread($fh, 128); // Because filesize() will not work on URLS?
}
fclose($fh);
} else {
$content = file_get_contents($filePath);
}
print('<b style="color:red;">Image</b> <img style="width:32px;"
src="data:image/png;base64,'.base64_encode($content).'"><hr size="1">');
}
// Return Favicon Url
return $filePath;
} // END MAIN Function
/* HELPER load use curl or file_get_contents (both with user_agent) and fopen/fread as fallback */
function load($url, $DEBUG) {
if ( function_exists('curl_version') ) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_USERAGENT, 'FaviconBot/1.0 (+http://'.$_SERVER['SERVER_NAME'].'/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$content = curl_exec($ch);
if ( $DEBUG=='debug' ) { // FOR DEBUG ONLY
$http_code = curl_getinfo($ch);
print('<b style="color:red;">cURL</b> #'.$http_code['http_code'].'#<br>');
}
curl_close($ch);
unset($ch);
} else {
$context = array ( 'http' => array (
'user_agent' => 'FaviconBot/1.0 (+http://'.$_SERVER['SERVER_NAME'].'/)'),
);
$context = stream_context_create($context);
if ( !function_exists('file_get_contents') ) {
$fh = fopen($url, 'r', FALSE, $context);
$content = '';
while (!feof($fh)) {
$content .= fread($fh, 128); // Because filesize() will not work on URLS?
}
fclose($fh);
} else {
$content = file_get_contents($url, NULL, $context);
}
}
return $content;
}
/* HELPER: Change URL from relative to absolute */
function rel2abs( $rel, $base ) {
extract( parse_url( $base ) );
if ( strpos( $rel,"//" ) === 0 ) return $scheme . ':' . $rel;
if ( parse_url( $rel, PHP_URL_SCHEME ) != '' ) return $rel;
if ( $rel[0] == '#' or $rel[0] == '?' ) return $base . $rel;
$path = preg_replace( '#/[^/]*$#', '', $path);
if ( $rel[0] == '/' ) $path = '';
$abs = $host . $path . "/" . $rel;
$abs = preg_replace( "/(\/\.?\/)/", "/", $abs);
$abs = preg_replace( "/\/(?!\.\.)[^\/]+\/\.\.\//", "/", $abs);
return $scheme . '://' . $abs;
}
Source: https://github.com/gaffling/PHP-Grab-Favicon
See this answer : https://stackoverflow.com/a/22771267. It's an easy to use PHP class to get the favicon URL and download it, and it also gives you some informations about the favicon like file type or how the favicon was found (default URL, <link> tag...) :
<?php
require 'FaviconDownloader.class.php';
$favicon = new FaviconDownloader('https://code.google.com/p/chromium/issues/detail?id=236848');
if($favicon->icoExists){
echo "Favicon found : ".$favicon->icoUrl."\n";
// Saving favicon to file
$filename = 'favicon-'.time().'.'.$favicon->icoType;
file_put_contents($filename, $favicon->icoData);
echo "Saved to ".$filename."\n\n";
} else {
echo "No favicon for ".$favicon->url."\n\n";
}
$favicon->debug();
/*
FaviconDownloader Object
(
[url] => https://code.google.com/p/chromium/issues/detail?id=236848
[pageUrl] => https://code.google.com/p/chromium/issues/detail?id=236848
[siteUrl] => https://code.google.com/
[icoUrl] => https://ssl.gstatic.com/codesite/ph/images/phosting.ico
[icoType] => ico
[findMethod] => head absolue_full
[error] =>
[icoExists] => 1
[icoMd5] => a6cd47e00e3acbddd2e8a760dfe64cdc
)
*/
?>
I find PHP Simple HTML DOM Parser to be more reliable than DOMDocument. So I use this instead:
require_once 'simple_html_dom.php';
$dom = new simple_html_dom();
$dom->load(file_get_contents($url));
$favicon = '';
foreach($dom->find('link') as $e)
{
if (!empty($e->rel) && strtolower(trim($e->rel)) == 'shortcut icon') {
$favicon = $url.'/'.$e->href;
}
}
print $favicon;
Found this thread... I have written a WordPress plugin that encompasses a lot of variations on retrieving the favicon. Since there are a lot the GPL code: http://plugins.svn.wordpress.org/wp-favicons/trunk/
It lets you run a server which you can request icons from via xml rpc requests so any client can request icons. It does have a plugin structure so you can try google, getfavicon, etc... to see if one of these services delivers anything. If not then it goes into a icon fetching mode taking into account all http statusses (301/302/404) and does it best to find an icon anywhere. After this it uses image library functions to check inside the file if it is really an image and what kind of image (sometimes the extension is wrong) and it is pluggable so you can add after image conversions or extra functionality in the pipeline.
the http fetching file does some logic around what i see above: http://plugins.svn.wordpress.org/wp-favicons/trunk/includes/server/class-http.php
but it is only part of the pipeline.
can get pretty complex once you dive into it.
$url = 'http://thamaraiselvam.strikingly.com/';
$doc = new DOMDocument();
$doc->strictErrorChecking = FALSE;
#$doc->loadHTML(file_get_contents($url));
$xml = simplexml_import_dom($doc);
$arr = $xml->xpath('//link[#rel="shortcut icon"]');
if (!empty($arr[0]['href'])) {
echo "<img src=".$arr[0]['href'].">";
}
else
echo "<img src='".$url."/favicon.ico'>";
I changed a bit Vivek second method and added a this function and it looks like this:
<?php
$website=$_GET['u'];
$fevicon= getFavicon($website);
echo '<img src="'.path_to_absolute($fevicon,$website).'"></img>';
function getFavicon($site)
{
$html=file_get_contents($site);
$dom=new DOMDocument();
#$dom->loadHTML($html);
$links=$dom->getElementsByTagName('link');
$fevicon='';
for($i=0;$i < $links->length;$i++ )
{
$link=$links->item($i);
if($link->getAttribute('rel')=='icon'||$link->getAttribute('rel')=="Shortcut Icon"||$link->getAttribute('rel')=="shortcut icon")
{
$fevicon=$link->getAttribute('href');
}
}
return $fevicon;
}
// transform to absolute path function...
function path_to_absolute($rel, $base)
{
/* return if already absolute URL */
if (parse_url($rel, PHP_URL_SCHEME) != '') return $rel;
/* queries and anchors */
if ($rel[0]=='#' || $rel[0]=='?') return $base.$rel;
/* parse base URL and convert to local variables:
$scheme, $host, $path */
extract(parse_url($base));
/* remove non-directory element from path */
$path = preg_replace('#/[^/]*$#', '', $path);
/* destroy path if relative url points to root */
if ($rel[0] == '/') $path = '';
/* dirty absolute URL */
$abs = "$host$path/$rel";
/* replace '//' or '/./' or '/foo/../' with '/' */
$re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
for($n=1; $n>0; $abs=preg_replace($re, '/', $abs, -1, $n)) {}
/* absolute URL is ready! */
return $scheme.'://'.$abs;
}
?>
Of course you call it with https://www.domain.tld/favicon/this_script.php?u=http://www.example.com
Still can't catch all options but now absolute path is resolved. Hope it helps.
If you want to retrieve the favicon from a particular website, you simply need to fetch favicon.ico from the root of their website. Like so:
$domain = "www.example.com";
$url = "http://".$domain."/favicon.ico";
$icondata = file_get_contents($url);
... you can now do what you like with the icon data
I want to save files from an external server into a folder on my server using fopen, fwrite.
First the page from the external site is loaded, and scanned for any image links. Then that list is sent from an to the fwrite function. The files are created, but they aren't the valid jpg files, viewing them in the browser it seems like their path on my server is written to them.
Here is the code:
//read the file
$data = file_get_contents("http://foo.html");
//scan content for jpg links
preg_match_all('/src=("[^"]*.jpg)/i', $data, $result);
//save img function
function save_image($inPath,$outPath)
{
$in= fopen($inPath, "rb");
$out= fopen($outPath, "wb");
while ($chunk = fread($in,8192))
{
fwrite($out, $chunk, 8192);
}
fclose($in);
fclose($out);
}
//output each img link from array
foreach ($result[1] as $imgurl) {
echo "$imgurl<br />\n";
$imgn = (basename ($imgurl));
echo "$imgn<br />\n";
save_image($imgurl, $imgn);
}
The save_image function works if I write out a list:
save_image('http://foo.html', foo1.jpg);
save_image('http://foo.html', foo1.jpg);
I was hoping that I'd be able to just loop the list from the matches in the array.
Thanks for looking.
There are two problems with your script. Firstly the quote mark is being included in the external image URL. To fix this your regex should be:
/src="([^"]*.jpg)/i
Secondly, the image URLs are probably not absolute (don't include http:// and the file path). Put this at the start of your foreach to fix that:
$url = 'http://foo.html';
# If the image is absolute.
if(substr($imgurl, 0, 7) == 'http://' || substr($imgurl, 0, 8) == 'https://')
{
$url = '';
}
# If the image URL starts with /, it goes from the website's root.
elseif(substr($imgurl, 0, 1) == '/')
{
# Repeat until only http:// and the domain remain.
while(substr_count($url, '/') != 2)
{
$url = dirname($url);
}
}
# If only http:// and a domain without a trailing slash.
elseif(substr_count($imgurl, '/') == 2)
{
$url .= '/';
}
# If the web page has an extension, find the directory name.
elseif(strrpos($url, '.') > strrpos($url, '/'))
{
$url = dirname($url);
}
$imgurl = $url. $imgurl;
fopen isn't guaranteed to work. You should be checking the return values of anything they may return something different on error...
fopen() - Returns a file pointer resource on success, or FALSE on error.
In fact all the file functions return false on error.
To figure out where it is failing I would recommend using a debugger, or printing out some information in the save_image function. i.e. What the $inPath and $outPath are, so you can validate they are being passed what you would expect.
The main issue I see is that the regex may not capture the full http:// path. Most sites leave this off and use relative paths. You should code in a check for that and add it in if that is not present.
Your match includes the src bit, so try this instead:
preg_match_all('/(?<=src=")[^"]*.jpg/i', $data, $result);
And then I think this should work:
unset($result[0]);
//output each img link from array
foreach ($result as $imgurl) {
echo "$imgurl<br />\n";
$imgn = (basename ($imgurl));
echo "$imgn<br />\n";
save_image($imgurl, $imgn);
}